001: package gnu.bytecode;
002:
003: import java.util.Hashtable;
004: import java.net.URL;
005:
006: /** Load classes from a set of byte arrays.
007: * @author Per Bothner
008: */
009:
010: public class ArrayClassLoader extends ClassLoader {
011: Hashtable map = new Hashtable(100);
012:
013: /** If non-null, context to use for finding resources. */
014: URL context;
015:
016: public ArrayClassLoader() {
017: }
018:
019: public ArrayClassLoader(ClassLoader parent) {
020: super (parent);
021: }
022:
023: /** Get base URL to use for finding resources, or null if none is set. */
024: public URL getResourceContext() {
025: return context;
026: }
027:
028: /** Set base URL to use for finding resources. */
029: public void setResourceContext(URL context) {
030: this .context = context;
031: }
032:
033: /** Load classes from the given byte arrays.
034: By convention, the classes we manage are named "lambda"+<INTEGER>. */
035: public ArrayClassLoader(byte[][] classBytes) {
036: for (int i = classBytes.length; --i >= 0;)
037: addClass("lambda" + i, classBytes[i]);
038: }
039:
040: public ArrayClassLoader(String[] classNames, byte[][] classBytes) {
041: for (int i = classBytes.length; --i >= 0;)
042: addClass(classNames[i], classBytes[i]);
043: }
044:
045: public void addClass(Class clas) {
046: map.put(clas.getName(), clas);
047: }
048:
049: public void addClass(String name, byte[] bytes) {
050: map.put(name, bytes);
051: }
052:
053: public void addClass(ClassType ctype) throws java.io.IOException {
054: if ((ctype.flags & ClassType.EXISTING_CLASS) != 0)
055: addClass(ctype.getReflectClass());
056: else
057: addClass(ctype.getName(), ctype.writeToArray());
058: }
059:
060: protected URL findResource(String name) {
061: if (context != null) {
062: try {
063: URL url = new URL(context, name);
064: url.openConnection().connect();
065: return url;
066: } catch (Throwable ex) {
067: // Fall through ...
068: }
069: }
070: return super .findResource(name);
071: }
072:
073: /* #ifdef JAVA2 */
074: public Class findClass(String name)
075: /* #else */
076: // public Class loadClass (String name, boolean resolve)
077: /* #endif */
078: throws ClassNotFoundException {
079: Object r = map.get(name);
080: Class clas;
081: if (r == null) {
082: /* #ifdef JAVA2 */
083: throw new ClassNotFoundException(name);
084: /* #else */
085: // clas = Class.forName(name);
086: /* #endif */
087: } else if (r instanceof byte[]) {
088: // double-locking? is this safe? or needed? FIXME.
089: synchronized (this ) {
090: r = map.get(name);
091: if (r instanceof byte[]) {
092: byte[] bytes = (byte[]) r;
093: clas = defineClass(name, bytes, 0, bytes.length);
094: map.put(name, clas);
095: } else
096: clas = (Class) r;
097: }
098: } else
099: clas = (Class) r;
100: /* #ifndef JAVA2 */
101: // if (resolve && clas != null)
102: // resolveClass (clas);
103: /* #endif */
104: return clas;
105: }
106: }
|