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  }