You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ClassPath.java 11KB

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