|
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 * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> |
|
70 */ |
|
71 public class ClassPath implements Serializable { |
|
72 public static final ClassPath SYSTEM_CLASS_PATH = new ClassPath(); |
|
73 |
|
74 private PathEntry[] paths; |
|
75 private String class_path; |
|
76 |
|
77 /** |
|
78 * Search for classes in given path. |
|
79 */ |
|
80 public ClassPath(String class_path) { |
|
81 this.class_path = class_path; |
|
82 |
|
83 ArrayList vec = new ArrayList(); |
|
84 |
|
85 for(StringTokenizer tok=new StringTokenizer(class_path, |
|
86 System.getProperty("path.separator")); |
|
87 tok.hasMoreTokens();) |
|
88 { |
|
89 String path = tok.nextToken(); |
|
90 |
|
91 if(!path.equals("")) { |
|
92 File file = new File(path); |
|
93 |
|
94 try { |
|
95 if(file.exists()) { |
|
96 if(file.isDirectory()) |
|
97 vec.add(new Dir(path)); |
|
98 else |
|
99 vec.add(new Zip(new ZipFile(file))); |
|
100 } |
|
101 } catch(IOException e) { |
|
102 System.err.println("CLASSPATH component " + file + ": " + e); |
|
103 } |
|
104 } |
|
105 } |
|
106 |
|
107 paths = new PathEntry[vec.size()]; |
|
108 vec.toArray(paths); |
|
109 } |
|
110 |
|
111 /** |
|
112 * Search for classes in CLASSPATH. |
|
113 * @deprecated Use SYSTEM_CLASS_PATH constant |
|
114 */ |
|
115 public ClassPath() { |
|
116 // this(getClassPath()); |
|
117 this(""); |
|
118 } |
|
119 |
|
120 /** @return used class path string |
|
121 */ |
|
122 public String toString() { |
|
123 return class_path; |
|
124 } |
|
125 |
|
126 public int hashCode() { |
|
127 return class_path.hashCode(); |
|
128 } |
|
129 |
|
130 public boolean equals(Object o) { |
|
131 if(o instanceof ClassPath) { |
|
132 return class_path.equals(((ClassPath)o).class_path); |
|
133 } |
|
134 |
|
135 return false; |
|
136 } |
|
137 |
|
138 private static final void getPathComponents(String path, ArrayList list) { |
|
139 if(path != null) { |
|
140 StringTokenizer tok = new StringTokenizer(path, File.pathSeparator); |
|
141 |
|
142 while(tok.hasMoreTokens()) { |
|
143 String name = tok.nextToken(); |
|
144 File file = new File(name); |
|
145 |
|
146 if(file.exists()) |
|
147 list.add(name); |
|
148 } |
|
149 } |
|
150 } |
|
151 |
|
152 /** Checks for class path components in the following properties: |
|
153 * "java.class.path", "sun.boot.class.path", "java.ext.dirs" |
|
154 * |
|
155 * @return class path as used by default by BCEL |
|
156 */ |
|
157 public static final String getClassPath() { |
|
158 |
|
159 String class_path, boot_path, ext_path; |
|
160 |
|
161 try { |
|
162 class_path = System.getProperty("java.class.path"); |
|
163 boot_path = System.getProperty("sun.boot.class.path"); |
|
164 ext_path = System.getProperty("java.ext.dirs"); |
|
165 } |
|
166 catch (SecurityException e) { |
|
167 return ""; |
|
168 } |
|
169 |
|
170 ArrayList list = new ArrayList(); |
|
171 |
|
172 getPathComponents(class_path, list); |
|
173 getPathComponents(boot_path, list); |
|
174 |
|
175 ArrayList dirs = new ArrayList(); |
|
176 getPathComponents(ext_path, dirs); |
|
177 |
|
178 for(Iterator e = dirs.iterator(); e.hasNext(); ) { |
|
179 File ext_dir = new File((String)e.next()); |
|
180 String[] extensions = ext_dir.list(new FilenameFilter() { |
|
181 public boolean accept(File dir, String name) { |
|
182 name = name.toLowerCase(); |
|
183 return name.endsWith(".zip") || name.endsWith(".jar"); |
|
184 } |
|
185 }); |
|
186 |
|
187 if(extensions != null) |
|
188 for(int i=0; i < extensions.length; i++) |
|
189 list.add(ext_path + File.separatorChar + extensions[i]); |
|
190 } |
|
191 |
|
192 StringBuffer buf = new StringBuffer(); |
|
193 |
|
194 for(Iterator e = list.iterator(); e.hasNext(); ) { |
|
195 buf.append((String)e.next()); |
|
196 |
|
197 if(e.hasNext()) |
|
198 buf.append(File.pathSeparatorChar); |
|
199 } |
|
200 |
|
201 return buf.toString().intern(); |
|
202 } |
|
203 |
|
204 /** |
|
205 * @param name fully qualified class name, e.g. java.lang.String |
|
206 * @return input stream for class |
|
207 */ |
|
208 public InputStream getInputStream(String name) throws IOException { |
|
209 return getInputStream(name, ".class"); |
|
210 } |
|
211 |
|
212 /** |
|
213 * Return stream for class or resource on CLASSPATH. |
|
214 * |
|
215 * @param name fully qualified file name, e.g. java/lang/String |
|
216 * @param suffix file name ends with suff, e.g. .java |
|
217 * @return input stream for file on class path |
|
218 */ |
|
219 public InputStream getInputStream(String name, String suffix) throws IOException { |
|
220 InputStream is = null; |
|
221 |
|
222 try { |
|
223 is = getClass().getClassLoader().getResourceAsStream(name + suffix); |
|
224 } catch(Exception e) { } |
|
225 |
|
226 if(is != null) |
|
227 return is; |
|
228 |
|
229 return getClassFile(name, suffix).getInputStream(); |
|
230 } |
|
231 |
|
232 /** |
|
233 * @param name fully qualified file name, e.g. java/lang/String |
|
234 * @param suffix file name ends with suff, e.g. .java |
|
235 * @return class file for the java class |
|
236 */ |
|
237 public ClassFile getClassFile(String name, String suffix) throws IOException { |
|
238 for(int i=0; i < paths.length; i++) { |
|
239 ClassFile cf; |
|
240 |
|
241 if((cf = paths[i].getClassFile(name, suffix)) != null) |
|
242 return cf; |
|
243 } |
|
244 |
|
245 throw new IOException("Couldn't find: " + name + suffix); |
|
246 } |
|
247 |
|
248 /** |
|
249 * @param name fully qualified class name, e.g. java.lang.String |
|
250 * @return input stream for class |
|
251 */ |
|
252 public ClassFile getClassFile(String name) throws IOException { |
|
253 return getClassFile(name, ".class"); |
|
254 } |
|
255 |
|
256 /** |
|
257 * @param name fully qualified file name, e.g. java/lang/String |
|
258 * @param suffix file name ends with suffix, e.g. .java |
|
259 * @return byte array for file on class path |
|
260 */ |
|
261 public byte[] getBytes(String name, String suffix) throws IOException { |
|
262 InputStream is = getInputStream(name, suffix); |
|
263 |
|
264 if(is == null) |
|
265 throw new IOException("Couldn't find: " + name + suffix); |
|
266 |
|
267 DataInputStream dis = new DataInputStream(is); |
|
268 byte[] bytes = new byte[is.available()]; |
|
269 dis.readFully(bytes); |
|
270 dis.close(); is.close(); |
|
271 |
|
272 return bytes; |
|
273 } |
|
274 |
|
275 /** |
|
276 * @return byte array for class |
|
277 */ |
|
278 public byte[] getBytes(String name) throws IOException { |
|
279 return getBytes(name, ".class"); |
|
280 } |
|
281 |
|
282 /** |
|
283 * @param name name of file to search for, e.g. java/lang/String.java |
|
284 * @return full (canonical) path for file |
|
285 */ |
|
286 public String getPath(String name) throws IOException { |
|
287 int index = name.lastIndexOf('.'); |
|
288 String suffix = ""; |
|
289 |
|
290 if(index > 0) { |
|
291 suffix = name.substring(index); |
|
292 name = name.substring(0, index); |
|
293 } |
|
294 |
|
295 return getPath(name, suffix); |
|
296 } |
|
297 |
|
298 /** |
|
299 * @param name name of file to search for, e.g. java/lang/String |
|
300 * @param suffix file name suffix, e.g. .java |
|
301 * @return full (canonical) path for file, if it exists |
|
302 */ |
|
303 public String getPath(String name, String suffix) throws IOException { |
|
304 return getClassFile(name, suffix).getPath(); |
|
305 } |
|
306 |
|
307 private static abstract class PathEntry implements Serializable { |
|
308 abstract ClassFile getClassFile(String name, String suffix) throws IOException; |
|
309 } |
|
310 |
|
311 /** Contains information about file/ZIP entry of the Java class. |
|
312 */ |
|
313 public interface ClassFile { |
|
314 /** @return input stream for class file. |
|
315 */ |
|
316 public abstract InputStream getInputStream() throws IOException; |
|
317 |
|
318 /** @return canonical path to class file. |
|
319 */ |
|
320 public abstract String getPath(); |
|
321 |
|
322 /** @return base path of found class, i.e. class is contained relative |
|
323 * to that path, which may either denote a directory, or zip file |
|
324 */ |
|
325 public abstract String getBase(); |
|
326 |
|
327 /** @return modification time of class file. |
|
328 */ |
|
329 public abstract long getTime(); |
|
330 |
|
331 /** @return size of class file. |
|
332 */ |
|
333 public abstract long getSize(); |
|
334 } |
|
335 |
|
336 private static class Dir extends PathEntry { |
|
337 private String dir; |
|
338 |
|
339 Dir(String d) { dir = d; } |
|
340 |
|
341 ClassFile getClassFile(String name, String suffix) throws IOException { |
|
342 final File file = new File(dir + File.separatorChar + |
|
343 name.replace('.', File.separatorChar) + suffix); |
|
344 |
|
345 return file.exists()? new ClassFile() { |
|
346 public InputStream getInputStream() throws IOException { return new FileInputStream(file); } |
|
347 |
|
348 public String getPath() { try { |
|
349 return file.getCanonicalPath(); |
|
350 } catch(IOException e) { return null; } |
|
351 |
|
352 } |
|
353 public long getTime() { return file.lastModified(); } |
|
354 public long getSize() { return file.length(); } |
|
355 public String getBase() { return dir; } |
|
356 |
|
357 } : null; |
|
358 } |
|
359 |
|
360 public String toString() { return dir; } |
|
361 } |
|
362 |
|
363 private static class Zip extends PathEntry { |
|
364 private ZipFile zip; |
|
365 |
|
366 Zip(ZipFile z) { zip = z; } |
|
367 |
|
368 ClassFile getClassFile(String name, String suffix) throws IOException { |
|
369 final ZipEntry entry = zip.getEntry(name.replace('.', '/') + suffix); |
|
370 |
|
371 return (entry != null)? new ClassFile() { |
|
372 public InputStream getInputStream() throws IOException { return zip.getInputStream(entry); } |
|
373 public String getPath() { return entry.toString(); } |
|
374 public long getTime() { return entry.getTime(); } |
|
375 public long getSize() { return entry.getSize(); } |
|
376 public String getBase() { |
|
377 return zip.getName(); |
|
378 } |
|
379 } : null; |
|
380 } |
|
381 } |
|
382 } |