History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/java/net/URLClassLoader.java (1 of 18352 files). Show all

Unified · Split

java/pkg/java/net/URLClassLoader.java+791−0
@@ -0,0 +1,791 @@
1+/*
2+ * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package java.net;
27+
28+import java.lang.reflect.Method;
29+import java.lang.reflect.Modifier;
30+import java.lang.ref.*;
31+import java.io.*;
32+import java.net.URL;
33+import java.net.URLConnection;
34+import java.net.URLStreamHandlerFactory;
35+import java.util.Enumeration;
36+import java.util.*;
37+import java.util.jar.Manifest;
38+import java.util.jar.JarFile;
39+import java.util.jar.Attributes;
40+import java.util.jar.Attributes.Name;
41+import java.security.CodeSigner;
42+import java.security.PrivilegedAction;
43+import java.security.PrivilegedExceptionAction;
44+import java.security.AccessController;
45+import java.security.AccessControlContext;
46+import java.security.SecureClassLoader;
47+import java.security.CodeSource;
48+import java.security.Permission;
49+import java.security.PermissionCollection;
50+import sun.misc.Resource;
51+import sun.misc.URLClassPath;
52+import sun.net.www.ParseUtil;
53+import sun.security.util.SecurityConstants;
54+
55+/**
56+ * This class loader is used to load classes and resources from a search
57+ * path of URLs referring to both JAR files and directories. Any URL that
58+ * ends with a '/' is assumed to refer to a directory. Otherwise, the URL
59+ * is assumed to refer to a JAR file which will be opened as needed.
60+ * <p>
61+ * The AccessControlContext of the thread that created the instance of
62+ * URLClassLoader will be used when subsequently loading classes and
63+ * resources.
64+ * <p>
65+ * The classes that are loaded are by default granted permission only to
66+ * access the URLs specified when the URLClassLoader was created.
67+ *
68+ * @author David Connelly
69+ * @since 1.2
70+ */
71+public class URLClassLoader extends SecureClassLoader implements Closeable {
72+ /* The search path for classes and resources */
73+ private final URLClassPath ucp;
74+
75+ /* The context to be used when loading classes and resources */
76+ private final AccessControlContext acc;
77+
78+ /**
79+ * Constructs a new URLClassLoader for the given URLs. The URLs will be
80+ * searched in the order specified for classes and resources after first
81+ * searching in the specified parent class loader. Any URL that ends with
82+ * a '/' is assumed to refer to a directory. Otherwise, the URL is assumed
83+ * to refer to a JAR file which will be downloaded and opened as needed.
84+ *
85+ * <p>If there is a security manager, this method first
86+ * calls the security manager's {@code checkCreateClassLoader} method
87+ * to ensure creation of a class loader is allowed.
88+ *
89+ * @param urls the URLs from which to load classes and resources
90+ * @param parent the parent class loader for delegation
91+ * @exception SecurityException if a security manager exists and its
92+ * {@code checkCreateClassLoader} method doesn't allow
93+ * creation of a class loader.
94+ * @see SecurityManager#checkCreateClassLoader
95+ */
96+ public URLClassLoader(URL[] urls, ClassLoader parent) {
97+ super(parent);
98+ // this is to make the stack depth consistent with 1.1
99+ SecurityManager security = System.getSecurityManager();
100+ if (security != null) {
101+ security.checkCreateClassLoader();
102+ }
103+ ucp = new URLClassPath(urls);
104+ this.acc = AccessController.getContext();
105+ }
106+
107+ URLClassLoader(URL[] urls, ClassLoader parent,
108+ AccessControlContext acc) {
109+ super(parent);
110+ // this is to make the stack depth consistent with 1.1
111+ SecurityManager security = System.getSecurityManager();
112+ if (security != null) {
113+ security.checkCreateClassLoader();
114+ }
115+ ucp = new URLClassPath(urls);
116+ this.acc = acc;
117+ }
118+
119+ /**
120+ * Constructs a new URLClassLoader for the specified URLs using the
121+ * default delegation parent <code>ClassLoader</code>. The URLs will
122+ * be searched in the order specified for classes and resources after
123+ * first searching in the parent class loader. Any URL that ends with
124+ * a '/' is assumed to refer to a directory. Otherwise, the URL is
125+ * assumed to refer to a JAR file which will be downloaded and opened
126+ * as needed.
127+ *
128+ * <p>If there is a security manager, this method first
129+ * calls the security manager's <code>checkCreateClassLoader</code> method
130+ * to ensure creation of a class loader is allowed.
131+ *
132+ * @param urls the URLs from which to load classes and resources
133+ *
134+ * @exception SecurityException if a security manager exists and its
135+ * <code>checkCreateClassLoader</code> method doesn't allow
136+ * creation of a class loader.
137+ * @see SecurityManager#checkCreateClassLoader
138+ */
139+ public URLClassLoader(URL[] urls) {
140+ super();
141+ // this is to make the stack depth consistent with 1.1
142+ SecurityManager security = System.getSecurityManager();
143+ if (security != null) {
144+ security.checkCreateClassLoader();
145+ }
146+ ucp = new URLClassPath(urls);
147+ this.acc = AccessController.getContext();
148+ }
149+
150+ URLClassLoader(URL[] urls, AccessControlContext acc) {
151+ super();
152+ // this is to make the stack depth consistent with 1.1
153+ SecurityManager security = System.getSecurityManager();
154+ if (security != null) {
155+ security.checkCreateClassLoader();
156+ }
157+ ucp = new URLClassPath(urls);
158+ this.acc = acc;
159+ }
160+
161+ /**
162+ * Constructs a new URLClassLoader for the specified URLs, parent
163+ * class loader, and URLStreamHandlerFactory. The parent argument
164+ * will be used as the parent class loader for delegation. The
165+ * factory argument will be used as the stream handler factory to
166+ * obtain protocol handlers when creating new jar URLs.
167+ *
168+ * <p>If there is a security manager, this method first
169+ * calls the security manager's <code>checkCreateClassLoader</code> method
170+ * to ensure creation of a class loader is allowed.
171+ *
172+ * @param urls the URLs from which to load classes and resources
173+ * @param parent the parent class loader for delegation
174+ * @param factory the URLStreamHandlerFactory to use when creating URLs
175+ *
176+ * @exception SecurityException if a security manager exists and its
177+ * <code>checkCreateClassLoader</code> method doesn't allow
178+ * creation of a class loader.
179+ * @see SecurityManager#checkCreateClassLoader
180+ */
181+ public URLClassLoader(URL[] urls, ClassLoader parent,
182+ URLStreamHandlerFactory factory) {
183+ super(parent);
184+ // this is to make the stack depth consistent with 1.1
185+ SecurityManager security = System.getSecurityManager();
186+ if (security != null) {
187+ security.checkCreateClassLoader();
188+ }
189+ ucp = new URLClassPath(urls, factory);
190+ acc = AccessController.getContext();
191+ }
192+
193+ /* A map (used as a set) to keep track of closeable local resources
194+ * (either JarFiles or FileInputStreams). We don't care about
195+ * Http resources since they don't need to be closed.
196+ *
197+ * If the resource is coming from a jar file
198+ * we keep a (weak) reference to the JarFile object which can
199+ * be closed if URLClassLoader.close() called. Due to jar file
200+ * caching there will typically be only one JarFile object
201+ * per underlying jar file.
202+ *
203+ * For file resources, which is probably a less common situation
204+ * we have to keep a weak reference to each stream.
205+ */
206+
207+ private WeakHashMap<Closeable,Void>
208+ closeables = new WeakHashMap<>();
209+
210+ /**
211+ * Returns an input stream for reading the specified resource.
212+ * If this loader is closed, then any resources opened by this method
213+ * will be closed.
214+ *
215+ * <p> The search order is described in the documentation for {@link
216+ * #getResource(String)}. </p>
217+ *
218+ * @param name
219+ * The resource name
220+ *
221+ * @return An input stream for reading the resource, or <tt>null</tt>
222+ * if the resource could not be found
223+ *
224+ * @since 1.7
225+ */
226+ public InputStream getResourceAsStream(String name) {
227+ URL url = getResource(name);
228+ try {
229+ if (url == null) {
230+ return null;
231+ }
232+ URLConnection urlc = url.openConnection();
233+ InputStream is = urlc.getInputStream();
234+ if (urlc instanceof JarURLConnection) {
235+ JarURLConnection juc = (JarURLConnection)urlc;
236+ JarFile jar = juc.getJarFile();
237+ synchronized (closeables) {
238+ if (!closeables.containsKey(jar)) {
239+ closeables.put(jar, null);
240+ }
241+ }
242+ } else if (urlc instanceof sun.net.www.protocol.file.FileURLConnection) {
243+ synchronized (closeables) {
244+ closeables.put(is, null);
245+ }
246+ }
247+ return is;
248+ } catch (IOException e) {
249+ return null;
250+ }
251+ }
252+
253+ /**
254+ * Closes this URLClassLoader, so that it can no longer be used to load
255+ * new classes or resources that are defined by this loader.
256+ * Classes and resources defined by any of this loader's parents in the
257+ * delegation hierarchy are still accessible. Also, any classes or resources
258+ * that are already loaded, are still accessible.
259+ * <p>
260+ * In the case of jar: and file: URLs, it also closes any files
261+ * that were opened by it. If another thread is loading a
262+ * class when the {@code close} method is invoked, then the result of
263+ * that load is undefined.
264+ * <p>
265+ * The method makes a best effort attempt to close all opened files,
266+ * by catching {@link IOException}s internally. Unchecked exceptions
267+ * and errors are not caught. Calling close on an already closed
268+ * loader has no effect.
269+ * <p>
270+ * @throws IOException if closing any file opened by this class loader
271+ * resulted in an IOException. Any such exceptions are caught internally.
272+ * If only one is caught, then it is re-thrown. If more than one exception
273+ * is caught, then the second and following exceptions are added
274+ * as suppressed exceptions of the first one caught, which is then re-thrown.
275+ *
276+ * @throws SecurityException if a security manager is set, and it denies
277+ * {@link RuntimePermission}<tt>("closeClassLoader")</tt>
278+ *
279+ * @since 1.7
280+ */
281+ public void close() throws IOException {
282+ SecurityManager security = System.getSecurityManager();
283+ if (security != null) {
284+ security.checkPermission(new RuntimePermission("closeClassLoader"));
285+ }
286+ List<IOException> errors = ucp.closeLoaders();
287+
288+ // now close any remaining streams.
289+
290+ synchronized (closeables) {
291+ Set<Closeable> keys = closeables.keySet();
292+ for (Closeable c : keys) {
293+ try {
294+ c.close();
295+ } catch (IOException ioex) {
296+ errors.add(ioex);
297+ }
298+ }
299+ closeables.clear();
300+ }
301+
302+ if (errors.isEmpty()) {
303+ return;
304+ }
305+
306+ IOException firstex = errors.remove(0);
307+
308+ // Suppress any remaining exceptions
309+
310+ for (IOException error: errors) {
311+ firstex.addSuppressed(error);
312+ }
313+ throw firstex;
314+ }
315+
316+ /**
317+ * Appends the specified URL to the list of URLs to search for
318+ * classes and resources.
319+ * <p>
320+ * If the URL specified is <code>null</code> or is already in the
321+ * list of URLs, or if this loader is closed, then invoking this
322+ * method has no effect.
323+ *
324+ * @param url the URL to be added to the search path of URLs
325+ */
326+ protected void addURL(URL url) {
327+ ucp.addURL(url);
328+ }
329+
330+ /**
331+ * Returns the search path of URLs for loading classes and resources.
332+ * This includes the original list of URLs specified to the constructor,
333+ * along with any URLs subsequently appended by the addURL() method.
334+ * @return the search path of URLs for loading classes and resources.
335+ */
336+ public URL[] getURLs() {
337+ return ucp.getURLs();
338+ }
339+
340+ /**
341+ * Finds and loads the class with the specified name from the URL search
342+ * path. Any URLs referring to JAR files are loaded and opened as needed
343+ * until the class is found.
344+ *
345+ * @param name the name of the class
346+ * @return the resulting class
347+ * @exception ClassNotFoundException if the class could not be found,
348+ * or if the loader is closed.
349+ */
350+ protected Class<?> findClass(final String name)
351+ throws ClassNotFoundException
352+ {
353+ try {
354+ return AccessController.doPrivileged(
355+ new PrivilegedExceptionAction<Class>() {
356+ public Class run() throws ClassNotFoundException {
357+ String path = name.replace('.', '/').concat(".class");
358+ Resource res = ucp.getResource(path, false);
359+ if (res != null) {
360+ try {
361+ return defineClass(name, res);
362+ } catch (IOException e) {
363+ throw new ClassNotFoundException(name, e);
364+ }
365+ } else {
366+ throw new ClassNotFoundException(name);
367+ }
368+ }
369+ }, acc);
370+ } catch (java.security.PrivilegedActionException pae) {
371+ throw (ClassNotFoundException) pae.getException();
372+ }
373+ }
374+
375+ /*
376+ * Retrieve the package using the specified package name.
377+ * If non-null, verify the package using the specified code
378+ * source and manifest.
379+ */
380+ private Package getAndVerifyPackage(String pkgname,
381+ Manifest man, URL url) {
382+ Package pkg = getPackage(pkgname);
383+ if (pkg != null) {
384+ // Package found, so check package sealing.
385+ if (pkg.isSealed()) {
386+ // Verify that code source URL is the same.
387+ if (!pkg.isSealed(url)) {
388+ throw new SecurityException(
389+ "sealing violation: package " + pkgname + " is sealed");
390+ }
391+ } else {
392+ // Make sure we are not attempting to seal the package
393+ // at this code source URL.
394+ if ((man != null) && isSealed(pkgname, man)) {
395+ throw new SecurityException(
396+ "sealing violation: can't seal package " + pkgname +
397+ ": already loaded");
398+ }
399+ }
400+ }
401+ return pkg;
402+ }
403+
404+ /*
405+ * Defines a Class using the class bytes obtained from the specified
406+ * Resource. The resulting Class must be resolved before it can be
407+ * used.
408+ */
409+ private Class defineClass(String name, Resource res) throws IOException {
410+ long t0 = System.nanoTime();
411+ int i = name.lastIndexOf('.');
412+ URL url = res.getCodeSourceURL();
413+ if (i != -1) {
414+ String pkgname = name.substring(0, i);
415+ // Check if package already loaded.
416+ Manifest man = res.getManifest();
417+ if (getAndVerifyPackage(pkgname, man, url) == null) {
418+ try {
419+ if (man != null) {
420+ definePackage(pkgname, man, url);
421+ } else {
422+ definePackage(pkgname, null, null, null, null, null, null, null);
423+ }
424+ } catch (IllegalArgumentException iae) {
425+ // parallel-capable class loaders: re-verify in case of a
426+ // race condition
427+ if (getAndVerifyPackage(pkgname, man, url) == null) {
428+ // Should never happen
429+ throw new AssertionError("Cannot find package " +
430+ pkgname);
431+ }
432+ }
433+ }
434+ }
435+ // Now read the class bytes and define the class
436+ java.nio.ByteBuffer bb = res.getByteBuffer();
437+ if (bb != null) {
438+ // Use (direct) ByteBuffer:
439+ CodeSigner[] signers = res.getCodeSigners();
440+ CodeSource cs = new CodeSource(url, signers);
441+ sun.misc.PerfCounter.getReadClassBytesTime().addElapsedTimeFrom(t0);
442+ return defineClass(name, bb, cs);
443+ } else {
444+ byte[] b = res.getBytes();
445+ // must read certificates AFTER reading bytes.
446+ CodeSigner[] signers = res.getCodeSigners();
447+ CodeSource cs = new CodeSource(url, signers);
448+ sun.misc.PerfCounter.getReadClassBytesTime().addElapsedTimeFrom(t0);
449+ return defineClass(name, b, 0, b.length, cs);
450+ }
451+ }
452+
453+ /**
454+ * Defines a new package by name in this ClassLoader. The attributes
455+ * contained in the specified Manifest will be used to obtain package
456+ * version and sealing information. For sealed packages, the additional
457+ * URL specifies the code source URL from which the package was loaded.
458+ *
459+ * @param name the package name
460+ * @param man the Manifest containing package version and sealing
461+ * information
462+ * @param url the code source url for the package, or null if none
463+ * @exception IllegalArgumentException if the package name duplicates
464+ * an existing package either in this class loader or one
465+ * of its ancestors
466+ * @return the newly defined Package object
467+ */
468+ protected Package definePackage(String name, Manifest man, URL url)
469+ throws IllegalArgumentException
470+ {
471+ String path = name.replace('.', '/').concat("/");
472+ String specTitle = null, specVersion = null, specVendor = null;
473+ String implTitle = null, implVersion = null, implVendor = null;
474+ String sealed = null;
475+ URL sealBase = null;
476+
477+ Attributes attr = man.getAttributes(path);
478+ if (attr != null) {
479+ specTitle = attr.getValue(Name.SPECIFICATION_TITLE);
480+ specVersion = attr.getValue(Name.SPECIFICATION_VERSION);
481+ specVendor = attr.getValue(Name.SPECIFICATION_VENDOR);
482+ implTitle = attr.getValue(Name.IMPLEMENTATION_TITLE);
483+ implVersion = attr.getValue(Name.IMPLEMENTATION_VERSION);
484+ implVendor = attr.getValue(Name.IMPLEMENTATION_VENDOR);
485+ sealed = attr.getValue(Name.SEALED);
486+ }
487+ attr = man.getMainAttributes();
488+ if (attr != null) {
489+ if (specTitle == null) {
490+ specTitle = attr.getValue(Name.SPECIFICATION_TITLE);
491+ }
492+ if (specVersion == null) {
493+ specVersion = attr.getValue(Name.SPECIFICATION_VERSION);
494+ }
495+ if (specVendor == null) {
496+ specVendor = attr.getValue(Name.SPECIFICATION_VENDOR);
497+ }
498+ if (implTitle == null) {
499+ implTitle = attr.getValue(Name.IMPLEMENTATION_TITLE);
500+ }
501+ if (implVersion == null) {
502+ implVersion = attr.getValue(Name.IMPLEMENTATION_VERSION);
503+ }
504+ if (implVendor == null) {
505+ implVendor = attr.getValue(Name.IMPLEMENTATION_VENDOR);
506+ }
507+ if (sealed == null) {
508+ sealed = attr.getValue(Name.SEALED);
509+ }
510+ }
511+ if ("true".equalsIgnoreCase(sealed)) {
512+ sealBase = url;
513+ }
514+ return definePackage(name, specTitle, specVersion, specVendor,
515+ implTitle, implVersion, implVendor, sealBase);
516+ }
517+
518+ /*
519+ * Returns true if the specified package name is sealed according to the
520+ * given manifest.
521+ */
522+ private boolean isSealed(String name, Manifest man) {
523+ String path = name.replace('.', '/').concat("/");
524+ Attributes attr = man.getAttributes(path);
525+ String sealed = null;
526+ if (attr != null) {
527+ sealed = attr.getValue(Name.SEALED);
528+ }
529+ if (sealed == null) {
530+ if ((attr = man.getMainAttributes()) != null) {
531+ sealed = attr.getValue(Name.SEALED);
532+ }
533+ }
534+ return "true".equalsIgnoreCase(sealed);
535+ }
536+
537+ /**
538+ * Finds the resource with the specified name on the URL search path.
539+ *
540+ * @param name the name of the resource
541+ * @return a <code>URL</code> for the resource, or <code>null</code>
542+ * if the resource could not be found, or if the loader is closed.
543+ */
544+ public URL findResource(final String name) {
545+ /*
546+ * The same restriction to finding classes applies to resources
547+ */
548+ URL url = AccessController.doPrivileged(
549+ new PrivilegedAction<URL>() {
550+ public URL run() {
551+ return ucp.findResource(name, true);
552+ }
553+ }, acc);
554+
555+ return url != null ? ucp.checkURL(url) : null;
556+ }
557+
558+ /**
559+ * Returns an Enumeration of URLs representing all of the resources
560+ * on the URL search path having the specified name.
561+ *
562+ * @param name the resource name
563+ * @exception IOException if an I/O exception occurs
564+ * @return an <code>Enumeration</code> of <code>URL</code>s
565+ * If the loader is closed, the Enumeration will be empty.
566+ */
567+ public Enumeration<URL> findResources(final String name)
568+ throws IOException
569+ {
570+ final Enumeration<URL> e = ucp.findResources(name, true);
571+
572+ return new Enumeration<URL>() {
573+ private URL url = null;
574+
575+ private boolean next() {
576+ if (url != null) {
577+ return true;
578+ }
579+ do {
580+ URL u = AccessController.doPrivileged(
581+ new PrivilegedAction<URL>() {
582+ public URL run() {
583+ if (!e.hasMoreElements())
584+ return null;
585+ return e.nextElement();
586+ }
587+ }, acc);
588+ if (u == null)
589+ break;
590+ url = ucp.checkURL(u);
591+ } while (url == null);
592+ return url != null;
593+ }
594+
595+ public URL nextElement() {
596+ if (!next()) {
597+ throw new NoSuchElementException();
598+ }
599+ URL u = url;
600+ url = null;
601+ return u;
602+ }
603+
604+ public boolean hasMoreElements() {
605+ return next();
606+ }
607+ };
608+ }
609+
610+ /**
611+ * Returns the permissions for the given codesource object.
612+ * The implementation of this method first calls super.getPermissions
613+ * and then adds permissions based on the URL of the codesource.
614+ * <p>
615+ * If the protocol of this URL is "jar", then the permission granted
616+ * is based on the permission that is required by the URL of the Jar
617+ * file.
618+ * <p>
619+ * If the protocol is "file" and there is an authority component, then
620+ * permission to connect to and accept connections from that authority
621+ * may be granted. If the protocol is "file"
622+ * and the path specifies a file, then permission to read that
623+ * file is granted. If protocol is "file" and the path is
624+ * a directory, permission is granted to read all files
625+ * and (recursively) all files and subdirectories contained in
626+ * that directory.
627+ * <p>
628+ * If the protocol is not "file", then permission
629+ * to connect to and accept connections from the URL's host is granted.
630+ * @param codesource the codesource
631+ * @return the permissions granted to the codesource
632+ */
633+ protected PermissionCollection getPermissions(CodeSource codesource)
634+ {
635+ PermissionCollection perms = super.getPermissions(codesource);
636+
637+ URL url = codesource.getLocation();
638+
639+ Permission p;
640+ URLConnection urlConnection;
641+
642+ try {
643+ urlConnection = url.openConnection();
644+ p = urlConnection.getPermission();
645+ } catch (java.io.IOException ioe) {
646+ p = null;
647+ urlConnection = null;
648+ }
649+
650+ if (p instanceof FilePermission) {
651+ // if the permission has a separator char on the end,
652+ // it means the codebase is a directory, and we need
653+ // to add an additional permission to read recursively
654+ String path = p.getName();
655+ if (path.endsWith(File.separator)) {
656+ path += "-";
657+ p = new FilePermission(path, SecurityConstants.FILE_READ_ACTION);
658+ }
659+ } else if ((p == null) && (url.getProtocol().equals("file"))) {
660+ String path = url.getFile().replace('/', File.separatorChar);
661+ path = ParseUtil.decode(path);
662+ if (path.endsWith(File.separator))
663+ path += "-";
664+ p = new FilePermission(path, SecurityConstants.FILE_READ_ACTION);
665+ } else {
666+ /**
667+ * Not loading from a 'file:' URL so we want to give the class
668+ * permission to connect to and accept from the remote host
669+ * after we've made sure the host is the correct one and is valid.
670+ */
671+ URL locUrl = url;
672+ if (urlConnection instanceof JarURLConnection) {
673+ locUrl = ((JarURLConnection)urlConnection).getJarFileURL();
674+ }
675+ String host = locUrl.getHost();
676+ if (host != null && (host.length() > 0))
677+ p = new SocketPermission(host,
678+ SecurityConstants.SOCKET_CONNECT_ACCEPT_ACTION);
679+ }
680+
681+ // make sure the person that created this class loader
682+ // would have this permission
683+
684+ if (p != null) {
685+ final SecurityManager sm = System.getSecurityManager();
686+ if (sm != null) {
687+ final Permission fp = p;
688+ AccessController.doPrivileged(new PrivilegedAction<Void>() {
689+ public Void run() throws SecurityException {
690+ sm.checkPermission(fp);
691+ return null;
692+ }
693+ }, acc);
694+ }
695+ perms.add(p);
696+ }
697+ return perms;
698+ }
699+
700+ /**
701+ * Creates a new instance of URLClassLoader for the specified
702+ * URLs and parent class loader. If a security manager is
703+ * installed, the <code>loadClass</code> method of the URLClassLoader
704+ * returned by this method will invoke the
705+ * <code>SecurityManager.checkPackageAccess</code> method before
706+ * loading the class.
707+ *
708+ * @param urls the URLs to search for classes and resources
709+ * @param parent the parent class loader for delegation
710+ * @return the resulting class loader
711+ */
712+ public static URLClassLoader newInstance(final URL[] urls,
713+ final ClassLoader parent) {
714+ // Save the caller's context
715+ final AccessControlContext acc = AccessController.getContext();
716+ // Need a privileged block to create the class loader
717+ URLClassLoader ucl = AccessController.doPrivileged(
718+ new PrivilegedAction<URLClassLoader>() {
719+ public URLClassLoader run() {
720+ return new FactoryURLClassLoader(urls, parent, acc);
721+ }
722+ });
723+ return ucl;
724+ }
725+
726+ /**
727+ * Creates a new instance of URLClassLoader for the specified
728+ * URLs and default parent class loader. If a security manager is
729+ * installed, the <code>loadClass</code> method of the URLClassLoader
730+ * returned by this method will invoke the
731+ * <code>SecurityManager.checkPackageAccess</code> before
732+ * loading the class.
733+ *
734+ * @param urls the URLs to search for classes and resources
735+ * @return the resulting class loader
736+ */
737+ public static URLClassLoader newInstance(final URL[] urls) {
738+ // Save the caller's context
739+ final AccessControlContext acc = AccessController.getContext();
740+ // Need a privileged block to create the class loader
741+ URLClassLoader ucl = AccessController.doPrivileged(
742+ new PrivilegedAction<URLClassLoader>() {
743+ public URLClassLoader run() {
744+ return new FactoryURLClassLoader(urls, acc);
745+ }
746+ });
747+ return ucl;
748+ }
749+
750+ static {
751+ sun.misc.SharedSecrets.setJavaNetAccess (
752+ new sun.misc.JavaNetAccess() {
753+ public URLClassPath getURLClassPath (URLClassLoader u) {
754+ return u.ucp;
755+ }
756+ }
757+ );
758+ ClassLoader.registerAsParallelCapable();
759+ }
760+}
761+
762+final class FactoryURLClassLoader extends URLClassLoader {
763+
764+ static {
765+ ClassLoader.registerAsParallelCapable();
766+ }
767+
768+ FactoryURLClassLoader(URL[] urls, ClassLoader parent,
769+ AccessControlContext acc) {
770+ super(urls, parent, acc);
771+ }
772+
773+ FactoryURLClassLoader(URL[] urls, AccessControlContext acc) {
774+ super(urls, acc);
775+ }
776+
777+ public final Class loadClass(String name, boolean resolve)
778+ throws ClassNotFoundException
779+ {
780+ // First check if we have permission to access the package. This
781+ // should go away once we've added support for exported packages.
782+ SecurityManager sm = System.getSecurityManager();
783+ if (sm != null) {
784+ int i = name.lastIndexOf('.');
785+ if (i != -1) {
786+ sm.checkPackageAccess(name.substring(0, i));
787+ }
788+ }
789+ return super.loadClass(name, resolve);
790+ }
791+}