Save This Page
Home » openjdk-7 » sun » misc » [javadoc | source]
    1   /*
    2    * Copyright (c) 1998, 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 sun.misc;
   27   
   28   import java.io.File;
   29   import java.io.IOException;
   30   import java.io.FilePermission;
   31   import java.net.URL;
   32   import java.net.URLClassLoader;
   33   import java.net.MalformedURLException;
   34   import java.net.URLStreamHandler;
   35   import java.net.URLStreamHandlerFactory;
   36   import java.util.HashSet;
   37   import java.util.StringTokenizer;
   38   import java.util.Set;
   39   import java.util.Vector;
   40   import java.security.AccessController;
   41   import java.security.PrivilegedAction;
   42   import java.security.PrivilegedExceptionAction;
   43   import java.security.AccessControlContext;
   44   import java.security.PermissionCollection;
   45   import java.security.Permissions;
   46   import java.security.Permission;
   47   import java.security.ProtectionDomain;
   48   import java.security.CodeSource;
   49   import sun.security.util.SecurityConstants;
   50   import sun.net.www.ParseUtil;
   51   
   52   /**
   53    * This class is used by the system to launch the main application.
   54   Launcher */
   55   public class Launcher {
   56       private static URLStreamHandlerFactory factory = new Factory();
   57       private static Launcher launcher = new Launcher();
   58       private static String bootClassPath =
   59           System.getProperty("sun.boot.class.path");
   60   
   61       public static Launcher getLauncher() {
   62           return launcher;
   63       }
   64   
   65       private ClassLoader loader;
   66   
   67       public Launcher() {
   68           // Create the extension class loader
   69           ClassLoader extcl;
   70           try {
   71               extcl = ExtClassLoader.getExtClassLoader();
   72           } catch (IOException e) {
   73               throw new InternalError(
   74                   "Could not create extension class loader");
   75           }
   76   
   77           // Now create the class loader to use to launch the application
   78           try {
   79               loader = AppClassLoader.getAppClassLoader(extcl);
   80           } catch (IOException e) {
   81               throw new InternalError(
   82                   "Could not create application class loader");
   83           }
   84   
   85           // Also set the context class loader for the primordial thread.
   86           Thread.currentThread().setContextClassLoader(loader);
   87   
   88           // Finally, install a security manager if requested
   89           String s = System.getProperty("java.security.manager");
   90           if (s != null) {
   91               SecurityManager sm = null;
   92               if ("".equals(s) || "default".equals(s)) {
   93                   sm = new java.lang.SecurityManager();
   94               } else {
   95                   try {
   96                       sm = (SecurityManager)loader.loadClass(s).newInstance();
   97                   } catch (IllegalAccessException e) {
   98                   } catch (InstantiationException e) {
   99                   } catch (ClassNotFoundException e) {
  100                   } catch (ClassCastException e) {
  101                   }
  102               }
  103               if (sm != null) {
  104                   System.setSecurityManager(sm);
  105               } else {
  106                   throw new InternalError(
  107                       "Could not create SecurityManager: " + s);
  108               }
  109           }
  110       }
  111   
  112       /*
  113        * Returns the class loader used to launch the main application.
  114        */
  115       public ClassLoader getClassLoader() {
  116           return loader;
  117       }
  118   
  119       /*
  120        * The class loader used for loading installed extensions.
  121        */
  122       static class ExtClassLoader extends URLClassLoader {
  123   
  124           static {
  125               ClassLoader.registerAsParallelCapable();
  126           }
  127   
  128           /**
  129            * create an ExtClassLoader. The ExtClassLoader is created
  130            * within a context that limits which files it can read
  131            */
  132           public static ExtClassLoader getExtClassLoader() throws IOException
  133           {
  134               final File[] dirs = getExtDirs();
  135   
  136               try {
  137                   // Prior implementations of this doPrivileged() block supplied
  138                   // aa synthesized ACC via a call to the private method
  139                   // ExtClassLoader.getContext().
  140   
  141                   return AccessController.doPrivileged(
  142                       new PrivilegedExceptionAction<ExtClassLoader>() {
  143                           public ExtClassLoader run() throws IOException {
  144                               int len = dirs.length;
  145                               for (int i = 0; i < len; i++) {
  146                                   MetaIndex.registerDirectory(dirs[i]);
  147                               }
  148                               return new ExtClassLoader(dirs);
  149                           }
  150                       });
  151               } catch (java.security.PrivilegedActionException e) {
  152                   throw (IOException) e.getException();
  153               }
  154           }
  155   
  156           void addExtURL(URL url) {
  157               super.addURL(url);
  158           }
  159   
  160           /*
  161            * Creates a new ExtClassLoader for the specified directories.
  162            */
  163           public ExtClassLoader(File[] dirs) throws IOException {
  164               super(getExtURLs(dirs), null, factory);
  165           }
  166   
  167           private static File[] getExtDirs() {
  168               String s = System.getProperty("java.ext.dirs");
  169               File[] dirs;
  170               if (s != null) {
  171                   StringTokenizer st =
  172                       new StringTokenizer(s, File.pathSeparator);
  173                   int count = st.countTokens();
  174                   dirs = new File[count];
  175                   for (int i = 0; i < count; i++) {
  176                       dirs[i] = new File(st.nextToken());
  177                   }
  178               } else {
  179                   dirs = new File[0];
  180               }
  181               return dirs;
  182           }
  183   
  184           private static URL[] getExtURLs(File[] dirs) throws IOException {
  185               Vector<URL> urls = new Vector<URL>();
  186               for (int i = 0; i < dirs.length; i++) {
  187                   String[] files = dirs[i].list();
  188                   if (files != null) {
  189                       for (int j = 0; j < files.length; j++) {
  190                           if (!files[j].equals("meta-index")) {
  191                               File f = new File(dirs[i], files[j]);
  192                               urls.add(getFileURL(f));
  193                           }
  194                       }
  195                   }
  196               }
  197               URL[] ua = new URL[urls.size()];
  198               urls.copyInto(ua);
  199               return ua;
  200           }
  201   
  202           /*
  203            * Searches the installed extension directories for the specified
  204            * library name. For each extension directory, we first look for
  205            * the native library in the subdirectory whose name is the value
  206            * of the system property <code>os.arch</code>. Failing that, we
  207            * look in the extension directory itself.
  208            */
  209           public String findLibrary(String name) {
  210               name = System.mapLibraryName(name);
  211               URL[] urls = super.getURLs();
  212               File prevDir = null;
  213               for (int i = 0; i < urls.length; i++) {
  214                   // Get the ext directory from the URL
  215                   File dir = new File(urls[i].getPath()).getParentFile();
  216                   if (dir != null && !dir.equals(prevDir)) {
  217                       // Look in architecture-specific subdirectory first
  218                       // Read from the saved system properties to avoid deadlock
  219                       String arch = VM.getSavedProperty("os.arch");
  220                       if (arch != null) {
  221                           File file = new File(new File(dir, arch), name);
  222                           if (file.exists()) {
  223                               return file.getAbsolutePath();
  224                           }
  225                       }
  226                       // Then check the extension directory
  227                       File file = new File(dir, name);
  228                       if (file.exists()) {
  229                           return file.getAbsolutePath();
  230                       }
  231                   }
  232                   prevDir = dir;
  233               }
  234               return null;
  235           }
  236   
  237           private static AccessControlContext getContext(File[] dirs)
  238               throws IOException
  239           {
  240               PathPermissions perms =
  241                   new PathPermissions(dirs);
  242   
  243               ProtectionDomain domain = new ProtectionDomain(
  244                   new CodeSource(perms.getCodeBase(),
  245                       (java.security.cert.Certificate[]) null),
  246                   perms);
  247   
  248               AccessControlContext acc =
  249                   new AccessControlContext(new ProtectionDomain[] { domain });
  250   
  251               return acc;
  252           }
  253       }
  254   
  255       /**
  256        * The class loader used for loading from java.class.path.
  257        * runs in a restricted security context.
  258        */
  259       static class AppClassLoader extends URLClassLoader {
  260   
  261           static {
  262               ClassLoader.registerAsParallelCapable();
  263           }
  264   
  265           public static ClassLoader getAppClassLoader(final ClassLoader extcl)
  266               throws IOException
  267           {
  268               final String s = System.getProperty("java.class.path");
  269               final File[] path = (s == null) ? new File[0] : getClassPath(s);
  270   
  271               // Note: on bugid 4256530
  272               // Prior implementations of this doPrivileged() block supplied
  273               // a rather restrictive ACC via a call to the private method
  274               // AppClassLoader.getContext(). This proved overly restrictive
  275               // when loading  classes. Specifically it prevent
  276               // accessClassInPackage.sun.* grants from being honored.
  277               //
  278               return AccessController.doPrivileged(
  279                   new PrivilegedAction<AppClassLoader>() {
  280                       public AppClassLoader run() {
  281                       URL[] urls =
  282                           (s == null) ? new URL[0] : pathToURLs(path);
  283                       return new AppClassLoader(urls, extcl);
  284                   }
  285               });
  286           }
  287   
  288           /*
  289            * Creates a new AppClassLoader
  290            */
  291           AppClassLoader(URL[] urls, ClassLoader parent) {
  292               super(urls, parent, factory);
  293           }
  294   
  295           /**
  296            * Override loadClass so we can checkPackageAccess.
  297            */
  298           public Class loadClass(String name, boolean resolve)
  299               throws ClassNotFoundException
  300           {
  301               int i = name.lastIndexOf('.');
  302               if (i != -1) {
  303                   SecurityManager sm = System.getSecurityManager();
  304                   if (sm != null) {
  305                       sm.checkPackageAccess(name.substring(0, i));
  306                   }
  307               }
  308               return (super.loadClass(name, resolve));
  309           }
  310   
  311           /**
  312            * allow any classes loaded from classpath to exit the VM.
  313            */
  314           protected PermissionCollection getPermissions(CodeSource codesource)
  315           {
  316               PermissionCollection perms = super.getPermissions(codesource);
  317               perms.add(new RuntimePermission("exitVM"));
  318               return perms;
  319           }
  320   
  321           /**
  322            * This class loader supports dynamic additions to the class path
  323            * at runtime.
  324            *
  325            * @see java.lang.instrument.Instrumentation#appendToSystemClassPathSearch
  326            */
  327           private void appendToClassPathForInstrumentation(String path) {
  328               assert(Thread.holdsLock(this));
  329   
  330               // addURL is a no-op if path already contains the URL
  331               super.addURL( getFileURL(new File(path)) );
  332           }
  333   
  334           /**
  335            * create a context that can read any directories (recursively)
  336            * mentioned in the class path. In the case of a jar, it has to
  337            * be the directory containing the jar, not just the jar, as jar
  338            * files might refer to other jar files.
  339            */
  340   
  341           private static AccessControlContext getContext(File[] cp)
  342               throws java.net.MalformedURLException
  343           {
  344               PathPermissions perms =
  345                   new PathPermissions(cp);
  346   
  347               ProtectionDomain domain =
  348                   new ProtectionDomain(new CodeSource(perms.getCodeBase(),
  349                       (java.security.cert.Certificate[]) null),
  350                   perms);
  351   
  352               AccessControlContext acc =
  353                   new AccessControlContext(new ProtectionDomain[] { domain });
  354   
  355               return acc;
  356           }
  357       }
  358   
  359       private static class BootClassPathHolder {
  360           static final URLClassPath bcp;
  361           static {
  362               URL[] urls;
  363               if (bootClassPath != null) {
  364                   urls = AccessController.doPrivileged(
  365                       new PrivilegedAction<URL[]>() {
  366                           public URL[] run() {
  367                               File[] classPath = getClassPath(bootClassPath);
  368                               int len = classPath.length;
  369                               Set<File> seenDirs = new HashSet<File>();
  370                               for (int i = 0; i < len; i++) {
  371                                   File curEntry = classPath[i];
  372                                   // Negative test used to properly handle
  373                                   // nonexistent jars on boot class path
  374                                   if (!curEntry.isDirectory()) {
  375                                       curEntry = curEntry.getParentFile();
  376                                   }
  377                                   if (curEntry != null && seenDirs.add(curEntry)) {
  378                                       MetaIndex.registerDirectory(curEntry);
  379                                   }
  380                               }
  381                               return pathToURLs(classPath);
  382                           }
  383                       }
  384                   );
  385               } else {
  386                   urls = new URL[0];
  387               }
  388               bcp = new URLClassPath(urls, factory);
  389           }
  390       }
  391   
  392       public static URLClassPath getBootstrapClassPath() {
  393           return BootClassPathHolder.bcp;
  394       }
  395   
  396       private static URL[] pathToURLs(File[] path) {
  397           URL[] urls = new URL[path.length];
  398           for (int i = 0; i < path.length; i++) {
  399               urls[i] = getFileURL(path[i]);
  400           }
  401           // DEBUG
  402           //for (int i = 0; i < urls.length; i++) {
  403           //  System.out.println("urls[" + i + "] = " + '"' + urls[i] + '"');
  404           //}
  405           return urls;
  406       }
  407   
  408       private static File[] getClassPath(String cp) {
  409           File[] path;
  410           if (cp != null) {
  411               int count = 0, maxCount = 1;
  412               int pos = 0, lastPos = 0;
  413               // Count the number of separators first
  414               while ((pos = cp.indexOf(File.pathSeparator, lastPos)) != -1) {
  415                   maxCount++;
  416                   lastPos = pos + 1;
  417               }
  418               path = new File[maxCount];
  419               lastPos = pos = 0;
  420               // Now scan for each path component
  421               while ((pos = cp.indexOf(File.pathSeparator, lastPos)) != -1) {
  422                   if (pos - lastPos > 0) {
  423                       path[count++] = new File(cp.substring(lastPos, pos));
  424                   } else {
  425                       // empty path component translates to "."
  426                       path[count++] = new File(".");
  427                   }
  428                   lastPos = pos + 1;
  429               }
  430               // Make sure we include the last path component
  431               if (lastPos < cp.length()) {
  432                   path[count++] = new File(cp.substring(lastPos));
  433               } else {
  434                   path[count++] = new File(".");
  435               }
  436               // Trim array to correct size
  437               if (count != maxCount) {
  438                   File[] tmp = new File[count];
  439                   System.arraycopy(path, 0, tmp, 0, count);
  440                   path = tmp;
  441               }
  442           } else {
  443               path = new File[0];
  444           }
  445           // DEBUG
  446           //for (int i = 0; i < path.length; i++) {
  447           //  System.out.println("path[" + i + "] = " + '"' + path[i] + '"');
  448           //}
  449           return path;
  450       }
  451   
  452       private static URLStreamHandler fileHandler;
  453   
  454       static URL getFileURL(File file) {
  455           try {
  456               file = file.getCanonicalFile();
  457           } catch (IOException e) {}
  458   
  459           try {
  460               return ParseUtil.fileToEncodedURL(file);
  461           } catch (MalformedURLException e) {
  462               // Should never happen since we specify the protocol...
  463               throw new InternalError();
  464           }
  465       }
  466   
  467       /*
  468        * The stream handler factory for loading system protocol handlers.
  469        */
  470       private static class Factory implements URLStreamHandlerFactory {
  471           private static String PREFIX = "sun.net.www.protocol";
  472   
  473           public URLStreamHandler createURLStreamHandler(String protocol) {
  474               String name = PREFIX + "." + protocol + ".Handler";
  475               try {
  476                   Class c = Class.forName(name);
  477                   return (URLStreamHandler)c.newInstance();
  478               } catch (ClassNotFoundException e) {
  479                   e.printStackTrace();
  480               } catch (InstantiationException e) {
  481                   e.printStackTrace();
  482               } catch (IllegalAccessException e) {
  483                   e.printStackTrace();
  484               }
  485               throw new InternalError("could not load " + protocol +
  486                                       "system protocol handler");
  487           }
  488       }
  489   }
  490   
  491   class PathPermissions extends PermissionCollection {
  492       // use serialVersionUID from JDK 1.2.2 for interoperability
  493       private static final long serialVersionUID = 8133287259134945693L;
  494   
  495       private File path[];
  496       private Permissions perms;
  497   
  498       URL codeBase;
  499   
  500       PathPermissions(File path[])
  501       {
  502           this.path = path;
  503           this.perms = null;
  504           this.codeBase = null;
  505       }
  506   
  507       URL getCodeBase()
  508       {
  509           return codeBase;
  510       }
  511   
  512       public void add(java.security.Permission permission) {
  513           throw new SecurityException("attempt to add a permission");
  514       }
  515   
  516       private synchronized void init()
  517       {
  518           if (perms != null)
  519               return;
  520   
  521           perms = new Permissions();
  522   
  523           // this is needed to be able to create the classloader itself!
  524           perms.add(SecurityConstants.CREATE_CLASSLOADER_PERMISSION);
  525   
  526           // add permission to read any "java.*" property
  527           perms.add(new java.util.PropertyPermission("java.*",
  528               SecurityConstants.PROPERTY_READ_ACTION));
  529   
  530           AccessController.doPrivileged(new PrivilegedAction<Void>() {
  531               public Void run() {
  532                   for (int i=0; i < path.length; i++) {
  533                       File f = path[i];
  534                       String path;
  535                       try {
  536                           path = f.getCanonicalPath();
  537                       } catch (IOException ioe) {
  538                           path = f.getAbsolutePath();
  539                       }
  540                       if (i == 0) {
  541                           codeBase = Launcher.getFileURL(new File(path));
  542                       }
  543                       if (f.isDirectory()) {
  544                           if (path.endsWith(File.separator)) {
  545                               perms.add(new FilePermission(path+"-",
  546                                   SecurityConstants.FILE_READ_ACTION));
  547                           } else {
  548                               perms.add(new FilePermission(
  549                                   path + File.separator+"-",
  550                                   SecurityConstants.FILE_READ_ACTION));
  551                           }
  552                       } else {
  553                           int endIndex = path.lastIndexOf(File.separatorChar);
  554                           if (endIndex != -1) {
  555                               path = path.substring(0, endIndex+1) + "-";
  556                               perms.add(new FilePermission(path,
  557                                   SecurityConstants.FILE_READ_ACTION));
  558                           } else {
  559                               // XXX?
  560                           }
  561                       }
  562                   }
  563                   return null;
  564               }
  565           });
  566       }
  567   
  568       public boolean implies(java.security.Permission permission) {
  569           if (perms == null)
  570               init();
  571           return perms.implies(permission);
  572       }
  573   
  574       public java.util.Enumeration<Permission> elements() {
  575           if (perms == null)
  576               init();
  577           synchronized (perms) {
  578               return perms.elements();
  579           }
  580       }
  581   
  582       public String toString() {
  583           if (perms == null)
  584               init();
  585           return perms.toString();
  586       }
  587   }

Save This Page
Home » openjdk-7 » sun » misc » [javadoc | source]