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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libjava/] [classpath/] [java/] [net/] [URLClassLoader.java] - Blame information for rev 771

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 771 jeremybenn
/* URLClassLoader.java --  ClassLoader that loads classes from one or more URLs
2
   Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
3
   Free Software Foundation, Inc.
4
 
5
This file is part of GNU Classpath.
6
 
7
GNU Classpath is free software; you can redistribute it and/or modify
8
it under the terms of the GNU General Public License as published by
9
the Free Software Foundation; either version 2, or (at your option)
10
any later version.
11
 
12
GNU Classpath is distributed in the hope that it will be useful, but
13
WITHOUT ANY WARRANTY; without even the implied warranty of
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
General Public License for more details.
16
 
17
You should have received a copy of the GNU General Public License
18
along with GNU Classpath; see the file COPYING.  If not, write to the
19
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20
02110-1301 USA.
21
 
22
Linking this library statically or dynamically with other modules is
23
making a combined work based on this library.  Thus, the terms and
24
conditions of the GNU General Public License cover the whole
25
combination.
26
 
27
As a special exception, the copyright holders of this library give you
28
permission to link this library with independent modules to produce an
29
executable, regardless of the license terms of these independent
30
modules, and to copy and distribute the resulting executable under
31
terms of your choice, provided that you also meet, for each linked
32
independent module, the terms and conditions of the license of that
33
module.  An independent module is a module which is not derived from
34
or based on this library.  If you modify this library, you may extend
35
this exception to your version of the library, but you are not
36
obligated to do so.  If you do not wish to do so, delete this
37
exception statement from your version. */
38
 
39
 
40
package java.net;
41
 
42
import gnu.java.lang.CPStringBuilder;
43
 
44
import gnu.java.net.loader.FileURLLoader;
45
import gnu.java.net.loader.JarURLLoader;
46
import gnu.java.net.loader.RemoteURLLoader;
47
import gnu.java.net.loader.Resource;
48
import gnu.java.net.loader.URLLoader;
49
import gnu.java.net.loader.URLStreamHandlerCache;
50
 
51
import java.io.ByteArrayOutputStream;
52
import java.io.EOFException;
53
import java.io.File;
54
import java.io.FilePermission;
55
import java.io.IOException;
56
import java.io.InputStream;
57
import java.lang.reflect.Constructor;
58
import java.lang.reflect.InvocationTargetException;
59
import java.security.AccessControlContext;
60
import java.security.AccessController;
61
import java.security.CodeSource;
62
import java.security.PermissionCollection;
63
import java.security.PrivilegedAction;
64
import java.security.SecureClassLoader;
65
import java.security.cert.Certificate;
66
import java.util.ArrayList;
67
import java.util.Enumeration;
68
import java.util.Vector;
69
import java.util.jar.Attributes;
70
import java.util.jar.Manifest;
71
 
72
 
