1   package org.codehaus.classworlds;
2   
3   /*
4    $Id: ConfiguratorTest.java,v 1.3 2004/09/07 13:17:43 brett Exp $
5   
6    Copyright 2002 (C) The Werken Company. All Rights Reserved.
7    
8    Redistribution and use of this software and associated documentation
9    ("Software"), with or without modification, are permitted provided
10   that the following conditions are met:
11  
12   1. Redistributions of source code must retain copyright
13      statements and notices.  Redistributions must also contain a
14      copy of this document.
15   
16   2. Redistributions in binary form must reproduce the
17      above copyright notice, this list of conditions and the
18      following disclaimer in the documentation and/or other
19      materials provided with the distribution.
20   
21   3. The name "classworlds" must not be used to endorse or promote
22      products derived from this Software without prior written
23      permission of The Werken Company.  For written permission,
24      please contact bob@werken.com.
25   
26   4. Products derived from this Software may not be called "classworlds"
27      nor may "classworlds" appear in their names without prior written
28      permission of The Werken Company. "classworlds" is a registered
29      trademark of The Werken Company.
30   
31   5. Due credit should be given to The Werken Company.
32      (http://classworlds.werken.com/).
33   
34   THIS SOFTWARE IS PROVIDED BY THE WERKEN COMPANY AND CONTRIBUTORS
35   ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
36   NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
37   FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
38   THE WERKEN COMPANY OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
39   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
40   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
41   SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
42   HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
43   STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
44   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
45   OF THE POSSIBILITY OF SUCH DAMAGE.
46   
47   */
48  
49  import junit.framework.TestCase;
50  
51  import java.io.File;
52  import java.io.FileInputStream;
53  import java.io.FileNotFoundException;
54  import java.net.URL;
55  import java.util.Collection;
56  
57  public class ConfiguratorTest extends TestCase
58  {
59      private Launcher launcher;
60      private Configurator configurator;
61  
62      public ConfiguratorTest(String name)
63      {
64          super( name );
65      }
66  
67      public void setUp()
68      {
69          this.launcher = new Launcher();
70          this.configurator = new Configurator( this.launcher );
71      }
72  
73      public void tearDown()
74      {
75          this.launcher = null;
76          this.configurator = null;
77          System.getProperties().remove( "set.using.existent" );
78          System.getProperties().remove( "set.using.default" );
79          System.getProperties().remove( "set.using.nonexistent" );
80          System.getProperties().remove( "set.using.nonexistent.default" );
81  	System.getProperties().remove( "set.using.missing" );
82  	System.getProperties().remove( "set.using.filtered.default" );
83      }
84  
85      public void testConfigure_Nonexistent() throws Exception
86      {
87          try
88          {
89              this.configurator.configure( getConfigPath( "notfound.conf" ) );
90              fail( "throw FileNotFoundException" );
91          }
92          catch (FileNotFoundException e)
93          {
94              // expected and correct
95          }
96      }
97  
98      public void testConfigure_DuplicateMain() throws Exception
99      {
100         try
101         {
102             this.configurator.configure( getConfigPath( "dupe-main.conf" ) );
103             fail( "throw ConfigurationException" );
104         }
105         catch (ConfigurationException e)
106         {
107             // expected and correct
108             assertTrue( e.getMessage().startsWith( "Duplicate main" ) );
109         }
110     }
111 
112     public void testConfigure_DuplicateRealm() throws Exception
113     {
114         try
115         {
116             this.configurator.configure( getConfigPath( "dupe-realm.conf" ) );
117             fail( "throw DuplicateRealmException" );
118         }
119         catch (DuplicateRealmException e)
120         {
121             // expected and correct
122             assertEquals( "dupe.realm",
123                           e.getId() );
124         }
125     }
126 
127     public void testConfigure_EarlyImport() throws Exception
128     {
129         try
130         {
131             this.configurator.configure( getConfigPath( "early-import.conf" ) );
132             fail( "throw ConfigurationException" );
133         }
134         catch (ConfigurationException e)
135         {
136             // expected and correct
137             assertTrue( e.getMessage().startsWith( "Unhandled import" ) );
138         }
139     }
140 
141     public void testConfigure_RealmSyntax() throws Exception
142     {
143         try
144         {
145             this.configurator.configure( getConfigPath( "realm-syntax.conf" ) );
146             fail( "throw ConfigurationException" );
147         }
148         catch (ConfigurationException e)
149         {
150             // expected and correct
151             assertTrue( e.getMessage().startsWith( "Invalid realm" ) );
152         }
153     }
154 
155     public void testConfigure_Valid() throws Exception
156     {
157         this.configurator.configure( getConfigPath( "valid.conf" ) );
158 
159         assertEquals( "org.apache.maven.app.App",
160                       this.launcher.getMainClassName() );
161         
162         assertEquals( "maven",
163                       this.launcher.getMainRealmName() );
164 
165         ClassWorld world = this.launcher.getWorld();
166 
167         Collection realms = world.getRealms();
168 
169         assertEquals( 4,
170                       realms.size() );
171 
172         assertNotNull( world.getRealm( "ant" ) );
173         assertNotNull( world.getRealm( "maven" ) );
174         assertNotNull( world.getRealm( "xml" ) );
175 
176         ClassRealm antRealm = world.getRealm( "ant" );
177         ClassRealm mavenRealm = world.getRealm( "maven" );
178         ClassRealm xmlRealm = world.getRealm( "xml" );
179         ClassRealm globRealm = world.getRealm( "glob" );
180 
181         assertSame( antRealm,
182                     antRealm.locateSourceRealm( "org.apache.tools.Ant" ) );
183 
184         assertSame( xmlRealm,
185                     antRealm.locateSourceRealm( "org.xml.sax.SAXException" ) );
186 
187         assertSame( mavenRealm,
188                     mavenRealm.locateSourceRealm( "org.apache.maven.app.App" ) );
189 
190         assertSame( xmlRealm,
191                     mavenRealm.locateSourceRealm( "org.xml.sax.SAXException" ) );
192                     
193         // Test the glob support
194         RealmClassLoader cl = (RealmClassLoader) globRealm.getClassLoader();
195         URL[] urls = cl.getURLs();
196         
197         assertArrayContains(urls, new File(System.getProperty("basedir") + "/target/test-data/nested.jar").toURL());
198         assertArrayContains(urls, new File(System.getProperty("basedir") + "/target/test-data/a.jar").toURL());
199         assertArrayContains(urls, new File(System.getProperty("basedir") + "/target/test-data/b.jar").toURL());
200         assertArrayContains(urls, new File(System.getProperty("basedir") + "/target/test-data/c.jar").toURL());
201     }
202 
203     public void testConfigure_Optionally_NonExistent() throws Exception
204     {
205         this.configurator.configure( getConfigPath( "optionally-nonexistent.conf" ) );
206 
207         assertEquals( "org.apache.maven.app.App",
208                       this.launcher.getMainClassName() );
209         
210         assertEquals( "opt",
211                       this.launcher.getMainRealmName() );
212 
213         ClassWorld world = this.launcher.getWorld();
214 
215         Collection realms = world.getRealms();
216 
217         assertEquals( 1,
218                       realms.size() );
219 
220         assertNotNull( world.getRealm( "opt" ) );
221 
222         ClassRealm optRealm = world.getRealm( "opt" );
223 
224         RealmClassLoader cl = (RealmClassLoader) optRealm.getClassLoader();
225 
226         URL[] urls = cl.getURLs();
227 
228         assertEquals( "no urls",
229                       0,
230                       urls.length );
231     }
232 
233     public void testConfigure_Optionally_Existent() throws Exception
234     {
235         this.configurator.configure( getConfigPath( "optionally-existent.conf" ) );
236 
237         assertEquals( "org.apache.maven.app.App",
238                       this.launcher.getMainClassName() );
239         
240         assertEquals( "opt",
241                       this.launcher.getMainRealmName() );
242 
243         ClassWorld world = this.launcher.getWorld();
244 
245         Collection realms = world.getRealms();
246 
247         assertEquals( 1,
248                       realms.size() );
249 
250         assertNotNull( world.getRealm( "opt" ) );
251 
252         ClassRealm optRealm = world.getRealm( "opt" );
253 
254         RealmClassLoader cl = (RealmClassLoader) optRealm.getClassLoader();
255 
256         URL[] urls = cl.getURLs();
257 
258         assertEquals( "one url",
259                       1,
260                       urls.length );
261 
262         assertSame( optRealm,
263                     optRealm.locateSourceRealm( "org.xml.sax.SAXException" ) );
264     }
265 
266     public void testConfigure_Unhandled() throws Exception
267     {
268         try
269         {
270             this.configurator.configure( getConfigPath( "unhandled.conf" ) );
271             fail( "throw ConfigurationException" );
272         }
273         catch (ConfigurationException e)
274         {
275             // expected and correct
276             assertTrue( e.getMessage().startsWith( "Unhandled configuration" ) );
277         }
278     }
279 
280     public void testFilter_Unterminated() throws Exception
281     {
282         try
283         {
284             this.configurator.filter( "${cheese" );
285             fail( "throw ConfigurationException" );
286         }
287         catch (ConfigurationException e)
288         {
289             // expected and correct
290             assertTrue( e.getMessage().startsWith( "Unterminated" ) );
291         }
292     }
293 
294     public void testFilter_Solitary() throws Exception
295     {
296         System.setProperty( "classworlds.test.prop",
297                             "test prop value" );
298 
299         String result = this.configurator.filter( "${classworlds.test.prop}" );
300 
301         assertEquals( "test prop value",
302                       result );
303     }
304 
305     public void testFilter_AtStart() throws Exception
306     {
307         System.setProperty( "classworlds.test.prop",
308                             "test prop value" );
309 
310         String result = this.configurator.filter( "${classworlds.test.prop}cheese" );
311 
312         assertEquals( "test prop valuecheese",
313                       result );
314     }
315 
316     public void testFilter_AtEnd() throws Exception
317     {
318         System.setProperty( "classworlds.test.prop",
319                             "test prop value" );
320 
321         String result = this.configurator.filter( "cheese${classworlds.test.prop}" );
322 
323         assertEquals( "cheesetest prop value",
324                       result );
325     }
326 
327     public void testFilter_Multiple() throws Exception
328     {
329         System.setProperty( "classworlds.test.prop.one",
330                             "test prop value one" );
331 
332         System.setProperty( "classworlds.test.prop.two",
333                             "test prop value two" );
334 
335         String result = this.configurator.filter( "I like ${classworlds.test.prop.one} and ${classworlds.test.prop.two} a lot" );
336 
337         assertEquals( "I like test prop value one and test prop value two a lot",
338                       result );
339     }
340 
341     public void testFilter_NonExistent() throws Exception
342     {
343         try
344         {
345             this.configurator.filter( "${gollygeewillikers}" );
346             fail( "throw ConfigurationException" );
347         }
348         catch (ConfigurationException e)
349         {
350             // expected and correct
351             assertTrue( e.getMessage().startsWith( "No such property" ) );
352         }
353     }
354 
355     public void testFilter_InMiddle() throws Exception
356     {
357         System.setProperty( "classworlds.test.prop",
358                             "test prop value" );
359 
360         String result = this.configurator.filter( "cheese${classworlds.test.prop}toast" );
361 
362         assertEquals( "cheesetest prop valuetoast",
363                       result );
364     }
365 
366     public void testSet_Using_Existent() throws Exception
367     {
368         assertNull( System.getProperty( "set.using.existent" ) );
369         
370         this.configurator.configure( getConfigPath( "set-using-existent.conf" ) );
371 
372         assertEquals( "testSet_Using_Existent", System.getProperty( "set.using.existent" ) );
373     }
374 
375     public void testSet_Using_NonExistent() throws Exception
376     {
377         assertNull( System.getProperty( "set.using.nonexistent" ) );
378         
379         this.configurator.configure( getConfigPath( "set-using-nonexistent.conf" ) );
380 
381         assertNull( System.getProperty( "set.using.nonexistent" ) );
382     }
383 
384     public void testSet_Using_NonExistent_Default() throws Exception
385     {
386         assertNull( System.getProperty( "set.using.nonexistent.default" ) );
387         
388         this.configurator.configure( getConfigPath( "set-using-nonexistent.conf" ) );
389 
390         assertEquals( "testSet_Using_NonExistent_Default", System.getProperty( "set.using.nonexistent.default" ) );
391     }
392 
393     public void testSet_Using_NonExistent_Override() throws Exception
394     {
395         assertNull( System.getProperty( "set.using.default" ) );
396         System.setProperty( "set.using.default", "testSet_Using_NonExistent_Override" );
397         
398         this.configurator.configure( getConfigPath( "set-using-nonexistent.conf" ) );
399 
400         assertEquals( "testSet_Using_NonExistent_Override", System.getProperty( "set.using.default" ) );
401     }
402 
403     public void testSet_Using_Existent_Override() throws Exception
404     {
405         assertNull( System.getProperty( "set.using.existent" ) );
406         System.setProperty( "set.using.existent", "testSet_Using_Existent_Override" );
407         
408         this.configurator.configure( getConfigPath( "set-using-existent.conf" ) );
409 
410         assertEquals( "testSet_Using_Existent_Override", System.getProperty( "set.using.existent" ) );
411     }
412 
413     public void testSet_Using_Existent_Default() throws Exception
414     {
415         assertNull( System.getProperty( "set.using.default" ) );
416         
417         this.configurator.configure( getConfigPath( "set-using-existent.conf" ) );
418 
419         assertEquals( "testSet_Using_Existent_Default", System.getProperty( "set.using.default" ) );
420     }
421 
422     public void testSet_Using_Missing_Default() throws Exception
423     {
424         assertNull( System.getProperty( "set.using.missing" ) );
425         
426         this.configurator.configure( getConfigPath( "set-using-missing.conf" ) );
427 
428         assertEquals( "testSet_Using_Missing_Default", System.getProperty( "set.using.missing" ) );
429     }
430 
431     public void testSet_Using_Missing_Override() throws Exception
432     {
433         assertNull( System.getProperty( "set.using.missing" ) );
434         System.setProperty( "set.using.missing", "testSet_Using_Missing_Override" );
435         
436         this.configurator.configure( getConfigPath( "set-using-missing.conf" ) );
437 
438         assertEquals( "testSet_Using_Missing_Override", System.getProperty( "set.using.missing" ) );
439     }
440 
441     public void testSet_Using_Filtered_Default() throws Exception
442     {
443         assertNull( System.getProperty( "set.using.filtered.default" ) );
444         
445         this.configurator.configure( getConfigPath( "set-using-missing.conf" ) );
446 
447         assertEquals( System.getProperty( "user.home" ) + "/m2", System.getProperty( "set.using.filtered.default" ) );
448     }
449 
450     private FileInputStream getConfigPath(String name)
451         throws Exception
452     {
453         return new FileInputStream( new File( new File( System.getProperty( "basedir" ), "target/test-data" ), name ) ) ;
454     }
455 
456     private void assertArrayContains(URL[] array, URL url) throws Exception {
457         for (int i = 0; i < array.length; ++i)
458             if (url.equals(array[i]))
459                 return;
460         fail("URL (" + url + ") not found in array of URLs");
461     }
462 }