jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/xjc/api/util/ApClassLoader.java
changeset 26658 e04929038abf
parent 26542 9d0e6639a4d7
child 26659 5de9ea7b214e
equal deleted inserted replaced
26542:9d0e6639a4d7 26658:e04929038abf
     1 /*
       
     2  * Copyright (c) 1997, 2012, 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 com.sun.tools.internal.xjc.api.util;
       
    27 
       
    28 import java.io.ByteArrayOutputStream;
       
    29 import java.io.IOException;
       
    30 import java.io.InputStream;
       
    31 import java.io.File;
       
    32 import java.net.URL;
       
    33 import java.net.URLClassLoader;
       
    34 import java.net.MalformedURLException;
       
    35 
       
    36 import com.sun.istack.internal.Nullable;
       
    37 
       
    38 /**
       
    39  * {@link ClassLoader} that loads Annotation Processing and specified classes
       
    40  * both into the same classloader, so that they can reference each other.
       
    41  *
       
    42  * @author Bhakti Mehta
       
    43  * @since 2.0 beta
       
    44  */
       
    45 public final class ApClassLoader extends URLClassLoader {
       
    46     /**
       
    47      * List of package prefixes we want to mask the
       
    48      * parent classLoader from loading
       
    49      */
       
    50     private final String[] packagePrefixes;
       
    51 
       
    52     /**
       
    53      *
       
    54      * @param packagePrefixes
       
    55      *      The package prefixes that are forced to resolve within this class loader.
       
    56      * @param parent
       
    57      *      The parent class loader to delegate to. Null to indicate bootstrap classloader.
       
    58      */
       
    59     public ApClassLoader(@Nullable ClassLoader parent, String[] packagePrefixes) throws ToolsJarNotFoundException {
       
    60         super(getToolsJar(parent),parent);
       
    61         if(getURLs().length==0)
       
    62             // if tools.jar was found in our classloader, no need to create
       
    63             // a parallel classes
       
    64             this.packagePrefixes = new String[0];
       
    65         else
       
    66             this.packagePrefixes = packagePrefixes;
       
    67     }
       
    68 
       
    69     public Class loadClass(String className) throws ClassNotFoundException {
       
    70         for( String prefix : packagePrefixes ) {
       
    71             if (className.startsWith(prefix) ) {
       
    72                 // we need to load those classes in this class loader
       
    73                 // without delegation.
       
    74                 return findClass(className);
       
    75             }
       
    76         }
       
    77 
       
    78         return super.loadClass(className);
       
    79 
       
    80     }
       
    81 
       
    82     protected Class findClass(String name) throws ClassNotFoundException {
       
    83 
       
    84         StringBuilder sb = new StringBuilder(name.length() + 6);
       
    85         sb.append(name.replace('.','/')).append(".class");
       
    86 
       
    87         InputStream is = getResourceAsStream(sb.toString());
       
    88         if (is==null)
       
    89             throw new ClassNotFoundException("Class not found" + sb);
       
    90 
       
    91         try {
       
    92             ByteArrayOutputStream baos = new ByteArrayOutputStream();
       
    93             byte[] buf = new byte[1024];
       
    94             int len;
       
    95             while((len=is.read(buf))>=0)
       
    96                 baos.write(buf,0,len);
       
    97 
       
    98             buf = baos.toByteArray();
       
    99 
       
   100             // define package if not defined yet
       
   101             int i = name.lastIndexOf('.');
       
   102             if (i != -1) {
       
   103                 String pkgname = name.substring(0, i);
       
   104                 Package pkg = getPackage(pkgname);
       
   105                 if(pkg==null)
       
   106                     definePackage(pkgname, null, null, null, null, null, null, null);
       
   107             }
       
   108 
       
   109             return defineClass(name,buf,0,buf.length);
       
   110         } catch (IOException e) {
       
   111             throw new ClassNotFoundException(name,e);
       
   112         } finally {
       
   113             try {
       
   114                 is.close();
       
   115             } catch (IOException ioe) {
       
   116                 //ignore
       
   117             }
       
   118         }
       
   119     }
       
   120 
       
   121     /**
       
   122      * Returns a class loader that can load classes from JDK tools.jar.
       
   123      * @param parent
       
   124      */
       
   125     private static URL[] getToolsJar(@Nullable ClassLoader parent) throws ToolsJarNotFoundException {
       
   126 
       
   127         try {
       
   128             Class.forName("com.sun.tools.javac.Main", false, parent);
       
   129             return new URL[0];
       
   130             // we can already load them in the parent class loader.
       
   131             // so no need to look for tools.jar.
       
   132             // this happens when we are run inside IDE/Ant, or
       
   133             // in Mac OS.
       
   134         } catch (ClassNotFoundException e) {
       
   135             // otherwise try to find tools.jar
       
   136         }
       
   137 
       
   138         File jreHome = new File(System.getProperty("java.home"));
       
   139         File toolsJar = new File( jreHome.getParent(), "lib/tools.jar" );
       
   140 
       
   141         if (!toolsJar.exists()) {
       
   142             throw new ToolsJarNotFoundException(toolsJar);
       
   143         }
       
   144 
       
   145         try {
       
   146             return new URL[]{toolsJar.toURL()};
       
   147         } catch (MalformedURLException e) {
       
   148             // impossible
       
   149             throw new AssertionError(e);
       
   150         }
       
   151     }
       
   152 }