/Users/lyon/j4p/src/classUtils/pack/util/pool2/StubClassLoader.java
|
1 package classUtils.pack.util.pool2;
2
3 import java.io.IOException;
4 import java.io.PrintStream;
5 import java.util.HashMap;
6 import java.util.Map;
7
8 /**
9 * This classloader can generate and load code for pooled object
10 * to wrap existing classes, if the <tt>org.sadun.util.pool2.StubClassLoader.generate</tt>
11 * property is set.
12 *
13 * @author Cristiano Sadun
14 *
15 */
16 class StubClassLoader extends ClassLoader {
17
18 private Map stubsMap = new HashMap();
19 private StubGenerator sg;
20 private PrintStream logStream;
21 public boolean generateIfNotFound;
22
23 public StubClassLoader(Class basePooledObject) throws IOException {
24 this(basePooledObject, System.getProperty("org.sadun.util.pool2.StubClassLoader.generate") != null);
25 }
26
27 public StubClassLoader(Class basePooledObject, boolean generateIfNotFound) throws IOException {
28 sg = new StubGenerator(basePooledObject);
29 this.generateIfNotFound=generateIfNotFound;
30 }
31
32 public static String getPooledClassName(Class cls) {
33 return getPooledClassName(cls.getName());
34 }
35
36 /**
37 * Return the qualifed class name of the pooled object for the given qualifed class name.
38 */
39 public static String getPooledClassName(String qualifiedName) {
40
41 int i=qualifiedName.lastIndexOf(".");
42 String name;
43 if (i==-1) name=qualifiedName;
44 else name=qualifiedName.substring(0,i)+".Pooled"+qualifiedName.substring(i+1);
45
46 return name;
47 }
48
49
50 /**
51 * @see java.lang.ClassLoader#findClass(String)
52 */
53 protected Class findClass(String qualifiedName) throws ClassNotFoundException {
54
55 if (!generateIfNotFound)
56 throw new ClassNotFoundException(qualifiedName+" is not in class path. Please define the property \"org.sadun.util.pool2.StubClassLoader.generate\" if you want to auto-generate stub classes at runtime");
57
58 String pooledClassName=getPooledClassName(qualifiedName);
59 Class cls;
60 if ((cls=(Class)stubsMap.get(pooledClassName))!=null) {
61 if (logStream!=null)
62 logStream.println("Bytecode for "+pooledClassName+" already generated");
63 return cls;
64 }
65
66 if (logStream!=null)
67 logStream.println("Generating and loading bytecode for "+pooledClassName);
68
69 int i=qualifiedName.lastIndexOf(".");
70 String name;
71 if (i==-1) name=qualifiedName;
72 else name=qualifiedName.substring(i+1);
73
74 if (!name.startsWith("Pooled"))
75 throw new IllegalArgumentException("This ClassLoader can be only used to load pooled objects");
76 Object obj = stubsMap.get(name);
77 if (obj != null) return (Class)obj;
78 String name2=qualifiedName.substring(0,i)+"."+name.substring(6);
79 try {
80 byte [] clsBytes = sg.generateStub(this.loadClass(name2));
81 cls=this.defineClass(qualifiedName, clsBytes, 0, clsBytes.length);
82 } catch (IOException e) {
83 throw new ClassNotFoundException("Could not generate stub", e);
84 }
85 stubsMap.put(name, cls);
86 return cls;
87 }
88
89 public static void main(String[] args) throws Exception {
90 new StubClassLoader(BasePooledObject.class).loadClass("org.sadun.util.pool2.PooledStubGenerator");
91 }
92
93
94 /**
95 * Returns the logStream.
96 * @return PrintStream
97 */
98 public PrintStream getLogStream() {
99 return logStream;
100 }
101
102 /**
103 * Sets the logStream.
104 * @param logStream The logStream to set
105 */
106 public void setLogStream(PrintStream logStream) {
107 this.logStream=logStream;
108 this.sg.setLogStream(logStream);
109 }
110
111 }
112