001: /*
002: * @(#)ClassFileLoader.java 1.3 05/04/29
003: *
004: * Copyright (c) 1997-2004 Sun Microsystems, Inc. All Rights Reserved.
005: *
006: * See the file "LICENSE.txt" for information on usage and redistribution
007: * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
008: */
009: package org.pnuts.lang;
010:
011: import java.io.ByteArrayOutputStream;
012: import java.io.File;
013: import java.io.FileOutputStream;
014: import java.io.IOException;
015: import java.lang.reflect.Method;
016:
017: import pnuts.compiler.ClassFile;
018: import pnuts.compiler.ClassFileHandler;
019: import pnuts.lang.Context;
020: import pnuts.lang.Package;
021: import pnuts.lang.PnutsException;
022:
023: public class ClassFileLoader extends ClassLoader implements
024: ClassFileHandler {
025: private final static boolean DEBUG = true;
026: private static long ID = 0L;
027:
028: private Package pkg;
029: private Context context;
030: private String id;
031: private int classes = 0;
032:
033: public ClassFileLoader(ClassLoader parent) {
034: super (parent);
035: this .id = Long.toHexString(ID++);
036: }
037:
038: /*
039: * setup for subclass()
040: */
041: public void setup(Package pkg, Context context) {
042: this .pkg = pkg;
043: this .context = context;
044: }
045:
046: public Object handle(ClassFile cf) {
047: return define(cf);
048: }
049:
050: protected Class define(ClassFile cf) {
051: try {
052: ByteArrayOutputStream bout = new ByteArrayOutputStream();
053: cf.write(bout);
054: byte[] barray = bout.toByteArray();
055: return define(cf.getClassName(), barray, 0, barray.length);
056: } catch (IOException e) {
057: e.printStackTrace();
058: return null;
059: } finally {
060: classes++;
061: }
062: }
063:
064: protected Class define(String name, byte[] barray, int offset,
065: int len) {
066: try {
067: Class cls = defineClass(name, barray, offset, len,
068: getClass().getProtectionDomain());
069: resolveClass(cls);
070: if (pkg != null && context != null) {
071: try {
072: Method m = cls.getMethod("attach",
073: new Class[] { Context.class });
074: m.invoke(null, new Object[] { context });
075: } catch (Exception e) {
076: try {
077: Method m = cls.getMethod("attach", new Class[] {
078: Context.class, Package.class });
079: m.invoke(null, new Object[] { context, pkg });
080: } catch (Exception e2) {
081: throw new PnutsException(e2, context);
082: }
083: }
084: } else if (context != null) {
085: try {
086: Method m = cls.getMethod("attach",
087: new Class[] { Context.class });
088: m.invoke(null, new Object[] { context });
089: } catch (Exception e3) {
090: throw new PnutsException(e3, context);
091: }
092: }
093: return cls;
094: } catch (LinkageError e) {
095: if (DEBUG) {
096: try {
097: String temp = System.getProperty("java.io.tmpdir");
098: FileOutputStream out = new FileOutputStream(
099: new File(temp, name + ".class"));
100: out.write(barray, offset, len);
101: out.close();
102: } catch (IOException ioe) {
103: }
104: }
105: throw e;
106: }
107: }
108:
109: public int getClassCount() {
110: return classes;
111: }
112:
113: public String getId() {
114: return id;
115: }
116: }
|