KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > alt > jiapi > util > InstrumentingClassLoader


1 /*
2  * Copyright (C) 2001 Mika Riekkinen, Joni Suominen
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  */

18
19 package alt.jiapi.util;
20
21 import java.io.File JavaDoc;
22 import java.io.IOException JavaDoc;
23 import java.net.JarURLConnection JavaDoc;
24 import java.net.MalformedURLException JavaDoc;
25 import java.net.URL JavaDoc;
26 import java.net.URLClassLoader JavaDoc;
27 import java.security.CodeSource JavaDoc;
28 import java.security.cert.Certificate JavaDoc;
29 import java.util.Collections JavaDoc;
30 import java.util.ArrayList JavaDoc;
31 import java.util.HashMap JavaDoc;
32 import java.util.List JavaDoc;
33 import java.util.Map JavaDoc;
34 import java.util.StringTokenizer JavaDoc;
35
36 import org.apache.log4j.Category;
37
38 import alt.jiapi.InstrumentationContext;
39 import alt.jiapi.Runtime;
40 import alt.jiapi.reflect.JiapiClass;
41 import alt.jiapi.JiapiException;
42
43 /**
44  * A sample ClassLoader which can be used when instrumenting Java
45  * applications. It knows how to load classes from CLASSPATH.
46  * <p>
47  * NOTE: Should the jar files found from jre/lib/ext
48  * (System.getProperty("java.ext.dirs")) also be added to search path?
49  *
50  * @author Mika Riekkinen
51  * @author Joni Suominen
52  * @version $Revision: 1.5 $ $Date: 2004/08/04 08:58:04 $
53  */

