KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > edu > rice > cs > drjava > model > junit > DrJavaTestCaseClassLoader


1 /*BEGIN_COPYRIGHT_BLOCK
2  *
3  * This file is part of DrJava. Download the current version of this project from http://www.drjava.org/
4  * or http://sourceforge.net/projects/drjava/
5  *
6  * DrJava Open Source License
7  *
8  * Copyright (C) 2001-2005 JavaPLT group at Rice University (javaplt@rice.edu). All rights reserved.
9  *
10  * Developed by: Java Programming Languages Team, Rice University, http://www.cs.rice.edu/~javaplt/
11  *
12  * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
13  * documentation files (the "Software"), to deal with the Software without restriction, including without limitation
14  * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
15  * to permit persons to whom the Software is furnished to do so, subject to the following conditions:
16  *
17  * - Redistributions of source code must retain the above copyright notice, this list of conditions and the
18  * following disclaimers.
19  * - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
20  * following disclaimers in the documentation and/or other materials provided with the distribution.
21  * - Neither the names of DrJava, the JavaPLT, Rice University, nor the names of its contributors may be used to
22  * endorse or promote products derived from this Software without specific prior written permission.
23  * - Products derived from this software may not be called "DrJava" nor use the term "DrJava" as part of their
24  * names without prior written permission from the JavaPLT group. For permission, write to javaplt@rice.edu.
25  *
26  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
27  * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
28  * CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
29  * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
30  * WITH THE SOFTWARE.
31  *
32 END_COPYRIGHT_BLOCK*/

33
34 package edu.rice.cs.drjava.model.junit;
35
36 import junit.runner.*;
37 import java.util.*;
38 import java.io.*;
39 import java.net.*;
40 import java.util.zip.*;
41
42 import edu.rice.cs.util.FileOps;
43
44 /** A custom classloader for use in running test cases. this will load all classes for the test case. This loader also
45  * provides an excludes list. any class that matches an entry in the list will be loaded by the system class loader
46  * instead.
47  *
48  * This class extends junit.runner.TestCaseClassLoader. however, since the junit version kept all non public code as private, we
49  * had to duplicate the class to add the features we need.
50  *
51  * getResource and getResourceAsStream will not defer to the system class loader, as the junit version does, but instead will use
52  * the custom internal classpath to get resources.
53  *
54  * This allows this class to be used an a remote classloader to test cases that spawn multiple jvms.
55  */

