1 | package dmg.cells.nucleus ; |
2 | |
3 | import dmg.util.* ; |
4 | import java.util.* ; |
5 | import java.io.* ; |
6 | |
7 | import org.slf4j.Logger; |
8 | import org.slf4j.LoggerFactory; |
9 | |
10 | public class ClassLoaderProvider { |
11 | |
12 | private class _TreeNode { |
13 | private Hashtable _hash = null ; |
14 | private ClassDataProvider _entry = null ; |
15 | private _TreeNode( ClassDataProvider entry ){ |
16 | _entry = entry ; |
17 | } |
18 | private _TreeNode(){} |
19 | private void put( String key , _TreeNode value ){ |
20 | if( _hash == null )_hash = new Hashtable() ; |
21 | _hash.put( key , value ) ; |
22 | } |
23 | private _TreeNode get( String key ){ |
24 | return _hash==null?null:(_TreeNode)_hash.get( key ) ; |
25 | } |
26 | private void setDefault( ClassDataProvider entry ){ |
27 | _entry = entry ; |
28 | } |
29 | private ClassDataProvider getDefault(){ return _entry ; } |
30 | private Enumeration keys(){ return _hash==null?null:_hash.keys() ; } |
31 | |
32 | |
33 | } |
34 | // |
35 | // set the default ( root ) to the system loader |
36 | // |
37 | private _TreeNode _root = new _TreeNode( new CDPDummy() ) ; |
38 | |
39 | |
40 | public ClassLoaderProvider(){} |
41 | public String [][] getProviders(){ |
42 | Vector v = new Vector() ; |
43 | getProviders( v , "*" , _root ) ; |
44 | String [][] rt = new String[v.size()][] ; |
45 | v.copyInto( rt ) ; |
46 | return rt ; |
47 | } |
48 | public void getProviders( Vector v , String name , _TreeNode cursor ){ |
49 | ClassDataProvider le = cursor.getDefault() ; |
50 | String [] out = new String[2] ; |
51 | out[0] = name ; |
52 | out[1] = le==null?"none":le.toString() ; |
53 | v.addElement( out ) ; |
54 | Enumeration e = cursor.keys() ; |
55 | if( e == null )return ; |
56 | for( ; e.hasMoreElements() ; ){ |
57 | String nodeName = (String)e.nextElement() ; |
58 | _TreeNode node = cursor.get( nodeName ) ; |
59 | getProviders( v , name+"."+nodeName , node ) ; |
60 | } |
61 | } |
62 | public void setDefault( ClassDataProvider defEntry ){ |
63 | _root.setDefault( defEntry ) ; |
64 | } |
65 | public void addEntry( String selection , ClassDataProvider provider ){ |
66 | |
67 | StringTokenizer st = new StringTokenizer( selection , ".") ; |
68 | _TreeNode cursor = _root ; |
69 | for( ; st.hasMoreTokens() ; ){ |
70 | String token = st.nextToken() ; |
71 | if( token.equals("*") )break ; |
72 | _TreeNode rt = cursor.get( token ) ; |
73 | if( rt == null ){ |
74 | rt = new _TreeNode() ; |
75 | cursor.put( token , rt ) ; |
76 | } |
77 | cursor = rt ; |
78 | } |
79 | cursor.setDefault( provider ) ; |
80 | } |
81 | public void removeSystemProvider( String selection ){ |
82 | addEntry( selection , null ) ; |
83 | } |
84 | public void addSystemProvider( String selection ){ |
85 | addEntry( selection , new CDPDummy() ) ; |
86 | } |
87 | public void addFileProvider( String selection , File file ){ |
88 | addEntry( selection , new ClassDataProvider0( file ) ) ; |
89 | } |
90 | public void addCellProvider( String selection , |
91 | CellNucleus nucleus , |
92 | CellPath cellPath ){ |
93 | |
94 | addEntry( selection , new ClassDataProvider0( nucleus , cellPath ) ) ; |
95 | |
96 | } |
97 | ClassDataProvider getEntry( String className ){ |
98 | StringTokenizer st = new StringTokenizer( className , ".") ; |
99 | _TreeNode cursor = _root ; |
100 | ClassDataProvider def = _root.getDefault() ; |
101 | for( ; st.hasMoreTokens() ; ){ |
102 | String token = st.nextToken() ; |
103 | _TreeNode rt = cursor.get( token ) ; |
104 | if( rt == null )return def ; |
105 | ClassDataProvider tmp = rt.getDefault() ; |
106 | def = tmp == null ? def : tmp ; |
107 | cursor = rt ; |
108 | } |
109 | return def ; |
110 | } |
111 | public Class loadClass( String className ) throws ClassNotFoundException { |
112 | ClassLoader loader = new ClassLoaderC( this ) ; |
113 | return loader.loadClass( className ) ; |
114 | } |
115 | public static void main( String [] args ) throws Exception { |
116 | if( args.length < 1 ){ |
117 | System.out.println( "USAGE : ... <selection> ... " ) ; |
118 | System.exit(43); |
119 | } |
120 | ClassLoaderProvider clp = new ClassLoaderProvider() ; |
121 | int i ; |
122 | for( i = 0 ; i < args.length ; i++ ){ |
123 | if( args[i].equals(".") )break ; |
124 | System.out.println( "Loading .... "+args[i] ) ; |
125 | StringTokenizer st = new StringTokenizer( args[i] ,":") ; |
126 | String selection = st.nextToken() ; |
127 | String provider = st.nextToken() ; |
128 | ClassDataProvider loader = null ; |
129 | if( ! provider.equals( "system" ) ){ |
130 | loader = new ClassDataProvider0( new File( provider) ); |
131 | } |
132 | clp.addEntry( selection , loader ) ; |
133 | } |
134 | String [] [] out = clp.getProviders() ; |
135 | for( int j = 0 ; j < out.length ; j++ ){ |
136 | System.out.println( " "+out[j][0]+" -> "+out[j][1] ) ; |
137 | // System.out.println( "Displaying .........................." ) ; |
138 | // clp.display() ; |
139 | // for( i++ ; i < args.length ; i++ ){ |
140 | // System.out.println( "Class Loading .... "+args[i] ) ; |
141 | // Class entry = clp.loadClass( args[args.length-1] ) ; |
142 | // System.out.println( "Found ............ "+entry ) ; |
143 | } |
144 | } |
145 | } |
146 | class CDPDummy implements ClassDataProvider { |
147 | |
148 | public byte [] getClassData( String className ) |
149 | throws IOException { |
150 | return null ; |
151 | } |
152 | public String toString(){ |
153 | return "CDP=System" ; |
154 | } |
155 | } |
156 | class ClassDataProvider0 implements ClassDataProvider { |
157 | |
158 | private final static Logger _log = |
159 | LoggerFactory.getLogger(ClassDataProvider0.class); |
160 | |
161 | private CellNucleus _nucleus = null ; |
162 | private CellPath _cellPath = null ; |
163 | private File _dir = null ; |
164 | private boolean _useSystem = false ; |
165 | |
166 | ClassDataProvider0( CellNucleus nucleus , CellPath cellPath ){ |
167 | _nucleus = nucleus ; |
168 | _cellPath = cellPath ; |
169 | } |
170 | ClassDataProvider0( File dir ){ |
171 | _dir = dir ; |
172 | } |
173 | ClassDataProvider0(){ |
174 | _useSystem = true ; |
175 | } |
176 | public boolean useSystem(){ return _useSystem ; } |
177 | public String toString(){ |
178 | if( _dir != null ) |
179 | return "CDP0;Directory="+_dir ; |
180 | if( ( _nucleus != null ) && ( _cellPath != null ) ) |
181 | return "CDP0;Cell="+_nucleus.getCellName()+ |
182 | "CellPath="+_cellPath ; |
183 | return "CDP0;PANIC" ; |
184 | } |
185 | public byte [] getClassData( String className ) |
186 | throws IOException { |
187 | |
188 | if( _dir != null ){ |
189 | className = className.replace( '.' , '/' )+".class" ; |
190 | return loadClassDataFile( _dir , className ) ; |
191 | } |
192 | if( ( _nucleus != null ) && ( _cellPath != null ) ){ |
193 | |
194 | return loadClassDataCell( className ) ; |
195 | } |
196 | throw new IOException( "PANIC in ClassDataProvider0" ) ; |
197 | } |
198 | private byte [] loadClassDataCell( String className ) |
199 | throws IOException { |
200 | |
201 | _log.info( "getClassData("+className+") send to classProvider" ) ; |
202 | CellMessage answer = null ; |
203 | try{ |
204 | answer = _nucleus.sendAndWait( |
205 | new CellMessage( _cellPath , |
206 | "get class "+className |
207 | ) , |
208 | 4000 |
209 | ) ; |
210 | }catch( InterruptedException e ){ |
211 | _log.info( "getClassData Exception : "+e ) ; |
212 | throw new IOException( e.toString() ) ; |
213 | }catch( NoRouteToCellException e ){ |
214 | _log.info( "getClassData Exception : "+e ) ; |
215 | throw new IOException( e.toString() ) ; |
216 | } |
217 | if( answer == null ){ |
218 | _log.info( "getClassData sendAndWait timed out" ) ; |
219 | throw new IOException( "getClassData sendAndWait timed out" ) ; |
220 | } |
221 | Object answerObject = answer.getMessageObject() ; |
222 | if( answerObject == null ) |
223 | throw new IOException( "PANIC Message didn't contain data" ) ; |
224 | |
225 | if( ! ( answerObject instanceof byte [] ) ){ |
226 | _log.info( "getClassData sendAndWait got : "+ |
227 | answerObject.toString() ) ; |
228 | throw new IOException( "Unknown data arrived" ) ; |
229 | } |
230 | |
231 | return (byte [] )answerObject ; |
232 | |
233 | } |
234 | private byte [] loadClassDataFile( File dir , String name) |
235 | throws IOException { |
236 | |
237 | _log.info("loadClassData : File="+name ) ; |
238 | File file = new File( dir , name ) ; |
239 | long length = file.length() ; |
240 | _log.debug( "loadClassData : length="+length ) ; |
241 | if( length == 0 ) |
242 | throw new IOException( "Datafile has zero size" ) ; |
243 | DataInputStream in = new DataInputStream(new FileInputStream(file)); |
244 | try { |
245 | byte[] data = new byte[(int)length]; |
246 | in.read(data); |
247 | return data; |
248 | } finally { |
249 | try { |
250 | in.close(); |
251 | } catch (IOException e) { |
252 | _log.error("Close failed: " + e.getMessage()); |
253 | } |
254 | } |
255 | } |
256 | } |
257 | class ClassLoaderC extends ClassLoader { |
258 | |
259 | private ClassLoaderProvider _provider = null ; |
260 | private static int __version = 0 ; |
261 | |
262 | ClassLoaderC( ClassLoaderProvider classLoaderProvider ){ |
263 | _provider = classLoaderProvider ; |
264 | synchronized( getClass() ){ |
265 | __version++ ; |
266 | } |
267 | } |
268 | public String toString(){ |
269 | return "CLC-"+__version ; |
270 | } |
271 | public synchronized Class loadClass(String name, boolean resolve) |
272 | throws ClassNotFoundException { |
273 | |
274 | byte [] data = null ; |
275 | try{ |
276 | |
277 | ClassDataProvider dp = _provider.getEntry( name ) ; |
278 | |
279 | // System.out.print( "Loading class V-"+__version+" "+name ) ; |
280 | if( dp != null ){ |
281 | if( dp instanceof CDPDummy ){ |
282 | // System.out.println( " throu <System>" ) ; |
283 | return Class.forName( name ) ; |
284 | }else{ |
285 | // System.out.println( " throu "+dp ) ; |
286 | data = dp.getClassData( name ) ; |
287 | } |
288 | }else{ |
289 | // System.out.println( " Failed" ) ; |
290 | throw new ClassNotFoundException( "No class provider specified" ) ; |
291 | } |
292 | }catch( IOException ioe ){ |
293 | throw new ClassNotFoundException( ioe.toString() ) ; |
294 | } |
295 | |
296 | if( data == null ) |
297 | throw new |
298 | ClassNotFoundException( "PANIC : class provider returned null" ) ; |
299 | |
300 | Class entry = defineClass( name , data, 0, data.length); |
301 | |
302 | if( resolve )resolveClass(entry ); |
303 | |
304 | return entry ; |
305 | } |
306 | |
307 | |
308 | } |