< prev index next >

src/share/classes/sun/misc/URLClassPath.java

Print this page
rev 1388 : 6600143: Remove another 450 unnecessary casts
Reviewed-by: alanb, iris, lmalvent, bristor, peterjones, darcy, wetmore

  73  *
  74  * @author  David Connelly
  75  */
  76 public class URLClassPath {
  77     final static String USER_AGENT_JAVA_VERSION = "UA-Java-Version";
  78     final static String JAVA_VERSION;
  79     private static final boolean DEBUG;
  80     private static final boolean DISABLE_JAR_CHECKING;
  81 
  82     static {
  83         JAVA_VERSION = java.security.AccessController.doPrivileged(
  84             new sun.security.action.GetPropertyAction("java.version"));
  85         DEBUG        = (java.security.AccessController.doPrivileged(
  86             new sun.security.action.GetPropertyAction("sun.misc.URLClassPath.debug")) != null);
  87         String p = java.security.AccessController.doPrivileged(
  88             new sun.security.action.GetPropertyAction("sun.misc.URLClassPath.disableJarChecking"));
  89         DISABLE_JAR_CHECKING = p != null ? p.equals("true") || p.equals("") : false;
  90     }
  91 
  92     /* The original search path of URLs. */
  93     private ArrayList path = new ArrayList();
  94 
  95     /* The stack of unopened URLs */
  96     Stack urls = new Stack();
  97 
  98     /* The resulting search path of Loaders */
  99     ArrayList loaders = new ArrayList();
 100 
 101     /* Map of each URL opened to its corresponding Loader */
 102     HashMap lmap = new HashMap();
 103 
 104     /* The jar protocol handler to use when creating new URLs */
 105     private URLStreamHandler jarHandler;
 106 
 107     /**
 108      * Creates a new URLClassPath for the given URLs. The URLs will be
 109      * searched in the order specified for classes and resources. A URL
 110      * ending with a '/' is assumed to refer to a directory. Otherwise,
 111      * the URL is assumed to refer to a JAR file.
 112      *
 113      * @param urls the directory and JAR file URLs to search for classes
 114      *        and resources
 115      * @param factory the URLStreamHandlerFactory to use when creating new URLs
 116      */
 117     public URLClassPath(URL[] urls, URLStreamHandlerFactory factory) {
 118         for (int i = 0; i < urls.length; i++) {
 119             path.add(urls[i]);
 120         }
 121         push(urls);
 122         if (factory != null) {


 130 
 131     /**
 132      * Appends the specified URL to the search path of directory and JAR
 133      * file URLs from which to load classes and resources.
 134      */
 135     public void addURL(URL url) {
 136         synchronized (urls) {
 137             if (path.contains(url))
 138                 return;
 139 
 140             urls.add(0, url);
 141             path.add(url);
 142         }
 143     }
 144 
 145     /**
 146      * Returns the original search path of URLs.
 147      */
 148     public URL[] getURLs() {
 149         synchronized (urls) {
 150             return (URL[])path.toArray(new URL[path.size()]);
 151         }
 152     }
 153 
 154     /**
 155      * Finds the resource with the specified name on the URL search path
 156      * or null if not found or security check fails.
 157      *
 158      * @param name      the name of the resource
 159      * @param check     whether to perform a security check
 160      * @return a <code>URL</code> for the resource, or <code>null</code>
 161      * if the resource could not be found.
 162      */
 163     public URL findResource(String name, boolean check) {
 164         Loader loader;
 165         for (int i = 0; (loader = getLoader(i)) != null; i++) {
 166             URL url = loader.findResource(name, check);
 167             if (url != null) {
 168                 return url;
 169             }
 170         }


 184             System.err.println("URLClassPath.getResource(\"" + name + "\")");
 185         }
 186 
 187         Loader loader;
 188         for (int i = 0; (loader = getLoader(i)) != null; i++) {
 189             Resource res = loader.getResource(name, check);
 190             if (res != null) {
 191                 return res;
 192             }
 193         }
 194         return null;
 195     }
 196 
 197     /**
 198      * Finds all resources on the URL search path with the given name.
 199      * Returns an enumeration of the URL objects.
 200      *
 201      * @param name the resource name
 202      * @return an Enumeration of all the urls having the specified name
 203      */
 204     public Enumeration findResources(final String name,
 205                                      final boolean check) {
 206         return new Enumeration() {
 207             private int index = 0;
 208             private URL url = null;
 209 
 210             private boolean next() {
 211                 if (url != null) {
 212                     return true;
 213                 } else {
 214                     Loader loader;
 215                     while ((loader = getLoader(index++)) != null) {
 216                         url = loader.findResource(name, check);
 217                         if (url != null) {
 218                             return true;
 219                         }
 220                     }
 221                     return false;
 222                 }
 223             }
 224 
 225             public boolean hasMoreElements() {
 226                 return next();
 227             }
 228 
 229             public Object nextElement() {
 230                 if (!next()) {
 231                     throw new NoSuchElementException();
 232                 }
 233                 URL u = url;
 234                 url = null;
 235                 return u;
 236             }
 237         };
 238     }
 239 
 240     public Resource getResource(String name) {
 241         return getResource(name, true);
 242     }
 243 
 244     /**
 245      * Finds all resources on the URL search path with the given name.
 246      * Returns an enumeration of the Resource objects.
 247      *
 248      * @param name the resource name
 249      * @return an Enumeration of all the resources having the specified name
 250      */
 251     public Enumeration getResources(final String name,
 252                                     final boolean check) {
 253         return new Enumeration() {
 254             private int index = 0;
 255             private Resource res = null;
 256 
 257             private boolean next() {
 258                 if (res != null) {
 259                     return true;
 260                 } else {
 261                     Loader loader;
 262                     while ((loader = getLoader(index++)) != null) {
 263                         res = loader.getResource(name, check);
 264                         if (res != null) {
 265                             return true;
 266                         }
 267                     }
 268                     return false;
 269                 }
 270             }
 271 
 272             public boolean hasMoreElements() {
 273                 return next();
 274             }
 275 
 276             public Object nextElement() {
 277                 if (!next()) {
 278                     throw new NoSuchElementException();
 279                 }
 280                 Resource r = res;
 281                 res = null;
 282                 return r;
 283             }
 284         };
 285     }
 286 
 287     public Enumeration getResources(final String name) {
 288         return getResources(name, true);
 289     }
 290 
 291     /*
 292      * Returns the Loader at the specified position in the URL search
 293      * path. The URLs are opened and expanded as needed. Returns null
 294      * if the specified index is out of range.
 295      */
 296      private synchronized Loader getLoader(int index) {
 297          // Expand URL search path until the request can be satisfied
 298          // or the URL stack is empty.
 299         while (loaders.size() < index + 1) {
 300             // Pop the next URL from the URL stack
 301             URL url;
 302             synchronized (urls) {
 303                 if (urls.empty()) {
 304                     return null;
 305                 } else {
 306                     url = (URL)urls.pop();
 307                 }
 308             }
 309             // Skip this URL if it already has a Loader. (Loader
 310             // may be null in the case where URL has not been opened
 311             // but is referenced by a JAR index.)
 312             if (lmap.containsKey(url)) {
 313                 continue;
 314             }
 315             // Otherwise, create a new Loader for the URL.
 316             Loader loader;
 317             try {
 318                 loader = getLoader(url);
 319                 // If the loader defines a local class path then add the
 320                 // URLs to the list of URLs to be opened.
 321                 URL[] urls = loader.getClassPath();
 322                 if (urls != null) {
 323                     push(urls);
 324                 }
 325             } catch (IOException e) {
 326                 // Silently ignore for now...
 327                 continue;
 328             }
 329             // Finally, add the Loader to the search path.
 330             loaders.add(loader);
 331             lmap.put(url, loader);
 332         }
 333         return (Loader)loaders.get(index);
 334     }
 335 
 336     /*
 337      * Returns the Loader for the specified base URL.
 338      */
 339     private Loader getLoader(final URL url) throws IOException {
 340         try {
 341             return (Loader)java.security.AccessController.doPrivileged
 342                 (new java.security.PrivilegedExceptionAction() {
 343                 public Object run() throws IOException {
 344                     String file = url.getFile();
 345                     if (file != null && file.endsWith("/")) {
 346                         if ("file".equals(url.getProtocol())) {
 347                             return new FileLoader(url);
 348                         } else {
 349                             return new Loader(url);
 350                         }
 351                     } else {
 352                         return new JarLoader(url, jarHandler, lmap);
 353                     }
 354                 }
 355             });
 356         } catch (java.security.PrivilegedActionException pae) {
 357             throw (IOException)pae.getException();
 358         }
 359     }
 360 
 361     /*
 362      * Pushes the specified URLs onto the list of unopened URLs.
 363      */


 545             return getResource(name, true);
 546         }
 547 
 548         /*
 549          * Returns the local class path for this loader, or null if none.
 550          */
 551         URL[] getClassPath() throws IOException {
 552             return null;
 553         }
 554     }
 555 
 556     /*
 557      * Inner class used to represent a Loader of resources from a JAR URL.
 558      */
 559     static class JarLoader extends Loader {
 560         private JarFile jar;
 561         private URL csu;
 562         private JarIndex index;
 563         private MetaIndex metaIndex;
 564         private URLStreamHandler handler;
 565         private HashMap lmap;
 566         private static final sun.misc.JavaUtilZipFileAccess zipAccess =
 567                 sun.misc.SharedSecrets.getJavaUtilZipFileAccess();
 568 
 569         /*
 570          * Creates a new JarLoader for the specified URL referring to
 571          * a JAR file.
 572          */
 573         JarLoader(URL url, URLStreamHandler jarHandler, HashMap loaderMap)

 574             throws IOException
 575         {
 576             super(new URL("jar", "", -1, url + "!/", jarHandler));
 577             csu = url;
 578             handler = jarHandler;
 579             lmap = loaderMap;
 580 
 581             if (!isOptimizable(url)) {
 582                 ensureOpen();
 583             } else {
 584                  String fileName = url.getFile();
 585                 if (fileName != null) {
 586                     fileName = ParseUtil.decode(fileName);
 587                     File f = new File(fileName);
 588                     metaIndex = MetaIndex.forJar(f);
 589                     // If the meta index is found but the file is not
 590                     // installed, set metaIndex to null. A typical
 591                     // senario is charsets.jar which won't be installed
 592                     // when the user is running in certain locale environment.
 593                     // The side effect of null metaIndex will cause


 601                 // entry recorded in meta-index file or such jar file is
 602                 // missing in JRE. See bug 6340399.
 603                 if (metaIndex == null) {
 604                     ensureOpen();
 605                 }
 606             }
 607         }
 608 
 609         JarFile getJarFile () {
 610             return jar;
 611         }
 612 
 613         private boolean isOptimizable(URL url) {
 614             return "file".equals(url.getProtocol());
 615         }
 616 
 617         private void ensureOpen() throws IOException {
 618             if (jar == null) {
 619                 try {
 620                     java.security.AccessController.doPrivileged(
 621                         new java.security.PrivilegedExceptionAction() {
 622                             public Object run() throws IOException {
 623                                 if (DEBUG) {
 624                                     System.err.println("Opening " + csu);
 625                                     Thread.dumpStack();
 626                                 }
 627 
 628                                 jar = getJarFile(csu);
 629                                 index = JarIndex.getJarIndex(jar, metaIndex);
 630                                 if (index != null) {
 631                                     String[] jarfiles = index.getJarFiles();
 632                                 // Add all the dependent URLs to the lmap so that loaders
 633                                 // will not be created for them by URLClassPath.getLoader(int)
 634                                 // if the same URL occurs later on the main class path.  We set
 635                                 // Loader to null here to avoid creating a Loader for each
 636                                 // URL until we actually need to try to load something from them.
 637                                     for(int i = 0; i < jarfiles.length; i++) {
 638                                         try {
 639                                             URL jarURL = new URL(csu, jarfiles[i]);
 640                                             // If a non-null loader already exists, leave it alone.
 641                                             if (!lmap.containsKey(jarURL)) {
 642                                                 lmap.put(jarURL, null);


 727                     { return entry.getCertificates(); };
 728                 public CodeSigner[] getCodeSigners()
 729                     { return entry.getCodeSigners(); };
 730             };
 731         }
 732 
 733 
 734         /*
 735          * Returns true iff atleast one resource in the jar file has the same
 736          * package name as that of the specified resource name.
 737          */
 738         boolean validIndex(final String name) {
 739             String packageName = name;
 740             int pos;
 741             if((pos = name.lastIndexOf("/")) != -1) {
 742                 packageName = name.substring(0, pos);
 743             }
 744 
 745             String entryName;
 746             ZipEntry entry;
 747             Enumeration enum_ = jar.entries();
 748             while (enum_.hasMoreElements()) {
 749                 entry = (ZipEntry)enum_.nextElement();
 750                 entryName = entry.getName();
 751                 if((pos = entryName.lastIndexOf("/")) != -1)
 752                     entryName = entryName.substring(0, pos);
 753                 if (entryName.equals(packageName)) {
 754                     return true;
 755                 }
 756             }
 757             return false;
 758         }
 759 
 760         /*
 761          * Returns the URL for a resource with the specified name
 762          */
 763         URL findResource(final String name, boolean check) {
 764             Resource rsc = getResource(name, check);
 765             if (rsc != null) {
 766                 return rsc.getURL();
 767             }
 768             return null;
 769         }


 773          */
 774         Resource getResource(final String name, boolean check) {
 775             if (metaIndex != null) {
 776                 if (!metaIndex.mayContain(name)) {
 777                     return null;
 778                 }
 779             }
 780 
 781             try {
 782                 ensureOpen();
 783             } catch (IOException e) {
 784                 throw (InternalError) new InternalError().initCause(e);
 785             }
 786             final JarEntry entry = jar.getJarEntry(name);
 787             if (entry != null)
 788                 return checkResource(name, check, entry);
 789 
 790             if (index == null)
 791                 return null;
 792 
 793             HashSet visited = new HashSet();
 794             return getResource(name, check, visited);
 795         }
 796 
 797         /*
 798          * Version of getResource() that tracks the jar files that have been
 799          * visited by linking through the index files. This helper method uses
 800          * a HashSet to store the URLs of jar files that have been searched and
 801          * uses it to avoid going into an infinite loop, looking for a
 802          * non-existent resource
 803          */
 804         Resource getResource(final String name, boolean check,
 805                 Set visited) {
 806 
 807             Resource res;
 808             Object[] jarFiles;
 809             boolean done = false;
 810             int count = 0;
 811             LinkedList jarFilesList = null;
 812 
 813             /* If there no jar files in the index that can potential contain
 814              * this resource then return immediately.
 815              */
 816             if((jarFilesList = index.get(name)) == null)
 817                 return null;
 818 
 819             do {
 820                 jarFiles = jarFilesList.toArray();
 821                 int size = jarFilesList.size();
 822                 /* loop through the mapped jar file list */
 823                 while(count < size) {
 824                     String jarName = (String)jarFiles[count++];
 825                     JarLoader newLoader;
 826                     final URL url;
 827 
 828                     try{
 829                         url = new URL(csu, jarName);
 830                         if ((newLoader = (JarLoader)lmap.get(url)) == null) {
 831                             /* no loader has been set up for this jar file
 832                              * before
 833                              */
 834                             newLoader = (JarLoader)
 835                                 AccessController.doPrivileged(
 836                                     new PrivilegedExceptionAction() {
 837                                     public Object run() throws IOException {
 838                                         return new JarLoader(url, handler,
 839                                             lmap);
 840                                     }
 841                                 });
 842 
 843                             /* this newly opened jar file has its own index,
 844                              * merge it into the parent's index, taking into
 845                              * account the relative path.
 846                              */
 847                             JarIndex newIndex = newLoader.getIndex();
 848                             if(newIndex != null) {
 849                                 int pos = jarName.lastIndexOf("/");
 850                                 newIndex.merge(this.index, (pos == -1 ?
 851                                     null : jarName.substring(0, pos + 1)));
 852                             }
 853 
 854                             /* put it in the global hashtable */
 855                             lmap.put(url, newLoader);
 856                         }
 857                     } catch (java.security.PrivilegedActionException pae) {



  73  *
  74  * @author  David Connelly
  75  */
  76 public class URLClassPath {
  77     final static String USER_AGENT_JAVA_VERSION = "UA-Java-Version";
  78     final static String JAVA_VERSION;
  79     private static final boolean DEBUG;
  80     private static final boolean DISABLE_JAR_CHECKING;
  81 
  82     static {
  83         JAVA_VERSION = java.security.AccessController.doPrivileged(
  84             new sun.security.action.GetPropertyAction("java.version"));
  85         DEBUG        = (java.security.AccessController.doPrivileged(
  86             new sun.security.action.GetPropertyAction("sun.misc.URLClassPath.debug")) != null);
  87         String p = java.security.AccessController.doPrivileged(
  88             new sun.security.action.GetPropertyAction("sun.misc.URLClassPath.disableJarChecking"));
  89         DISABLE_JAR_CHECKING = p != null ? p.equals("true") || p.equals("") : false;
  90     }
  91 
  92     /* The original search path of URLs. */
  93     private ArrayList<URL> path = new ArrayList<URL>();
  94 
  95     /* The stack of unopened URLs */
  96     Stack<URL> urls = new Stack<URL>();
  97 
  98     /* The resulting search path of Loaders */
  99     ArrayList<Loader> loaders = new ArrayList<Loader>();
 100 
 101     /* Map of each URL opened to its corresponding Loader */
 102     HashMap<URL, Loader> lmap = new HashMap<URL, Loader>();
 103 
 104     /* The jar protocol handler to use when creating new URLs */
 105     private URLStreamHandler jarHandler;
 106 
 107     /**
 108      * Creates a new URLClassPath for the given URLs. The URLs will be
 109      * searched in the order specified for classes and resources. A URL
 110      * ending with a '/' is assumed to refer to a directory. Otherwise,
 111      * the URL is assumed to refer to a JAR file.
 112      *
 113      * @param urls the directory and JAR file URLs to search for classes
 114      *        and resources
 115      * @param factory the URLStreamHandlerFactory to use when creating new URLs
 116      */
 117     public URLClassPath(URL[] urls, URLStreamHandlerFactory factory) {
 118         for (int i = 0; i < urls.length; i++) {
 119             path.add(urls[i]);
 120         }
 121         push(urls);
 122         if (factory != null) {


 130 
 131     /**
 132      * Appends the specified URL to the search path of directory and JAR
 133      * file URLs from which to load classes and resources.
 134      */
 135     public void addURL(URL url) {
 136         synchronized (urls) {
 137             if (path.contains(url))
 138                 return;
 139 
 140             urls.add(0, url);
 141             path.add(url);
 142         }
 143     }
 144 
 145     /**
 146      * Returns the original search path of URLs.
 147      */
 148     public URL[] getURLs() {
 149         synchronized (urls) {
 150             return path.toArray(new URL[path.size()]);
 151         }
 152     }
 153 
 154     /**
 155      * Finds the resource with the specified name on the URL search path
 156      * or null if not found or security check fails.
 157      *
 158      * @param name      the name of the resource
 159      * @param check     whether to perform a security check
 160      * @return a <code>URL</code> for the resource, or <code>null</code>
 161      * if the resource could not be found.
 162      */
 163     public URL findResource(String name, boolean check) {
 164         Loader loader;
 165         for (int i = 0; (loader = getLoader(i)) != null; i++) {
 166             URL url = loader.findResource(name, check);
 167             if (url != null) {
 168                 return url;
 169             }
 170         }


 184             System.err.println("URLClassPath.getResource(\"" + name + "\")");
 185         }
 186 
 187         Loader loader;
 188         for (int i = 0; (loader = getLoader(i)) != null; i++) {
 189             Resource res = loader.getResource(name, check);
 190             if (res != null) {
 191                 return res;
 192             }
 193         }
 194         return null;
 195     }
 196 
 197     /**
 198      * Finds all resources on the URL search path with the given name.
 199      * Returns an enumeration of the URL objects.
 200      *
 201      * @param name the resource name
 202      * @return an Enumeration of all the urls having the specified name
 203      */
 204     public Enumeration<URL> findResources(final String name,
 205                                      final boolean check) {
 206         return new Enumeration<URL>() {
 207             private int index = 0;
 208             private URL url = null;
 209 
 210             private boolean next() {
 211                 if (url != null) {
 212                     return true;
 213                 } else {
 214                     Loader loader;
 215                     while ((loader = getLoader(index++)) != null) {
 216                         url = loader.findResource(name, check);
 217                         if (url != null) {
 218                             return true;
 219                         }
 220                     }
 221                     return false;
 222                 }
 223             }
 224 
 225             public boolean hasMoreElements() {
 226                 return next();
 227             }
 228 
 229             public URL nextElement() {
 230                 if (!next()) {
 231                     throw new NoSuchElementException();
 232                 }
 233                 URL u = url;
 234                 url = null;
 235                 return u;
 236             }
 237         };
 238     }
 239 
 240     public Resource getResource(String name) {
 241         return getResource(name, true);
 242     }
 243 
 244     /**
 245      * Finds all resources on the URL search path with the given name.
 246      * Returns an enumeration of the Resource objects.
 247      *
 248      * @param name the resource name
 249      * @return an Enumeration of all the resources having the specified name
 250      */
 251     public Enumeration<Resource> getResources(final String name,
 252                                     final boolean check) {
 253         return new Enumeration<Resource>() {
 254             private int index = 0;
 255             private Resource res = null;
 256 
 257             private boolean next() {
 258                 if (res != null) {
 259                     return true;
 260                 } else {
 261                     Loader loader;
 262                     while ((loader = getLoader(index++)) != null) {
 263                         res = loader.getResource(name, check);
 264                         if (res != null) {
 265                             return true;
 266                         }
 267                     }
 268                     return false;
 269                 }
 270             }
 271 
 272             public boolean hasMoreElements() {
 273                 return next();
 274             }
 275 
 276             public Resource nextElement() {
 277                 if (!next()) {
 278                     throw new NoSuchElementException();
 279                 }
 280                 Resource r = res;
 281                 res = null;
 282                 return r;
 283             }
 284         };
 285     }
 286 
 287     public Enumeration<Resource> getResources(final String name) {
 288         return getResources(name, true);
 289     }
 290 
 291     /*
 292      * Returns the Loader at the specified position in the URL search
 293      * path. The URLs are opened and expanded as needed. Returns null
 294      * if the specified index is out of range.
 295      */
 296      private synchronized Loader getLoader(int index) {
 297          // Expand URL search path until the request can be satisfied
 298          // or the URL stack is empty.
 299         while (loaders.size() < index + 1) {
 300             // Pop the next URL from the URL stack
 301             URL url;
 302             synchronized (urls) {
 303                 if (urls.empty()) {
 304                     return null;
 305                 } else {
 306                     url = urls.pop();
 307                 }
 308             }
 309             // Skip this URL if it already has a Loader. (Loader
 310             // may be null in the case where URL has not been opened
 311             // but is referenced by a JAR index.)
 312             if (lmap.containsKey(url)) {
 313                 continue;
 314             }
 315             // Otherwise, create a new Loader for the URL.
 316             Loader loader;
 317             try {
 318                 loader = getLoader(url);
 319                 // If the loader defines a local class path then add the
 320                 // URLs to the list of URLs to be opened.
 321                 URL[] urls = loader.getClassPath();
 322                 if (urls != null) {
 323                     push(urls);
 324                 }
 325             } catch (IOException e) {
 326                 // Silently ignore for now...
 327                 continue;
 328             }
 329             // Finally, add the Loader to the search path.
 330             loaders.add(loader);
 331             lmap.put(url, loader);
 332         }
 333         return loaders.get(index);
 334     }
 335 
 336     /*
 337      * Returns the Loader for the specified base URL.
 338      */
 339     private Loader getLoader(final URL url) throws IOException {
 340         try {
 341             return java.security.AccessController.doPrivileged(
 342                 new java.security.PrivilegedExceptionAction<Loader>() {
 343                 public Loader run() throws IOException {
 344                     String file = url.getFile();
 345                     if (file != null && file.endsWith("/")) {
 346                         if ("file".equals(url.getProtocol())) {
 347                             return new FileLoader(url);
 348                         } else {
 349                             return new Loader(url);
 350                         }
 351                     } else {
 352                         return new JarLoader(url, jarHandler, lmap);
 353                     }
 354                 }
 355             });
 356         } catch (java.security.PrivilegedActionException pae) {
 357             throw (IOException)pae.getException();
 358         }
 359     }
 360 
 361     /*
 362      * Pushes the specified URLs onto the list of unopened URLs.
 363      */


 545             return getResource(name, true);
 546         }
 547 
 548         /*
 549          * Returns the local class path for this loader, or null if none.
 550          */
 551         URL[] getClassPath() throws IOException {
 552             return null;
 553         }
 554     }
 555 
 556     /*
 557      * Inner class used to represent a Loader of resources from a JAR URL.
 558      */
 559     static class JarLoader extends Loader {
 560         private JarFile jar;
 561         private URL csu;
 562         private JarIndex index;
 563         private MetaIndex metaIndex;
 564         private URLStreamHandler handler;
 565         private HashMap<URL, Loader> lmap;
 566         private static final sun.misc.JavaUtilZipFileAccess zipAccess =
 567                 sun.misc.SharedSecrets.getJavaUtilZipFileAccess();
 568 
 569         /*
 570          * Creates a new JarLoader for the specified URL referring to
 571          * a JAR file.
 572          */
 573         JarLoader(URL url, URLStreamHandler jarHandler,
 574                   HashMap<URL, Loader> loaderMap)
 575             throws IOException
 576         {
 577             super(new URL("jar", "", -1, url + "!/", jarHandler));
 578             csu = url;
 579             handler = jarHandler;
 580             lmap = loaderMap;
 581 
 582             if (!isOptimizable(url)) {
 583                 ensureOpen();
 584             } else {
 585                  String fileName = url.getFile();
 586                 if (fileName != null) {
 587                     fileName = ParseUtil.decode(fileName);
 588                     File f = new File(fileName);
 589                     metaIndex = MetaIndex.forJar(f);
 590                     // If the meta index is found but the file is not
 591                     // installed, set metaIndex to null. A typical
 592                     // senario is charsets.jar which won't be installed
 593                     // when the user is running in certain locale environment.
 594                     // The side effect of null metaIndex will cause


 602                 // entry recorded in meta-index file or such jar file is
 603                 // missing in JRE. See bug 6340399.
 604                 if (metaIndex == null) {
 605                     ensureOpen();
 606                 }
 607             }
 608         }
 609 
 610         JarFile getJarFile () {
 611             return jar;
 612         }
 613 
 614         private boolean isOptimizable(URL url) {
 615             return "file".equals(url.getProtocol());
 616         }
 617 
 618         private void ensureOpen() throws IOException {
 619             if (jar == null) {
 620                 try {
 621                     java.security.AccessController.doPrivileged(
 622                         new java.security.PrivilegedExceptionAction<Void>() {
 623                             public Void run() throws IOException {
 624                                 if (DEBUG) {
 625                                     System.err.println("Opening " + csu);
 626                                     Thread.dumpStack();
 627                                 }
 628 
 629                                 jar = getJarFile(csu);
 630                                 index = JarIndex.getJarIndex(jar, metaIndex);
 631                                 if (index != null) {
 632                                     String[] jarfiles = index.getJarFiles();
 633                                 // Add all the dependent URLs to the lmap so that loaders
 634                                 // will not be created for them by URLClassPath.getLoader(int)
 635                                 // if the same URL occurs later on the main class path.  We set
 636                                 // Loader to null here to avoid creating a Loader for each
 637                                 // URL until we actually need to try to load something from them.
 638                                     for(int i = 0; i < jarfiles.length; i++) {
 639                                         try {
 640                                             URL jarURL = new URL(csu, jarfiles[i]);
 641                                             // If a non-null loader already exists, leave it alone.
 642                                             if (!lmap.containsKey(jarURL)) {
 643                                                 lmap.put(jarURL, null);


 728                     { return entry.getCertificates(); };
 729                 public CodeSigner[] getCodeSigners()
 730                     { return entry.getCodeSigners(); };
 731             };
 732         }
 733 
 734 
 735         /*
 736          * Returns true iff atleast one resource in the jar file has the same
 737          * package name as that of the specified resource name.
 738          */
 739         boolean validIndex(final String name) {
 740             String packageName = name;
 741             int pos;
 742             if((pos = name.lastIndexOf("/")) != -1) {
 743                 packageName = name.substring(0, pos);
 744             }
 745 
 746             String entryName;
 747             ZipEntry entry;
 748             Enumeration<JarEntry> enum_ = jar.entries();
 749             while (enum_.hasMoreElements()) {
 750                 entry = enum_.nextElement();
 751                 entryName = entry.getName();
 752                 if((pos = entryName.lastIndexOf("/")) != -1)
 753                     entryName = entryName.substring(0, pos);
 754                 if (entryName.equals(packageName)) {
 755                     return true;
 756                 }
 757             }
 758             return false;
 759         }
 760 
 761         /*
 762          * Returns the URL for a resource with the specified name
 763          */
 764         URL findResource(final String name, boolean check) {
 765             Resource rsc = getResource(name, check);
 766             if (rsc != null) {
 767                 return rsc.getURL();
 768             }
 769             return null;
 770         }


 774          */
 775         Resource getResource(final String name, boolean check) {
 776             if (metaIndex != null) {
 777                 if (!metaIndex.mayContain(name)) {
 778                     return null;
 779                 }
 780             }
 781 
 782             try {
 783                 ensureOpen();
 784             } catch (IOException e) {
 785                 throw (InternalError) new InternalError().initCause(e);
 786             }
 787             final JarEntry entry = jar.getJarEntry(name);
 788             if (entry != null)
 789                 return checkResource(name, check, entry);
 790 
 791             if (index == null)
 792                 return null;
 793 
 794             HashSet<URL> visited = new HashSet<URL>();
 795             return getResource(name, check, visited);
 796         }
 797 
 798         /*
 799          * Version of getResource() that tracks the jar files that have been
 800          * visited by linking through the index files. This helper method uses
 801          * a HashSet to store the URLs of jar files that have been searched and
 802          * uses it to avoid going into an infinite loop, looking for a
 803          * non-existent resource
 804          */
 805         Resource getResource(final String name, boolean check,
 806                              Set<URL> visited) {
 807 
 808             Resource res;
 809             Object[] jarFiles;
 810             boolean done = false;
 811             int count = 0;
 812             LinkedList jarFilesList = null;
 813 
 814             /* If there no jar files in the index that can potential contain
 815              * this resource then return immediately.
 816              */
 817             if((jarFilesList = index.get(name)) == null)
 818                 return null;
 819 
 820             do {
 821                 jarFiles = jarFilesList.toArray();
 822                 int size = jarFilesList.size();
 823                 /* loop through the mapped jar file list */
 824                 while(count < size) {
 825                     String jarName = (String)jarFiles[count++];
 826                     JarLoader newLoader;
 827                     final URL url;
 828 
 829                     try{
 830                         url = new URL(csu, jarName);
 831                         if ((newLoader = (JarLoader)lmap.get(url)) == null) {
 832                             /* no loader has been set up for this jar file
 833                              * before
 834                              */
 835                             newLoader = AccessController.doPrivileged(
 836                                 new PrivilegedExceptionAction<JarLoader>() {
 837                                     public JarLoader run() throws IOException {

 838                                         return new JarLoader(url, handler,
 839                                             lmap);
 840                                     }
 841                                 });
 842 
 843                             /* this newly opened jar file has its own index,
 844                              * merge it into the parent's index, taking into
 845                              * account the relative path.
 846                              */
 847                             JarIndex newIndex = newLoader.getIndex();
 848                             if(newIndex != null) {
 849                                 int pos = jarName.lastIndexOf("/");
 850                                 newIndex.merge(this.index, (pos == -1 ?
 851                                     null : jarName.substring(0, pos + 1)));
 852                             }
 853 
 854                             /* put it in the global hashtable */
 855                             lmap.put(url, newLoader);
 856                         }
 857                     } catch (java.security.PrivilegedActionException pae) {


< prev index next >