1 /*
   2  * Copyright (c) 2000, 2004, 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 package sun.rmi.rmic.iiop;
  26 
  27 import java.io.*;
  28 import sun.tools.java.ClassPath ;
  29 import sun.tools.java.ClassFile ;
  30 
  31 /**
  32  * A ClassLoader that will ultimately use a given sun.tools.java.ClassPath to
  33  * find the desired file.  This works for any JAR files specified in the given
  34  * ClassPath as well -- reusing all of that wonderful sun.tools.java code.
  35  *
  36  *@author Everett Anderson
  37  */
  38 public class ClassPathLoader extends ClassLoader
  39 {
  40     private ClassPath classPath;
  41 
  42     public ClassPathLoader(ClassPath classPath) {
  43         this.classPath = classPath;
  44     }
  45 
  46     // Called by the super class
  47     protected Class findClass(String name) throws ClassNotFoundException
  48     {
  49         byte[] b = loadClassData(name);
  50         return defineClass(name, b, 0, b.length);
  51     }
  52 
  53     /**
  54      * Load the class with the given fully qualified name from the ClassPath.
  55      */
  56     private byte[] loadClassData(String className)
  57         throws ClassNotFoundException
  58     {
  59         // Build the file name and subdirectory from the
  60         // class name
  61         String filename = className.replace('.', File.separatorChar)
  62                           + ".class";
  63 
  64         // Have ClassPath find the file for us, and wrap it in a
  65         // ClassFile.  Note:  This is where it looks inside jar files that
  66         // are specified in the path.
  67         ClassFile classFile = classPath.getFile(filename);
  68 
  69         if (classFile != null) {
  70 
  71             // Provide the most specific reason for failure in addition
  72             // to ClassNotFound
  73             Exception reportedError = null;
  74             byte data[] = null;
  75 
  76             try {
  77                 // ClassFile is beautiful because it shields us from
  78                 // knowing if it's a separate file or an entry in a
  79                 // jar file.
  80                 DataInputStream input
  81                     = new DataInputStream(classFile.getInputStream());
  82 
  83                 // Can't rely on input available() since it will be
  84                 // something unusual if it's a jar file!  May need
  85                 // to worry about a possible problem if someone
  86                 // makes a jar file entry with a size greater than
  87                 // max int.
  88                 data = new byte[(int)classFile.length()];
  89 
  90                 try {
  91                     input.readFully(data);
  92                 } catch (IOException ex) {
  93                     // Something actually went wrong reading the file.  This
  94                     // is a real error so save it to report it.
  95                     data = null;
  96                     reportedError = ex;
  97                 } finally {
  98                     // Just don't care if there's an exception on close!
  99                     // I hate that close can throw an IOException!
 100                     try { input.close(); } catch (IOException ex) {}
 101                 }
 102             } catch (IOException ex) {
 103                 // Couldn't get the input stream for the file.  This is
 104                 // probably also a real error.
 105                 reportedError = ex;
 106             }
 107 
 108             if (data == null)
 109                 throw new ClassNotFoundException(className, reportedError);
 110 
 111             return data;
 112         }
 113 
 114         // Couldn't find the file in the class path.
 115         throw new ClassNotFoundException(className);
 116     }
 117 }