KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javassist > ClassPoolTail


1 /*
2  * Javassist, a Java-bytecode translator toolkit.
3  * Copyright (C) 1999-2005 Shigeru Chiba. All Rights Reserved.
4  *
5  * The contents of this file are subject to the Mozilla Public License Version
6  * 1.1 (the "License"); you may not use this file except in compliance with
7  * the License. Alternatively, the contents of this file may be used under
8  * the terms of the GNU Lesser General Public License Version 2.1 or later.
9  *
10  * Software distributed under the License is distributed on an "AS IS" basis,
11  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12  * for the specific language governing rights and limitations under the
13  * License.
14  */

15
16 package javassist;
17
18 import java.io.*;
19 import java.util.jar.*;
20 import java.net.MalformedURLException JavaDoc;
21 import java.net.URL JavaDoc;
22 import java.util.Hashtable JavaDoc;
23
24 final class ClassPathList {
25     ClassPathList next;
26     ClassPath path;
27
28     ClassPathList(ClassPath p, ClassPathList n) {
29         next = n;
30         path = p;
31     }
32 }
33
34 final class DirClassPath implements ClassPath {
35     String JavaDoc directory;
36
37     DirClassPath(String JavaDoc dirName) {
38         directory = dirName;
39     }
40
41     public InputStream openClassfile(String JavaDoc classname) {
42         try {
43             char sep = File.separatorChar;
44             String JavaDoc filename = directory + sep
45                 + classname.replace('.', sep) + ".class";
46             return new FileInputStream(filename.toString());
47         }
48         catch (FileNotFoundException e) {}
49         catch (SecurityException JavaDoc e) {}
50         return null;
51     }
52
53     public URL JavaDoc find(String JavaDoc classname) {
54         char sep = File.separatorChar;
55         String JavaDoc filename = directory + sep
56             + classname.replace('.', sep) + ".class";
57         File f = new File(filename);
58         if (f.exists())
59             try {
60                 return f.getCanonicalFile().toURL();
61             }
62             catch (MalformedURLException JavaDoc e) {}
63             catch (IOException e) {}
64
65         return null;
66     }
67
68     public void close() {}
69
70     public String JavaDoc toString() {
71         return directory;
72     }
73 }
74
75 final class JarClassPath implements ClassPath {
76     JarFile jarfile;
77     String JavaDoc jarfileURL;
78
79     JarClassPath(String JavaDoc pathname) throws NotFoundException {
80         try {
81             jarfile = new JarFile(pathname);
82             jarfileURL = new File(pathname).getCanonicalFile()
83                                            .toURL().toString();
84             return;
85         }
86         catch (IOException e) {}
87         throw new NotFoundException(pathname);
88     }
89
90     public InputStream openClassfile(String JavaDoc classname)
91         throws NotFoundException
92     {
93         try {
94             String JavaDoc jarname = classname.replace('.', '/') + ".class";
95             JarEntry je = jarfile.getJarEntry(jarname);
96             if (je != null)
97                 return jarfile.getInputStream(je);
98             else
99                 return null; // not found
100
}
101         catch (IOException e) {}
102         throw new NotFoundException("broken jar file?: "
103                                     + jarfile.getName());
104     }
105
106     public URL JavaDoc find(String JavaDoc classname) {
107         String JavaDoc jarname = classname.replace('.', '/') + ".class";
108         JarEntry je = jarfile.getJarEntry(jarname);
109         if (je != null)
110             try {
111                 return new URL JavaDoc("jar:" + jarfileURL + "!/" + jarname);
112             }
113             catch (MalformedURLException JavaDoc e) {}
114
115         return null; // not found
116
}
117
118     public void close() {
119         try {
120             jarfile.close();
121             jarfile = null;
122         }
123         catch (IOException e) {}
124     }
125
126     public String JavaDoc toString() {
127         return jarfile == null ? "<null>" : jarfile.toString();
128     }
129 }
130
131 final class ClassPoolTail {
132     protected ClassPathList pathList;
133     private Hashtable JavaDoc packages; // should be synchronized.
134

135     public ClassPoolTail() {
136         pathList = null;
137         packages = new Hashtable JavaDoc();
138     }
139
140     public String JavaDoc toString() {
141         StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
142         buf.append("[class path: ");
143         ClassPathList list = pathList;
144         while (list != null) {
145             buf.append(list.path.toString());
146             buf.append(File.pathSeparatorChar);
147             list = list.next;
148         }
149
150         buf.append(']');
151         return buf.toString();
152     }
153
154     public synchronized ClassPath insertClassPath(ClassPath cp) {
155         pathList = new ClassPathList(cp, pathList);
156         return cp;
157     }
158
159     public synchronized ClassPath appendClassPath(ClassPath cp) {
160         ClassPathList tail = new ClassPathList(cp, null);
161         ClassPathList list = pathList;
162         if (list == null)
163             pathList = tail;
164         else {
165             while (list.next != null)
166                 list = list.next;
167
168             list.next = tail;
169         }
170
171         return cp;
172     }
173
174     public synchronized void removeClassPath(ClassPath cp) {
175         ClassPathList list = pathList;
176         if (list != null)
177             if (list.path == cp)
178                 pathList = list.next;
179             else {
180                 while (list.next != null)
181                     if (list.next.path == cp)
182                         list.next = list.next.next;
183                     else
184                         list = list.next;
185             }
186
187         cp.close();
188     }
189
190     public ClassPath appendSystemPath() {
191         return appendClassPath(new ClassClassPath());
192     }
193
194     public ClassPath insertClassPath(String JavaDoc pathname)
195         throws NotFoundException
196     {
197         return insertClassPath(makePathObject(pathname));
198     }
199
200     public ClassPath appendClassPath(String JavaDoc pathname)
201         throws NotFoundException
202     {
203         return appendClassPath(makePathObject(pathname));
204     }
205
206     private static ClassPath makePathObject(String JavaDoc pathname)
207         throws NotFoundException
208     {
209         int i = pathname.lastIndexOf('.');
210         if (i >= 0) {
211             String JavaDoc ext = pathname.substring(i).toLowerCase();
212             if (ext.equals(".jar") || ext.equals(".zip"))
213                 return new JarClassPath(pathname);
214         }
215
216         return new DirClassPath(pathname);
217     }
218
219     /**
220      * You can record "System" so that java.lang.System can be quickly
221      * found although "System" is not a package name.
222      */

223     public void recordInvalidClassName(String JavaDoc name) {
224         packages.put(name, name);
225     }
226
227     /**
228      * This method does not close the output stream.
229      */

230     void writeClassfile(String JavaDoc classname, OutputStream out)
231         throws NotFoundException, IOException, CannotCompileException
232     {
233         InputStream fin = openClassfile(classname);
234         if (fin == null)
235             throw new NotFoundException(classname);
236
237         try {
238             copyStream(fin, out);
239         }
240         finally {
241             fin.close();
242         }
243     }
244
245     /*
246     -- faster version --
247     void checkClassName(String classname) throws NotFoundException {
248         if (find(classname) == null)
249             throw new NotFoundException(classname);
250     }
251
252     -- slower version --
253
254     void checkClassName(String classname) throws NotFoundException {
255         InputStream fin = openClassfile(classname);
256         try {
257             fin.close();
258         }
259         catch (IOException e) {}
260     }
261     */

262
263
264     /**
265      * Opens the class file for the class specified by
266      * <code>classname</code>.
267      *
268      * @param classname a fully-qualified class name
269      * @return null if the file has not been found.
270      * @throws NotFoundException if any error is reported by ClassPath.
271      */

272     InputStream openClassfile(String JavaDoc classname)
273         throws NotFoundException
274     {
275         if (packages.get(classname) != null)
276             return null; // not found
277

278         ClassPathList list = pathList;
279         InputStream ins = null;
280         NotFoundException error = null;
281         while (list != null) {
282             try {
283                 ins = list.path.openClassfile(classname);
284             }
285             catch (NotFoundException e) {
286                 if (error == null)
287                     error = e;
288             }
289
290             if (ins == null)
291                 list = list.next;
292             else
293                 return ins;
294         }
295
296         if (error != null)
297             throw error;
298         else
299             return null; // not found
300
}
301
302     /**
303      * Searches the class path to obtain the URL of the class file
304      * specified by classname. It is also used to determine whether
305      * the class file exists.
306      *
307      * @param classname a fully-qualified class name.
308      * @return null if the class file could not be found.
309      */

310     public URL JavaDoc find(String JavaDoc classname) {
311         if (packages.get(classname) != null)
312             return null;
313
314         ClassPathList list = pathList;
315         URL JavaDoc url = null;
316         while (list != null) {
317             url = list.path.find(classname);
318             if (url == null)
319                 list = list.next;
320             else
321                 return url;
322         }
323
324         return null;
325     }
326
327     /**
328      * Reads from an input stream until it reaches the end.
329      *
330      * @return the contents of that input stream
331      */

332     public static byte[] readStream(InputStream fin) throws IOException {
333         byte[][] bufs = new byte[8][];
334         int bufsize = 4096;
335
336         for (int i = 0; i < 8; ++i) {
337             bufs[i] = new byte[bufsize];
338             int size = 0;
339             int len = 0;
340             do {
341                 len = fin.read(bufs[i], size, bufsize - size);
342                 if (len >= 0)
343                     size += len;
344                 else {
345                     byte[] result = new byte[bufsize - 4096 + size];
346                     int s = 0;
347                     for (int j = 0; j < i; ++j) {
348                         System.arraycopy(bufs[j], 0, result, s, s + 4096);
349                         s = s + s + 4096;
350                     }
351
352                     System.arraycopy(bufs[i], 0, result, s, size);
353                     return result;
354                 }
355             } while (size < bufsize);
356             bufsize *= 2;
357         }
358
359         throw new IOException("too much data");
360     }
361
362     /**
363      * Reads from an input stream and write to an output stream
364      * until it reaches the end. This method does not close the
365      * streams.
366      */

367     public static void copyStream(InputStream fin, OutputStream fout)
368         throws IOException
369     {
370         int bufsize = 4096;
371         for (int i = 0; i < 8; ++i) {
372             byte[] buf = new byte[bufsize];
373             int size = 0;
374             int len = 0;
375             do {
376                 len = fin.read(buf, size, bufsize - size);
377                 if (len >= 0)
378                     size += len;
379                 else {
380                     fout.write(buf, 0, size);
381                     return;
382                 }
383             } while (size < bufsize);
384             fout.write(buf);
385             bufsize *= 2;
386         }
387
388         throw new IOException("too much data");
389     }
390 }
391
Popular Tags