1 /*
   2  * Copyright (c) 1998, 2007, 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 /*
  27  * Licensed Materials - Property of IBM
  28  * RMI-IIOP v1.0
  29  * Copyright IBM Corp. 1998 1999  All Rights Reserved
  30  *
  31  */
  32 
  33 package sun.rmi.rmic.iiop;
  34 
  35 import java.util.Hashtable;
  36 import java.io.File;
  37 import java.io.FileInputStream;
  38 
  39 /**
  40  * DirectoryLoader is a simple ClassLoader which loads from a specified
  41  * file system directory.
  42  * @author Bryan Atsatt
  43  */
  44 
  45 public class DirectoryLoader extends ClassLoader {
  46 
  47     private Hashtable cache;
  48     private File root;
  49 
  50     /**
  51      * Constructor.
  52      */
  53     public DirectoryLoader (File rootDir) {
  54         cache = new Hashtable();
  55         if (rootDir == null || !rootDir.isDirectory()) {
  56             throw new IllegalArgumentException();
  57         }
  58         root = rootDir;
  59     }
  60 
  61     private DirectoryLoader () {}
  62 
  63     /**
  64      * Convenience version of loadClass which sets 'resolve' == true.
  65      */
  66     public Class loadClass(String className) throws ClassNotFoundException {
  67         return loadClass(className, true);
  68     }
  69 
  70     /**
  71      * This is the required version of loadClass which is called
  72      * both from loadClass above and from the internal function
  73      * FindClassFromClass.
  74      */
  75     public synchronized Class loadClass(String className, boolean resolve)
  76         throws ClassNotFoundException {
  77         Class result;
  78         byte  classData[];
  79 
  80         // Do we already have it in the cache?
  81 
  82         result = (Class) cache.get(className);
  83 
  84         if (result == null) {
  85 
  86             // Nope, can we get if from the system class loader?
  87 
  88             try {
  89 
  90                 result = super.findSystemClass(className);
  91 
  92             } catch (ClassNotFoundException e) {
  93 
  94                 // No, so try loading it...
  95 
  96                 classData = getClassFileData(className);
  97 
  98                 if (classData == null) {
  99                     throw new ClassNotFoundException();
 100                 }
 101 
 102                 // Parse the class file data...
 103 
 104                 result = defineClass(classData, 0, classData.length);
 105 
 106                 if (result == null) {
 107                     throw new ClassFormatError();
 108                 }
 109 
 110                 // Resolve it...
 111 
 112                 if (resolve) resolveClass(result);
 113 
 114                 // Add to cache...
 115 
 116                 cache.put(className, result);
 117             }
 118         }
 119 
 120         return result;
 121     }
 122 
 123     /**
 124      * Reurn a byte array containing the contents of the class file.  Returns null
 125      * if an exception occurs.
 126      */
 127     private byte[] getClassFileData (String className) {
 128 
 129         byte result[] = null;
 130         FileInputStream stream = null;
 131 
 132         // Get the file...
 133 
 134         File classFile = new File(root,className.replace('.',File.separatorChar) + ".class");
 135 
 136         // Now get the bits...
 137 
 138         try {
 139             stream = new FileInputStream(classFile);
 140             result = new byte[stream.available()];
 141             stream.read(result);
 142         } catch(ThreadDeath death) {
 143             throw death;
 144         } catch (Throwable e) {
 145         }
 146 
 147         finally {
 148             if (stream != null) {
 149                 try {
 150                     stream.close();
 151                 } catch(ThreadDeath death) {
 152                     throw death;
 153                 } catch (Throwable e) {
 154                 }
 155             }
 156         }
 157 
 158         return result;
 159     }
 160 }