/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