PageRenderTime 20ms CodeModel.GetById 2ms app.highlight 14ms RepoModel.GetById 2ms app.codeStats 0ms

/src/kilim/mirrors/RuntimeClassMirrors.java

http://github.com/kilim/kilim
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}