View Javadoc
1   package org.codehaus.plexus.classworlds.launcher;
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.io.File;
20  import java.io.IOException;
21  import java.io.InputStream;
22  import java.net.MalformedURLException;
23  import java.net.URL;
24  import java.util.ArrayList;
25  import java.util.Collections;
26  import java.util.Comparator;
27  import java.util.HashMap;
28  import java.util.List;
29  import java.util.Map;
30  
31  import org.codehaus.plexus.classworlds.ClassWorld;
32  import org.codehaus.plexus.classworlds.realm.ClassRealm;
33  import org.codehaus.plexus.classworlds.realm.DuplicateRealmException;
34  import org.codehaus.plexus.classworlds.realm.NoSuchRealmException;
35  
36  /**
37   * <code>Launcher</code> configurator.
38   *
39   * @author <a href="mailto:bob@eng.werken.com">bob mcwhirter</a>
40   * @author Jason van Zyl
41   */
42  public class Configurator implements ConfigurationHandler
43  {
44      /**
45       * The launcher to configure.
46       */
47      private Launcher launcher;
48  
49      private ClassWorld world;
50  
51      /**
52       * Processed Realms.
53       */
54      private Map<String, ClassRealm> configuredRealms;
55  
56      /**
57       * Current Realm.
58       */
59      private ClassRealm curRealm;
60  
61      private ClassLoader foreignClassLoader = null;
62      
63      /**
64       * Construct.
65       *
66       * @param launcher The launcher to configure.
67       */
68      public Configurator( Launcher launcher )
69      {
70          this.launcher = launcher;
71  
72          configuredRealms = new HashMap<String, ClassRealm>();
73  
74          if ( launcher != null )
75          {
76              this.foreignClassLoader = launcher.getSystemClassLoader();
77          }
78      }
79  
80      /**
81       * Construct.
82       *
83       * @param world The classWorld to configure.
84       */
85      public Configurator( ClassWorld world )
86      {
87          setClassWorld( world );
88      }
89  
90      /**
91       * set world.
92       * this setter is provided so you can use the same configurator to configure several "worlds"
93       *
94       * @param world The classWorld to configure.
95       */
96      public void setClassWorld( ClassWorld world )
97      {
98          this.world = world;
99  
100         configuredRealms = new HashMap<String, ClassRealm>();
101     }
102 
103     /**
104      * Configure from a file.
105      *
106      * @param is The config input stream
107      * @throws IOException             If an error occurs reading the config file.
108      * @throws MalformedURLException   If the config file contains invalid URLs.
109      * @throws ConfigurationException  If the config file is corrupt.
110      * @throws org.codehaus.plexus.classworlds.realm.DuplicateRealmException If the config file defines two realms with the same id.
111      * @throws org.codehaus.plexus.classworlds.realm.NoSuchRealmException    If the config file defines a main entry point in
112      *                                 a non-existent realm.
113      */
114     public void configure( InputStream is )
115         throws IOException, ConfigurationException, DuplicateRealmException, NoSuchRealmException
116     {
117         if ( world == null )
118         {
119             world = new ClassWorld();
120         }
121 
122         curRealm = null;
123 
124         foreignClassLoader = null;
125 
126         if ( this.launcher != null )
127         {
128             foreignClassLoader = this.launcher.getSystemClassLoader();
129         }
130 
131         ConfigurationParser parser = new ConfigurationParser( this, System.getProperties() );
132 
133         parser.parse( is );
134 
135         // Associate child realms to their parents.
136         associateRealms();
137 
138         if ( this.launcher != null )
139         {
140             this.launcher.setWorld( world );
141         }
142 
143     }
144 
145     // TODO return this to protected when the legacy wrappers can be removed.
146     /**
147      * Associate parent realms with their children.
148      */
149     public void associateRealms()
150     {
151         List<String> sortRealmNames = new ArrayList<String>( configuredRealms.keySet() );
152 
153         // sort by name
154         Comparator<String> comparator = new Comparator<String>()
155         {
156             public int compare( String g1,
157                                 String g2 )
158             {
159                 return g1.compareTo( g2 );
160             }
161         };
162 
163         Collections.sort( sortRealmNames, comparator );
164 
165         // So now we have something like the following for defined
166         // realms:
167         //
168         // root
169         // root.maven
170         // root.maven.plugin
171         //
172         // Now if the name of a realm is a superset of an existing realm
173         // the we want to make child/parent associations.
174 
175         for ( String realmName : sortRealmNames )
176         {
177             int j = realmName.lastIndexOf( '.' );
178 
179             if ( j > 0 )
180             {
181                 String parentRealmName = realmName.substring( 0, j );
182 
183                 ClassRealm parentRealm = configuredRealms.get( parentRealmName );
184 
185                 if ( parentRealm != null )
186                 {
187                     ClassRealm realm = configuredRealms.get( realmName );
188 
189                     realm.setParentRealm( parentRealm );
190                 }
191             }
192         }
193     }
194 
195     public void addImportFrom( String relamName, String importSpec )
196         throws NoSuchRealmException
197     {
198         curRealm.importFrom( relamName, importSpec );
199     }
200 
201     public void addLoadFile( File file )
202     {
203         try
204         {
205             curRealm.addURL( file.toURI().toURL() );
206         }
207         catch ( MalformedURLException e )
208         {
209             // can't really happen... or can it?
210         }
211     }
212 
213     public void addLoadURL( URL url )
214     {
215         curRealm.addURL( url );
216     }
217 
218     public void addRealm( String realmName )
219         throws DuplicateRealmException
220     {
221         curRealm = world.newRealm( realmName, foreignClassLoader );
222 
223         // Stash the configured realm for subsequent association processing.
224         configuredRealms.put( realmName, curRealm );
225     }
226 
227     public void setAppMain( String mainClassName, String mainRealmName )
228     {
229         if ( this.launcher != null )
230         {
231             this.launcher.setAppMain( mainClassName, mainRealmName );
232         }
233     }
234 }