/src/kilim/mirrors/RuntimeClassMirrors.java
Java | 194 lines | 147 code | 34 blank | 13 comment | 17 complexity | 0a7fa6ecdd70ac40f11ea15ea4709a0d MD5 | raw file
1package kilim.mirrors; 2 3import java.lang.reflect.Method; 4import java.util.Collections; 5import java.util.Map; 6import java.util.WeakHashMap; 7 8import kilim.KilimClassLoader; 9 10import org.objectweb.asm.Type; 11 12/** 13 * This class provides the Mirrors facade over a set of Class objects 14 * @see Mirrors 15 */ 16 17public class RuntimeClassMirrors implements Mirrors { 18 // Weakly cache the mirror objects. 19 Map<String, RuntimeClassMirror> cachedClasses = Collections 20 .synchronizedMap(new WeakHashMap<String, RuntimeClassMirror>()); 21 22 public final KilimClassLoader classLoader; 23 24 public RuntimeClassMirrors() { 25 this(Thread.currentThread().getContextClassLoader()); 26 } 27 28 public RuntimeClassMirrors(ClassLoader cl) { 29 if (!(cl instanceof KilimClassLoader)) { 30 cl = new KilimClassLoader(cl); 31 } 32 this.classLoader = (KilimClassLoader) cl; 33 } 34 35 @Override 36 public ClassMirror classForName(String className) throws ClassMirrorNotFoundException { 37 try { 38 RuntimeClassMirror ret = cachedClasses.get(className); 39 if (ret == null) { 40 ret = make(classLoader.loadClass(className)); 41 } 42 return ret; 43 } catch (ClassNotFoundException e) { 44 throw new ClassMirrorNotFoundException(className, e); 45 } 46 } 47 48 @Override 49 public ClassMirror mirror(Class<?> clazz) { 50 if (clazz == null) 51 return null; 52 return make(clazz); 53 } 54 55 @Override 56 public ClassMirror mirror(String className, byte[] bytecode) { 57 try { 58 return classForName(className); 59 } catch (ClassMirrorNotFoundException ignore) {} 60 return null; 61 } 62 63 /** 64 * Like classForName, but only if the class is already loaded. This does not force loading of a 65 * class. 66 * 67 * @param className 68 * @return null if className not loaded, else a RuntimeClassMirror to represent the loaded 69 * class. 70 */ 71 public ClassMirror loadedClassForName(String className) { 72 Class<?> c = classLoader.getLoadedClass(className); 73 return (c == null) ? null : make(c); 74 } 75 76 public Class<?> getLoadedClass(String className) { 77 return classLoader.getLoadedClass(className); 78 } 79 80 public boolean isLoaded(String className) { 81 return classLoader.isLoaded(className); 82 } 83 84 private RuntimeClassMirror make(Class<?> c) { 85 if (c == null) { 86 throw new NullPointerException(); 87 } 88 RuntimeClassMirror ret = new RuntimeClassMirror(c); 89 cachedClasses.put(c.getName(), ret); 90 return ret; 91 } 92} 93 94class RuntimeMethodMirror implements MethodMirror { 95 96 private final Method method; 97 98 public RuntimeMethodMirror(Method method) { 99 this.method = method; 100 } 101 102 public String getName() { 103 return method.getName(); 104 } 105 106 public String[] getExceptionTypes() { 107 String[] ret = new String[method.getExceptionTypes().length]; 108 int i = 0; 109 for (Class<?> excl : method.getExceptionTypes()) { 110 ret[i++] = excl.getName(); 111 } 112 return ret; 113 } 114 115 public String getMethodDescriptor() { 116 return Type.getMethodDescriptor(method); 117 } 118 119 public boolean isBridge() { 120 return method.isBridge(); 121 } 122} 123 124class RuntimeClassMirror implements ClassMirror { 125 126 private final Class<?> clazz; 127 private MethodMirror[] methods; 128 129 public RuntimeClassMirror(Class<?> clazz) { 130 this.clazz = clazz; 131 } 132 133 @Override 134 public String getName() { 135 return clazz.getName(); 136 } 137 138 @Override 139 public boolean isInterface() { 140 return clazz.isInterface(); 141 } 142 143 @Override 144 public boolean equals(Object obj) { 145 if (obj instanceof ClassMirror) { 146 return ((ClassMirror) obj).getName().equals(this.getName()); 147 } 148 return false; 149 } 150 151 @Override 152 public int hashCode() { 153 return clazz.hashCode(); 154 } 155 156 @Override 157 public MethodMirror[] getDeclaredMethods() { 158 if (methods == null) { 159 Method[] declaredMethods = clazz.getDeclaredMethods(); 160 methods = new MethodMirror[declaredMethods.length]; 161 for (int i = 0; i < declaredMethods.length; i++) { 162 methods[i] = new RuntimeMethodMirror(declaredMethods[i]); 163 } 164 } 165 return methods; 166 } 167 168 @Override 169 public String[] getInterfaces() { 170 Class<?>[] ifs = clazz.getInterfaces(); 171 String[] result = new String[ifs.length]; 172 for (int i = 0; i < result.length; i++) { 173 result[i] = ifs[i].getName(); 174 } 175 return result; 176 } 177 178 @Override 179 public String getSuperclass() { 180 Class<?> supcl = clazz.getSuperclass(); 181 return supcl != null ? supcl.getName() : null; 182 } 183 184 @Override 185 public boolean isAssignableFrom(ClassMirror c) { 186 if (c instanceof RuntimeClassMirror) { 187 RuntimeClassMirror cc = (RuntimeClassMirror) c; 188 return clazz.isAssignableFrom(cc.clazz); 189 } else { 190 return false; 191 } 192 } 193 194}