56
57
58 public final class DrJavaTestCaseClassLoader extends TestCaseClassLoader {
59   /** the class loader that will load from the custom inner classpath */
60   ClassLoader JavaDoc _loader;
61   
62   /** scanned class path */
63   private Vector<String JavaDoc> fPathItems;
64   
65   /** default excluded paths */
66   private String JavaDoc[] defaultExclusions= {"junit.framework.", "junit.extensions.", "junit.runner.", "java."};
67   
68   /** Name of excluded properties file */
69   static final String JavaDoc EXCLUDED_FILE= "excluded.properties";
70   
71   /** Excluded paths */
72   private Vector<String JavaDoc> fExcluded;
73   
74   /** Constructs a TestCaseLoader. It scans the class path and the excluded package paths. */
75   public DrJavaTestCaseClassLoader() { this(System.getProperty("java.class.path")); }
76   
77   /** Constructs a TestCaseLoader. It scans the class path and the excluded package paths. */
78   public DrJavaTestCaseClassLoader(String JavaDoc classPath) {
79     _loader = getClass().getClassLoader();
80     scanPath(classPath);
81     readExcludedPackages();
82   }
83   
84   /** Scans the classpath, and creates an internal IR for the classpath and initializes the
85    * internal loader
86    */

87   private void scanPath(String JavaDoc classPath) {
88     String JavaDoc separator= System.getProperty("path.separator");
89     fPathItems= new Vector<String JavaDoc>(10);
90     StringTokenizer st= new StringTokenizer(classPath, separator);
91     String JavaDoc item;
92     while (st.hasMoreTokens()) {
93       item = st.nextToken();
94       fPathItems.addElement(item);
95       try{ _loader = new DrJavaURLClassLoader(new URL[]{FileOps.toURL(new File(item))}, _loader); }
96       catch(MalformedURLException e) {
97         /* do nothing */
98       }
99     }
100   }
101   
102   /** Gets a resource from the custom classpath. */
103   public URL getResource(String JavaDoc name) { return _loader.getResource(name); }
104   
105   /** Gets a resource stream from the custom classpath. */
106   public InputStream getResourceAsStream(String JavaDoc name) {
107     return _loader.getResourceAsStream(name);
108   }
109   
110   /** Teturns true if the classname should be excluded
111    * (loaded from system), false otherwise
112    */

113   public boolean isExcluded(String JavaDoc name) {
114     for (int i= 0; i < fExcluded.size(); i++) {
115       if (name.startsWith(fExcluded.elementAt(i))) return true;
116     }
117     return false;
118   }
119   
120   /** Loads the class. 1st. checks if the class is already loaded. 2nd. checks if it should be loaded by system.
121    * 3rd. try to load the class myself
122    */

123   public synchronized Class JavaDoc<?> loadClass(String JavaDoc name, boolean resolve)
124     throws ClassNotFoundException JavaDoc {
125     Class JavaDoc<?> c= findLoadedClass(name);
126     if (c != null)
127       return c;
128     //
129
// Delegate the loading of excluded classes to the
130
// standard class loader.
131
//
132
if (isExcluded(name)) {
133       try {
134         c= findSystemClass(name);
135         return c;
136       } catch (ClassNotFoundException JavaDoc e) {
137         // keep searching
138
}
139     }
140     
141     try{
142       if (c == null) {
143         byte[] data= lookupClassData(name);
144         if (data == null) {
145           throw new ClassNotFoundException JavaDoc();
146         }
147         c= defineClass(name, data, 0, data.length);
148       }
149       if (resolve)
150         resolveClass(c);
151     }catch(ClassNotFoundException JavaDoc e) {
152       // we couldn't load it, try the system
153
return findSystemClass(name);
154     }
155     return c;
156   }
157   
158   /** Reads in and returns data from class file for the given classname. */
159   private byte[] lookupClassData(String JavaDoc className) throws ClassNotFoundException JavaDoc {
160     byte[] data= null;
161     for (int i= 0; i < fPathItems.size(); i++) {
162       String JavaDoc path= fPathItems.elementAt(i);
163       String JavaDoc fileName= className.replace('.', '/')+".class";
164       if (isJar(path)) {
165         data= loadJarData(path, fileName);
166       } else {
167         data= loadFileData(path, fileName);
168       }
169       if (data != null) {
170         return data;
171       }
172     }
173     throw new ClassNotFoundException JavaDoc(className);
174   }
175   
176   /**
177    * returns true if the pathEntry points to a jar file
178    */

179   private boolean isJar(String JavaDoc pathEntry) {
180     return pathEntry.endsWith(".jar") || pathEntry.endsWith(".zip");
181   }
182   
183   /**
184    * reads in data from a class file and returns it
185    */

186   private byte[] loadFileData(String JavaDoc path, String JavaDoc fileName) {
187     File file= new File(path, fileName);
188     if (file.exists()) {
189       return getClassData(file);
190     }
191     return null;
192   }
193   
194   /**
195    * returns the contents of the file as an array of bytes
196    */

197   private byte[] getClassData(File f) {
198     try {
199       FileInputStream stream= new FileInputStream(f);
200       ByteArrayOutputStream out= new ByteArrayOutputStream(1000);
201       byte[] b= new byte[1000];
202       int n;
203       while ((n= stream.read(b)) != -1)
204         out.write(b, 0, n);
205       stream.close();
206       out.close();
207       return out.toByteArray();
208       
209     } catch (IOException e) {
210     }
211     return null;
212   }
213   
214   /**
215    * searches the contents of the jar for the specified fileName
216    * and returns an array of bytes
217    */

218   private byte[] loadJarData(String JavaDoc path, String JavaDoc fileName) {
219     ZipFile zipFile= null;
220     InputStream stream= null;
221     File archive= new File(path);
222     if (!archive.exists())
223       return null;
224     try {
225       zipFile= new ZipFile(archive);
226     } catch(IOException io) {
227       return null;
228     }
229     ZipEntry entry= zipFile.getEntry(fileName);
230     if (entry == null)
231       return null;
232     int size= (int) entry.getSize();
233     try {
234       stream= zipFile.getInputStream(entry);
235       byte[] data= new byte[size];
236       int pos= 0;
237       while (pos < size) {
238         int n= stream.read(data, pos, data.length - pos);
239         pos += n;
240       }
241       zipFile.close();
242       return data;
243     } catch (IOException e) {
244     } finally {
245       try {
246         if (stream != null)
247           stream.close();
248       } catch (IOException e) {
249       }
250     }
251     return null;
252   }
253   
254   /**
255    * reads in a list of excluded packages from a config file
256    */

257   private void readExcludedPackages() {
258     fExcluded = new Vector<String JavaDoc>(10);
259     for (String JavaDoc de: defaultExclusions) fExcluded.addElement(de);
260     
261     InputStream is = getClass().getResourceAsStream(EXCLUDED_FILE);
262     if (is == null) return;
263     Properties p = new Properties();
264     try { p.load(is); }
265     catch (IOException e) { return; }
266     finally {
267       try { is.close(); }
268       catch (IOException e) {
269         /* do nothing */
270       }
271     }
272     
273     // Raw type because Properties is not generified.
274
Enumeration pnames = p.propertyNames();
275     
276     while (pnames.hasMoreElements()) {
277       String JavaDoc key = (String JavaDoc) pnames.nextElement();
278       if (key.startsWith("excluded.")) {
279         String JavaDoc path = p.getProperty(key);
280         path = path.trim();
281         if (path.endsWith("*")) path= path.substring(0, path.length()-1);
282         if (path.length() > 0) fExcluded.addElement(path);
283       }
284     }
285   }
286   
287   /** Allows more control over the URLClassLoader. specifically,
288    * allows us to view what's loaded when
289    */

290   private static class DrJavaURLClassLoader extends URLClassLoader{
291     
292     public DrJavaURLClassLoader(URL[] urls, ClassLoader JavaDoc c) { super(urls, c); }
293     
294     public URL getResource(String JavaDoc name) {
295       URL ret = getParent().getResource(name);
296       if (ret == null) ret = super.getResource(name);
297       return ret;
298     }
299   }
300 }
Popular Tags