ArrayClassLoader.java 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. package gnu.bytecode;
  2. import java.util.Hashtable;
  3. import java.net.URL;
  4. import java.io.*;
  5. /** Load classes from a set of byte arrays.
  6. * @author Per Bothner
  7. */
  8. public class ArrayClassLoader extends ClassLoader
  9. {
  10. /** Map String to union(byte[], ClassType). */
  11. Hashtable map = new Hashtable(100);
  12. /** Map String to Class. */
  13. Hashtable cmap = new Hashtable(100);
  14. /** If non-null, context to use for finding resources. */
  15. URL context;
  16. public ArrayClassLoader ()
  17. {
  18. }
  19. public ArrayClassLoader (ClassLoader parent)
  20. {
  21. super(parent);
  22. }
  23. /** Get base URL to use for finding resources, or null if none is set. */
  24. public URL getResourceContext () { return context; }
  25. /** Set base URL to use for finding resources. */
  26. public void setResourceContext (URL context) { this.context = context; }
  27. /** Load classes from the given byte arrays.
  28. * By convention, the classes we manage are named
  29. * {@code "lambda"+<INTEGER>}.
  30. */
  31. public ArrayClassLoader (byte[][] classBytes)
  32. {
  33. for (int i = classBytes.length; --i >= 0; )
  34. addClass("lambda" + i, classBytes[i]);
  35. }
  36. public ArrayClassLoader (String[] classNames, byte[][] classBytes)
  37. {
  38. for (int i = classBytes.length; --i >= 0; )
  39. addClass(classNames[i], classBytes[i]);
  40. }
  41. public void addClass(Class clas)
  42. {
  43. cmap.put(clas.getName(), clas);
  44. }
  45. public void addClass(String name, byte[] bytes)
  46. {
  47. map.put(name, bytes);
  48. }
  49. public void addClass (ClassType ctype)
  50. {
  51. map.put(ctype.getName(), ctype);
  52. }
  53. public InputStream getResourceAsStream(String name)
  54. {
  55. InputStream in = super.getResourceAsStream(name);
  56. if (in == null && name.endsWith(".class"))
  57. {
  58. String cname = name.substring(0, name.length()-6).replace('/', '.');
  59. Object r = map.get(cname);
  60. if (r instanceof byte[])
  61. return new ByteArrayInputStream((byte[]) r);
  62. }
  63. return in;
  64. }
  65. protected URL findResource(String name)
  66. {
  67. if (context != null)
  68. {
  69. try
  70. {
  71. URL url = new URL(context, name);
  72. url.openConnection().connect();
  73. return url;
  74. }
  75. catch (Exception ex)
  76. {
  77. // Fall through ...
  78. }
  79. }
  80. return super.findResource(name);
  81. }
  82. public Class loadClass (String name, boolean resolve)
  83. throws ClassNotFoundException
  84. {
  85. Class clas = loadClass(name);
  86. if (resolve)
  87. resolveClass(clas);
  88. return clas;
  89. }
  90. /** Load named class.
  91. * Note we deliberately don't follow the Java2 delegation model,
  92. * in order to allow classes to be overridden and replaced.
  93. * Specifically, we depend on this for the "session class-loader".
  94. */
  95. public Class loadClass (String name)
  96. throws ClassNotFoundException {
  97. Object r = cmap.get(name);
  98. if (r != null)
  99. return (Class) r;
  100. synchronized (this) {
  101. r = map.get(name);
  102. if (r instanceof ClassType) {
  103. ClassType ctype = (ClassType) r;
  104. if (ctype.isExisting())
  105. r = ctype.reflectClass;
  106. else
  107. r = ctype.writeToArray();
  108. }
  109. if (r instanceof byte[]) {
  110. byte[] bytes = (byte[]) r;
  111. Class clas = defineClass(name, bytes, 0, bytes.length);
  112. cmap.put(name, clas);
  113. return clas;
  114. }
  115. else if (r == null)
  116. return getParent().loadClass(name);
  117. else
  118. return (Class) r;
  119. }
  120. }
  121. /* #ifdef JAVA2 */
  122. public static Package getContextPackage (String cname)
  123. {
  124. ClassLoader loader;
  125. try
  126. {
  127. loader = Thread.currentThread().getContextClassLoader();
  128. if (loader instanceof ArrayClassLoader)
  129. return ((ArrayClassLoader) loader).getPackage(cname);
  130. }
  131. catch (java.lang.SecurityException ex)
  132. {
  133. }
  134. return Package.getPackage(cname);
  135. }
  136. /* #endif */
  137. }