Save This Page
Home » openjdk-7 » java » net » [javadoc | source]
    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   }

Save This Page
Home » openjdk-7 » java » net » [javadoc | source]