1 /* 2 * $Id$ 3 * 4 * Copyright (c) 1996, 2009, Oracle and/or its affiliates. All rights reserved. 5 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 6 * 7 * This code is free software; you can redistribute it and/or modify it 8 * under the terms of the GNU General Public License version 2 only, as 9 * published by the Free Software Foundation. Oracle designates this 10 * particular file as subject to the "Classpath" exception as provided 11 * by Oracle in the LICENSE file that accompanied this code. 12 * 13 * This code is distributed in the hope that it will be useful, but WITHOUT 14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 16 * version 2 for more details (a copy is included in the LICENSE file that 17 * accompanied this code). 18 * 19 * You should have received a copy of the GNU General Public License version 20 * 2 along with this work; if not, write to the Free Software Foundation, 21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 22 * 23 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 24 * or visit www.oracle.com if you need additional information or have any 25 * questions. 26 */ 27 package com.sun.javatest.util; 28 29 import java.io.File; 30 import java.io.FileInputStream; 31 import java.io.FileNotFoundException; 32 import java.io.InputStream; 33 import java.io.IOException; 34 import java.net.URL; 35 import java.util.Hashtable; 36 import java.util.Map; 37 38 /** 39 * This class loader loads classes from files a specified directory. 40 * @see com.sun.javatest.util.PathClassLoader 41 * @deprecated use PathClassLoader 42 */ 43 public class DirectoryClassLoader extends ClassLoader 44 { 45 /** 46 * Constructor that provides the name of the directory in which to search 47 * for a given class. 48 * 49 * @param dir The File specifying the directory to search. 50 */ 51 public DirectoryClassLoader(File dir) { 52 loadDir = dir; 53 } 54 55 /** 56 * Constructor that provides the name of the directory in which to search 57 * for a given class. 58 * 59 * @param dirName A file pathname specifying the directory to search. 60 */ 61 public DirectoryClassLoader(String dirName) { 62 loadDir = new File(dirName); 63 } 64 65 //----------ClassLoader methods--------------------------------------------- 66 67 /** 68 * Attempt to load a class if it is not already loaded, and optionally 69 * resolve any imports it might have. 70 * 71 * @param name The fully-qualified name of the class to load. 72 * @param resolve True if imports should be resolved, false otherwise. 73 * @return the class that was loaded 74 * @throws ClassNotFoundException if the class was not found. 75 */ 76 protected Class<?> loadClass(String name, boolean resolve) 77 throws ClassNotFoundException { 78 79 // check the cache first 80 Class<?> cl = classes.get(name); 81 82 // not found in the cache? 83 if (cl == null) { 84 // see if it is a system class 85 try { 86 cl = findSystemClass(name); 87 } 88 catch (ClassNotFoundException e) { 89 // It's not a system class, look in the directory for this 90 // class loader. If there is an IO problem, we'll throw 91 // ClassNotFoundException; if the class file is read correctly 92 // but is an invalid class, we'll get a LinkageError 93 cl = locateClass(name); 94 } 95 } 96 97 if (resolve) 98 resolveClass(cl); 99 100 return cl; 101 102 } 103 104 /** 105 * Returns an input stream for reading the specified resource. 106 * 107 * @param name the resource name 108 * @return an input stream for reading the resource, or <code>null</code> 109 * if the resource could not be found 110 * 111 * redundant in 1.2 112 */ 113 public InputStream getResourceAsStream(String name) { 114 URL url = getResource(name); 115 try { 116 return url != null ? url.openStream() : null; 117 } catch (IOException e) { 118 return null; 119 } 120 } 121 122 /** 123 * Finds the resource with the given name. A resource is some data 124 * (images, audio, text, etc) that can be accessed by class code 125 * in a way that is independent of the location of the code. 126 * <p> 127 * The name of a resource is a "/"-separated path name that identifies 128 * the resource. 129 * <p> 130 * This method will first search the parent class loader for the 131 * resource, then call <code>findResource</code> to find the 132 * resource. 133 * 134 * @param name resource name 135 * @return a URL for reading the resource, or <code>null</code> if 136 * the resource could not be found or the caller doesn't have 137 * adequate privileges to get the resource. 138 * 139 * redundant in 1.2 140 */ 141 public URL getResource(String name) { 142 // the ordering of this code looks very strange, but it 143 // corresponds to the implementation in JDK 1.2. 144 URL url = getSystemResource(name); 145 if (url == null) { 146 url = findResource(name); 147 } 148 return url; 149 } 150 151 /** 152 * Finds the resource with the given name. Class loader 153 * implementations should override this method to specify where to 154 * find resources. 155 * 156 * @param name the resource name 157 * @return a URL for reading the resource, or <code>null</code> 158 * if the resource could not be found 159 * @since JDK1.2 160 */ 161 public URL findResource(String name) { 162 try { 163 File f = new File(loadDir, name); 164 if (f.exists()) 165 return new URL("file:" + f.getAbsolutePath()); 166 else 167 return null; 168 } 169 catch (java.net.MalformedURLException e) { 170 return null; 171 } 172 } 173 174 //----------internal methods------------------------------------------------ 175 176 private synchronized Class<?> locateClass(String name) 177 throws ClassNotFoundException { 178 //This check is currently necessary; we just 179 // check the cache at the one call site, but that was not 180 // synchronized, so there is a very small remote chance another 181 // caller has just loaded this class. 182 Class<?> cl = classes.get(name); 183 if (cl != null) 184 return cl; 185 186 String cname = name.replace('.', '/') + ".class"; 187 188 File file = new File(loadDir, cname); 189 190 try { 191 byte[] data; 192 try (InputStream in = new FileInputStream(file)) { 193 int len = in.available(); 194 data = new byte[len]; 195 for (int total = 0; total < data.length; ) { 196 total += in.read(data, total, data.length - total); 197 } 198 } 199 // the next line may throw LinkageError, which we let 200 // escape to the caller 201 cl = defineClass(name, data, 0, data.length); 202 classes.put(name, cl); 203 return cl; 204 } 205 catch (FileNotFoundException e) { 206 // ClassNotFoundException is obviously the correct 207 // exception to throw in this case 208 throw new ClassNotFoundException(name); 209 } 210 catch (IOException e) { 211 // This one is more iffy; we found a file, but had trouble 212 // reading it; still use ClassNotFoundException for now. 213 throw new ClassNotFoundException(name); 214 } 215 216 } 217 218 //----------Data members---------------------------------------------------- 219 220 private File loadDir; 221 private Map<String, Class<?>> classes = new Hashtable<>(); 222 }