73
/**
74
 * A secure class loader that can load classes and resources from
75
 * multiple locations.  Given an array of <code>URL</code>s this class
76
 * loader will retrieve classes and resources by fetching them from
77
 * possible remote locations.  Each <code>URL</code> is searched in
78
 * order in which it was added.  If the file portion of the
79
 * <code>URL</code> ends with a '/' character then it is interpreted
80
 * as a base directory, otherwise it is interpreted as a jar file from
81
 * which the classes/resources are resolved.
82
 *
83
 * <p>New instances can be created by two static
84
 * <code>newInstance()</code> methods or by three public
85
 * contructors. Both ways give the option to supply an initial array
86
 * of <code>URL</code>s and (optionally) a parent classloader (that is
87
 * different from the standard system class loader).</p>
88
 *
89
 * <p>Normally creating a <code>URLClassLoader</code> throws a
90
 * <code>SecurityException</code> if a <code>SecurityManager</code> is
91
 * installed and the <code>checkCreateClassLoader()</code> method does
92
 * not return true.  But the <code>newInstance()</code> methods may be
93
 * used by any code as long as it has permission to acces the given
94
 * <code>URL</code>s.  <code>URLClassLoaders</code> created by the
95
 * <code>newInstance()</code> methods also explicitly call the
96
 * <code>checkPackageAccess()</code> method of
97
 * <code>SecurityManager</code> if one is installed before trying to
98
 * load a class.  Note that only subclasses of
99
 * <code>URLClassLoader</code> can add new URLs after the
100
 * URLClassLoader had been created. But it is always possible to get
101
 * an array of all URLs that the class loader uses to resolve classes
102
 * and resources by way of the <code>getURLs()</code> method.</p>
103
 *
104
 * <p>Open issues:
105
 * <ul>
106
 *
107
 * <li>Should the URLClassLoader actually add the locations found in
108
 * the manifest or is this the responsibility of some other
109
 * loader/(sub)class?  (see <a
110
 * href="http://java.sun.com/products/jdk/1.4/docs/guide/extensions/spec.html">
111
 * Extension Mechanism Architecture - Bundles Extensions</a>)</li>
112
 *
113
 * <li>How does <code>definePackage()</code> and sealing work
114
 * precisely?</li>
115
 *
116
 * <li>We save and use the security context (when a created by
117
 * <code>newInstance()</code> but do we have to use it in more
118
 * places?</li>
119
 *
120
 * <li>The use of <code>URLStreamHandler</code>s has not been tested.</li>
121
 *
122
 * </ul>
123
 * </p>
124
 *
125
 * @since 1.2
126
 *
127
 * @author Mark Wielaard (mark@klomp.org)
128
 * @author Wu Gansha (gansha.wu@intel.com)
129
 */
