View Javadoc

1   /**
2    * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
3    */
4   package net.sourceforge.pmd.typeresolution;
5   
6   import net.sourceforge.pmd.typeresolution.visitors.PMDASMVisitor;
7   
8   import org.objectweb.asm.ClassReader;
9   
10  import java.io.IOException;
11  import java.util.LinkedList;
12  import java.util.HashSet;
13  import java.util.List;
14  import java.util.Map;
15  import java.util.Set;
16  
17  /*
18   * I've refactored this class to not cache the results any more. This is a
19   * tradeoff in testing I've found the CPU tradeoff is negligeable. With the
20   * cache, large codebases consumed a lot of memory and slowed down greatly when
21   * approaching 3,000 classes. I'm adding this comment in case someone is looking
22   * at this code and thinks a cache may help.
23   */
24  public class PMDASMClassLoader extends ClassLoader {
25  
26      public PMDASMClassLoader(ClassLoader parent) {
27      	super(parent);
28      }
29  
30      private Set<String> dontBother = new HashSet<String>();
31  
32      public synchronized Map<String, String> getImportedClasses(String name) throws ClassNotFoundException {
33  
34          if (dontBother.contains(name)) {
35              throw new ClassNotFoundException(name);
36          }
37          try {
38              ClassReader reader = new ClassReader(getResourceAsStream(name.replace('.', '/') + ".class"));
39              PMDASMVisitor asmVisitor = new PMDASMVisitor();
40              reader.accept(asmVisitor, 0);
41  
42              List<String> inner = asmVisitor.getInnerClasses();
43              if (inner != null && !inner.isEmpty()) {
44                  inner = new LinkedList<String>(inner); // to avoid ConcurrentModificationException
45                  for (String str: inner) {
46                      reader = new ClassReader(getResourceAsStream(str.replace('.', '/') + ".class"));
47                      reader.accept(asmVisitor, 0);
48                  }
49              }
50              return asmVisitor.getPackages();
51          } catch (IOException e) {
52              dontBother.add(name);
53              throw new ClassNotFoundException(name, e);
54          }
55      }
56  }