OpenCores
URL https://opencores.org/ocsvn/scarts/scarts/trunk

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [libjava/] [classpath/] [java/] [lang/] [ClassLoader.java] - Blame information for rev 14

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 14 jlechner
/* ClassLoader.java -- responsible for loading classes into the VM
2
   Copyright (C) 1998, 1999, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
3
 
4
This file is part of GNU Classpath.
5
 
6
GNU Classpath is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2, or (at your option)
9
any later version.
10
 
11
GNU Classpath is distributed in the hope that it will be useful, but
12
WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
General Public License for more details.
15
 
16
You should have received a copy of the GNU General Public License
17
along with GNU Classpath; see the file COPYING.  If not, write to the
18
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19
02110-1301 USA.
20
 
21
Linking this library statically or dynamically with other modules is
22
making a combined work based on this library.  Thus, the terms and
23
conditions of the GNU General Public License cover the whole
24
combination.
25
 
26
As a special exception, the copyright holders of this library give you
27
permission to link this library with independent modules to produce an
28
executable, regardless of the license terms of these independent
29
modules, and to copy and distribute the resulting executable under
30
terms of your choice, provided that you also meet, for each linked
31
independent module, the terms and conditions of the license of that
32
module.  An independent module is a module which is not derived from
33
or based on this library.  If you modify this library, you may extend
34
this exception to your version of the library, but you are not
35
obligated to do so.  If you do not wish to do so, delete this
36
exception statement from your version. */
37
 
38
 
39
package java.lang;
40
 
41
import gnu.classpath.SystemProperties;
42
import gnu.classpath.VMStackWalker;
43
import gnu.java.util.DoubleEnumeration;
44
import gnu.java.util.EmptyEnumeration;
45
 
46
import java.io.File;
47
import java.io.IOException;
48
import java.io.InputStream;
49
import java.lang.reflect.Constructor;
50
import java.net.URL;
51
import java.net.URLClassLoader;
52
import java.nio.ByteBuffer;
53
import java.security.CodeSource;
54
import java.security.PermissionCollection;
55
import java.security.Policy;
56
import java.security.ProtectionDomain;
57
import java.util.ArrayList;
58
import java.util.Enumeration;
59
import java.util.HashMap;
60
import java.util.Map;
61
import java.util.StringTokenizer;
62
 
63
/**
64
 * The ClassLoader is a way of customizing the way Java gets its classes
65
 * and loads them into memory.  The verifier and other standard Java things
66
 * still run, but the ClassLoader is allowed great flexibility in determining
67
 * where to get the classfiles and when to load and resolve them. For that
68
 * matter, a custom ClassLoader can perform on-the-fly code generation or
69
 * modification!
70
 *
71
 * <p>Every classloader has a parent classloader that is consulted before
72
 * the 'child' classloader when classes or resources should be loaded.
73
 * This is done to make sure that classes can be loaded from an hierarchy of
74
 * multiple classloaders and classloaders do not accidentially redefine
75
 * already loaded classes by classloaders higher in the hierarchy.
76
 *
77
 * <p>The grandparent of all classloaders is the bootstrap classloader, which
78
 * loads all the standard system classes as implemented by GNU Classpath. The
79
 * other special classloader is the system classloader (also called
80
 * application classloader) that loads all classes from the CLASSPATH
81
 * (<code>java.class.path</code> system property). The system classloader
82
 * is responsible for finding the application classes from the classpath,
83
 * and delegates all requests for the standard library classes to its parent
84
 * the bootstrap classloader. Most programs will load all their classes
85
 * through the system classloaders.
86
 *
87
 * <p>The bootstrap classloader in GNU Classpath is implemented as a couple of
88
 * static (native) methods on the package private class
89
 * <code>java.lang.VMClassLoader</code>, the system classloader is an
90
 * anonymous inner class of ClassLoader and a subclass of
91
 * <code>java.net.URLClassLoader</code>.
92
 *
93
 * <p>Users of a <code>ClassLoader</code> will normally just use the methods
94
 * <ul>
95
 *  <li> <code>loadClass()</code> to load a class.</li>
96
 *  <li> <code>getResource()</code> or <code>getResourceAsStream()</code>
97
 *       to access a resource.</li>
98
 *  <li> <code>getResources()</code> to get an Enumeration of URLs to all
99
 *       the resources provided by the classloader and its parents with the
100
 *       same name.</li>
101
 * </ul>
102
 *
103
 * <p>Subclasses should implement the methods
104
 * <ul>
105
 *  <li> <code>findClass()</code> which is called by <code>loadClass()</code>
106
 *       when the parent classloader cannot provide a named class.</li>
107
 *  <li> <code>findResource()</code> which is called by
108
 *       <code>getResource()</code> when the parent classloader cannot provide
109
 *       a named resource.</li>
110
 *  <li> <code>findResources()</code> which is called by
111
 *       <code>getResource()</code> to combine all the resources with the
112
 *       same name from the classloader and its parents.</li>
113
 *  <li> <code>findLibrary()</code> which is called by
114
 *       <code>Runtime.loadLibrary()</code> when a class defined by the
115
 *       classloader wants to load a native library.</li>
116
 * </ul>
117
 *
118
 * @author John Keiser
119
 * @author Mark Wielaard
120
 * @author Eric Blake (ebb9@email.byu.edu)
121
 * @see Class
122
 * @since 1.0
123
 * @status still missing 1.4 functionality
124
 */
