1
2
3
4 package joeq.Main;
5
6 import java.io.BufferedReader;
7 import java.io.File;
8 import java.io.FileNotFoundException;
9 import java.io.FileOutputStream;
10 import java.io.FileReader;
11 import java.io.IOException;
12 import java.io.PrintWriter;
13 import java.util.Collection;
14 import java.util.HashSet;
15 import java.util.Iterator;
16 import java.util.LinkedList;
17 import java.util.List;
18 import joeq.Class.PrimordialClassLoader;
19 import joeq.Class.jq_Class;
20 import joeq.Class.jq_Type;
21 import jwutil.util.Assert;
22
23 /***
24 * author: V.Benjamin Livshits
25 * $Id: ClasspathWalker.java 2326 2005-10-08 19:51:20Z joewhaley $
26 * */
27 public class ClasspathWalker {
28 private static final boolean TRACE = !System.getProperty("trace", "no").equals("no");
29 private static PrintWriter pw;
30 private static int classCount = 0;
31 static boolean SKIP_ABSTRACT = !System.getProperty("skipabstract", "no").equals("no");
32 static boolean GC = !System.getProperty("gc", "no").equals("no");
33 static boolean AUTOFLUSH = !System.getProperty("autoflush", "no").equals("no");
34
35 public static void main(String[] args) throws FileNotFoundException {
36 HostedVM.initialize();
37
38 System.out.println("Classpath: " + PrimordialClassLoader.loader.classpathToString() + "\n");
39 pw = new PrintWriter(new FileOutputStream("subclasses.txt"), AUTOFLUSH);
40 processPackages();
41 pw.close();
42 }
43
44 private static void processPackages() {
45 for(Iterator iter = listPackages(); iter.hasNext();){
46
47 String packageName = (String) iter.next();
48 HashSet loaded = new HashSet();
49 if(TRACE) System.out.println("Processing package " + packageName + ", " + classCount + " classes loaded so far.");
50
51 for(Iterator classIter = PrimordialClassLoader.loader.listPackage(packageName, true); classIter.hasNext();){
52 String className = (String) classIter.next();
53 String canonicalClassName = canonicalizeClassName(className);
54 if (loaded.contains(canonicalClassName)){
55
56 continue;
57 }
58 loaded.add(canonicalClassName);
59 try {
60 jq_Class c = (jq_Class) PrimordialClassLoader.loader.getOrCreateBSType(canonicalClassName);
61 if (canonicalClassName.equals("Ljava/lang/Object;")) {
62 Assert._assert(c == PrimordialClassLoader.getJavaLangObject());
63 }
64 c.load();
65 c.prepare();
66 Collection interfaces = new LinkedList();
67 Collection superclasses = new LinkedList();
68
69 collectSuperclasses(c, interfaces, superclasses);
70 pw.println("CLASS " + c.getName());
71 pw.println("INTERFACES ");
72 for(Iterator iter2 = interfaces.iterator(); iter2.hasNext();){
73 pw.println("\t" + iter2.next().toString());
74 }
75 pw.println("SUPERCLASSES ");
76 for(Iterator iter2 = superclasses.iterator(); iter2.hasNext();){
77 pw.println("\t" + iter2.next().toString());
78 }
79 pw.println();
80
81
82 classCount++;
83
84 } catch (NoClassDefFoundError x) {
85 if(TRACE) System.err.println("\tPackage " + packageName + ": Class not found (canonical name " + canonicalClassName + "): "+x);
86
87 } catch (ClassFormatError cfe) {
88 if(TRACE) System.err.println("\tClass format error occurred while loading class (" + canonicalClassName + "): " + cfe.toString());
89
90 } catch (LinkageError le) {
91 if(TRACE) System.err.println("\tLinkage error occurred while loading class (" + canonicalClassName + "): " + le.toString());
92
93 } catch (RuntimeException e){
94 if(TRACE) System.err.println("\tSecurity error occurred: " + e.getMessage());
95 }
96 }
97 if(GC && (classCount % 17) == 3){
98 if(TRACE) System.err.println("GCing...");
99 System.gc();
100 if(TRACE) System.err.println("Done GCing.");
101 }
102 }
103 if(TRACE) System.out.println("Done.");
104 }
105
106 static void collectSuperclasses(jq_Class c, Collection interfaces, Collection superclasses) {
107 do {
108 if(!SKIP_ABSTRACT || !c.isAbstract()){
109 if(TRACE) System.out.println("Skipping abstract class " + c);
110 superclasses.add(c);
111 }
112 if(c.getInterfaces() != null){
113 for(int i = 0; i < c.getInterfaces().length; i++){
114 jq_Class inter = c.getInterfaces()[i];
115 interfaces.add(inter);
116 }
117 }
118 c = c.getSuperclass();
119 } while(c != null && c != PrimordialClassLoader.JavaLangObject);
120 }
121
122 static Iterator listPackages(){
123 Collection result = new LinkedList();
124 for(Iterator iter = PrimordialClassLoader.loader.listPackages(); iter.hasNext();){
125 String packageName = (String) iter.next();
126 if(packageName.equals(".") || packageName.equals("")){
127 continue;
128 }
129 if(packageName.endsWith("javabdd-1.0b2.jar") || packageName.endsWith("jwutil-1.0.jar")){
130 continue;
131 }
132 if(packageName.endsWith("joeq_core")){
133 continue;
134 }
135 if(packageName.startsWith("joeq") || packageName.startsWith("jwutil")){
136 continue;
137 }
138
139 result.add(packageName);
140 }
141
142 return result.iterator();
143 }
144
145 public static String canonicalizeClassName(String s) {
146 if (s.endsWith(".class")) s = s.substring(0, s.length() - 6);
147 s = s.replace('.', '/');
148 String desc = "L" + s + ";";
149 return desc;
150 }
151
152 public static jq_Type load(String classname) {
153 try {
154 jq_Type c = jq_Type.parseType(classname);
155 c.load();
156 c.prepare();
157 return c;
158 } catch (NoClassDefFoundError e) {
159 System.err.println("Could not find class " + classname
160 + ", skipping.");
161 }
162 return null;
163 }
164
165 public static jq_Type[] loadPackage(String packagename) {
166 return loadPackages(packagename, false);
167 }
168
169 public static jq_Type[] loadPackages(String packagename) {
170 return loadPackages(packagename, true);
171 }
172
173 public static jq_Type[] loadPackages(String packagename, boolean recursive) {
174 String canonicalPackageName = packagename.replace('.', '/');
175 if (!canonicalPackageName.equals("")
176 && !canonicalPackageName.endsWith("/")) canonicalPackageName += '/';
177 Iterator i = joeq.Class.PrimordialClassLoader.loader.listPackage(
178 canonicalPackageName, recursive);
179 if (!i.hasNext()) {
180 System.err.println("Package " + canonicalPackageName
181 + " not found.");
182 }
183 LinkedList ll = new LinkedList();
184 while (i.hasNext()) {
185 String c = (String) i.next();
186 c = c.substring(0, c.length() - 6);
187 jq_Type t = ClasspathWalker.load(c);
188 if (t != null) ll.add(t);
189 }
190 return (jq_Class[]) ll.toArray(new jq_Class[0]);
191 }
192
193 /***
194 * Add paths contained in file fileName.
195 * @param fileName -- name of the file with class paths
196 * */
197 public static void addToClassPath(String fileName) {
198 try {
199 BufferedReader br = new BufferedReader(new FileReader(fileName));
200 for (;;) {
201 String s = br.readLine();
202 if (s == null) break;
203 if (s.length() == 0) continue;
204 if (s.startsWith("%")) continue;
205 if (s.startsWith("#")) continue;
206 PrimordialClassLoader.loader.addToClasspath(s);
207 }
208 br.close();
209 } catch (IOException e) {
210 e.printStackTrace();
211 System.exit(2);
212 }
213 }
214
215 public static void addJarDir(String dir) {
216 List jars = new LinkedList();
217
218 addJarDir_aux(new File(dir), jars);
219
220 for (Iterator i = jars.iterator(); i.hasNext();) {
221 PrimordialClassLoader.loader.addToClasspath(i.next().toString());
222 }
223 }
224
225 public static void addClassDir(String dir, boolean recurse) {
226 List classes = new LinkedList();
227
228 addClassDir_aux(new File(dir), classes, recurse);
229
230 for (Iterator i = classes.iterator(); i.hasNext();) {
231 String className = i.next().toString();
232 if(TRACE) System.out.println("Adding class " + className);
233 PrimordialClassLoader.loader.addToClasspath(className);
234 }
235 }
236
237 static private void addJarDir_aux(File f, List results) {
238 if (f.getPath().endsWith(".jar")) {
239 results.add(f.getPath());
240 } else if (f.list() != null) {
241 String[] contents=f.list();
242 for (int i = 0; i<contents.length; i++) {
243 addJarDir_aux(new File(f.getPath(), contents[i]), results);
244 }
245 }
246 }
247
248 static private void addClassDir_aux(File f, List results, boolean recurse) {
249 if (f.getPath().endsWith(".class")) {
250 results.add(f.getPath());
251 } else if (f.list() != null && recurse) {
252
253 String[] contents = f.list();
254 for (int i = 0; i<contents.length; i++) {
255 addClassDir_aux(new File(f.getPath(), contents[i]), results, recurse);
256 }
257 }
258 }
259
260
261 }