|
|||||||||||||||||||
| 30 day Evaluation Version distributed via the Maven Jar Repository. Clover is not free. You have 30 days to evaluate it. Please visit http://www.thecortex.net/clover to obtain a licensed version of Clover | |||||||||||||||||||
| Source file | Conditionals | Statements | Methods | TOTAL | |||||||||||||||
| DefaultClassRealm.java | 46% | 53.5% | 73.7% | 53.5% |
|
||||||||||||||
| 1 |
package org.codehaus.classworlds;
|
|
| 2 |
|
|
| 3 |
/*
|
|
| 4 |
$Id: DefaultClassRealm.java,v 1.8 2004/08/09 22:00:16 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 |
|
|
| 50 |
import java.io.File;
|
|
| 51 |
import java.io.IOException;
|
|
| 52 |
import java.io.InputStream;
|
|
| 53 |
import java.net.URL;
|
|
| 54 |
import java.util.Enumeration;
|
|
| 55 |
import java.util.Iterator;
|
|
| 56 |
import java.util.TreeSet;
|
|
| 57 |
import java.util.Vector;
|
|
| 58 |
|
|
| 59 |
|
|
| 60 |
/**
|
|
| 61 |
* Implementation of <code>ClassRealm</code>. The realm is the class loading gateway.
|
|
| 62 |
* The search is proceded as follows:
|
|
| 63 |
* <ol>
|
|
| 64 |
* <li>Search the parent class loader (passed via the constructor) if there
|
|
| 65 |
* is one.</li>
|
|
| 66 |
* <li>Search the imports.</li>
|
|
| 67 |
* <li>Search this realm's constituents.</li>
|
|
| 68 |
* <li>Search the parent realm.</li>
|
|
| 69 |
* </ol>
|
|
| 70 |
*
|
|
| 71 |
* @author <a href="mailto:bob@eng.werken.com">bob mcwhirter</a>
|
|
| 72 |
* @author <a href="mailto:jason@zenplex.com">Jason van Zyl</a>
|
|
| 73 |
* @version $Id: DefaultClassRealm.java,v 1.8 2004/08/09 22:00:16 jvanzyl Exp $
|
|
| 74 |
* @todo allow inheritance to be turn on/off at runtime.
|
|
| 75 |
* @todo allow direction of search
|
|
| 76 |
*/
|
|
| 77 |
public class DefaultClassRealm |
|
| 78 |
implements ClassRealm
|
|
| 79 |
{
|
|
| 80 |
private ClassWorld world;
|
|
| 81 |
|
|
| 82 |
private String id;
|
|
| 83 |
|
|
| 84 |
private TreeSet imports;
|
|
| 85 |
|
|
| 86 |
private ClassLoader foreignClassLoader;
|
|
| 87 |
|
|
| 88 |
private RealmClassLoader classLoader;
|
|
| 89 |
|
|
| 90 |
private ClassRealm parent;
|
|
| 91 |
|
|
| 92 | 180 |
public DefaultClassRealm( ClassWorld world, String id )
|
| 93 |
{
|
|
| 94 | 180 |
this( world, id, null ); |
| 95 |
} |
|
| 96 |
|
|
| 97 | 180 |
public DefaultClassRealm( ClassWorld world, String id, ClassLoader foreignClassLoader )
|
| 98 |
{
|
|
| 99 | 180 |
this.world = world;
|
| 100 |
|
|
| 101 | 180 |
this.id = id;
|
| 102 |
|
|
| 103 | 180 |
imports = new TreeSet();
|
| 104 |
|
|
| 105 | 180 |
if ( foreignClassLoader != null ) |
| 106 |
{
|
|
| 107 | 0 |
this.foreignClassLoader = foreignClassLoader;
|
| 108 |
} |
|
| 109 |
|
|
| 110 | 180 |
if ( "true".equals( System.getProperty( "classworlds.bootstrapped" ) ) ) |
| 111 |
{
|
|
| 112 | 14 |
classLoader = new UberJarRealmClassLoader( this ); |
| 113 |
} |
|
| 114 |
else
|
|
| 115 |
{
|
|
| 116 | 166 |
classLoader = new RealmClassLoader( this ); |
| 117 |
} |
|
| 118 |
} |
|
| 119 |
|
|
| 120 | 0 |
public URL[] getConstituents()
|
| 121 |
{
|
|
| 122 | 0 |
return classLoader.getURLs();
|
| 123 |
} |
|
| 124 |
|
|
| 125 | 84 |
public ClassRealm getParent()
|
| 126 |
{
|
|
| 127 | 84 |
return parent;
|
| 128 |
} |
|
| 129 |
|
|
| 130 | 12 |
public void setParent( ClassRealm parent ) |
| 131 |
{
|
|
| 132 | 12 |
this.parent = parent;
|
| 133 |
} |
|
| 134 |
|
|
| 135 | 4 |
public String getId()
|
| 136 |
{
|
|
| 137 | 4 |
return this.id; |
| 138 |
} |
|
| 139 |
|
|
| 140 | 290 |
public ClassWorld getWorld()
|
| 141 |
{
|
|
| 142 | 290 |
return this.world; |
| 143 |
} |
|
| 144 |
|
|
| 145 | 32 |
public void importFrom( String realmId, String packageName ) |
| 146 |
throws NoSuchRealmException
|
|
| 147 |
{
|
|
| 148 | 32 |
imports.add( new Entry( getWorld().getRealm( realmId ), packageName ) );
|
| 149 | 32 |
imports.add( new Entry( getWorld().getRealm( realmId ), packageName.replace('.', '/') ) );
|
| 150 |
} |
|
| 151 |
|
|
| 152 | 90 |
public void addConstituent( URL constituent ) |
| 153 |
{
|
|
| 154 | 90 |
classLoader.addConstituent( constituent ); |
| 155 |
} |
|
| 156 |
|
|
| 157 |
/**
|
|
| 158 |
* Adds a byte[] class definition as a constituent for locating classes.
|
|
| 159 |
* Currently uses BytesURLStreamHandler to hold a reference of the byte[] in memory.
|
|
| 160 |
* This ensures we have a unifed URL resource model for all constituents.
|
|
| 161 |
* The code to cache to disk is commented out - maybe a property to choose which method?
|
|
| 162 |
*
|
|
| 163 |
* @param constituent class name
|
|
| 164 |
* @param b the class definition as a byte[]
|
|
| 165 |
*/
|
|
| 166 | 0 |
public void addConstituent(String constituent, |
| 167 |
byte[] b) throws ClassNotFoundException |
|
| 168 |
{
|
|
| 169 | 0 |
try
|
| 170 |
{
|
|
| 171 | 0 |
File path, file; |
| 172 | 0 |
if (constituent.lastIndexOf('.') != -1)
|
| 173 |
{
|
|
| 174 | 0 |
path = new File("byteclass/" + constituent.substring(0, constituent.lastIndexOf('.') + 1).replace('.', File.separatorChar)); |
| 175 |
|
|
| 176 | 0 |
file = new File(path, constituent.substring(constituent.lastIndexOf('.') + 1) + ".class"); |
| 177 |
} |
|
| 178 |
else
|
|
| 179 |
{
|
|
| 180 | 0 |
path = new File("byteclass/"); |
| 181 |
|
|
| 182 | 0 |
file = new File(path, constituent + ".class"); |
| 183 |
} |
|
| 184 |
|
|
| 185 | 0 |
addConstituent( new URL( null, |
| 186 |
file.toURL().toExternalForm(), |
|
| 187 |
new BytesURLStreamHandler(b) ) );
|
|
| 188 |
} |
|
| 189 |
catch (java.io.IOException e)
|
|
| 190 |
{
|
|
| 191 | 0 |
throw new ClassNotFoundException( "Couldn't load byte stream.", e ); |
| 192 |
} |
|
| 193 |
} |
|
| 194 |
|
|
| 195 | 308 |
public ClassRealm locateSourceRealm( String classname )
|
| 196 |
{
|
|
| 197 | 308 |
for ( Iterator iterator = imports.iterator(); iterator.hasNext(); )
|
| 198 |
{
|
|
| 199 | 250 |
Entry entry = (Entry) iterator.next(); |
| 200 |
|
|
| 201 | 250 |
if ( entry.matches( classname ) )
|
| 202 |
{
|
|
| 203 | 50 |
return entry.getRealm();
|
| 204 |
} |
|
| 205 |
} |
|
| 206 |
|
|
| 207 | 258 |
return this; |
| 208 |
} |
|
| 209 |
|
|
| 210 | 64 |
public ClassLoader getClassLoader()
|
| 211 |
{
|
|
| 212 | 64 |
return classLoader;
|
| 213 |
} |
|
| 214 |
|
|
| 215 | 8 |
public ClassRealm createChildRealm( String id )
|
| 216 |
throws DuplicateRealmException
|
|
| 217 |
{
|
|
| 218 | 8 |
ClassRealm childRealm = getWorld().newRealm( id ); |
| 219 |
|
|
| 220 | 8 |
childRealm.setParent( this );
|
| 221 |
|
|
| 222 | 8 |
return childRealm;
|
| 223 |
} |
|
| 224 |
|
|
| 225 |
// ----------------------------------------------------------------------
|
|
| 226 |
// ClassLoader API
|
|
| 227 |
// ----------------------------------------------------------------------
|
|
| 228 |
|
|
| 229 | 428 |
public Class loadClass( String name )
|
| 230 |
throws ClassNotFoundException
|
|
| 231 |
{
|
|
| 232 | 428 |
if ( name.startsWith( "org.codehaus.classworlds." ) ) |
| 233 |
{
|
|
| 234 | 216 |
return getWorld().loadClass( name );
|
| 235 |
} |
|
| 236 |
|
|
| 237 | 212 |
try
|
| 238 |
{
|
|
| 239 | 212 |
if ( foreignClassLoader != null ) |
| 240 |
{
|
|
| 241 | 0 |
try
|
| 242 |
{
|
|
| 243 | 0 |
return foreignClassLoader.loadClass( name );
|
| 244 |
} |
|
| 245 |
catch ( ClassNotFoundException e )
|
|
| 246 |
{
|
|
| 247 |
// Do nothing as we will now look in the realm.
|
|
| 248 |
} |
|
| 249 |
} |
|
| 250 |
|
|
| 251 | 212 |
ClassRealm sourceRealm = locateSourceRealm( name ); |
| 252 |
|
|
| 253 | 212 |
if ( sourceRealm == this ) |
| 254 |
{
|
|
| 255 | 202 |
return classLoader.loadClassDirect( name );
|
| 256 |
} |
|
| 257 |
else
|
|
| 258 |
{
|
|
| 259 | 10 |
try
|
| 260 |
{
|
|
| 261 | 10 |
return sourceRealm.loadClass( name );
|
| 262 |
} |
|
| 263 |
catch ( ClassNotFoundException cnfe )
|
|
| 264 |
{
|
|
| 265 |
// If we can't find it in an import, try loading directly.
|
|
| 266 | 0 |
return classLoader.loadClassDirect( name );
|
| 267 |
} |
|
| 268 |
} |
|
| 269 |
} |
|
| 270 |
catch ( ClassNotFoundException e )
|
|
| 271 |
{
|
|
| 272 | 46 |
if ( getParent() != null ) |
| 273 |
{
|
|
| 274 | 24 |
return getParent().loadClass( name );
|
| 275 |
} |
|
| 276 |
|
|
| 277 | 22 |
throw e;
|
| 278 |
} |
|
| 279 |
} |
|
| 280 |
|
|
| 281 | 28 |
public URL getResource( String name )
|
| 282 |
{
|
|
| 283 | 28 |
URL resource = null;
|
| 284 | 28 |
name = UrlUtils.normalizeUrlPath( name ); |
| 285 |
|
|
| 286 | 28 |
if ( foreignClassLoader != null ) |
| 287 |
{
|
|
| 288 | 0 |
resource = foreignClassLoader.getResource( name ); |
| 289 |
|
|
| 290 | 0 |
if ( resource != null ) |
| 291 |
{
|
|
| 292 | 0 |
return resource;
|
| 293 |
} |
|
| 294 |
} |
|
| 295 |
|
|
| 296 | 28 |
ClassRealm sourceRealm = locateSourceRealm( name ); |
| 297 |
|
|
| 298 | 28 |
if ( sourceRealm == this ) |
| 299 |
{
|
|
| 300 | 28 |
resource = classLoader.getResourceDirect( name ); |
| 301 |
} |
|
| 302 |
else
|
|
| 303 |
{
|
|
| 304 | 0 |
resource = sourceRealm.getResource( name ); |
| 305 |
|
|
| 306 | 0 |
if ( resource == null ) |
| 307 |
{
|
|
| 308 | 0 |
resource = classLoader.getResourceDirect( name ); |
| 309 |
} |
|
| 310 |
} |
|
| 311 |
|
|
| 312 | 28 |
if ( resource == null && getParent() != null ) |
| 313 |
{
|
|
| 314 | 6 |
resource = getParent().getResource( name ); |
| 315 |
} |
|
| 316 |
|
|
| 317 | 28 |
return resource;
|
| 318 |
} |
|
| 319 |
|
|
| 320 | 0 |
public InputStream getResourceAsStream( String name )
|
| 321 |
{
|
|
| 322 | 0 |
URL url = getResource( name ); |
| 323 |
|
|
| 324 | 0 |
InputStream is = null;
|
| 325 |
|
|
| 326 | 0 |
if ( url != null ) |
| 327 |
{
|
|
| 328 | 0 |
try
|
| 329 |
{
|
|
| 330 | 0 |
is = url.openStream(); |
| 331 |
} |
|
| 332 |
catch ( IOException e )
|
|
| 333 |
{
|
|
| 334 |
// do nothing
|
|
| 335 |
} |
|
| 336 |
} |
|
| 337 |
|
|
| 338 | 0 |
return is;
|
| 339 |
} |
|
| 340 |
|
|
| 341 | 2 |
public Enumeration findResources(String name)
|
| 342 |
throws IOException
|
|
| 343 |
{
|
|
| 344 | 2 |
name = UrlUtils.normalizeUrlPath(name); |
| 345 |
|
|
| 346 | 2 |
Vector resources = new Vector();
|
| 347 |
|
|
| 348 |
// Find resources from the parent class loader
|
|
| 349 | 2 |
if ( foreignClassLoader != null ) |
| 350 |
{
|
|
| 351 | 0 |
for ( Enumeration res = foreignClassLoader.getResources(name); res.hasMoreElements(); )
|
| 352 |
{
|
|
| 353 | 0 |
resources.addElement(res.nextElement()); |
| 354 |
} |
|
| 355 |
} |
|
| 356 |
|
|
| 357 |
// Load imports
|
|
| 358 | 2 |
ClassRealm sourceRealm = locateSourceRealm( name ); |
| 359 |
|
|
| 360 | 2 |
if ( sourceRealm != this ) |
| 361 |
{
|
|
| 362 |
// Attempt to load directly first, then go to the imported packages.
|
|
| 363 | 0 |
for ( Enumeration res = sourceRealm.findResources(name); res.hasMoreElements(); )
|
| 364 |
{
|
|
| 365 | 0 |
resources.addElement(res.nextElement()); |
| 366 |
} |
|
| 367 |
} |
|
| 368 |
|
|
| 369 |
// Load from our classloader
|
|
| 370 | 2 |
for ( Enumeration direct = classLoader.findResourcesDirect(name); direct.hasMoreElements(); )
|
| 371 |
{
|
|
| 372 | 4 |
resources.addElement(direct.nextElement()); |
| 373 |
} |
|
| 374 |
|
|
| 375 |
// Find resources from the parent realm.
|
|
| 376 | 2 |
if (parent != null) |
| 377 |
{
|
|
| 378 | 0 |
for ( Enumeration parent = getParent().findResources(name); parent.hasMoreElements(); )
|
| 379 |
{
|
|
| 380 | 0 |
resources.addElement(parent.nextElement()); |
| 381 |
} |
|
| 382 |
} |
|
| 383 |
|
|
| 384 | 2 |
return resources.elements();
|
| 385 |
} |
|
| 386 |
|
|
| 387 | 0 |
public void display() |
| 388 |
{
|
|
| 389 | 0 |
ClassRealm cr = this;
|
| 390 |
|
|
| 391 | 0 |
System.out.println( "-----------------------------------------------------" );
|
| 392 |
|
|
| 393 |
|
|
| 394 | 0 |
showUrls( cr ); |
| 395 |
|
|
| 396 | 0 |
while( cr.getParent() != null ) |
| 397 |
{
|
|
| 398 | 0 |
System.out.println( "\n" );
|
| 399 |
|
|
| 400 | 0 |
cr = cr.getParent(); |
| 401 |
|
|
| 402 | 0 |
showUrls( cr ); |
| 403 |
} |
|
| 404 |
|
|
| 405 | 0 |
System.out.println( "-----------------------------------------------------" );
|
| 406 |
} |
|
| 407 |
|
|
| 408 | 0 |
private void showUrls( ClassRealm classRealm ) |
| 409 |
{
|
|
| 410 | 0 |
System.out.println( "this realm = " + classRealm.getId() );
|
| 411 |
|
|
| 412 | 0 |
URL[] urls = classRealm.getConstituents(); |
| 413 |
|
|
| 414 | 0 |
for ( int i = 0; i < urls.length; i++ ) |
| 415 |
{
|
|
| 416 | 0 |
System.out.println( "urls[" + i + "] = " + urls[i] ); |
| 417 |
} |
|
| 418 |
|
|
| 419 | 0 |
System.out.println( "Number of imports: " + imports.size() );
|
| 420 |
|
|
| 421 | 0 |
for ( Iterator i = imports.iterator(); i.hasNext(); )
|
| 422 |
{
|
|
| 423 | 0 |
System.out.println( "import: " + i.next() );
|
| 424 |
} |
|
| 425 |
} |
|
| 426 |
} |
|
| 427 |
|
|
||||||||||