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   import org.objectweb.asm.ClassWriter;
10  
11  import java.io.IOException;
12  import java.util.HashMap;
13  import java.util.HashSet;
14  import java.util.List;
15  import java.util.Map;
16  import java.util.Set;
17  
18  public class PMDASMClassLoader extends ClassLoader {
19  
20  	public PMDASMClassLoader() {
21  	}
22  
23  	public synchronized Class loadClass(String name) throws ClassNotFoundException {
24  		return defineClass(name);
25  	}
26  
27  	private Map importedClasses = new HashMap();
28  
29  	private Set dontBother = new HashSet();
30  
31  	public Map getImportedClasses(String className) {
32  		Map ret = (Map) importedClasses.get(className);
33  		return ret == null ? new HashMap() : ret;
34  	}
35  
36  	private Class defineClass(String name) throws ClassNotFoundException {
37  
38  		if (dontBother.contains(name)) {
39  			throw new ClassNotFoundException(name);
40  		}
41  		try {
42  			if (name.startsWith("java.")) {
43  				return Class.forName(name);
44  			}
45  			if (importedClasses.containsKey(name)) {
46  				if (super.findLoadedClass(name) != null) {
47  					return super.findLoadedClass(name);
48  				}
49  			}
50  			ClassReader reader = new ClassReader(getResourceAsStream(name.replace('.', '/') + ".class"));
51  			PMDASMVisitor asmVisitor = new PMDASMVisitor();
52  			reader.accept(asmVisitor, 0);
53  
54  			List inner = asmVisitor.getInnerClasses();
55  			if (inner != null && !inner.isEmpty()) {
56  				for (int ix = 0; ix < inner.size(); ix++) {
57  					String str = (String) inner.get(ix);
58  					ClassReader innerReader = new ClassReader(getResourceAsStream(str.replace('.', '/') + ".class"));
59  					innerReader.accept(asmVisitor, 0);
60  				}
61  			}
62  			importedClasses.put(name, asmVisitor.getPackages());
63  			ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);
64  			reader.accept(writer, 0);
65  
66  			byte[] byteCode = writer.toByteArray();
67  			return defineClass(name, byteCode, 0, byteCode.length);
68  		} catch (ClassNotFoundException e) {
69  			dontBother.add(name);
70  			throw e;
71  		} catch (IOException e) {
72  			dontBother.add(name);
73  			throw new ClassNotFoundException(name, e);
74  		}
75  	}
76  }