View Javadoc
1   package org.codehaus.plexus.classworlds.realm;
2   
3   /*
4    * Copyright 2001-2006 Codehaus Foundation.
5    *
6    * Licensed under the Apache License, Version 2.0 (the "License");
7    * you may not use this file except in compliance with the License.
8    * You may obtain a copy of the License at
9    *
10   *      http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  
19  import java.net.URL;
20  import java.util.ArrayList;
21  import java.util.Arrays;
22  import java.util.Collections;
23  import java.util.Iterator;
24  import java.util.List;
25  
26  import org.codehaus.plexus.classworlds.AbstractClassWorldsTestCase;
27  import org.codehaus.plexus.classworlds.ClassWorld;
28  
29  public class ClassRealmImplTest
30      extends AbstractClassWorldsTestCase
31  {
32      private ClassWorld world;
33  
34      public ClassRealmImplTest( String name )
35      {
36          super( name );
37      }
38  
39      public void setUp()
40      {
41          this.world = new ClassWorld();
42      }
43  
44      public void tearDown()
45      {
46          this.world = null;
47      }
48  
49      public void testNewRealm()
50          throws Exception
51      {
52          ClassRealm realm = this.world.newRealm( "foo" );
53  
54          assertNotNull( realm );
55  
56          assertSame( this.world, realm.getWorld() );
57  
58          assertEquals( "foo", realm.getId() );
59      }
60  
61      public void testLocateSourceRealm_NoImports()
62          throws Exception
63      {
64          ClassRealm realm = new ClassRealm( this.world, "foo", null );
65  
66          assertSame( null, realm.getImportClassLoader( "com.werken.Stuff" ) );
67      }
68  
69      public void testLocateSourceRealm_SimpleImport()
70          throws Exception
71      {
72          ClassRealm mainRealm = this.world.newRealm( "main" );
73  
74          ClassRealm werkflowRealm = this.world.newRealm( "werkflow" );
75  
76          mainRealm.importFrom( "werkflow", "com.werken.werkflow" );
77  
78          assertSame( werkflowRealm, mainRealm.getImportClassLoader( "com.werken.werkflow.WerkflowEngine" ) );
79  
80          assertSame( werkflowRealm, mainRealm.getImportClassLoader( "com/werken/werkflow/some.properties" ) );
81  
82          assertSame( werkflowRealm, mainRealm.getImportClassLoader( "com.werken.werkflow.process.ProcessManager" ) );
83  
84          assertSame( null, mainRealm.getImportClassLoader( "com.werken.blissed.Process" ) );
85  
86          assertSame( null, mainRealm.getImportClassLoader( "java.lang.Object" ) );
87  
88          assertSame( null, mainRealm.getImportClassLoader( "NoviceProgrammerClass" ) );
89      }
90  
91      public void testLocateSourceRealm_MultipleImport()
92          throws Exception
93      {
94          ClassRealm mainRealm = this.world.newRealm( "main" );
95  
96          ClassRealm werkflowRealm = this.world.newRealm( "werkflow" );
97  
98          ClassRealm blissedRealm = this.world.newRealm( "blissed" );
99  
100         mainRealm.importFrom( "werkflow", "com.werken.werkflow" );
101 
102         mainRealm.importFrom( "blissed", "com.werken.blissed" );
103 
104         assertSame( werkflowRealm, mainRealm.getImportClassLoader( "com.werken.werkflow.WerkflowEngine" ) );
105 
106         assertSame( werkflowRealm, mainRealm.getImportClassLoader( "com.werken.werkflow.process.ProcessManager" ) );
107 
108         assertSame( blissedRealm, mainRealm.getImportClassLoader( "com.werken.blissed.Process" ) );
109 
110         assertSame( blissedRealm, mainRealm.getImportClassLoader( "com.werken.blissed.guard.BooleanGuard" ) );
111 
112         assertSame( null, mainRealm.getImportClassLoader( "java.lang.Object" ) );
113 
114         assertSame( null, mainRealm.getImportClassLoader( "NoviceProgrammerClass" ) );
115     }
116 
117     public void testLocateSourceRealm_Hierachy()
118         throws Exception
119     {
120         ClassRealm mainRealm = this.world.newRealm( "main" );
121 
122         ClassRealm fooRealm = this.world.newRealm( "foo" );
123 
124         ClassRealm fooBarRealm = this.world.newRealm( "fooBar" );
125 
126         ClassRealm fooBarBazRealm = this.world.newRealm( "fooBarBaz" );
127 
128         mainRealm.importFrom( "foo", "foo" );
129 
130         mainRealm.importFrom( "fooBar", "foo.bar" );
131 
132         mainRealm.importFrom( "fooBarBaz", "foo.bar.baz" );
133 
134         assertSame( fooRealm, mainRealm.getImportClassLoader( "foo.Goober" ) );
135 
136         assertSame( fooRealm, mainRealm.getImportClassLoader( "foo.cheese.Goober" ) );
137 
138         assertSame( fooBarRealm, mainRealm.getImportClassLoader( "foo.bar.Goober" ) );
139 
140         assertSame( fooBarRealm, mainRealm.getImportClassLoader( "foo.bar.cheese.Goober" ) );
141 
142         assertSame( fooBarBazRealm, mainRealm.getImportClassLoader( "foo.bar.baz.Goober" ) );
143 
144         assertSame( fooBarBazRealm, mainRealm.getImportClassLoader( "foo.bar.baz.cheese.Goober" ) );
145 
146         assertSame( null, mainRealm.getImportClassLoader( "java.lang.Object" ) );
147 
148         assertSame( null, mainRealm.getImportClassLoader( "NoviceProgrammerClass" ) );
149     }
150 
151     public void testLocateSourceRealm_Hierachy_Reverse()
152         throws Exception
153     {
154         ClassRealm fooBarBazRealm = this.world.newRealm( "fooBarBaz" );
155 
156         ClassRealm fooBarRealm = this.world.newRealm( "fooBar" );
157 
158         ClassRealm fooRealm = this.world.newRealm( "foo" );
159 
160         ClassRealm mainRealm = this.world.newRealm( "main" );
161 
162         mainRealm.importFrom( "fooBarBaz", "foo.bar.baz" );
163 
164         mainRealm.importFrom( "fooBar", "foo.bar" );
165 
166         mainRealm.importFrom( "foo", "foo" );
167 
168         assertSame( fooRealm, mainRealm.getImportClassLoader( "foo.Goober" ) );
169 
170         assertSame( fooRealm, mainRealm.getImportClassLoader( "foo.cheese.Goober" ) );
171 
172         assertSame( fooBarRealm, mainRealm.getImportClassLoader( "foo.bar.Goober" ) );
173 
174         assertSame( fooBarRealm, mainRealm.getImportClassLoader( "foo.bar.cheese.Goober" ) );
175 
176         assertSame( fooBarBazRealm, mainRealm.getImportClassLoader( "foo.bar.baz.Goober" ) );
177 
178         assertSame( fooBarBazRealm, mainRealm.getImportClassLoader( "foo.bar.baz.cheese.Goober" ) );
179 
180         assertSame( null, mainRealm.getImportClassLoader( "java.lang.Object" ) );
181 
182         assertSame( null, mainRealm.getImportClassLoader( "NoviceProgrammerClass" ) );
183     }
184 
185     public void testLoadClass_SystemClass()
186         throws Exception
187     {
188         ClassRealm mainRealm = this.world.newRealm( "main" );
189 
190         Class<?> cls = mainRealm.loadClass( "java.lang.Object" );
191 
192         assertNotNull( cls );
193     }
194 
195     public void testLoadClass_NonSystemClass()
196         throws Exception
197     {
198         ClassRealm mainRealm = this.world.newRealm( "main" );
199 
200         try
201         {
202             Class<?> c = mainRealm.loadClass( "com.werken.projectz.UberThing" );
203 
204             System.out.println( "c = " + c );
205 
206             fail( "A ClassNotFoundException should be thrown!" );
207         }
208         catch ( ClassNotFoundException e )
209         {
210             // expected and correct
211         }
212     }
213 
214     public void testLoadClass_ClassWorldsClass()
215         throws Exception
216     {
217         ClassRealm mainRealm = this.world.newRealm( "main" );
218 
219         Class<?> cls = mainRealm.loadClass( "org.codehaus.plexus.classworlds.ClassWorld" );
220 
221         assertNotNull( cls );
222 
223         assertSame( ClassWorld.class, cls );
224     }
225 
226     public void testLoadClass_Local()
227         throws Exception
228     {
229         ClassRealm mainRealm = this.world.newRealm( "main" );
230 
231         try
232         {
233             mainRealm.loadClass( "a.A" );
234         }
235         catch ( ClassNotFoundException e )
236         {
237             // expected and correct
238         }
239 
240         mainRealm.addURL( getJarUrl( "a.jar" ) );
241 
242         Class<?> classA = mainRealm.loadClass( "a.A" );
243 
244         assertNotNull( classA );
245 
246         ClassRealm otherRealm = this.world.newRealm( "other" );
247 
248         try
249         {
250             otherRealm.loadClass( "a.A" );
251         }
252         catch ( ClassNotFoundException e )
253         {
254             // expected and correct
255         }
256     }
257 
258     public void testLoadClass_Imported()
259         throws Exception
260     {
261         ClassRealm mainRealm = this.world.newRealm( "main" );
262 
263         ClassRealm realmA = this.world.newRealm( "realmA" );
264 
265         try
266         {
267             realmA.loadClass( "a.A" );
268 
269             fail( "realmA.loadClass(a.A) should have thrown a ClassNotFoundException" );
270         }
271         catch ( ClassNotFoundException e )
272         {
273             // expected and correct
274         }
275 
276         realmA.addURL( getJarUrl( "a.jar" ) );
277 
278         try
279         {
280             mainRealm.loadClass( "a.A" );
281 
282             fail( "mainRealm.loadClass(a.A) should have thrown a ClassNotFoundException" );
283         }
284         catch ( ClassNotFoundException e )
285         {
286             // expected and correct
287         }
288 
289         mainRealm.importFrom( "realmA", "a" );
290 
291         Class<?> classA = realmA.loadClass( "a.A" );
292 
293         assertNotNull( classA );
294 
295         assertEquals( realmA, classA.getClassLoader() );
296 
297         Class<?> classMain = mainRealm.loadClass( "a.A" );
298 
299         assertNotNull( classMain );
300 
301         assertEquals( realmA, classMain.getClassLoader() );
302 
303         assertSame( classA, classMain );
304     }
305 
306     public void testLoadClass_Package()
307         throws Exception
308     {
309         ClassRealm realmA = this.world.newRealm( "realmA" );
310         realmA.addURL( getJarUrl( "a.jar" ) );
311 
312         Class<?> clazz = realmA.loadClass( "a.A" );
313         assertNotNull( clazz );
314         assertEquals( "a.A", clazz.getName() );
315 
316         Package p = clazz.getPackage();
317         assertNotNull( p );
318         assertEquals( "p.getName()", "a", p.getName() );
319     }
320 
321 
322     public void testLoadClass_Complex()
323         throws Exception
324     {
325         ClassRealm realmA = this.world.newRealm( "realmA" );
326         ClassRealm realmB = this.world.newRealm( "realmB" );
327         ClassRealm realmC = this.world.newRealm( "realmC" );
328 
329         realmA.addURL( getJarUrl( "a.jar" ) );
330         realmB.addURL( getJarUrl( "b.jar" ) );
331         realmC.addURL( getJarUrl( "c.jar" ) );
332 
333         realmC.importFrom( "realmA", "a" );
334 
335         realmC.importFrom( "realmB", "b" );
336 
337         realmA.importFrom( "realmC", "c" );
338 
339         Class<?> classA_A = realmA.loadClass( "a.A" );
340         Class<?> classB_B = realmB.loadClass( "b.B" );
341         Class<?> classC_C = realmC.loadClass( "c.C" );
342 
343         assertNotNull( classA_A );
344         assertNotNull( classB_B );
345         assertNotNull( classC_C );
346 
347         assertEquals( realmA, classA_A.getClassLoader() );
348 
349         assertEquals( realmB, classB_B.getClassLoader() );
350 
351         assertEquals( realmC, classC_C.getClassLoader() );
352 
353         // load from C
354 
355         Class<?> classA_C = realmC.loadClass( "a.A" );
356 
357         assertNotNull( classA_C );
358 
359         assertSame( classA_A, classA_C );
360 
361         assertEquals( realmA, classA_C.getClassLoader() );
362 
363         Class<?> classB_C = realmC.loadClass( "b.B" );
364 
365         assertNotNull( classB_C );
366 
367         assertSame( classB_B, classB_C );
368 
369         assertEquals( realmB, classB_C.getClassLoader() );
370 
371         // load from A
372 
373         Class<?> classC_A = realmA.loadClass( "c.C" );
374 
375         assertNotNull( classC_A );
376 
377         assertSame( classC_C, classC_A );
378 
379         assertEquals( realmC, classC_A.getClassLoader() );
380 
381         try
382         {
383             realmA.loadClass( "b.B" );
384             fail( "throw ClassNotFoundException" );
385         }
386         catch ( ClassNotFoundException e )
387         {
388             // expected and correct
389         }
390 
391         // load from B
392 
393         try
394         {
395             realmB.loadClass( "a.A" );
396             fail( "throw ClassNotFoundException" );
397         }
398         catch ( ClassNotFoundException e )
399         {
400             // expected and correct
401         }
402 
403         try
404         {
405             realmB.loadClass( "c.C" );
406             fail( "throw ClassNotFoundException" );
407         }
408         catch ( ClassNotFoundException e )
409         {
410             // expected and correct
411         }
412     }
413 
414     public void testLoadClass_ClassWorldsClassRepeatedly()
415         throws Exception
416     {
417         ClassRealm mainRealm = this.world.newRealm( "main" );
418 
419         for ( int i = 0; i < 100; i++ )
420         {
421             Class<?> cls = mainRealm.loadClass( "org.codehaus.plexus.classworlds.ClassWorld" );
422 
423             assertNotNull( cls );
424 
425             assertSame( ClassWorld.class, cls );
426         }
427     }
428 
429     public void testGetResources_BaseBeforeSelf()
430         throws Exception
431     {
432         String resource = "common.properties";
433 
434         ClassRealm base = this.world.newRealm( "realmA" );
435         base.addURL( getJarUrl( "a.jar" ) );
436 
437         URL baseUrl = base.getResource( resource );
438         assertNotNull( baseUrl );
439 
440         ClassRealm sub = this.world.newRealm( "realmB", base );
441         sub.addURL( getJarUrl( "b.jar" ) );
442 
443         URL subUrl = sub.getResource( resource );
444         assertNotNull( subUrl );
445 
446         assertEquals( baseUrl, subUrl );
447 
448         List<String> urls = new ArrayList<String>();
449         for ( Iterator<URL> it = Collections.list( sub.getResources( resource ) ).iterator(); it.hasNext(); )
450         {
451             String path = it.next().toString();
452             path = path.substring( path.lastIndexOf( '/', path.lastIndexOf( ".jar!" ) ) );
453             urls.add( path );
454         }
455         assertEquals( Arrays.asList( new String[] { "/a.jar!/common.properties", "/b.jar!/common.properties" } ), urls );
456     }
457 
458     public void testGetResources_SelfBeforeParent()
459         throws Exception
460     {
461         String resource = "common.properties";
462 
463         ClassRealm parent = this.world.newRealm( "realmA" );
464         parent.addURL( getJarUrl( "a.jar" ) );
465 
466         URL parentUrl = parent.getResource( resource );
467         assertNotNull( parentUrl );
468 
469         ClassRealm child = parent.createChildRealm( "realmB" );
470         child.addURL( getJarUrl( "b.jar" ) );
471 
472         URL childUrl = child.getResource( resource );
473         assertNotNull( childUrl );
474 
475         List<URL> urls = Collections.list( child.getResources( resource ) );
476         assertNotNull( urls );
477         assertEquals( Arrays.asList( new URL[] { childUrl, parentUrl } ), urls );
478     }
479 
480 }