1 /* 2 * reserved comment block 3 * DO NOT REMOVE OR ALTER! 4 */ 5 package com.sun.org.apache.bcel.internal.util; 6 7 /* ==================================================================== 8 * The Apache Software License, Version 1.1 9 * 10 * Copyright (c) 2001 The Apache Software Foundation. All rights 11 * reserved. 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions 15 * are met: 16 * 17 * 1. Redistributions of source code must retain the above copyright 18 * notice, this list of conditions and the following disclaimer. 19 * 20 * 2. Redistributions in binary form must reproduce the above copyright 21 * notice, this list of conditions and the following disclaimer in 22 * the documentation and/or other materials provided with the 23 * distribution. 24 * 25 * 3. The end-user documentation included with the redistribution, 26 * if any, must include the following acknowledgment: 27 * "This product includes software developed by the 28 * Apache Software Foundation (http://www.apache.org/)." 29 * Alternately, this acknowledgment may appear in the software itself, 30 * if and wherever such third-party acknowledgments normally appear. 31 * 32 * 4. The names "Apache" and "Apache Software Foundation" and 33 * "Apache BCEL" must not be used to endorse or promote products 34 * derived from this software without prior written permission. For 35 * written permission, please contact apache@apache.org. 36 * 37 * 5. Products derived from this software may not be called "Apache", 38 * "Apache BCEL", nor may "Apache" appear in their name, without 39 * prior written permission of the Apache Software Foundation. 40 * 41 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 42 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 43 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 44 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR 45 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 46 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 47 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 48 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 49 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 50 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 51 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 52 * SUCH DAMAGE. 53 * ==================================================================== 54 * 55 * This software consists of voluntary contributions made by many 56 * individuals on behalf of the Apache Software Foundation. For more 57 * information on the Apache Software Foundation, please see 58 * <http://www.apache.org/>. 59 */ 60 61 import java.util.*; 62 import java.util.zip.*; 63 import java.io.*; 64 65 /** 66 * Responsible for loading (class) files from the CLASSPATH. Inspired by 67 * sun.tools.ClassPath. 68 * 69 * @version $Id: ClassPath.java,v 1.4 2007-07-19 04:34:52 ofung Exp $ 70 * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> 71 */ 72 public class ClassPath implements Serializable { 73 public static final ClassPath SYSTEM_CLASS_PATH = new ClassPath(); 74 75 private PathEntry[] paths; 76 private String class_path; 77 78 /** 79 * Search for classes in given path. 80 */ ClassPath(String class_path)81 public ClassPath(String class_path) { 82 this.class_path = class_path; 83 84 ArrayList vec = new ArrayList(); 85 86 for(StringTokenizer tok=new StringTokenizer(class_path, 87 SecuritySupport.getSystemProperty("path.separator")); 88 tok.hasMoreTokens();) 89 { 90 String path = tok.nextToken(); 91 92 if(!path.equals("")) { 93 File file = new File(path); 94 95 try { 96 if(SecuritySupport.getFileExists(file)) { 97 if(file.isDirectory()) 98 vec.add(new Dir(path)); 99 else 100 vec.add(new Zip(new ZipFile(file))); 101 } 102 } catch(IOException e) { 103 System.err.println("CLASSPATH component " + file + ": " + e); 104 } 105 } 106 } 107 108 paths = new PathEntry[vec.size()]; 109 vec.toArray(paths); 110 } 111 112 /** 113 * Search for classes in CLASSPATH. 114 * @deprecated Use SYSTEM_CLASS_PATH constant 115 */ ClassPath()116 public ClassPath() { 117 // this(getClassPath()); 118 this(""); 119 } 120 121 /** @return used class path string 122 */ toString()123 public String toString() { 124 return class_path; 125 } 126 hashCode()127 public int hashCode() { 128 return class_path.hashCode(); 129 } 130 equals(Object o)131 public boolean equals(Object o) { 132 if(o instanceof ClassPath) { 133 return class_path.equals(((ClassPath)o).class_path); 134 } 135 136 return false; 137 } 138 getPathComponents(String path, ArrayList list)139 private static final void getPathComponents(String path, ArrayList list) { 140 if(path != null) { 141 StringTokenizer tok = new StringTokenizer(path, File.pathSeparator); 142 143 while(tok.hasMoreTokens()) { 144 String name = tok.nextToken(); 145 File file = new File(name); 146 147 if(SecuritySupport.getFileExists(file)) { 148 list.add(name); 149 } 150 } 151 } 152 } 153 154 /** Checks for class path components in the following properties: 155 * "java.class.path", "sun.boot.class.path", "java.ext.dirs" 156 * 157 * @return class path as used by default by BCEL 158 */ getClassPath()159 public static final String getClassPath() { 160 161 String class_path, boot_path, ext_path; 162 163 try { 164 class_path = SecuritySupport.getSystemProperty("java.class.path"); 165 boot_path = SecuritySupport.getSystemProperty("sun.boot.class.path"); 166 ext_path = SecuritySupport.getSystemProperty("java.ext.dirs"); 167 } 168 catch (SecurityException e) { 169 return ""; 170 } 171 172 ArrayList list = new ArrayList(); 173 174 getPathComponents(class_path, list); 175 getPathComponents(boot_path, list); 176 177 ArrayList dirs = new ArrayList(); 178 getPathComponents(ext_path, dirs); 179 180 for(Iterator e = dirs.iterator(); e.hasNext(); ) { 181 File ext_dir = new File((String)e.next()); 182 String[] extensions = SecuritySupport.getFileList(ext_dir, new FilenameFilter() { 183 public boolean accept(File dir, String name) { 184 name = name.toLowerCase(); 185 return name.endsWith(".zip") || name.endsWith(".jar"); 186 } 187 }); 188 189 if(extensions != null) 190 for(int i=0; i < extensions.length; i++) 191 list.add(ext_path + File.separatorChar + extensions[i]); 192 } 193 194 StringBuffer buf = new StringBuffer(); 195 196 for(Iterator e = list.iterator(); e.hasNext(); ) { 197 buf.append((String)e.next()); 198 199 if(e.hasNext()) 200 buf.append(File.pathSeparatorChar); 201 } 202 203 return buf.toString().intern(); 204 } 205 206 /** 207 * @param name fully qualified class name, e.g. java.lang.String 208 * @return input stream for class 209 */ getInputStream(String name)210 public InputStream getInputStream(String name) throws IOException { 211 return getInputStream(name, ".class"); 212 } 213 214 /** 215 * Return stream for class or resource on CLASSPATH. 216 * 217 * @param name fully qualified file name, e.g. java/lang/String 218 * @param suffix file name ends with suff, e.g. .java 219 * @return input stream for file on class path 220 */ getInputStream(String name, String suffix)221 public InputStream getInputStream(String name, String suffix) throws IOException { 222 InputStream is = null; 223 224 try { 225 is = getClass().getClassLoader().getResourceAsStream(name + suffix); 226 } catch(Exception e) { } 227 228 if(is != null) 229 return is; 230 231 return getClassFile(name, suffix).getInputStream(); 232 } 233 234 /** 235 * @param name fully qualified file name, e.g. java/lang/String 236 * @param suffix file name ends with suff, e.g. .java 237 * @return class file for the java class 238 */ getClassFile(String name, String suffix)239 public ClassFile getClassFile(String name, String suffix) throws IOException { 240 for(int i=0; i < paths.length; i++) { 241 ClassFile cf; 242 243 if((cf = paths[i].getClassFile(name, suffix)) != null) 244 return cf; 245 } 246 247 throw new IOException("Couldn't find: " + name + suffix); 248 } 249 250 /** 251 * @param name fully qualified class name, e.g. java.lang.String 252 * @return input stream for class 253 */ getClassFile(String name)254 public ClassFile getClassFile(String name) throws IOException { 255 return getClassFile(name, ".class"); 256 } 257 258 /** 259 * @param name fully qualified file name, e.g. java/lang/String 260 * @param suffix file name ends with suffix, e.g. .java 261 * @return byte array for file on class path 262 */ getBytes(String name, String suffix)263 public byte[] getBytes(String name, String suffix) throws IOException { 264 InputStream is = getInputStream(name, suffix); 265 266 if(is == null) 267 throw new IOException("Couldn't find: " + name + suffix); 268 269 DataInputStream dis = new DataInputStream(is); 270 byte[] bytes = new byte[is.available()]; 271 dis.readFully(bytes); 272 dis.close(); is.close(); 273 274 return bytes; 275 } 276 277 /** 278 * @return byte array for class 279 */ getBytes(String name)280 public byte[] getBytes(String name) throws IOException { 281 return getBytes(name, ".class"); 282 } 283 284 /** 285 * @param name name of file to search for, e.g. java/lang/String.java 286 * @return full (canonical) path for file 287 */ getPath(String name)288 public String getPath(String name) throws IOException { 289 int index = name.lastIndexOf('.'); 290 String suffix = ""; 291 292 if(index > 0) { 293 suffix = name.substring(index); 294 name = name.substring(0, index); 295 } 296 297 return getPath(name, suffix); 298 } 299 300 /** 301 * @param name name of file to search for, e.g. java/lang/String 302 * @param suffix file name suffix, e.g. .java 303 * @return full (canonical) path for file, if it exists 304 */ getPath(String name, String suffix)305 public String getPath(String name, String suffix) throws IOException { 306 return getClassFile(name, suffix).getPath(); 307 } 308 309 private static abstract class PathEntry implements Serializable { getClassFile(String name, String suffix)310 abstract ClassFile getClassFile(String name, String suffix) throws IOException; 311 } 312 313 /** Contains information about file/ZIP entry of the Java class. 314 */ 315 public interface ClassFile { 316 /** @return input stream for class file. 317 */ getInputStream()318 public abstract InputStream getInputStream() throws IOException; 319 320 /** @return canonical path to class file. 321 */ getPath()322 public abstract String getPath(); 323 324 /** @return base path of found class, i.e. class is contained relative 325 * to that path, which may either denote a directory, or zip file 326 */ getBase()327 public abstract String getBase(); 328 329 /** @return modification time of class file. 330 */ getTime()331 public abstract long getTime(); 332 333 /** @return size of class file. 334 */ getSize()335 public abstract long getSize(); 336 } 337 338 private static class Dir extends PathEntry { 339 private String dir; 340 Dir(String d)341 Dir(String d) { dir = d; } 342 getClassFile(String name, String suffix)343 ClassFile getClassFile(String name, String suffix) throws IOException { 344 final File file = new File(dir + File.separatorChar + 345 name.replace('.', File.separatorChar) + suffix); 346 347 return SecuritySupport.getFileExists(file)? new ClassFile() { 348 public InputStream getInputStream() throws IOException { return new FileInputStream(file); } 349 350 public String getPath() { try { 351 return file.getCanonicalPath(); 352 } catch(IOException e) { return null; } 353 354 } 355 public long getTime() { return file.lastModified(); } 356 public long getSize() { return file.length(); } 357 public String getBase() { return dir; } 358 359 } : null; 360 } 361 toString()362 public String toString() { return dir; } 363 } 364 365 private static class Zip extends PathEntry { 366 private ZipFile zip; 367 368 Zip(ZipFile z) { zip = z; } 369 370 ClassFile getClassFile(String name, String suffix) throws IOException { 371 final ZipEntry entry = zip.getEntry(name.replace('.', '/') + suffix); 372 373 return (entry != null)? new ClassFile() { 374 public InputStream getInputStream() throws IOException { return zip.getInputStream(entry); } 375 public String getPath() { return entry.toString(); } 376 public long getTime() { return entry.getTime(); } 377 public long getSize() { return entry.getSize(); } 378 public String getBase() { 379 return zip.getName(); 380 } 381 } : null; 382 } 383 } 384 } 385