* doc/xml/manual/status_cxx2017.xml: Update status table.
[official-gcc.git] / libjava / classpath / java / net / URLClassLoader.java
blob418ee77f3589cf5433b1dcd6c5af89c348e4c257
1 /* 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.
5 This file is part of GNU Classpath.
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.
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.
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.
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.
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. */
40 package java.net;
42 import gnu.java.lang.CPStringBuilder;
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;
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;
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.
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>
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>
104 * <p>Open issues:
105 * <ul>
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>
113 * <li>How does <code>definePackage()</code> and sealing work
114 * precisely?</li>
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>
120 * <li>The use of <code>URLStreamHandler</code>s has not been tested.</li>
122 * </ul>
123 * </p>
125 * @since 1.2
127 * @author Mark Wielaard (mark@klomp.org)
128 * @author Wu Gansha (gansha.wu@intel.com)
130 public class URLClassLoader extends SecureClassLoader
132 // Class Variables
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.
139 private static URLStreamHandlerCache factoryCache
140 = new URLStreamHandlerCache();
143 * The prefix for URL loaders.
145 private static final String URL_LOADER_PREFIX = "gnu.java.net.loader.Load_";
147 // Instance variables
149 /** Locations to load classes from */
150 private final Vector<URL> urls = new Vector<URL>();
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.
158 private final Vector<URLLoader> urlinfos = new Vector<URLLoader>();
160 /** Factory used to get the protocol handlers of the URLs */
161 private final URLStreamHandlerFactory factory;
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.
168 private final AccessControlContext securityContext;
170 // Helper classes
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).
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
186 public URLClassLoader(URL[] urls) throws SecurityException
188 super();
189 this.factory = null;
190 this.securityContext = null;
191 addURLs(urls);
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
211 public URLClassLoader(URL[] urls, ClassLoader parent)
212 throws SecurityException
214 super(parent);
215 this.factory = null;
216 this.securityContext = null;
217 addURLs(urls);
220 // Package-private to avoid a trampoline constructor.
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.
232 * @param securityContext the security context of the unprivileged code.
234 URLClassLoader(ClassLoader parent, AccessControlContext securityContext)
236 super(parent);
237 this.factory = null;
238 this.securityContext = securityContext;
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
260 public URLClassLoader(URL[] urls, ClassLoader parent,
261 URLStreamHandlerFactory factory)
262 throws SecurityException
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);
272 // Methods
275 * Adds a new location to the end of the internal URL store.
276 * @param newUrl the location to add
278 protected void addURL(URL newUrl)
280 urls.add(newUrl);
281 addURLImpl(newUrl);
284 private void addURLImpl(URL newUrl)
286 synchronized (this)
288 if (newUrl == null)
289 return; // Silently ignore...
291 // Reset the toString() value.
292 thisString = null;
294 // Create a loader for this URL.
295 URLLoader loader = null;
296 String file = newUrl.getFile();
297 String protocol = newUrl.getProtocol();
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))
304 File dir = new File(file);
307 absoluteURL = dir.getCanonicalFile().toURL();
309 catch (IOException ignore)
313 absoluteURL = dir.getAbsoluteFile().toURL();
315 catch (MalformedURLException _)
317 // This really should not happen.
318 absoluteURL = newUrl;
322 else
324 // This doesn't hurt, and it simplifies the logic a
325 // little.
326 absoluteURL = newUrl;
329 // First see if we can find a handler with the correct name.
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 });
346 catch (ClassNotFoundException ignore)
348 // Fall through.
350 catch (NoSuchMethodException nsme)
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;
358 catch (InstantiationException inste)
360 // Programming error in the class library.
361 InternalError vme
362 = new InternalError("couldn't instantiate URLLoader");
363 vme.initCause(inste);
364 throw vme;
366 catch (InvocationTargetException ite)
368 // Programming error in the class library.
369 InternalError vme
370 = new InternalError("error instantiating URLLoader");
371 vme.initCause(ite);
372 throw vme;
374 catch (IllegalAccessException illae)
376 // Programming error in the class library.
377 InternalError vme
378 = new InternalError("invalid access to URLLoader");
379 vme.initCause(illae);
380 throw vme;
383 if (loader == null)
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);
397 urlinfos.add(loader);
398 ArrayList<URLLoader> extra = loader.getClassPath();
399 if (extra != null)
400 urlinfos.addAll(extra);
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.
411 * @param newUrls the locations to add
413 private void addURLs(URL[] newUrls)
415 for (int i = 0; i < newUrls.length; i++)
417 urls.add(newUrls[i]);
418 addURLImpl(newUrls[i]);
423 * Look in both Attributes for a given value. The first Attributes
424 * object, if not null, has precedence.
426 private String getAttributeValue(Attributes.Name name, Attributes first,
427 Attributes second)
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;
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.
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
452 protected Package definePackage(String name, Manifest manifest, URL url)
453 throws IllegalArgumentException
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();
464 Attributes entryAttr = manifest.getAttributes(xformName);
465 Attributes attr = manifest.getMainAttributes();
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);
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;
496 return definePackage(name,
497 specTitle, specVendor, specVersion,
498 implTitle, implVendor, implVersion,
499 url);
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.
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
511 protected Class<?> findClass(final String className)
512 throws ClassNotFoundException
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++)
520 URLLoader loader = (URLLoader)urlinfos.elementAt(i);
521 if (loader == null)
522 continue;
524 Class k = loader.getClass(className);
525 if (k != null)
526 return k;
528 resource = loader.getResource(resourceName);
530 if (resource == null)
531 throw new ClassNotFoundException(className + " not found in " + this);
533 // Try to read the class data, create the CodeSource, Package and
534 // construct the class (and watch out for those nasty IOExceptions)
537 byte[] data;
538 InputStream in = resource.getInputStream();
541 int length = resource.getLength();
542 if (length != -1)
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)
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;
557 else
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)
566 l = in.read(b);
567 if (l != -1)
568 out.write(b, 0, l);
570 data = out.toByteArray();
573 finally
575 in.close();
577 final byte[] classData = data;
579 // Now get the CodeSource
580 final CodeSource source = resource.getCodeSource();
582 // Find out package name
583 String packageName = null;
584 int lastDot = className.lastIndexOf('.');
585 if (lastDot != -1)
586 packageName = className.substring(0, lastDot);
588 if (packageName != null && getPackage(packageName) == null)
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());
600 // And finally construct the class!
601 SecurityManager sm = System.getSecurityManager();
602 Class result = null;
603 if (sm != null && securityContext != null)
605 result = AccessController.doPrivileged
606 (new PrivilegedAction<Class>()
608 public Class run()
610 return defineClass(className, classData,
611 0, classData.length,
612 source);
614 }, securityContext);
616 else
617 result = defineClass(className, classData, 0, classData.length, source);
619 // Avoid NullPointerExceptions.
620 Certificate[] resourceCertificates = resource.getCertificates();
621 if(resourceCertificates != null)
622 super.setSigners(result, resourceCertificates);
624 return result;
626 catch (IOException ioe)
628 throw new ClassNotFoundException(className + " not found in " + this, ioe);
632 // Cached String representation of this URLClassLoader
633 private String thisString;
636 * Returns a String representation of this URLClassLoader giving the
637 * actual Class name, the URLs that are searched and the parent
638 * ClassLoader.
640 public String toString()
642 synchronized (this)
644 if (thisString == null)
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++)
652 sb.append(thisURLs[i]);
653 if (i < thisURLs.length - 1)
654 sb.append(',');
656 sb.append(']');
657 sb.append(", parent=");
658 sb.append(getParent());
659 sb.append('}');
660 thisString = sb.toString();
662 return thisString;
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.
670 * @param resourceName the resource name to look for
671 * @return the URLResource for the resource if found, null otherwise
673 private Resource findURLResource(String resourceName)
675 int max = urlinfos.size();
676 for (int i = 0; i < max; i++)
678 URLLoader loader = (URLLoader) urlinfos.elementAt(i);
679 if (loader == null)
680 continue;
682 Resource resource = loader.getResource(resourceName);
683 if (resource != null)
684 return resource;
686 return null;
690 * Finds the first occurrence of a resource that can be found.
692 * @param resourceName the resource name to look for
693 * @return the URL if found, null otherwise
695 public URL findResource(String resourceName)
697 Resource resource = findURLResource(resourceName);
698 if (resource != null)
699 return resource.getURL();
701 // Resource not found
702 return null;
706 * Finds all the resources with a particular name from all the locations.
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
714 public Enumeration<URL> findResources(String resourceName)
715 throws IOException
717 Vector<URL> resources = new Vector<URL>();
718 int max = urlinfos.size();
719 for (int i = 0; i < max; i++)
721 URLLoader loader = (URLLoader) urlinfos.elementAt(i);
722 Resource resource = loader.getResource(resourceName);
723 if (resource != null)
724 resources.add(resource.getURL());
726 return resources.elements();
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.
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)
749 protected PermissionCollection getPermissions(CodeSource source)
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);
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"))
761 String file = url.getFile();
763 // If the file end in / it must be an directory.
764 if (file.endsWith("/") || file.endsWith(File.separator))
766 // Grant permission to read everything in that directory and
767 // all subdirectories.
768 permissions.add(new FilePermission(file + "-", "read"));
770 else
772 // It is a 'normal' file.
773 // Grant permission to access that file.
774 permissions.add(new FilePermission(file, "read"));
777 else
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"));
785 return permissions;
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
794 public URL[] getURLs()
796 return (URL[]) urls.toArray(new URL[urls.size()]);
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.
804 * @param urls the initial URLs used to resolve classes and
805 * resources
807 * @return the class loader
809 * @exception SecurityException when the calling code does not have
810 * permission to access the given <code>URL</code>s
812 public static URLClassLoader newInstance(URL[] urls)
813 throws SecurityException
815 return newInstance(urls, null);
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.
823 * @param urls the initial URLs used to resolve classes and
824 * resources
825 * @param parent the parent class loader
827 * @return the class loader
829 * @exception SecurityException when the calling code does not have
830 * permission to access the given <code>URL</code>s
832 public static URLClassLoader newInstance(URL[] urls, final ClassLoader parent)
833 throws SecurityException
835 SecurityManager sm = System.getSecurityManager();
836 if (sm == null)
837 return new URLClassLoader(urls, parent);
838 else
840 final Object securityContext = sm.getSecurityContext();
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);
847 URLClassLoader loader =
848 AccessController.doPrivileged(new PrivilegedAction<URLClassLoader>()
850 public URLClassLoader run()
852 return new URLClassLoader(parent,
853 (AccessControlContext) securityContext);
856 loader.addURLs(urls);
857 return loader;