KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > hansel > Startup


1 package org.hansel;
2
3 import java.io.IOException JavaDoc;
4 import java.lang.instrument.ClassDefinition JavaDoc;
5 import java.lang.instrument.ClassFileTransformer JavaDoc;
6 import java.lang.instrument.IllegalClassFormatException JavaDoc;
7 import java.lang.instrument.Instrumentation JavaDoc;
8 import java.lang.instrument.UnmodifiableClassException JavaDoc;
9 import java.lang.reflect.Method JavaDoc;
10 import java.security.ProtectionDomain JavaDoc;
11 import java.util.ArrayList JavaDoc;
12 import java.util.HashMap JavaDoc;
13 import java.util.HashSet JavaDoc;
14 import java.util.List JavaDoc;
15 import java.util.Map JavaDoc;
16
17 public class Startup {
18     private static Instrumentation JavaDoc instrumentation;
19
20     private static Transformer transformer;
21
22     private static Map JavaDoc<ClassKey, byte[]> map = new HashMap JavaDoc<ClassKey, byte[]>();
23
24     public static void premain(String JavaDoc options, Instrumentation JavaDoc instrumentation) {
25         Startup.instrumentation = instrumentation;
26
27     // load class, otherwise the class is loaded in transform(...) and might cause
28
// a deadlock.
29
new ClassKey(null, null);
30
31         instrumentation.addTransformer(new ClassBufferCache());
32     }
33
34     private static void delegate(HashSet JavaDoc<String JavaDoc> classNames) {
35         try {
36             Class JavaDoc clazz = ClassLoader.getSystemClassLoader().loadClass(Startup.class.getName());
37             Method JavaDoc m = clazz.getMethod("init", new Class JavaDoc[] { HashSet JavaDoc.class });
38             
39             m.invoke(null, new Object JavaDoc[] { classNames });
40         } catch (Exception JavaDoc e) {
41             throw new IllegalStateException JavaDoc(e);
42         }
43     }
44
45     public static void init(HashSet JavaDoc<String JavaDoc> classNames)
46         throws IOException JavaDoc, IllegalClassFormatException JavaDoc, ClassNotFoundException JavaDoc,
47         UnmodifiableClassException JavaDoc {
48
49         if (Startup.class.getClassLoader() != ClassLoader.getSystemClassLoader()) {
50             delegate(classNames);
51             return;
52         }
53  
54         if (instrumentation == null) {
55             throw new IllegalStateException JavaDoc("Instrumentation has not been initialized." +
56                                             " Please invoke VM with commandline option: " +
57                                             " -javaagent hansel.jar");
58         }
59
60         Class JavaDoc[] allClasses = instrumentation.getAllLoadedClasses();
61         
62         transformer = new Transformer(classNames);
63         instrumentation.addTransformer(transformer);
64
65     List JavaDoc<ClassDefinition JavaDoc> redefine = new ArrayList JavaDoc<ClassDefinition JavaDoc>();
66
67         for (int i=0; i<allClasses.length; i++) {
68             String JavaDoc className = allClasses[i].getName();
69          
70             if (classNames.contains(className)) {
71                 // Workaround for bug 5092850: Link class by calling getDeclaredFields.
72
//allClasses[i].getDeclaredFields();
73

74                 byte[] classfileBuffer = map.get(new ClassKey(allClasses[i].getName().replace('.', '/'),
75                                                               allClasses[i].getClassLoader()));
76                 if (classfileBuffer == null) {
77                     System.out.println("Skipping: " + allClasses[i].getName());
78                     new Exception JavaDoc().printStackTrace();
79                     /* throw new IllegalStateException("Getting Classfilebuffer for class " + allClasses[i].getName() + "/"
80                                                     + allClasses[i].getClassLoader() + "-" + new ClassKey(allClasses[i].getName().replace('.', '/'),
81                      allClasses[i].getClassLoader()).hashCode() + ": " + map + " failed.");*/

82                 } else {
83
84                 // getClassFileBuffer(className, allClasses[i].getClassLoader());
85
/*byte[] newClassDefinition =
86                     transformer.transform(allClasses[i].getClassLoader(),
87                                           allClasses[i].getName(),
88                                           allClasses[i],
89                                           allClasses[i].getProtectionDomain(),
90                  classfileBuffer);*/

91             redefine.add(new ClassDefinition JavaDoc(allClasses[i], classfileBuffer/*newClassDefinition*/));
92               
93                 }
94             }
95         }
96
97     instrumentation.redefineClasses(redefine.toArray(new ClassDefinition JavaDoc[redefine.size()]));
98        
99     }
100
101     /* private static final byte[] getClassFileBuffer(String className, ClassLoader cl) throws IOException {
102         InputStream is = cl.getResourceAsStream(className.replace('.', '/') + ".class");
103         byte[] buf = new byte[1024];
104
105         ByteArrayOutputStream baos = new ByteArrayOutputStream(is.available());
106         int read;
107         do {
108             read = is.read(buf);
109             if (read > -1) {
110                 baos.write(buf, 0, read);
111             }
112         } while (read > -1);
113
114         is.close();
115         return baos.toByteArray();
116      }*/

117
118     public static void tearDown()
119         throws ClassNotFoundException JavaDoc, UnmodifiableClassException JavaDoc {
120         
121         instrumentation.removeTransformer(transformer);
122         transformer.undo(instrumentation);
123     transformer = null;
124     }
125
126     private static class ClassKey {
127         private String JavaDoc classname;
128         private ClassLoader JavaDoc cl;
129
130         public ClassKey(String JavaDoc classname, ClassLoader JavaDoc cl) {
131             this.cl = cl;
132             this.classname = classname;
133         }
134
135         public boolean equals(Object JavaDoc obj) {
136             ClassKey ck = (ClassKey) obj;
137             return classname.equals(ck.classname) && cl.equals(ck.cl);
138         }
139
140         public int hashCode() {
141             int hashCode = classname.hashCode();
142             if (cl != null) {
143                 hashCode += cl.toString().hashCode();
144             }
145             return hashCode;
146         }
147
148         public String JavaDoc toString() {
149             return classname + "-" + cl + "-" + hashCode();
150         }
151     }
152
153     /**
154      * This is a horrible memory leak, but redefining classes is not possible otherwise :(
155      */

156     private static class ClassBufferCache implements ClassFileTransformer JavaDoc {
157         public byte[] transform(ClassLoader JavaDoc loader,
158                                 String JavaDoc className,
159                                 Class JavaDoc<?> classBeingRedefined,
160                                 ProtectionDomain JavaDoc protectionDomain,
161                                 byte[] classfileBuffer) {
162             //System.out.println("Transforming: " + new ClassKey(className, loader));
163
map.put(new ClassKey(className, loader), classfileBuffer);
164         return null;
165         }
166     }
167 }
168  
169
Popular Tags