1 package org.codehaus.classworlds;
2
3 /*
4 $Id: DefaultClassRealm.java,v 1.1 2003/09/23 14:09:46 jvanzyl 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 java.net.URL;
50 import java.util.TreeSet;
51 import java.util.Set;
52 import java.util.Iterator;
53
54 /*** Implementation of <code>ClassRealm</code>.
55 *
56 * @author <a href="mailto:bob@eng.werken.com">bob mcwhirter</a>
57 * @author <a href="mailto:jason@zenplex.com">Jason van Zyl</a>
58 *
59 * @version $Id: DefaultClassRealm.java,v 1.1 2003/09/23 14:09:46 jvanzyl Exp $
60 *
61 * @todo allow inheritance to be turn on/off at runtime.
62 * @todo allow direction of search
63 */
64 class DefaultClassRealm implements ClassRealm
65 {
66 // ------------------------------------------------------------
67 // Instance members
68 // ------------------------------------------------------------
69
70 /*** The world of which this realm is a member. */
71 private ClassWorld world;
72
73 /*** The id of this realm. */
74 private String id;
75
76 /*** Import spec entries. */
77 private Set imports;
78
79 /*** The classloader. */
80 private RealmClassLoader classLoader;
81
82 /*** Parent ClassRealm */
83 private ClassRealm parent;
84
85 // ------------------------------------------------------------
86 // Constructors
87 // ------------------------------------------------------------
88
89 /*** Construct.
90 *
91 * @param world The world of which this realm is a member.
92 * @param id This realm's id.
93 */
94 DefaultClassRealm( ClassWorld world,
95 String id )
96 {
97 this.world = world;
98 this.id = id;
99
100 this.imports = new TreeSet();
101
102 // We need to detect whether we are running in an UberJar
103 // or not.
104 if ( "true".equals( System.getProperty( "classworlds.bootstrapped" ) ) )
105 {
106 this.classLoader = new UberJarRealmClassLoader( this );
107 }
108 else
109 {
110 this.classLoader = new RealmClassLoader( this );
111 }
112 }
113
114 // ------------------------------------------------------------
115 // Instance methods
116 // ------------------------------------------------------------
117
118 /***
119 *
120 * @return
121 */
122 public ClassRealm getParent()
123 {
124 return parent;
125 }
126
127 /***
128 *
129 * @param parent
130 */
131 public void setParent( ClassRealm parent )
132 {
133 this.parent = parent;
134 }
135
136 /*** Retrieve the id.
137 *
138 * @return The id.
139 */
140 public String getId()
141 {
142 return this.id;
143 }
144
145 /*** Retrieve the <code>ClassWorld</code>.
146 *
147 * @return The world.
148 */
149 public ClassWorld getWorld()
150 {
151 return this.world;
152 }
153
154 /*** Import packages from another <code>ClassRealm</code>.
155 *
156 * <p>
157 * Specific packages can be imported from another realm
158 * instead of attempting to load them locally from this
159 * one. When importing a package a realm defers <b>completely</b>
160 * to the foreign realm to satisfy the package dependencies.
161 * </p>
162 *
163 * @param realmId The realm id from which to import.
164 * @param pkgName The package name to import.
165 *
166 * @throws NoSuchRealmException If the id of the realm from which
167 * to import does not correspond to a foreign realm within
168 * this realm's world.
169 */
170 public void importFrom( String realmId,
171 String pkgName ) throws NoSuchRealmException
172 {
173 this.imports.add( new Entry( getWorld().getRealmImpl( realmId ),
174 pkgName ) );
175 }
176
177 /*** Add a constituent to this realm for locating classes.
178 *
179 * @param constituent URL to contituent jar or directory.
180 */
181 public void addConstituent( URL constituent )
182 {
183 this.classLoader.addConstituent( constituent );
184 }
185
186 /*** Locate the <code>ClassRealm</code> that should
187 * satisfy loading of a class.
188 *
189 * @param classname The name of the class to load.
190 *
191 * @return The appropriate realm.
192 */
193 DefaultClassRealm locateSourceRealm( String classname )
194 {
195 Iterator entryIter = this.imports.iterator();
196
197 while ( entryIter.hasNext() )
198 {
199 Entry eachEntry = (Entry) entryIter.next();
200
201 if ( eachEntry.matches( classname ) )
202 {
203 return eachEntry.getRealm();
204 }
205 }
206
207 return this;
208 }
209
210 /*** Retrieve the <code>ClassLoader</code> view of
211 * this realm.
212 *
213 * @return The class-loader view of this realm.
214 */
215 public ClassLoader getClassLoader()
216 {
217 return this.classLoader;
218 }
219
220 /*** Load a class.
221 *
222 * @param name The name of the class to load.
223 *
224 * @return The loaded class.
225 *
226 * @throws ClassNotFoundException If the class cannot be found.
227 */
228 public Class loadClass( String name ) throws ClassNotFoundException
229 {
230 if ( name.startsWith( "org.codehaus.classworlds." ) )
231 {
232 return getWorld().loadClass( name );
233 }
234
235 DefaultClassRealm sourceRealm = locateSourceRealm( name );
236
237 if ( sourceRealm == this )
238 {
239 return loadClassDirect( name );
240 }
241
242 return sourceRealm.loadClass( name );
243 }
244
245 /*** Load a class.
246 *
247 * @param name The name of the class to load.
248 *
249 * @return The loaded class.
250 *
251 * @throws ClassNotFoundException If the class cannot be found.
252 */
253 Class loadClassDirect( String name ) throws ClassNotFoundException
254 {
255 // 1. Try this realm's ClassLoader.
256 // 2. If the realm has a parent try the parent's ClassLoader.
257
258 Class clazz = null;
259
260 try
261 {
262 clazz = this.classLoader.loadClassDirect( name );
263 }
264 catch ( ClassNotFoundException cnfe1 )
265 {
266 if ( getParent() != null )
267 {
268 clazz = getParent().getClassLoader().loadClass( name );
269 }
270 else
271 {
272 throw cnfe1;
273 }
274 }
275
276 return clazz;
277 }
278
279 /*** Retrieve a resource.
280 *
281 * @param name The resource name.
282 *
283 * @return The URL to the located resource or <code>null</code>
284 * if none could be located.
285 */
286 public URL getResource( String name )
287 {
288 name = UrlUtils.normalizeUrlPath( name );
289
290 DefaultClassRealm sourceRealm = locateSourceRealm( name );
291
292 if ( sourceRealm == this )
293 {
294 return loadResourceDirect( name );
295 }
296
297 return sourceRealm.getResource( name );
298 }
299
300
301 URL loadResourceDirect( String name )
302 {
303 // 1. Try this realm's ClassLoader.
304 // 2. If the realm has a parent try the parent's ClassLoader.
305
306 URL resource = this.classLoader.findResource( name );
307
308 if ( resource == null
309 &&
310 getParent() != null )
311 {
312 resource = getParent().getResource( name );
313 }
314
315 return resource;
316 }
317
318 /***
319 * @see ClassRealm#createChildRealm
320 */
321 public ClassRealm createChildRealm( String id )
322 {
323 ClassRealm childRealm = new DefaultClassRealm( getWorld(), id );
324 childRealm.setParent( this );
325
326 return childRealm;
327 }
328 }
This page was automatically generated by Maven