View Javadoc

1   // Helper.java, created Thu Jan 16 10:53:32 2003 by mcmartin
2   // Copyright (C) 2001-3 mcmartin
3   // Licensed under the terms of the GNU LGPL; see COPYING for details.
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              //System.out.println("\t" + iter.next());
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                      //if(TRACE) System.err.println("Skipping " + className);
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                      //PrimordialClassLoader.loader.unloadBSType(c);
82                      classCount++;
83                     //if(TRACE) System.out.println("Processing class # " + classCount + ", " + canonicalClassName);
84                  } catch (NoClassDefFoundError x) {
85                      if(TRACE) System.err.println("\tPackage " + packageName + ": Class not found (canonical name " + canonicalClassName + "): "+x);
86                      //x.printStackTrace();
87                  } catch (ClassFormatError cfe) {
88                      if(TRACE) System.err.println("\tClass format error occurred while loading class (" + canonicalClassName + "): " + cfe.toString());
89                      //cfe.printStackTrace(System.err);
90                  } catch (LinkageError le) {
91                      if(TRACE) System.err.println("\tLinkage error occurred while loading class (" + canonicalClassName + "): " + le.toString());
92                      //le.printStackTrace(System.err);
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             // directory 
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 }