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