PMDASMClassLoader.java
01 /**
02  * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
03  */
04 package net.sourceforge.pmd.lang.java.typeresolution;
05 
06 import java.io.IOException;
07 import java.util.ArrayList;
08 import java.util.HashSet;
09 import java.util.List;
10 import java.util.Map;
11 import java.util.Set;
12 
13 import net.sourceforge.pmd.lang.java.typeresolution.visitors.PMDASMVisitor;
14 
15 import org.objectweb.asm.ClassReader;
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 namethrows 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 ArrayList<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 }