54 public class InstrumentingClassLoader extends URLClassLoader JavaDoc {
55     private static Category log = Runtime.getLogCategory(InstrumentingClassLoader.class);
56
57     protected Map JavaDoc classes;
58     protected InstrumentationContext ctx;
59
60     /**
61      * Creates a new InstrumentingClassloader.
62      */

63     public static ClassLoader JavaDoc createClassLoader() {
64         return createClassLoader((InstrumentationContext)null);
65     }
66
67     /**
68      * Creates a new InstrumentingClassloader.
69      */

70     public static ClassLoader JavaDoc createClassLoader(InstrumentationContextProvider icp) throws JiapiException {
71         return createClassLoader(icp.getInstrumentationContext());
72     }
73
74     /**
75      * Creates a new InstrumentingClassloader.
76      */

77     public static ClassLoader JavaDoc createClassLoader(InstrumentationContextProvider icp, ClassLoader JavaDoc parent) throws JiapiException {
78         return createClassLoader(icp.getInstrumentationContext(), parent);
79     }
80
81     /**
82      * Creates a new InstrumentingClassloader.
83      */

84     public static ClassLoader JavaDoc createClassLoader(InstrumentationContext ctx) {
85         return createClassLoader(ctx, getSystemClassLoader());
86     }
87
88     /**
89      * Creates a new InstrumentingClassloader.
90      */

91     public static ClassLoader JavaDoc createClassLoader(InstrumentationContext ctx,
92                                                 ClassLoader JavaDoc parent) {
93         URL JavaDoc urls[] = getClassPathUrls();
94         SecurityManager JavaDoc sm = System.getSecurityManager();
95         if (sm != null) {
96             sm.checkCreateClassLoader();
97         }
98
99 // System.out.println("Creating class loader with context " + ctx.getClass().getName() + ", " + ctx + ", parent: " + parent);
100

101         return new InstrumentingClassLoader(ctx, urls, parent);
102     }
103
104     protected InstrumentingClassLoader(InstrumentationContext ctx, URL JavaDoc[] urls,
105                                        ClassLoader JavaDoc parent) {
106         super(urls, parent);
107         this.ctx = ctx;
108
109         classes = Collections.synchronizedMap(new HashMap JavaDoc());
110     }
111
112     protected synchronized Class JavaDoc loadClass(String JavaDoc className, boolean resolve)
113         throws ClassNotFoundException JavaDoc {
114         //System.out.println("Loading " + className);
115

116         Class JavaDoc cl = null;
117         JiapiClass jiapiClass = null;
118         log.debug("loadClass(" + className + ")");
119 // System.out.println("loadClass(" + className + ")");
120

121         // Core Java classes and Jiapi classes are delegated to parent
122
// class loader.
123
if (className.startsWith("java.") || className.startsWith("javax.") ||
124             className.startsWith("sun.") || className.startsWith("alt.jiapi.")) {
125 // System.out.println("getParent().loadClass(" + className + ")" +
126
// getParent());
127
return getParent().loadClass(className);
128         }
129
130         if ((cl = (Class JavaDoc) classes.get(className)) == null) {
131             log.debug("cache miss: " + className);
132             // Check if we have permission to access the package.
133
SecurityManager JavaDoc sm = System.getSecurityManager();
134             if (sm != null) {
135                 int i = className.lastIndexOf('.');
136                 if (i != -1) {
137                     sm.checkPackageAccess(className.substring(0, i));
138                 }
139             }
140
141             if (ctx == null) {
142                 return bootstrap(className);
143             }
144             
145             // Locate the class as a resource.
146
String JavaDoc path = className.replace('.', '/').concat(".class");
147             URL JavaDoc location = super.findResource(path);
148
149             if (location == null) {
150                 // Delagate to parent.
151

152                 return getParent().loadClass(className);
153             }
154
155             try {
156                 jiapiClass = ctx.getLoader().loadClass(className, location);
157             }
158             catch(java.io.IOException JavaDoc ioe) {
159                 throw new ClassNotFoundException JavaDoc(className);
160             }
161
162             ctx.instrument(jiapiClass);
163
164             byte[] bytes = jiapiClass.getByteCode();
165
166             if (System.getProperty("dump") != null) {
167                 try {
168                     jiapiClass.dump(new java.io.FileOutputStream JavaDoc(jiapiClass.getName() + ".dump"));
169                 }
170                 catch(Throwable JavaDoc t) {
171                 }
172             }
173
174             if (bytes != null) {
175                 CodeSource JavaDoc cs = createCodeSource(location);
176                 cl = defineClass(className, bytes, 0, bytes.length, cs);
177             }
178
179             log.debug(cl + " was loaded with " + cl.getClassLoader());
180
181             // Should we cache this or not.
182
// Could there be a case, where we want to instrument
183
// a class differently each time.
184
// debug on, debug off...
185
classes.put(className, cl);
186         }
187
188         if (resolve) {
189             resolveClass(cl);
190         }
191
192         return cl;
193     }
194
195     /**
196      * Form a CodeSource for loaded class.
197      *
198      * @param location a location where the class was loaded from
199      */

200     protected CodeSource JavaDoc createCodeSource(URL JavaDoc location) {
201         Certificate JavaDoc []certs = null;
202         if (location.getProtocol().equals("jar")) {
203             try {
204                 JarURLConnection JavaDoc jarConnection =
205                     (JarURLConnection JavaDoc) location.openConnection();
206
207                 certs = jarConnection.getCertificates();
208                 location = jarConnection.getJarFileURL();
209             } catch (IOException JavaDoc ioe) {
210                 ioe.printStackTrace();
211                 throw new RuntimeException JavaDoc(ioe.getMessage());
212             }
213         }
214         
215         return new CodeSource JavaDoc(location, certs);
216     }
217
218
219     /**
220      * Creates an array of URLs which are used for seaching classes.
221      */

222     private static URL JavaDoc []getClassPathUrls() {
223         String JavaDoc string = System.getProperty("java.class.path");
224         List JavaDoc urls = new ArrayList JavaDoc();
225         if (string != null) {
226             StringTokenizer JavaDoc st = new StringTokenizer JavaDoc(string,
227                                                      File.pathSeparator);
228             
229             while (st.hasMoreTokens()) {
230                 try {
231                     urls.add((new File JavaDoc(st.nextToken())).toURL());
232                 } catch (IOException JavaDoc ioe) {
233                     // Don't mind... CLASSPATH is supplied by user
234
// and can easily contain spelling mistakes etc.
235
}
236             }
237         }
238
239         return ((URL JavaDoc []) urls.toArray(new URL JavaDoc[0]));
240     }
241
242     /**
243      * Set the context for the ClassLoader.
244      *
245      * @param ctx an InstrumentationContext to be used
246      */

247     public void setContext(InstrumentationContext ctx) {
248         this.ctx = ctx;
249     }
250
251     // should be private:
252
public Class JavaDoc bootstrap(String JavaDoc className) throws ClassNotFoundException JavaDoc {
253         String JavaDoc s = className.replace('.', '/') + ".class";
254         
255         return findClass(s);
256     }
257
258     // This method is used only for bootstrapping the class.
259
byte [] byteBuffer = new byte[65000];
260     public Class JavaDoc findClass(String JavaDoc name) throws ClassNotFoundException JavaDoc {
261         log.debug("findClass(" + name + ")");
262         Class JavaDoc c = null;
263         //Class c = findClass(name);
264
try {
265             URL JavaDoc url = findResource(name);
266             if (url == null) {
267                 throw new ClassNotFoundException JavaDoc(name);
268             }
269
270             java.io.InputStream JavaDoc is = url.openStream();
271             int count = 0;
272             while (is.available() > 0) {
273                 int elemsRead = is.read(byteBuffer, count, is.available());
274                 if (elemsRead == -1) {
275                     break;
276                 }
277                 count += elemsRead;
278             }
279
280             c = defineClass(name.substring(0, name.lastIndexOf('.')),
281                             byteBuffer, 0, count);
282         }
283         catch (java.io.IOException JavaDoc e) {
284             e.printStackTrace();
285             throw new ClassNotFoundException JavaDoc(name);
286         }
287
288         classes.put(c.getName(), c);
289         return c;
290     }
291 }
292
293
Popular Tags