125
public abstract class ClassLoader
126
{
127
  /**
128
   * All packages defined by this classloader. It is not private in order to
129
   * allow native code (and trusted subclasses) access to this field.
130
   */
131
  final HashMap definedPackages = new HashMap();
132
 
133
  /**
134
   * The classloader that is consulted before this classloader.
135
   * If null then the parent is the bootstrap classloader.
136
   */
137
  private final ClassLoader parent;
138
 
139
  /**
140
   * This is true if this classloader was successfully initialized.
141
   * This flag is needed to avoid a class loader attack: even if the
142
   * security manager rejects an attempt to create a class loader, the
143
   * malicious class could have a finalize method which proceeds to
144
   * define classes.
145
   */
146
  private final boolean initialized;
147
 
148
  static class StaticData
149
  {
150
    /**
151
     * The System Class Loader (a.k.a. Application Class Loader). The one
152
     * returned by ClassLoader.getSystemClassLoader.
153
     */
154
    static final ClassLoader systemClassLoader =
155
                              VMClassLoader.getSystemClassLoader();
156
    static
157
    {
158
      // Find out if we have to install a default security manager. Note that
159
      // this is done here because we potentially need the system class loader
160
      // to load the security manager and note also that we don't need the
161
      // security manager until the system class loader is created.
162
      // If the runtime chooses to use a class loader that doesn't have the
163
      // system class loader as its parent, it is responsible for setting
164
      // up a security manager before doing so.
165
      String secman = SystemProperties.getProperty("java.security.manager");
166
      if (secman != null && SecurityManager.current == null)
167
        {
168
          if (secman.equals("") || secman.equals("default"))
169
            {
170
              SecurityManager.current = new SecurityManager();
171
            }
172
          else
173
            {
174
              try
175
                {
176
                  Class cl = Class.forName(secman, false, StaticData.systemClassLoader);
177
                  SecurityManager.current = (SecurityManager)cl.newInstance();
178
                }
179
              catch (Exception x)
180
                {
181
                  throw (InternalError)
182
                      new InternalError("Unable to create SecurityManager")
183
                          .initCause(x);
184
                }
185
            }
186
        }
187
    }
188
 
189
    /**
190
     * The default protection domain, used when defining a class with a null
191
     * parameter for the domain.
192
     */
193
    static final ProtectionDomain defaultProtectionDomain;
194
    static
195
    {
196
        CodeSource cs = new CodeSource(null, null);
197
        PermissionCollection perm = Policy.getPolicy().getPermissions(cs);
198
        defaultProtectionDomain = new ProtectionDomain(cs, perm);
199
    }
200
    /**
201
     * The command-line state of the package assertion status overrides. This
202
     * map is never modified, so it does not need to be synchronized.
203
     */
204
    // Package visible for use by Class.
205
    static final Map systemPackageAssertionStatus
206
      = VMClassLoader.packageAssertionStatus();
207
    /**
208
     * The command-line state of the class assertion status overrides. This
209
     * map is never modified, so it does not need to be synchronized.
210
     */
211
    // Package visible for use by Class.
212
    static final Map systemClassAssertionStatus
213
      = VMClassLoader.classAssertionStatus();
214
  }
215
 
216
  /**
217
   * The desired assertion status of classes loaded by this loader, if not
218
   * overridden by package or class instructions.
219
   */
220
  // Package visible for use by Class.
221
  boolean defaultAssertionStatus = VMClassLoader.defaultAssertionStatus();
222
 
223
  /**
224
   * The map of package assertion status overrides, or null if no package
225
   * overrides have been specified yet. The values of the map should be
226
   * Boolean.TRUE or Boolean.FALSE, and the unnamed package is represented
227
   * by the null key. This map must be synchronized on this instance.
228
   */
229
  // Package visible for use by Class.
230
  Map packageAssertionStatus;
231
 
232
  /**
233
   * The map of class assertion status overrides, or null if no class
234
   * overrides have been specified yet. The values of the map should be
235
   * Boolean.TRUE or Boolean.FALSE. This map must be synchronized on this
236
   * instance.
237
   */
238
  // Package visible for use by Class.
239
  Map classAssertionStatus;
240
 
241
  /**
242
   * VM private data.
243
   */
244
  transient Object vmdata;
245
 
246
  /**
247
   * Create a new ClassLoader with as parent the system classloader. There
248
   * may be a security check for <code>checkCreateClassLoader</code>.
249
   *
250
   * @throws SecurityException if the security check fails
251
   */
252
  protected ClassLoader() throws SecurityException
253
  {
254
    this(StaticData.systemClassLoader);
255
  }
256
 
257
  /**
258
   * Create a new ClassLoader with the specified parent. The parent will
259
   * be consulted when a class or resource is requested through
260
   * <code>loadClass()</code> or <code>getResource()</code>. Only when the
261
   * parent classloader cannot provide the requested class or resource the
262
   * <code>findClass()</code> or <code>findResource()</code> method
263
   * of this classloader will be called. There may be a security check for
264
   * <code>checkCreateClassLoader</code>.
265
   *
266
   * @param parent the classloader's parent, or null for the bootstrap
267
   *        classloader
268
   * @throws SecurityException if the security check fails
269
   * @since 1.2
270
   */
271
  protected ClassLoader(ClassLoader parent)
272
  {
273
    // May we create a new classloader?
274
    SecurityManager sm = SecurityManager.current;
275
    if (sm != null)
276
      sm.checkCreateClassLoader();
277
    this.parent = parent;
278
    this.initialized = true;
279
  }
280
 
281
  /**
282
   * Load a class using this ClassLoader or its parent, without resolving
283
   * it. Calls <code>loadClass(name, false)</code>.
284
   *
285
   * <p>Subclasses should not override this method but should override
286
   * <code>findClass()</code> which is called by this method.</p>
287
   *
288
   * @param name the name of the class relative to this ClassLoader
289
   * @return the loaded class
290
   * @throws ClassNotFoundException if the class cannot be found
291
   */
292
  public Class loadClass(String name) throws ClassNotFoundException
293
  {
294
    return loadClass(name, false);
295
  }
296
 
297
  /**
298
   * Load a class using this ClassLoader or its parent, possibly resolving
299
   * it as well using <code>resolveClass()</code>. It first tries to find
300
   * out if the class has already been loaded through this classloader by
301
   * calling <code>findLoadedClass()</code>. Then it calls
302
   * <code>loadClass()</code> on the parent classloader (or when there is
303
   * no parent it uses the VM bootclassloader). If the class is still
304
   * not loaded it tries to create a new class by calling
305
   * <code>findClass()</code>. Finally when <code>resolve</code> is
306
   * <code>true</code> it also calls <code>resolveClass()</code> on the
307
   * newly loaded class.
308
   *
309
   * <p>Subclasses should not override this method but should override
310
   * <code>findClass()</code> which is called by this method.</p>
311
   *
312
   * @param name the fully qualified name of the class to load
313
   * @param resolve whether or not to resolve the class
314
   * @return the loaded class
315
   * @throws ClassNotFoundException if the class cannot be found
316
   */
317
  protected synchronized Class loadClass(String name, boolean resolve)
318
    throws ClassNotFoundException
319
  {
320
    // Have we already loaded this class?
321
    Class c = findLoadedClass(name);
322
    if (c == null)
323
      {
324
        // Can the class be loaded by a parent?
325
        try
326
          {
327
            if (parent == null)
328
              {
329
                c = VMClassLoader.loadClass(name, resolve);
330
                if (c != null)
331
                  return c;
332
              }
333
            else
334
              {
335
                return parent.loadClass(name, resolve);
336
              }
337
          }
338
        catch (ClassNotFoundException e)
339
          {
340
          }
341
        // Still not found, we have to do it ourself.
342
        c = findClass(name);
343
      }
344
    if (resolve)
345
      resolveClass(c);
346
    return c;
347
  }
348
 
349
  /**
350
   * Called for every class name that is needed but has not yet been
351
   * defined by this classloader or one of its parents. It is called by
352
   * <code>loadClass()</code> after both <code>findLoadedClass()</code> and
353
   * <code>parent.loadClass()</code> couldn't provide the requested class.
354
   *
355
   * <p>The default implementation throws a
356
   * <code>ClassNotFoundException</code>. Subclasses should override this
357
   * method. An implementation of this method in a subclass should get the
358
   * class bytes of the class (if it can find them), if the package of the
359
   * requested class doesn't exist it should define the package and finally
360
   * it should call define the actual class. It does not have to resolve the
361
   * class. It should look something like the following:<br>
362
   *
363
   * <pre>
364
   * // Get the bytes that describe the requested class
365
   * byte[] classBytes = classLoaderSpecificWayToFindClassBytes(name);
366
   * // Get the package name
367
   * int lastDot = name.lastIndexOf('.');
368
   * if (lastDot != -1)
369
   *   {
370
   *     String packageName = name.substring(0, lastDot);
371
   *     // Look if the package already exists
372
   *     if (getPackage(packageName) == null)
373
   *       {
374
   *         // define the package
375
   *         definePackage(packageName, ...);
376
   *       }
377
   *   }
378
   * // Define and return the class
379
   *  return defineClass(name, classBytes, 0, classBytes.length);
380
   * </pre>
381
   *
382
   * <p><code>loadClass()</code> makes sure that the <code>Class</code>
383
   * returned by <code>findClass()</code> will later be returned by
384
   * <code>findLoadedClass()</code> when the same class name is requested.
385
   *
386
   * @param name class name to find (including the package name)
387
   * @return the requested Class
388
   * @throws ClassNotFoundException when the class can not be found
389
   * @since 1.2
390
   */
391
  protected Class findClass(String name) throws ClassNotFoundException
392
  {
393
    throw new ClassNotFoundException(name);
394
  }
395
 
396
  /**
397
   * Helper to define a class using a string of bytes. This version is not
398
   * secure.
399
   *
400
   * @param data the data representing the classfile, in classfile format
401
   * @param offset the offset into the data where the classfile starts
402
   * @param len the length of the classfile data in the array
403
   * @return the class that was defined
404
   * @throws ClassFormatError if data is not in proper classfile format
405
   * @throws IndexOutOfBoundsException if offset or len is negative, or
406
   *         offset + len exceeds data
407
   * @deprecated use {@link #defineClass(String, byte[], int, int)} instead
408
   */
409
  protected final Class defineClass(byte[] data, int offset, int len)
410
    throws ClassFormatError
411
  {
412
    return defineClass(null, data, offset, len);
413
  }
414
 
415
  /**
416
   * Helper to define a class using a string of bytes without a
417
   * ProtectionDomain. Subclasses should call this method from their
418
   * <code>findClass()</code> implementation. The name should use '.'
419
   * separators, and discard the trailing ".class".  The default protection
420
   * domain has the permissions of
421
   * <code>Policy.getPolicy().getPermissions(new CodeSource(null, null))</code>.
422
   *
423
   * @param name the name to give the class, or null if unknown
424
   * @param data the data representing the classfile, in classfile format
425
   * @param offset the offset into the data where the classfile starts
426
   * @param len the length of the classfile data in the array
427
   * @return the class that was defined
428
   * @throws ClassFormatError if data is not in proper classfile format
429
   * @throws IndexOutOfBoundsException if offset or len is negative, or
430
   *         offset + len exceeds data
431
   * @throws SecurityException if name starts with "java."
432
   * @since 1.1
433
   */
434
  protected final Class defineClass(String name, byte[] data, int offset,
435
                                    int len) throws ClassFormatError
436
  {
437
    return defineClass(name, data, offset, len, null);
438
  }
439
 
440
  /**
441
   * Helper to define a class using a string of bytes. Subclasses should call
442
   * this method from their <code>findClass()</code> implementation. If the
443
   * domain is null, the default of
444
   * <code>Policy.getPolicy().getPermissions(new CodeSource(null, null))</code>
445
   * is used. Once a class has been defined in a package, all further classes
446
   * in that package must have the same set of certificates or a
447
   * SecurityException is thrown.
448
   *
449
   * @param name the name to give the class.  null if unknown
450
   * @param data the data representing the classfile, in classfile format
451
   * @param offset the offset into the data where the classfile starts
452
   * @param len the length of the classfile data in the array
453
   * @param domain the ProtectionDomain to give to the class, null for the
454
   *        default protection domain
455
   * @return the class that was defined
456
   * @throws ClassFormatError if data is not in proper classfile format
457
   * @throws IndexOutOfBoundsException if offset or len is negative, or
458
   *         offset + len exceeds data
459
   * @throws SecurityException if name starts with "java.", or if certificates
460
   *         do not match up
461
   * @since 1.2
462
   */
463
  protected final synchronized Class defineClass(String name, byte[] data,
464
                                                 int offset, int len,
465
                                                 ProtectionDomain domain)
466
    throws ClassFormatError
467
  {
468
    checkInitialized();
469
    if (domain == null)
470
      domain = StaticData.defaultProtectionDomain;
471
 
472
    return VMClassLoader.defineClass(this, name, data, offset, len, domain);
473
  }
474
 
475
  /**
476
   * Helper to define a class using the contents of a byte buffer. If
477
   * the domain is null, the default of
478
   * <code>Policy.getPolicy().getPermissions(new CodeSource(null,
479
   * null))</code> is used. Once a class has been defined in a
480
   * package, all further classes in that package must have the same
481
   * set of certificates or a SecurityException is thrown.
482
   *
483
   * @param name the name to give the class.  null if unknown
484
   * @param buf a byte buffer containing bytes that form a class.
485
   * @param domain the ProtectionDomain to give to the class, null for the
486
   *        default protection domain
487
   * @return the class that was defined
488
   * @throws ClassFormatError if data is not in proper classfile format
489
   * @throws NoClassDefFoundError if the supplied name is not the same as
490
   *                              the one specified by the byte buffer.
491
   * @throws SecurityException if name starts with "java.", or if certificates
492
   *         do not match up
493
   * @since 1.5
494
   */
495
  protected final Class defineClass(String name, ByteBuffer buf,
496
                                    ProtectionDomain domain)
497
    throws ClassFormatError
498
  {
499
    byte[] data = new byte[buf.remaining()];
500
    buf.get(data);
501
    return defineClass(name, data, 0, data.length, domain);
502
  }
503
 
504
  /**
505
   * Links the class, if that has not already been done. Linking basically
506
   * resolves all references to other classes made by this class.
507
   *
508
   * @param c the class to resolve
509
   * @throws NullPointerException if c is null
510
   * @throws LinkageError if linking fails
511
   */
512
  protected final void resolveClass(Class c)
513
  {
514
    checkInitialized();
515
    VMClassLoader.resolveClass(c);
516
  }
517
 
518
  /**
519
   * Helper to find a Class using the system classloader, possibly loading it.
520
   * A subclass usually does not need to call this, if it correctly
521
   * overrides <code>findClass(String)</code>.
522
   *
523
   * @param name the name of the class to find
524
   * @return the found class
525
   * @throws ClassNotFoundException if the class cannot be found
526
   */
527
  protected final Class findSystemClass(String name)
528
    throws ClassNotFoundException
529
  {
530
    checkInitialized();
531
    return Class.forName(name, false, StaticData.systemClassLoader);
532
  }
533
 
534
  /**
535
   * Returns the parent of this classloader. If the parent of this
536
   * classloader is the bootstrap classloader then this method returns
537
   * <code>null</code>. A security check may be performed on
538
   * <code>RuntimePermission("getClassLoader")</code>.
539
   *
540
   * @return the parent <code>ClassLoader</code>
541
   * @throws SecurityException if the security check fails
542
   * @since 1.2
543
   */
544
  public final ClassLoader getParent()
545
  {
546
    // Check if we may return the parent classloader.
547
    SecurityManager sm = SecurityManager.current;
548
    if (sm != null)
549
      {
550
        ClassLoader cl = VMStackWalker.getCallingClassLoader();
551
        if (cl != null && ! cl.isAncestorOf(this))
552
          sm.checkPermission(new RuntimePermission("getClassLoader"));
553
      }
554
    return parent;
555
  }
556
 
557
  /**
558
   * Helper to set the signers of a class. This should be called after
559
   * defining the class.
560
   *
561
   * @param c the Class to set signers of
562
   * @param signers the signers to set
563
   * @since 1.1
564
   */
565
  protected final void setSigners(Class c, Object[] signers)
566
  {
567
    checkInitialized();
568
    c.setSigners(signers);
569
  }
570
 
571
  /**
572
   * Helper to find an already-loaded class in this ClassLoader.
573
   *
574
   * @param name the name of the class to find
575
   * @return the found Class, or null if it is not found
576
   * @since 1.1
577
   */
578
  protected final synchronized Class findLoadedClass(String name)
579
  {
580
    checkInitialized();
581
    return VMClassLoader.findLoadedClass(this, name);
582
  }
583
 
584
  /**
585
   * Get the URL to a resource using this classloader or one of its parents.
586
   * First tries to get the resource by calling <code>getResource()</code>
587
   * on the parent classloader. If the parent classloader returns null then
588
   * it tries finding the resource by calling <code>findResource()</code> on
589
   * this classloader. The resource name should be separated by '/' for path
590
   * elements.
591
   *
592
   * <p>Subclasses should not override this method but should override
593
   * <code>findResource()</code> which is called by this method.
594
   *
595
   * @param name the name of the resource relative to this classloader
596
   * @return the URL to the resource or null when not found
597
   */
598
  public URL getResource(String name)
599
  {
600
    URL result;
601
 
602
    if (parent == null)
603
      result = VMClassLoader.getResource(name);
604
    else
605
      result = parent.getResource(name);
606
 
607
    if (result == null)
608
      result = findResource(name);
609
    return result;
610
  }
611
 
612
  /**
613
   * Returns an Enumeration of all resources with a given name that can
614
   * be found by this classloader and its parents. Certain classloaders
615
   * (such as the URLClassLoader when given multiple jar files) can have
616
   * multiple resources with the same name that come from multiple locations.
617
   * It can also occur that a parent classloader offers a resource with a
618
   * certain name and the child classloader also offers a resource with that
619
   * same name. <code>getResource()</code> only offers the first resource (of the
620
   * parent) with a given name. This method lists all resources with the
621
   * same name. The name should use '/' as path separators.
622
   *
623
   * <p>The Enumeration is created by first calling <code>getResources()</code>
624
   * on the parent classloader and then calling <code>findResources()</code>
625
   * on this classloader.</p>
626
   *
627
   * @param name the resource name
628
   * @return an enumaration of all resources found
629
   * @throws IOException if I/O errors occur in the process
630
   * @since 1.2
631
   */
632
  public final Enumeration getResources(String name) throws IOException
633
  {
634
    Enumeration parentResources;
635
    if (parent == null)
636
      parentResources = VMClassLoader.getResources(name);
637
    else
638
      parentResources = parent.getResources(name);
639
    return new DoubleEnumeration(parentResources, findResources(name));
640
  }
641
 
642
  /**
643
   * Called whenever all locations of a named resource are needed.
644
   * It is called by <code>getResources()</code> after it has called
645
   * <code>parent.getResources()</code>. The results are combined by
646
   * the <code>getResources()</code> method.
647
   *
648
   * <p>The default implementation always returns an empty Enumeration.
649
   * Subclasses should override it when they can provide an Enumeration of
650
   * URLs (possibly just one element) to the named resource.
651
   * The first URL of the Enumeration should be the same as the one
652
   * returned by <code>findResource</code>.
653
   *
654
   * @param name the name of the resource to be found
655
   * @return a possibly empty Enumeration of URLs to the named resource
656
   * @throws IOException if I/O errors occur in the process
657
   * @since 1.2
658
   */
659
  protected Enumeration findResources(String name) throws IOException
660
  {
661
    return EmptyEnumeration.getInstance();
662
  }
663
 
664
  /**
665
   * Called whenever a resource is needed that could not be provided by
666
   * one of the parents of this classloader. It is called by
667
   * <code>getResource()</code> after <code>parent.getResource()</code>
668
   * couldn't provide the requested resource.
669
   *
670
   * <p>The default implementation always returns null. Subclasses should
671
   * override this method when they can provide a way to return a URL
672
   * to a named resource.
673
   *
674
   * @param name the name of the resource to be found
675
   * @return a URL to the named resource or null when not found
676
   * @since 1.2
677
   */
678
  protected URL findResource(String name)
679
  {
680
    return null;
681
  }
682
 
683
  /**
684
   * Get the URL to a resource using the system classloader.
685
   *
686
   * @param name the name of the resource relative to the system classloader
687
   * @return the URL to the resource
688
   * @since 1.1
689
   */
690
  public static final URL getSystemResource(String name)
691
  {
692
    return StaticData.systemClassLoader.getResource(name);
693
  }
694
 
695
  /**
696
   * Get an Enumeration of URLs to resources with a given name using the
697
   * the system classloader. The enumeration firsts lists the resources with
698
   * the given name that can be found by the bootstrap classloader followed
699
   * by the resources with the given name that can be found on the classpath.
700
   *
701
   * @param name the name of the resource relative to the system classloader
702
   * @return an Enumeration of URLs to the resources
703
   * @throws IOException if I/O errors occur in the process
704
   * @since 1.2
705
   */
706
  public static Enumeration getSystemResources(String name) throws IOException
707
  {
708
    return StaticData.systemClassLoader.getResources(name);
709
  }
710
 
711
  /**
712
   * Get a resource as stream using this classloader or one of its parents.
713
   * First calls <code>getResource()</code> and if that returns a URL to
714
   * the resource then it calls and returns the InputStream given by
715
   * <code>URL.openStream()</code>.
716
   *
717
   * <p>Subclasses should not override this method but should override
718
   * <code>findResource()</code> which is called by this method.
719
   *
720
   * @param name the name of the resource relative to this classloader
721
   * @return an InputStream to the resource, or null
722
   * @since 1.1
723
   */
724
  public InputStream getResourceAsStream(String name)
725
  {
726
    try
727
      {
728
        URL url = getResource(name);
729
        if (url == null)
730
          return null;
731
        return url.openStream();
732
      }
733
    catch (IOException e)
734
      {
735
        return null;
736
      }
737
  }
738
 
739
  /**
740
   * Get a resource using the system classloader.
741
   *
742
   * @param name the name of the resource relative to the system classloader
743
   * @return an input stream for the resource, or null
744
   * @since 1.1
745
   */
746
  public static final InputStream getSystemResourceAsStream(String name)
747
  {
748
    try
749
      {
750
        URL url = getSystemResource(name);
751
        if (url == null)
752
          return null;
753
        return url.openStream();
754
      }
755
    catch (IOException e)
756
      {
757
        return null;
758
      }
759
  }
760
 
761
  /**
762
   * Returns the system classloader. The system classloader (also called
763
   * the application classloader) is the classloader that is used to
764
   * load the application classes on the classpath (given by the system
765
   * property <code>java.class.path</code>. This is set as the context
766
   * class loader for a thread. The system property
767
   * <code>java.system.class.loader</code>, if defined, is taken to be the
768
   * name of the class to use as the system class loader, which must have
769
   * a public constructor which takes a ClassLoader as a parent. The parent
770
   * class loader passed in the constructor is the default system class
771
   * loader.
772
   *
773
   * <p>Note that this is different from the bootstrap classloader that
774
   * actually loads all the real "system" classes.
775
   *
776
   * <p>A security check will be performed for
777
   * <code>RuntimePermission("getClassLoader")</code> if the calling class
778
   * is not a parent of the system class loader.
779
   *
780
   * @return the system class loader
781
   * @throws SecurityException if the security check fails
782
   * @throws IllegalStateException if this is called recursively
783
   * @throws Error if <code>java.system.class.loader</code> fails to load
784
   * @since 1.2
785
   */
786
  public static ClassLoader getSystemClassLoader()
787
  {
788
    // Check if we may return the system classloader
789
    SecurityManager sm = SecurityManager.current;
790
    if (sm != null)
791
      {
792
        ClassLoader cl = VMStackWalker.getCallingClassLoader();
793
        if (cl != null && cl != StaticData.systemClassLoader)
794
          sm.checkPermission(new RuntimePermission("getClassLoader"));
795
      }
796
 
797
    return StaticData.systemClassLoader;
798
  }
799
 
800
  /**
801
   * Defines a new package and creates a Package object. The package should
802
   * be defined before any class in the package is defined with
803
   * <code>defineClass()</code>. The package should not yet be defined
804
   * before in this classloader or in one of its parents (which means that
805
   * <code>getPackage()</code> should return <code>null</code>). All
806
   * parameters except the <code>name</code> of the package may be
807
   * <code>null</code>.
808
   *
809
   * <p>Subclasses should call this method from their <code>findClass()</code>
810
   * implementation before calling <code>defineClass()</code> on a Class
811
   * in a not yet defined Package (which can be checked by calling
812
   * <code>getPackage()</code>).
813
   *
814
   * @param name the name of the Package
815
   * @param specTitle the name of the specification
816
   * @param specVendor the name of the specification designer
817
   * @param specVersion the version of this specification
818
   * @param implTitle the name of the implementation
819
   * @param implVendor the vendor that wrote this implementation
820
   * @param implVersion the version of this implementation
821
   * @param sealed if sealed the origin of the package classes
822
   * @return the Package object for the specified package
823
   * @throws IllegalArgumentException if the package name is null or it
824
   *         was already defined by this classloader or one of its parents
825
   * @see Package
826
   * @since 1.2
827
   */
828
  protected Package definePackage(String name, String specTitle,
829
                                  String specVendor, String specVersion,
830
                                  String implTitle, String implVendor,
831
                                  String implVersion, URL sealed)
832
  {
833
    if (getPackage(name) != null)
834
      throw new IllegalArgumentException("Package " + name
835
                                         + " already defined");
836
    Package p = new Package(name, specTitle, specVendor, specVersion,
837
                            implTitle, implVendor, implVersion, sealed);
838
    synchronized (definedPackages)
839
      {
840
        definedPackages.put(name, p);
841
      }
842
    return p;
843
  }
844
 
845
  /**
846
   * Returns the Package object for the requested package name. It returns
847
   * null when the package is not defined by this classloader or one of its
848
   * parents.
849
   *
850
   * @param name the package name to find
851
   * @return the package, if defined
852
   * @since 1.2
853
   */
854
  protected Package getPackage(String name)
855
  {
856
    Package p;
857
    if (parent == null)
858
      p = VMClassLoader.getPackage(name);
859
    else
860
      p = parent.getPackage(name);
861
 
862
    if (p == null)
863
      {
864
        synchronized (definedPackages)
865
          {
866
            p = (Package) definedPackages.get(name);
867
          }
868
      }
869
    return p;
870
  }
871
 
872
  /**
873
   * Returns all Package objects defined by this classloader and its parents.
874
   *
875
   * @return an array of all defined packages
876
   * @since 1.2
877
   */
878
  protected Package[] getPackages()
879
  {
880
    // Get all our packages.
881
    Package[] packages;
882
    synchronized(definedPackages)
883
      {
884
        packages = new Package[definedPackages.size()];
885
        definedPackages.values().toArray(packages);
886
      }
887
 
888
    // If we have a parent get all packages defined by our parents.
889
    Package[] parentPackages;
890
    if (parent == null)
891
      parentPackages = VMClassLoader.getPackages();
892
    else
893
      parentPackages = parent.getPackages();
894
 
895
    Package[] allPackages = new Package[parentPackages.length
896
                                        + packages.length];
897
    System.arraycopy(parentPackages, 0, allPackages, 0,
898
                     parentPackages.length);
899
    System.arraycopy(packages, 0, allPackages, parentPackages.length,
900
                     packages.length);
901
    return allPackages;
902
  }
903
 
904
  /**
905
   * Called by <code>Runtime.loadLibrary()</code> to get an absolute path
906
   * to a (system specific) library that was requested by a class loaded
907
   * by this classloader. The default implementation returns
908
   * <code>null</code>. It should be implemented by subclasses when they
909
   * have a way to find the absolute path to a library. If this method
910
   * returns null the library is searched for in the default locations
911
   * (the directories listed in the <code>java.library.path</code> system
912
   * property).
913
   *
914
   * @param name the (system specific) name of the requested library
915
   * @return the full pathname to the requested library, or null
916
   * @see Runtime#loadLibrary(String)
917
   * @since 1.2
918
   */
919
  protected String findLibrary(String name)
920
  {
921
    return null;
922
  }
923
 
924
  /**
925
   * Set the default assertion status for classes loaded by this classloader,
926
   * used unless overridden by a package or class request.
927
   *
928
   * @param enabled true to set the default to enabled
929
   * @see #setClassAssertionStatus(String, boolean)
930
   * @see #setPackageAssertionStatus(String, boolean)
931
   * @see #clearAssertionStatus()
932
   * @since 1.4
933
   */
934
  public void setDefaultAssertionStatus(boolean enabled)
935
  {
936
    defaultAssertionStatus = enabled;
937
  }
938
 
939
  /**
940
   * Set the default assertion status for packages, used unless overridden
941
   * by a class request. This default also covers subpackages, unless they
942
   * are also specified. The unnamed package should use null for the name.
943
   *
944
   * @param name the package (and subpackages) to affect
945
   * @param enabled true to set the default to enabled
946
   * @see #setDefaultAssertionStatus(boolean)
947
   * @see #setClassAssertionStatus(String, boolean)
948
   * @see #clearAssertionStatus()
949
   * @since 1.4
950
   */
951
  public synchronized void setPackageAssertionStatus(String name,
952
                                                     boolean enabled)
953
  {
954
    if (packageAssertionStatus == null)
955
      packageAssertionStatus
956
        = new HashMap(StaticData.systemPackageAssertionStatus);
957
    packageAssertionStatus.put(name, Boolean.valueOf(enabled));
958
  }
959
 
960
  /**
961
   * Set the default assertion status for a class. This only affects the
962
   * status of top-level classes, any other string is harmless.
963
   *
964
   * @param name the class to affect
965
   * @param enabled true to set the default to enabled
966
   * @throws NullPointerException if name is null
967
   * @see #setDefaultAssertionStatus(boolean)
968
   * @see #setPackageAssertionStatus(String, boolean)
969
   * @see #clearAssertionStatus()
970
   * @since 1.4
971
   */
972
  public synchronized void setClassAssertionStatus(String name,
973
                                                   boolean enabled)
974
  {
975
    if (classAssertionStatus == null)
976
      classAssertionStatus =
977
        new HashMap(StaticData.systemClassAssertionStatus);
978
    // The toString() hack catches null, as required.
979
    classAssertionStatus.put(name.toString(), Boolean.valueOf(enabled));
980
  }
981
 
982
  /**
983
   * Resets the default assertion status of this classloader, its packages
984
   * and classes, all to false. This allows overriding defaults inherited
985
   * from the command line.
986
   *
987
   * @see #setDefaultAssertionStatus(boolean)
988
   * @see #setClassAssertionStatus(String, boolean)
989
   * @see #setPackageAssertionStatus(String, boolean)
990
   * @since 1.4
991
   */
992
  public synchronized void clearAssertionStatus()
993
  {
994
    defaultAssertionStatus = false;
995
    packageAssertionStatus = new HashMap();
996
    classAssertionStatus = new HashMap();
997
  }
998
 
999
  /**
1000
   * Return true if this loader is either the specified class loader
1001
   * or an ancestor thereof.
1002
   * @param loader the class loader to check
1003
   */
1004
  final boolean isAncestorOf(ClassLoader loader)
1005
  {
1006
    while (loader != null)
1007
      {
1008
        if (this == loader)
1009
          return true;
1010
        loader = loader.parent;
1011
      }
1012
    return false;
1013
  }
1014
 
1015
  private static URL[] getExtClassLoaderUrls()
1016
  {
1017
    String classpath = SystemProperties.getProperty("java.ext.dirs", "");
1018
    StringTokenizer tok = new StringTokenizer(classpath, File.pathSeparator);
1019
    ArrayList list = new ArrayList();
1020
    while (tok.hasMoreTokens())
1021
      {
1022
        try
1023
          {
1024
            File f = new File(tok.nextToken());
1025
            File[] files = f.listFiles();
1026
            if (files != null)
1027
              for (int i = 0; i < files.length; i++)
1028
                list.add(files[i].toURL());
1029
          }
1030
        catch(Exception x)
1031
          {
1032
          }
1033
      }
1034
    URL[] urls = new URL[list.size()];
1035
    list.toArray(urls);
1036
    return urls;
1037
  }
1038
 
1039
  private static void addFileURL(ArrayList list, String file)
1040
  {
1041
    try
1042
      {
1043
        list.add(new File(file).toURL());
1044
      }
1045
    catch(java.net.MalformedURLException x)
1046
      {
1047
      }
1048
  }
1049
 
1050
  private static URL[] getSystemClassLoaderUrls()
1051
  {
1052
    String classpath = SystemProperties.getProperty("java.class.path", ".");
1053
    StringTokenizer tok = new StringTokenizer(classpath, File.pathSeparator, true);
1054
    ArrayList list = new ArrayList();
1055
    while (tok.hasMoreTokens())
1056
      {
1057
        String s = tok.nextToken();
1058
        if (s.equals(File.pathSeparator))
1059
            addFileURL(list, ".");
1060
        else
1061
          {
1062
            addFileURL(list, s);
1063
            if (tok.hasMoreTokens())
1064
              {
1065
                // Skip the separator.
1066
                tok.nextToken();
1067
                // If the classpath ended with a separator,
1068
                // append the current directory.
1069
                if (!tok.hasMoreTokens())
1070
                    addFileURL(list, ".");
1071
              }
1072
          }
1073
      }
1074
    URL[] urls = new URL[list.size()];
1075
    list.toArray(urls);
1076
    return urls;
1077
  }
1078
 
1079
  static ClassLoader defaultGetSystemClassLoader()
1080
  {
1081
    return createAuxiliarySystemClassLoader(
1082
        createSystemClassLoader(getSystemClassLoaderUrls(),
1083
            createExtClassLoader(getExtClassLoaderUrls(), null)));
1084
  }
1085
 
1086
  static ClassLoader createExtClassLoader(URL[] urls, ClassLoader parent)
1087
  {
1088
    if (urls.length > 0)
1089
      return new URLClassLoader(urls, parent);
1090
    else
1091
      return parent;
1092
  }
1093
 
1094
  static ClassLoader createSystemClassLoader(URL[] urls, ClassLoader parent)
1095
  {
1096
    return
1097
        new URLClassLoader(urls, parent)
1098
        {
1099
            protected synchronized Class loadClass(String name,
1100
                boolean resolve)
1101
                throws ClassNotFoundException
1102
            {
1103
                SecurityManager sm = SecurityManager.current;
1104
                if (sm != null)
1105
                {
1106
                    int lastDot = name.lastIndexOf('.');
1107
                    if (lastDot != -1)
1108
                        sm.checkPackageAccess(name.substring(0, lastDot));
1109
                }
1110
                return super.loadClass(name, resolve);
1111
            }
1112
        };
1113
  }
1114
 
1115
  static ClassLoader createAuxiliarySystemClassLoader(ClassLoader parent)
1116
  {
1117
    String loader = SystemProperties.getProperty("java.system.class.loader", null);
1118
    if (loader == null)
1119
      {
1120
        return parent;
1121
      }
1122
    try
1123
      {
1124
        Constructor c = Class.forName(loader, false, parent)
1125
            .getConstructor(new Class[] { ClassLoader.class });
1126
        return (ClassLoader)c.newInstance(new Object[] { parent });
1127
      }
1128
    catch (Exception e)
1129
      {
1130
        System.err.println("Requested system classloader " + loader + " failed.");
1131
        throw (Error)
1132
            new Error("Requested system classloader " + loader + " failed.")
1133
                .initCause(e);
1134
      }
1135
  }
1136
 
1137
  /**
1138
   * Before doing anything "dangerous" please call this method to make sure
1139
   * this class loader instance was properly constructed (and not obtained
1140
   * by exploiting the finalizer attack)
1141
   * @see #initialized
1142
   */
1143
  private void checkInitialized()
1144
  {
1145
    if (! initialized)
1146
      throw new SecurityException("attempt to use uninitialized class loader");
1147
  }
1148
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.