src/share/jaxws_classes/com/sun/istack/internal/tools/ParallelWorldClassLoader.java

Thu, 31 Aug 2017 15:18:52 +0800

author
aoqi
date
Thu, 31 Aug 2017 15:18:52 +0800
changeset 637
9c07ef4934dd
parent 397
b99d7e355d4b
parent 0
373ffda63c9a
permissions
-rw-r--r--

merge

     1 /*
     2  * Copyright (c) 1997, 2013, 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  */
    26 package com.sun.istack.internal.tools;
    28 import java.io.InputStream;
    29 import java.io.ByteArrayOutputStream;
    30 import java.io.Closeable;
    31 import java.io.File;
    32 import java.io.IOException;
    33 import java.net.JarURLConnection;
    34 import java.net.URISyntaxException;
    35 import java.net.URL;
    36 import java.net.MalformedURLException;
    37 import java.net.URLConnection;
    38 import java.util.Collections;
    39 import java.util.Enumeration;
    40 import java.util.HashSet;
    41 import java.util.Set;
    42 import java.util.jar.JarFile;
    43 import java.util.logging.Level;
    44 import java.util.logging.Logger;
    46 /**
    47  * Load classes/resources from a side folder, so that
    48  * classes of the same package can live in a single jar file.
    49  *
    50  * <p>
    51  * For example, with the following jar file:
    52  * <pre>
    53  *  /
    54  *  +- foo
    55  *     +- X.class
    56  *  +- bar
    57  *     +- X.class
    58  * </pre>
    59  * <p>
    60  * {@link ParallelWorldClassLoader}("foo/") would load <tt>X.class<tt> from
    61  * <tt>/foo/X.class</tt> (note that X is defined in the root package, not
    62  * <tt>foo.X</tt>.
    63  *
    64  * <p>
    65  * This can be combined with  {@link MaskingClassLoader} to mask classes which are loaded by the parent
    66  * class loader so that the child class loader
    67  * classes living in different folders are loaded
    68  * before the parent class loader loads classes living the jar file publicly
    69  * visible
    70  * For example, with the following jar file:
    71  * <pre>
    72  *  /
    73  *  +- foo
    74  *     +- X.class
    75  *  +- bar
    76  *     +-foo
    77  *        +- X.class
    78  * </pre>
    79  * <p>
    80  * {@link ParallelWorldClassLoader}(MaskingClassLoader.class.getClassLoader()) would load <tt>foo.X.class<tt> from
    81  * <tt>/bar/foo.X.class</tt> not the <tt>foo.X.class<tt> in the publicly visible place in the jar file, thus
    82  * masking the parent classLoader from loading the class from  <tt>foo.X.class<tt>
    83  * (note that X is defined in the  package foo, not
    84  * <tt>bar.foo.X</tt>.
    85  *
    86  * @author Kohsuke Kawaguchi
    87  */
    88 public class ParallelWorldClassLoader extends ClassLoader implements Closeable {
    90     /**
    91      * Strings like "prefix/", "abc/", or "" to indicate
    92      * classes should be loaded normally.
    93      */
    94     private final String prefix;
    95     private final Set<JarFile> jars;
    97     public ParallelWorldClassLoader(ClassLoader parent,String prefix) {
    98         super(parent);
    99         this.prefix = prefix;
   100         jars = Collections.synchronizedSet(new HashSet<JarFile>());
   101     }
   103     protected Class findClass(String name) throws ClassNotFoundException {
   105         StringBuffer sb = new StringBuffer(name.length()+prefix.length()+6);
   106         sb.append(prefix).append(name.replace('.','/')).append(".class");
   108         URL u  = getParent().getResource(sb.toString());
   109         if (u == null) {
   110             throw new ClassNotFoundException(name);
   111         }
   113         InputStream is = null;
   114         URLConnection con = null;
   116         try {
   117             con = u.openConnection();
   118             is = con.getInputStream();
   119         } catch (IOException ioe) {
   120             throw new ClassNotFoundException(name);
   121         }
   123         if (is==null)
   124             throw new ClassNotFoundException(name);
   126         try {
   127             ByteArrayOutputStream baos = new ByteArrayOutputStream();
   128             byte[] buf = new byte[1024];
   129             int len;
   130             while((len=is.read(buf))>=0)
   131                 baos.write(buf,0,len);
   133             buf = baos.toByteArray();
   134             int packIndex = name.lastIndexOf('.');
   135             if (packIndex != -1) {
   136                 String pkgname = name.substring(0, packIndex);
   137                 // Check if package already loaded.
   138                 Package pkg = getPackage(pkgname);
   139                 if (pkg == null) {
   140                     definePackage(pkgname, null, null, null, null, null, null, null);
   141                 }
   142             }
   143             return defineClass(name,buf,0,buf.length);
   144         } catch (IOException e) {
   145             throw new ClassNotFoundException(name,e);
   146         } finally {
   147             try {
   148                 if (con != null && con instanceof JarURLConnection) {
   149                     jars.add(((JarURLConnection) con).getJarFile());
   150                 }
   151             } catch (IOException ioe) {
   152                 //ignore
   153             }
   154             if (is != null) {
   155                 try {
   156                     is.close();
   157                 } catch (IOException ioe) {
   158                     //ignore
   159                 }
   160             }
   161         }
   162     }
   164     @Override
   165     protected URL findResource(String name) {
   166         URL u = getParent().getResource(prefix + name);
   167         if (u != null) {
   168             try {
   169                 jars.add(new JarFile(new File(toJarUrl(u).toURI())));
   170             } catch (URISyntaxException ex) {
   171                 Logger.getLogger(ParallelWorldClassLoader.class.getName()).log(Level.WARNING, null, ex);
   172             } catch (IOException ex) {
   173                 Logger.getLogger(ParallelWorldClassLoader.class.getName()).log(Level.WARNING, null, ex);
   174             } catch (ClassNotFoundException ex) {
   175                 //ignore - not a jar
   176             }
   177         }
   178         return u;
   179     }
   181     @Override
   182     protected Enumeration<URL> findResources(String name) throws IOException {
   183         Enumeration<URL> en = getParent().getResources(prefix + name);
   184         while (en.hasMoreElements()) {
   185             try {
   186                 jars.add(new JarFile(new File(toJarUrl(en.nextElement()).toURI())));
   187             } catch (URISyntaxException ex) {
   188                 //should not happen
   189                 Logger.getLogger(ParallelWorldClassLoader.class.getName()).log(Level.WARNING, null, ex);
   190             } catch (IOException ex) {
   191                 Logger.getLogger(ParallelWorldClassLoader.class.getName()).log(Level.WARNING, null, ex);
   192             } catch (ClassNotFoundException ex) {
   193                 //ignore - not a jar
   194             }
   195         }
   196         return en;
   197     }
   199     public synchronized void close() throws IOException {
   200         for (JarFile jar : jars) {
   201             jar.close();
   202         }
   203     }
   205     /**
   206      * Given the URL inside jar, returns the URL to the jar itself.
   207      */
   208     public static URL toJarUrl(URL res) throws ClassNotFoundException, MalformedURLException {
   209         String url = res.toExternalForm();
   210         if(!url.startsWith("jar:"))
   211             throw new ClassNotFoundException("Loaded outside a jar "+url);
   212         url = url.substring(4); // cut off jar:
   213         url = url.substring(0,url.lastIndexOf('!'));    // cut off everything after '!'
   214         url = url.replaceAll(" ", "%20"); // support white spaces in path
   215         return new URL(url);
   216     }
   217 }

mercurial