130
public class URLClassLoader extends SecureClassLoader
131
{
132
  // Class Variables
133
 
134
  /**
135
   * A cache to store mappings between handler factory and its
136
   * private protocol handler cache (also a HashMap), so we can avoid
137
   * creating handlers each time the same protocol comes.
138
   */
139
  private static URLStreamHandlerCache factoryCache
140
    = new URLStreamHandlerCache();
141
 
142
  /**
143
   * The prefix for URL loaders.
144
   */
145
  private static final String URL_LOADER_PREFIX = "gnu.java.net.loader.Load_";
146
 
147
  // Instance variables
148
 
149
  /** Locations to load classes from */
150
  private final Vector<URL> urls = new Vector<URL>();
151
 
152
  /**
153
   * Store pre-parsed information for each url into this vector: each
154
   * element is a URL loader.  A jar file has its own class-path
155
   * attribute which adds to the URLs that will be searched, but this
156
   * does not add to the list of urls.
157
   */
158
  private final Vector<URLLoader> urlinfos = new Vector<URLLoader>();
159
 
160
  /** Factory used to get the protocol handlers of the URLs */
161
  private final URLStreamHandlerFactory factory;
162
 
163
  /**
164
   * The security context when created from <code>newInstance()</code>
165
   * or null when created through a normal constructor or when no
166
   * <code>SecurityManager</code> was installed.
167
   */
168
  private final AccessControlContext securityContext;
169
 
170
  // Helper classes
171
 
172
  /**
173
   * Creates a URLClassLoader that gets classes from the supplied URLs.
174
   * To determine if this classloader may be created the constructor of
175
   * the super class (<code>SecureClassLoader</code>) is called first, which
176
   * can throw a SecurityException. Then the supplied URLs are added
177
   * in the order given to the URLClassLoader which uses these URLs to
178
   * load classes and resources (after using the default parent ClassLoader).
179
   *
180
   * @param urls Locations that should be searched by this ClassLoader when
181
   * resolving Classes or Resources.
182
   * @exception SecurityException if the SecurityManager disallows the
183
   * creation of a ClassLoader.
184
   * @see SecureClassLoader
185
   */
186
  public URLClassLoader(URL[] urls) throws SecurityException
187
  {
188
    super();
189
    this.factory = null;
190
    this.securityContext = null;
191
    addURLs(urls);
192
  }
193
 
194
  /**
195
   * Creates a <code>URLClassLoader</code> that gets classes from the supplied
196
   * <code>URL</code>s.
197
   * To determine if this classloader may be created the constructor of
198
   * the super class (<code>SecureClassLoader</code>) is called first, which
199
   * can throw a SecurityException. Then the supplied URLs are added
200
   * in the order given to the URLClassLoader which uses these URLs to
201
   * load classes and resources (after using the supplied parent ClassLoader).
202
   * @param urls Locations that should be searched by this ClassLoader when
203
   * resolving Classes or Resources.
204
   * @param parent The parent class loader used before trying this class
205
   * loader.
206
   * @exception SecurityException if the SecurityManager disallows the
207
   * creation of a ClassLoader.
208
   * @exception SecurityException
209
   * @see SecureClassLoader
210
   */
211
  public URLClassLoader(URL[] urls, ClassLoader parent)
212
    throws SecurityException
213
  {
214
    super(parent);
215
    this.factory = null;
216
    this.securityContext = null;
217
    addURLs(urls);
218
  }
219
 
220
  // Package-private to avoid a trampoline constructor.
221
  /**
222
   * Package-private constructor used by the static
223
   * <code>newInstance(URL[])</code> method.  Creates an
224
   * <code>URLClassLoader</code> with the given parent but without any
225
   * <code>URL</code>s yet. This is used to bypass the normal security
226
   * check for creating classloaders, but remembers the security
227
   * context which will be used when defining classes.  The
228
   * <code>URL</code>s to load from must be added by the
229
   * <code>newInstance()</code> method in the security context of the
230
   * caller.
231
   *
232
   * @param securityContext the security context of the unprivileged code.
233
   */
234
  URLClassLoader(ClassLoader parent, AccessControlContext securityContext)
235
  {
236
    super(parent);
237
    this.factory = null;
238
    this.securityContext = securityContext;
239
  }
240
 
241
  /**
242
   * Creates a URLClassLoader that gets classes from the supplied URLs.
243
   * To determine if this classloader may be created the constructor of
244
   * the super class (<CODE>SecureClassLoader</CODE>) is called first, which
245
   * can throw a SecurityException. Then the supplied URLs are added
246
   * in the order given to the URLClassLoader which uses these URLs to
247
   * load classes and resources (after using the supplied parent ClassLoader).
248
   * It will use the supplied <CODE>URLStreamHandlerFactory</CODE> to get the
249
   * protocol handlers of the supplied URLs.
250
   * @param urls Locations that should be searched by this ClassLoader when
251
   * resolving Classes or Resources.
252
   * @param parent The parent class loader used before trying this class
253
   * loader.
254
   * @param factory Used to get the protocol handler for the URLs.
255
   * @exception SecurityException if the SecurityManager disallows the
256
   * creation of a ClassLoader.
257
   * @exception SecurityException
258
   * @see SecureClassLoader
259
   */
260
  public URLClassLoader(URL[] urls, ClassLoader parent,
261
                        URLStreamHandlerFactory factory)
262
    throws SecurityException
263
  {
264
    super(parent);
265
    this.securityContext = null;
266
    this.factory = factory;
267
    // If this factory is not yet in factoryCache, add it.
268
    factoryCache.add(factory);
269
    addURLs(urls);
270
  }
271
 
272
  // Methods
273
 
274
  /**
275
   * Adds a new location to the end of the internal URL store.
276
   * @param newUrl the location to add
277
   */
278
  protected void addURL(URL newUrl)
279
  {
280
    urls.add(newUrl);
281
    addURLImpl(newUrl);
282
  }
283
 
284
  private void addURLImpl(URL newUrl)
285
  {
286
    synchronized (this)
287
      {
288
        if (newUrl == null)
289
          return; // Silently ignore...
290
 
291
        // Reset the toString() value.
292
        thisString = null;
293
 
294
        // Create a loader for this URL.
295
        URLLoader loader = null;
296
        String file = newUrl.getFile();
297
        String protocol = newUrl.getProtocol();
298
 
299
        // If we have a file: URL, we want to make it absolute
300
        // here, before we decide whether it is really a jar.
301
        URL absoluteURL;
302
        if ("file".equals (protocol))
303
          {
304
            File dir = new File(file);
305
            try
306
              {
307
                absoluteURL = dir.getCanonicalFile().toURL();
308
              }
309
            catch (IOException ignore)
310
              {
311
                try
312
                  {
313
                    absoluteURL = dir.getAbsoluteFile().toURL();
314
                  }
315
                catch (MalformedURLException _)
316
                  {
317
                    // This really should not happen.
318
                    absoluteURL = newUrl;
319
                  }
320
              }
321
          }
322
        else
323
          {
324
            // This doesn't hurt, and it simplifies the logic a
325
            // little.
326
            absoluteURL = newUrl;
327
          }
328
 
329
        // First see if we can find a handler with the correct name.
330
        try
331
          {
332
            Class<?> handler = Class.forName(URL_LOADER_PREFIX + protocol);
333
            Class<?>[] argTypes = new Class<?>[] { URLClassLoader.class,
334
                                                   URLStreamHandlerCache.class,
335
                                                   URLStreamHandlerFactory.class,
336
                                                   URL.class,
337
                                                   URL.class };
338
            Constructor k = handler.getDeclaredConstructor(argTypes);
339
            loader
340
              = (URLLoader) k.newInstance(new Object[] { this,
341
                                                         factoryCache,
342
                                                         factory,
343
                                                         newUrl,
344
                                                         absoluteURL });
345
          }
346
        catch (ClassNotFoundException ignore)
347
          {
348
            // Fall through.
349
          }
350
        catch (NoSuchMethodException nsme)
351
          {
352
            // Programming error in the class library.
353
            InternalError vme
354
              = new InternalError("couldn't find URLLoader constructor");
355
            vme.initCause(nsme);
356
            throw vme;
357
          }
358
        catch (InstantiationException inste)
359
          {
360
            // Programming error in the class library.
361
            InternalError vme
362
              = new InternalError("couldn't instantiate URLLoader");
363
            vme.initCause(inste);
364
            throw vme;
365
          }
366
        catch (InvocationTargetException ite)
367
          {
368
            // Programming error in the class library.
369
            InternalError vme
370
              = new InternalError("error instantiating URLLoader");
371
            vme.initCause(ite);
372
            throw vme;
373
          }
374
        catch (IllegalAccessException illae)
375
          {
376
            // Programming error in the class library.
377
            InternalError vme
378
              = new InternalError("invalid access to URLLoader");
379
            vme.initCause(illae);
380
            throw vme;
381
          }
382
 
383
        if (loader == null)
384
          {
385
            // If it is not a directory, use the jar loader.
386
            if (! (file.endsWith("/") || file.endsWith(File.separator)))
387
              loader = new JarURLLoader(this, factoryCache, factory,
388
                                        newUrl, absoluteURL);
389
            else if ("file".equals(protocol))
390
              loader = new FileURLLoader(this, factoryCache, factory,
391
                                         newUrl, absoluteURL);
392
            else
393
              loader = new RemoteURLLoader(this, factoryCache, factory,
394
                                           newUrl);
395
          }
396
 
397
        urlinfos.add(loader);
398
        ArrayList<URLLoader> extra = loader.getClassPath();
399
        if (extra != null)
400
          urlinfos.addAll(extra);
401
      }
402
  }
403
 
404
  /**
405
   * Adds an array of new locations to the end of the internal URL
406
   * store.  Called from the the constructors. Should not call to the
407
   * protected addURL() method since that can be overridden and
408
   * subclasses are not yet in a good state at this point.
409
   * jboss 4.0.3 for example depends on this.
410
   *
411
   * @param newUrls the locations to add
412
   */
413
  private void addURLs(URL[] newUrls)
414
  {
415
    for (int i = 0; i < newUrls.length; i++)
416
      {
417
        urls.add(newUrls[i]);
418
        addURLImpl(newUrls[i]);
419
      }
420
  }
421
 
422
  /**
423
   * Look in both Attributes for a given value.  The first Attributes
424
   * object, if not null, has precedence.
425
   */
426
  private String getAttributeValue(Attributes.Name name, Attributes first,
427
                                   Attributes second)
428
  {
429
    String result = null;
430
    if (first != null)
431
      result = first.getValue(name);
432
    if (result == null)
433
      result = second.getValue(name);
434
    return result;
435
  }
436
 
437
  /**
438
   * Defines a Package based on the given name and the supplied manifest
439
   * information. The manifest indicates the title, version and
440
   * vendor information of the specification and implementation and whether the
441
   * package is sealed. If the Manifest indicates that the package is sealed
442
   * then the Package will be sealed with respect to the supplied URL.
443
   *
444
   * @param name The name of the package
445
   * @param manifest The manifest describing the specification,
446
   * implementation and sealing details of the package
447
   * @param url the code source url to seal the package
448
   * @return the defined Package
449
   * @throws IllegalArgumentException If this package name already exists
450
   * in this class loader
451
   */
452
  protected Package definePackage(String name, Manifest manifest, URL url)
453
    throws IllegalArgumentException
454
  {
455
    // Compute the name of the package as it may appear in the
456
    // Manifest.
457
    CPStringBuilder xform = new CPStringBuilder(name);
458
    for (int i = xform.length () - 1; i >= 0; --i)
459
      if (xform.charAt(i) == '.')
460
        xform.setCharAt(i, '/');
461
    xform.append('/');
462
    String xformName = xform.toString();
463
 
464
    Attributes entryAttr = manifest.getAttributes(xformName);
465
    Attributes attr = manifest.getMainAttributes();
466
 
467
    String specTitle
468
      = getAttributeValue(Attributes.Name.SPECIFICATION_TITLE,
469
                          entryAttr, attr);
470
    String specVersion
471
      = getAttributeValue(Attributes.Name.SPECIFICATION_VERSION,
472
                          entryAttr, attr);
473
    String specVendor
474
      = getAttributeValue(Attributes.Name.SPECIFICATION_VENDOR,
475
                          entryAttr, attr);
476
    String implTitle
477
      = getAttributeValue(Attributes.Name.IMPLEMENTATION_TITLE,
478
                          entryAttr, attr);
479
    String implVersion
480
      = getAttributeValue(Attributes.Name.IMPLEMENTATION_VERSION,
481
                          entryAttr, attr);
482
    String implVendor
483
      = getAttributeValue(Attributes.Name.IMPLEMENTATION_VENDOR,
484
                          entryAttr, attr);
485
 
486
    // Look if the Manifest indicates that this package is sealed
487
    // XXX - most likely not completely correct!
488
    // Shouldn't we also check the sealed attribute of the complete jar?
489
    // http://java.sun.com/products/jdk/1.4/docs/guide/extensions/spec.html#bundled
490
    // But how do we get that jar manifest here?
491
    String sealed = attr.getValue(Attributes.Name.SEALED);
492
    if ("false".equals(sealed))
493
      // make sure that the URL is null so the package is not sealed
494
      url = null;
495
 
496
    return definePackage(name,
497
                         specTitle, specVendor, specVersion,
498
                         implTitle, implVendor, implVersion,
499
                         url);
500
  }
501
 
502
  /**
503
   * Finds (the first) class by name from one of the locations. The locations
504
   * are searched in the order they were added to the URLClassLoader.
505
   *
506
   * @param className the classname to find
507
   * @exception ClassNotFoundException when the class could not be found or
508
   * loaded
509
   * @return a Class object representing the found class
510
   */
511
  protected Class<?> findClass(final String className)
512
    throws ClassNotFoundException
513
  {
514
    // Just try to find the resource by the (almost) same name
515
    String resourceName = className.replace('.', '/') + ".class";
516
    int max = urlinfos.size();
517
    Resource resource = null;
518
    for (int i = 0; i < max && resource == null; i++)
519
      {
520
        URLLoader loader = (URLLoader)urlinfos.elementAt(i);
521
        if (loader == null)
522
          continue;
523
 
524
        Class k = loader.getClass(className);
525
        if (k != null)
526
          return k;
527
 
528
        resource = loader.getResource(resourceName);
529
      }
530
    if (resource == null)
531
      throw new ClassNotFoundException(className + " not found in " + this);
532
 
533
    // Try to read the class data, create the CodeSource, Package and
534
    // construct the class (and watch out for those nasty IOExceptions)
535
    try
536
      {
537
        byte[] data;
538
        InputStream in = resource.getInputStream();
539
        try
540
          {
541
            int length = resource.getLength();
542
            if (length != -1)
543
              {
544
                // We know the length of the data.
545
                // Just try to read it in all at once
546
                data = new byte[length];
547
                int pos = 0;
548
                while (length - pos > 0)
549
                  {
550
                    int len = in.read(data, pos, length - pos);
551
                    if (len == -1)
552
                      throw new EOFException("Not enough data reading from: "
553
                                             + in);
554
                    pos += len;
555
                  }
556
              }
557
            else
558
              {
559
                // We don't know the data length.
560
                // Have to read it in chunks.
561
                ByteArrayOutputStream out = new ByteArrayOutputStream(4096);
562
                byte[] b = new byte[4096];
563
                int l = 0;
564
                while (l != -1)
565
                  {
566
                    l = in.read(b);
567
                    if (l != -1)
568
                      out.write(b, 0, l);
569
                  }
570
                data = out.toByteArray();
571
              }
572
          }
573
        finally
574
          {
575
            in.close();
576
          }
577
        final byte[] classData = data;
578
 
579
        // Now get the CodeSource
580
        final CodeSource source = resource.getCodeSource();
581
 
582
        // Find out package name
583
        String packageName = null;
584
        int lastDot = className.lastIndexOf('.');
585
        if (lastDot != -1)
586
          packageName = className.substring(0, lastDot);
587
 
588
        if (packageName != null && getPackage(packageName) == null)
589
          {
590
            // define the package
591
            Manifest manifest = resource.getLoader().getManifest();
592
            if (manifest == null)
593
              definePackage(packageName, null, null, null, null, null, null,
594
                            null);
595
            else
596
              definePackage(packageName, manifest,
597
                            resource.getLoader().getBaseURL());
598
          }
599
 
600
        // And finally construct the class!
601
        SecurityManager sm = System.getSecurityManager();
602
        Class result = null;
603
        if (sm != null && securityContext != null)
604
          {
605
            result = AccessController.doPrivileged
606
              (new PrivilegedAction<Class>()
607
                {
608
                  public Class run()
609
                  {
610
                    return defineClass(className, classData,
611
                                       0, classData.length,
612
                                       source);
613
                  }
614
                }, securityContext);
615
          }
616
        else
617
          result = defineClass(className, classData, 0, classData.length, source);
618
 
619
        // Avoid NullPointerExceptions.
620
        Certificate[] resourceCertificates = resource.getCertificates();
621
        if(resourceCertificates != null)
622
          super.setSigners(result, resourceCertificates);
623
 
624
        return result;
625
      }
626
    catch (IOException ioe)
627
      {
628
        throw new ClassNotFoundException(className + " not found in " + this, ioe);
629
      }
630
  }
631
 
632
  // Cached String representation of this URLClassLoader
633
  private String thisString;
634
 
635
  /**
636
   * Returns a String representation of this URLClassLoader giving the
637
   * actual Class name, the URLs that are searched and the parent
638
   * ClassLoader.
639
   */
640
  public String toString()
641
  {
642
    synchronized (this)
643
      {
644
        if (thisString == null)
645
          {
646
            CPStringBuilder sb = new CPStringBuilder();
647
            sb.append(this.getClass().getName());
648
            sb.append("{urls=[" );
649
            URL[] thisURLs = getURLs();
650
            for (int i = 0; i < thisURLs.length; i++)
651
              {
652
                sb.append(thisURLs[i]);
653
                if (i < thisURLs.length - 1)
654
                  sb.append(',');
655
              }
656
            sb.append(']');
657
            sb.append(", parent=");
658
            sb.append(getParent());
659
            sb.append('}');
660
            thisString = sb.toString();
661
          }
662
        return thisString;
663
      }
664
  }
665
 
666
  /**
667
   * Finds the first occurrence of a resource that can be found. The locations
668
   * are searched in the order they were added to the URLClassLoader.
669
   *
670
   * @param resourceName the resource name to look for
671
   * @return the URLResource for the resource if found, null otherwise
672
   */
673
  private Resource findURLResource(String resourceName)
674
  {
675
    int max = urlinfos.size();
676
    for (int i = 0; i < max; i++)
677
      {
678
        URLLoader loader = (URLLoader) urlinfos.elementAt(i);
679
        if (loader == null)
680
          continue;
681
 
682
        Resource resource = loader.getResource(resourceName);
683
        if (resource != null)
684
          return resource;
685
      }
686
    return null;
687
  }
688
 
689
  /**
690
   * Finds the first occurrence of a resource that can be found.
691
   *
692
   * @param resourceName the resource name to look for
693
   * @return the URL if found, null otherwise
694
   */
695
  public URL findResource(String resourceName)
696
  {
697
    Resource resource = findURLResource(resourceName);
698
    if (resource != null)
699
      return resource.getURL();
700
 
701
    // Resource not found
702
    return null;
703
  }
704
 
705
  /**
706
   * Finds all the resources with a particular name from all the locations.
707
   *
708
   * @param resourceName the name of the resource to lookup
709
   * @return a (possible empty) enumeration of URLs where the resource can be
710
   * found
711
   * @exception IOException when an error occurs accessing one of the
712
   * locations
713
   */
714
  public Enumeration<URL> findResources(String resourceName)
715
    throws IOException
716
  {
717
    Vector<URL> resources = new Vector<URL>();
718
    int max = urlinfos.size();
719
    for (int i = 0; i < max; i++)
720
      {
721
        URLLoader loader = (URLLoader) urlinfos.elementAt(i);
722
        Resource resource = loader.getResource(resourceName);
723
        if (resource != null)
724
          resources.add(resource.getURL());
725
      }
726
    return resources.elements();
727
  }
728
 
729
  /**
730
   * Returns the permissions needed to access a particular code
731
   * source.  These permissions includes those returned by
732
   * <code>SecureClassLoader.getPermissions()</code> and the actual
733
   * permissions to access the objects referenced by the URL of the
734
   * code source.  The extra permissions added depend on the protocol
735
   * and file portion of the URL in the code source. If the URL has
736
   * the "file" protocol ends with a '/' character then it must be a
737
   * directory and a file Permission to read everything in that
738
   * directory and all subdirectories is added. If the URL had the
739
   * "file" protocol and doesn't end with a '/' character then it must
740
   * be a normal file and a file permission to read that file is
741
   * added. If the <code>URL</code> has any other protocol then a
742
   * socket permission to connect and accept connections from the host
743
   * portion of the URL is added.
744
   *
745
   * @param source The codesource that needs the permissions to be accessed
746
   * @return the collection of permissions needed to access the code resource
747
   * @see java.security.SecureClassLoader#getPermissions(CodeSource)
748
   */
749
  protected PermissionCollection getPermissions(CodeSource source)
750
  {
751
    // XXX - This implementation does exactly as the Javadoc describes.
752
    // But maybe we should/could use URLConnection.getPermissions()?
753
    // First get the permissions that would normally be granted
754
    PermissionCollection permissions = super.getPermissions(source);
755
 
756
    // Now add any extra permissions depending on the URL location.
757
    URL url = source.getLocation();
758
    String protocol = url.getProtocol();
759
    if (protocol.equals("file"))
760
      {
761
        String file = url.getFile();
762
 
763
        // If the file end in / it must be an directory.
764
        if (file.endsWith("/") || file.endsWith(File.separator))
765
          {
766
            // Grant permission to read everything in that directory and
767
            // all subdirectories.
768
            permissions.add(new FilePermission(file + "-", "read"));
769
          }
770
        else
771
          {
772
            // It is a 'normal' file.
773
            // Grant permission to access that file.
774
            permissions.add(new FilePermission(file, "read"));
775
          }
776
      }
777
    else
778
      {
779
        // Grant permission to connect to and accept connections from host
780
        String host = url.getHost();
781
        if (host != null)
782
          permissions.add(new SocketPermission(host, "connect,accept"));
783
      }
784
 
785
    return permissions;
786
  }
787
 
788
  /**
789
   * Returns all the locations that this class loader currently uses the
790
   * resolve classes and resource. This includes both the initially supplied
791
   * URLs as any URLs added later by the loader.
792
   * @return All the currently used URLs
793
   */
794
  public URL[] getURLs()
795
  {
796
    return (URL[]) urls.toArray(new URL[urls.size()]);
797
  }
798
 
799
  /**
800
   * Creates a new instance of a <code>URLClassLoader</code> that gets
801
   * classes from the supplied <code>URL</code>s. This class loader
802
   * will have as parent the standard system class loader.
803
   *
804
   * @param urls the initial URLs used to resolve classes and
805
   * resources
806
   *
807
   * @return the class loader
808
   *
809
   * @exception SecurityException when the calling code does not have
810
   * permission to access the given <code>URL</code>s
811
   */
812
  public static URLClassLoader newInstance(URL[] urls)
813
    throws SecurityException
814
  {
815
    return newInstance(urls, null);
816
  }
817
 
818
  /**
819
   * Creates a new instance of a <code>URLClassLoader</code> that gets
820
   * classes from the supplied <code>URL</code>s and with the supplied
821
   * loader as parent class loader.
822
   *
823
   * @param urls the initial URLs used to resolve classes and
824
   * resources
825
   * @param parent the parent class loader
826
   *
827
   * @return the class loader
828
   *
829
   * @exception SecurityException when the calling code does not have
830
   * permission to access the given <code>URL</code>s
831
   */
832
  public static URLClassLoader newInstance(URL[] urls, final ClassLoader parent)
833
    throws SecurityException
834
  {
835
    SecurityManager sm = System.getSecurityManager();
836
    if (sm == null)
837
      return new URLClassLoader(urls, parent);
838
    else
839
      {
840
        final Object securityContext = sm.getSecurityContext();
841
 
842
        // XXX - What to do with anything else then an AccessControlContext?
843
        if (! (securityContext instanceof AccessControlContext))
844
          throw new SecurityException("securityContext must be AccessControlContext: "
845
                                      + securityContext);
846
 
847
        URLClassLoader loader =
848
          AccessController.doPrivileged(new PrivilegedAction<URLClassLoader>()
849
              {
850
                public URLClassLoader run()
851
                {
852
                  return new URLClassLoader(parent,
853
                                            (AccessControlContext) securityContext);
854
                }
855
              });
856
        loader.addURLs(urls);
857
        return loader;
858
      }
859
  }
860
}

powered by: WebSVN 2.1.0

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