1. package com.sun.org.apache.bcel.internal.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.1 2003/12/12 09:01:32 rameshm Exp $
  63. * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
  64. */
  65. public class ClassPath {
  66. private PathEntry[] paths;
  67. /**
  68. * Search for classes in given path.
  69. */
  70. public ClassPath(String class_path) {
  71. ArrayList vec = new ArrayList();
  72. for(StringTokenizer tok=new StringTokenizer(class_path,
  73. java.io.File.pathSeparator);
  74. tok.hasMoreTokens();)
  75. {
  76. String path = tok.nextToken();
  77. if(!path.equals("")) {
  78. File file = new File(path);
  79. try {
  80. if(file.exists()) {
  81. if(file.isDirectory())
  82. vec.add(new Dir(path));
  83. else
  84. vec.add(new Zip(new ZipFile(file)));
  85. }
  86. } catch(IOException e) {
  87. System.err.println("CLASSPATH component " + file + ": " + e);
  88. }
  89. }
  90. }
  91. paths = new PathEntry[vec.size()];
  92. vec.toArray(paths);
  93. }
  94. /**
  95. * Search for classes in CLASSPATH.
  96. */
  97. public ClassPath() {
  98. this(getClassPath());
  99. }
  100. private static final void getPathComponents(String path, ArrayList list) {
  101. if(path != null) {
  102. StringTokenizer tok = new StringTokenizer(path, File.pathSeparator);
  103. while(tok.hasMoreTokens()) {
  104. String name = tok.nextToken();
  105. File file = new File(name);
  106. if(file.exists())
  107. list.add(name);
  108. }
  109. }
  110. }
  111. private static final String getClassPath() {
  112. String class_path = System.getProperty("java.class.path");
  113. String boot_path = System.getProperty("sun.boot.class.path");
  114. String ext_path = System.getProperty("java.ext.dirs");
  115. ArrayList list = new ArrayList();
  116. getPathComponents(class_path, list);
  117. getPathComponents(boot_path, list);
  118. ArrayList dirs = new ArrayList();
  119. getPathComponents(ext_path, dirs);
  120. for(Iterator e = dirs.iterator(); e.hasNext(); ) {
  121. File ext_dir = new File((String)e.next());
  122. String[] extensions = ext_dir.list(new FilenameFilter() {
  123. public boolean accept(File dir, String name) {
  124. name = name.toLowerCase();
  125. return name.endsWith(".zip") || name.endsWith(".jar");
  126. }
  127. });
  128. if(extensions != null)
  129. for(int i=0; i < extensions.length; i++)
  130. list.add(ext_path + File.separatorChar + extensions[i]);
  131. }
  132. StringBuffer buf = new StringBuffer();
  133. for(Iterator e = list.iterator(); e.hasNext(); ) {
  134. buf.append((String)e.next());
  135. if(e.hasNext())
  136. buf.append(File.pathSeparatorChar);
  137. }
  138. return buf.toString();
  139. }
  140. /**
  141. * @param name fully qualified class name, e.g. java.lang.String
  142. * @return input stream for class
  143. */
  144. public InputStream getInputStream(String name) throws IOException {
  145. return getInputStream(name, ".class");
  146. }
  147. /**
  148. * @param name fully qualified file name, e.g. java/lang/String
  149. * @param suffix file name ends with suff, e.g. .java
  150. * @return input stream for file on class path
  151. */
  152. public InputStream getInputStream(String name, String suffix) throws IOException {
  153. return getClassFile(name, suffix).getInputStream();
  154. }
  155. /**
  156. * @param name fully qualified file name, e.g. java/lang/String
  157. * @param suffix file name ends with suff, e.g. .java
  158. * @return class file for the java class
  159. */
  160. public ClassFile getClassFile(String name, String suffix) throws IOException {
  161. for(int i=0; i < paths.length; i++) {
  162. ClassFile cf;
  163. if((cf = paths[i].getClassFile(name, suffix)) != null)
  164. return cf;
  165. }
  166. throw new IOException("Couldn't find: " + name + suffix);
  167. }
  168. /**
  169. * @param name fully qualified class name, e.g. java.lang.String
  170. * @return input stream for class
  171. */
  172. public ClassFile getClassFile(String name) throws IOException {
  173. return getClassFile(name, ".class");
  174. }
  175. /**
  176. * @param name fully qualified file name, e.g. java/lang/String
  177. * @param suffix file name ends with suffix, e.g. .java
  178. * @return byte array for file on class path
  179. */
  180. public byte[] getBytes(String name, String suffix) throws IOException {
  181. InputStream is = getInputStream(name, suffix);
  182. if(is == null)
  183. throw new IOException("Couldn't find: " + name + suffix);
  184. DataInputStream dis = new DataInputStream(is);
  185. byte[] bytes = new byte[is.available()];
  186. dis.readFully(bytes);
  187. dis.close(); is.close();
  188. return bytes;
  189. }
  190. /**
  191. * @return byte array for class
  192. */
  193. public byte[] getBytes(String name) throws IOException {
  194. return getBytes(name, ".class");
  195. }
  196. /**
  197. * @param name name of file to search for, e.g. java/lang/String.java
  198. * @return full (canonical) path for file
  199. */
  200. public String getPath(String name) throws IOException {
  201. int index = name.lastIndexOf('.');
  202. String suffix = "";
  203. if(index > 0) {
  204. suffix = name.substring(index);
  205. name = name.substring(0, index);
  206. }
  207. return getPath(name, suffix);
  208. }
  209. /**
  210. * @param name name of file to search for, e.g. java/lang/String
  211. * @param suffix file name suffix, e.g. .java
  212. * @return full (canonical) path for file, if it exists
  213. */
  214. public String getPath(String name, String suffix) throws IOException {
  215. return getClassFile(name, suffix).getPath();
  216. }
  217. private static abstract class PathEntry {
  218. abstract ClassFile getClassFile(String name, String suffix) throws IOException;
  219. }
  220. /** Contains information about file/ZIP entry of the Java class.
  221. */
  222. public abstract static class ClassFile {
  223. /** @return input stream for class file.
  224. */
  225. public abstract InputStream getInputStream() throws IOException;
  226. /** @return canonical path to class file.
  227. */
  228. public abstract String getPath();
  229. /** @return modification time of class file.
  230. */
  231. public abstract long getTime();
  232. /** @return size of class file.
  233. */
  234. public abstract long getSize();
  235. }
  236. private static class Dir extends PathEntry {
  237. private String dir;
  238. Dir(String d) { dir = d; }
  239. ClassFile getClassFile(String name, String suffix) throws IOException {
  240. final File file = new File(dir + File.separatorChar +
  241. name.replace('.', File.separatorChar) + suffix);
  242. return file.exists()? new ClassFile() {
  243. public InputStream getInputStream() throws IOException { return new FileInputStream(file); }
  244. public String getPath() { try {
  245. return file.getCanonicalPath();
  246. } catch(IOException e) { return null; }
  247. }
  248. public long getTime() { return file.lastModified(); }
  249. public long getSize() { return file.length(); }
  250. } : null;
  251. }
  252. public String toString() { return dir; }
  253. }
  254. private static class Zip extends PathEntry {
  255. private ZipFile zip;
  256. Zip(ZipFile z) { zip = z; }
  257. ClassFile getClassFile(String name, String suffix) throws IOException {
  258. final ZipEntry entry = zip.getEntry(name.replace('.', '/') + suffix);
  259. return (entry != null)? new ClassFile() {
  260. public InputStream getInputStream() throws IOException { return zip.getInputStream(entry); }
  261. public String getPath() { return entry.toString(); }
  262. public long getTime() { return entry.getTime(); }
  263. public long getSize() { return entry.getSize(); }
  264. } : null;
  265. }
  266. }
  267. }