1 package org.codehaus.plexus.classworlds.realm;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 import org.codehaus.plexus.classworlds.ClassWorld;
20 import org.codehaus.plexus.classworlds.strategy.Strategy;
21 import org.codehaus.plexus.classworlds.strategy.StrategyFactory;
22
23 import java.io.Closeable;
24 import java.io.IOException;
25 import java.io.PrintStream;
26 import java.net.MalformedURLException;
27 import java.net.URL;
28 import java.net.URLClassLoader;
29 import java.util.Collection;
30 import java.util.Collections;
31 import java.util.Enumeration;
32 import java.util.HashSet;
33 import java.util.LinkedHashSet;
34 import java.util.SortedSet;
35 import java.util.TreeSet;
36
37
38
39
40
41
42
43
44
45
46
47 public class ClassRealm
48 extends URLClassLoader
49 {
50
51 private ClassWorld world;
52
53 private String id;
54
55 private SortedSet<Entry> foreignImports;
56
57 private SortedSet<Entry> parentImports;
58
59 private Strategy strategy;
60
61 private ClassLoader parentClassLoader;
62
63 private static final boolean isParallelCapable = Closeable.class.isAssignableFrom( URLClassLoader.class );
64
65
66
67
68
69
70
71
72
73 public ClassRealm( ClassWorld world, String id, ClassLoader baseClassLoader )
74 {
75 super( new URL[0], baseClassLoader );
76
77 this.world = world;
78
79 this.id = id;
80
81 foreignImports = new TreeSet<Entry>();
82
83 strategy = StrategyFactory.getStrategy( this );
84 }
85
86 public String getId()
87 {
88 return this.id;
89 }
90
91 public ClassWorld getWorld()
92 {
93 return this.world;
94 }
95
96 public void importFromParent( String packageName )
97 {
98 if ( parentImports == null )
99 {
100 parentImports = new TreeSet<Entry>();
101 }
102
103 parentImports.add( new Entry( null, packageName ) );
104 }
105
106 boolean isImportedFromParent( String name )
107 {
108 if ( parentImports != null && !parentImports.isEmpty() )
109 {
110 for ( Entry entry : parentImports )
111 {
112 if ( entry.matches( name ) )
113 {
114 return true;
115 }
116 }
117
118 return false;
119 }
120
121 return true;
122 }
123
124 public void importFrom( String realmId, String packageName )
125 throws NoSuchRealmException
126 {
127 importFrom( getWorld().getRealm( realmId ), packageName );
128 }
129
130 public void importFrom( ClassLoader classLoader, String packageName )
131 {
132 foreignImports.add( new Entry( classLoader, packageName ) );
133 }
134
135 public ClassLoader getImportClassLoader( String name )
136 {
137 for ( Entry entry : foreignImports )
138 {
139 if ( entry.matches( name ) )
140 {
141 return entry.getClassLoader();
142 }
143 }
144
145 return null;
146 }
147
148 public Collection<ClassRealm> getImportRealms()
149 {
150 Collection<ClassRealm> importRealms = new HashSet<ClassRealm>();
151
152 for ( Entry entry : foreignImports )
153 {
154 if ( entry.getClassLoader() instanceof ClassRealm )
155 {
156 importRealms.add( (ClassRealm) entry.getClassLoader() );
157 }
158 }
159
160 return importRealms;
161 }
162
163 public Strategy getStrategy()
164 {
165 return strategy;
166 }
167
168 public void setParentClassLoader( ClassLoader parentClassLoader )
169 {
170 this.parentClassLoader = parentClassLoader;
171 }
172
173 public ClassLoader getParentClassLoader()
174 {
175 return parentClassLoader;
176 }
177
178 public void setParentRealm( ClassRealm realm )
179 {
180 this.parentClassLoader = realm;
181 }
182
183 public ClassRealm getParentRealm()
184 {
185 return ( parentClassLoader instanceof ClassRealm ) ? (ClassRealm) parentClassLoader : null;
186 }
187
188 public ClassRealm createChildRealm( String id )
189 throws DuplicateRealmException
190 {
191 ClassRealm childRealm = getWorld().newRealm( id, null );
192
193 childRealm.setParentRealm( this );
194
195 return childRealm;
196 }
197
198 public void addURL( URL url )
199 {
200 String urlStr = url.toExternalForm();
201
202 if ( urlStr.startsWith( "jar:" ) && urlStr.endsWith( "!/" ) )
203 {
204 urlStr = urlStr.substring( 4, urlStr.length() - 2 );
205
206 try
207 {
208 url = new URL( urlStr );
209 }
210 catch ( MalformedURLException e )
211 {
212 e.printStackTrace();
213 }
214 }
215
216 super.addURL( url );
217 }
218
219
220
221
222
223
224 public Class<?> loadClass( String name )
225 throws ClassNotFoundException
226 {
227 return loadClass( name, false );
228 }
229
230 protected Class<?> loadClass( String name, boolean resolve )
231 throws ClassNotFoundException
232 {
233 if ( isParallelCapable )
234 {
235 return unsynchronizedLoadClass( name, resolve );
236
237 }
238 else
239 {
240 synchronized ( this )
241 {
242 return unsynchronizedLoadClass( name, resolve );
243 }
244
245 }
246 }
247
248 private Class<?> unsynchronizedLoadClass( String name, boolean resolve )
249 throws ClassNotFoundException
250 {
251 try
252 {
253
254 return super.loadClass( name, resolve );
255 }
256 catch ( ClassNotFoundException e )
257 {
258
259 return strategy.loadClass( name );
260 }
261 }
262
263 protected Class<?> findClass( String name )
264 throws ClassNotFoundException
265 {
266
267
268
269
270 throw new ClassNotFoundException( name );
271 }
272
273 public URL getResource( String name )
274 {
275 URL resource = super.getResource( name );
276 return resource != null ? resource : strategy.getResource( name );
277 }
278
279 public URL findResource( String name )
280 {
281 return super.findResource( name );
282 }
283
284 public Enumeration<URL> getResources( String name )
285 throws IOException
286 {
287 Collection<URL> resources = new LinkedHashSet<URL>( Collections.list( super.getResources( name ) ) );
288 resources.addAll( Collections.list( strategy.getResources( name ) ) );
289 return Collections.enumeration( resources );
290 }
291
292 public Enumeration<URL> findResources( String name )
293 throws IOException
294 {
295 return super.findResources( name );
296 }
297
298
299
300
301
302 public void display()
303 {
304 display( System.out );
305 }
306
307 public void display( PrintStream out )
308 {
309 out.println( "-----------------------------------------------------" );
310
311 for ( ClassRealm cr = this; cr != null; cr = cr.getParentRealm() )
312 {
313 out.println( "realm = " + cr.getId() );
314 out.println( "strategy = " + cr.getStrategy().getClass().getName() );
315
316 showUrls( cr, out );
317
318 out.println();
319 }
320
321 out.println( "-----------------------------------------------------" );
322 }
323
324 private static void showUrls( ClassRealm classRealm, PrintStream out )
325 {
326 URL[] urls = classRealm.getURLs();
327
328 for ( int i = 0; i < urls.length; i++ )
329 {
330 out.println( "urls[" + i + "] = " + urls[i] );
331 }
332
333 out.println( "Number of foreign imports: " + classRealm.foreignImports.size() );
334
335 for ( Entry entry : classRealm.foreignImports )
336 {
337 out.println( "import: " + entry );
338 }
339
340 if ( classRealm.parentImports != null )
341 {
342 out.println( "Number of parent imports: " + classRealm.parentImports.size() );
343
344 for ( Entry entry : classRealm.parentImports )
345 {
346 out.println( "import: " + entry );
347 }
348 }
349 }
350
351 public String toString()
352 {
353 return "ClassRealm[" + getId() + ", parent: " + getParentClassLoader() + "]";
354 }
355
356
357
358
359
360 public Class<?> loadClassFromImport( String name )
361 {
362 ClassLoader importClassLoader = getImportClassLoader( name );
363
364 if ( importClassLoader != null )
365 {
366 try
367 {
368 return importClassLoader.loadClass( name );
369 }
370 catch ( ClassNotFoundException e )
371 {
372 return null;
373 }
374 }
375
376 return null;
377 }
378
379 public Class<?> loadClassFromSelf( String name )
380 {
381 synchronized ( getClassRealmLoadingLock( name ) )
382 {
383 try
384 {
385 Class<?> clazz = findLoadedClass( name );
386
387 if ( clazz == null )
388 {
389 clazz = super.findClass( name );
390 }
391
392 return clazz;
393 }
394 catch ( ClassNotFoundException e )
395 {
396 return null;
397 }
398 }
399 }
400
401 private Object getClassRealmLoadingLock( String name )
402 {
403 if ( isParallelCapable )
404 {
405 return getClassLoadingLock( name );
406 }
407 else
408 {
409 return this;
410 }
411 }
412
413 public Class<?> loadClassFromParent( String name )
414 {
415 ClassLoader parent = getParentClassLoader();
416
417 if ( parent != null && isImportedFromParent( name ) )
418 {
419 try
420 {
421 return parent.loadClass( name );
422 }
423 catch ( ClassNotFoundException e )
424 {
425 return null;
426 }
427 }
428
429 return null;
430 }
431
432
433
434
435
436 public URL loadResourceFromImport( String name )
437 {
438 ClassLoader importClassLoader = getImportClassLoader( name );
439
440 if ( importClassLoader != null )
441 {
442 return importClassLoader.getResource( name );
443 }
444
445 return null;
446 }
447
448 public URL loadResourceFromSelf( String name )
449 {
450 return super.findResource( name );
451 }
452
453 public URL loadResourceFromParent( String name )
454 {
455 ClassLoader parent = getParentClassLoader();
456
457 if ( parent != null && isImportedFromParent( name ) )
458 {
459 return parent.getResource( name );
460 }
461 else
462 {
463 return null;
464 }
465 }
466
467
468
469
470
471 public Enumeration<URL> loadResourcesFromImport( String name )
472 {
473 ClassLoader importClassLoader = getImportClassLoader( name );
474
475 if ( importClassLoader != null )
476 {
477 try
478 {
479 return importClassLoader.getResources( name );
480 }
481 catch ( IOException e )
482 {
483 return null;
484 }
485 }
486
487 return null;
488 }
489
490 public Enumeration<URL> loadResourcesFromSelf( String name )
491 {
492 try
493 {
494 return super.findResources( name );
495 }
496 catch ( IOException e )
497 {
498 return null;
499 }
500 }
501
502 public Enumeration<URL> loadResourcesFromParent( String name )
503 {
504 ClassLoader parent = getParentClassLoader();
505
506 if ( parent != null && isImportedFromParent( name ) )
507 {
508 try
509 {
510 return parent.getResources( name );
511 }
512 catch ( IOException e )
513 {
514
515 }
516 }
517
518 return null;
519 }
520
521 static
522 {
523 if (isParallelCapable)
524 {
525 registerAsParallelCapable();
526 }
527 }
528
529 }