/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

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