KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > Adapt


1 /***
2  * ASM examples: examples showing how ASM can be used
3  * Copyright (c) 2000-2005 INRIA, France Telecom
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the distribution.
14  * 3. Neither the name of the copyright holders nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
28  * THE POSSIBILITY OF SUCH DAMAGE.
29  */

30 import org.objectweb.asm.FieldVisitor;
31 import org.objectweb.asm.ClassAdapter;
32 import org.objectweb.asm.ClassReader;
33 import org.objectweb.asm.ClassVisitor;
34 import org.objectweb.asm.ClassWriter;
35 import org.objectweb.asm.MethodAdapter;
36 import org.objectweb.asm.MethodVisitor;
37 import org.objectweb.asm.Opcodes;
38 import org.objectweb.asm.Type;
39
40 import java.io.FileOutputStream JavaDoc;
41 import java.io.InputStream JavaDoc;
42 import java.lang.reflect.Method JavaDoc;
43
44 /**
45  * @author Eric Bruneton
46  */

47 public class Adapt extends ClassLoader JavaDoc {
48
49     protected synchronized Class JavaDoc loadClass(
50         final String JavaDoc name,
51         final boolean resolve) throws ClassNotFoundException JavaDoc
52     {
53         if (name.startsWith("java.")) {
54             System.err.println("Adapt: loading class '" + name
55                     + "' without on the fly adaptation");
56             return super.loadClass(name, resolve);
57         } else {
58             System.err.println("Adapt: loading class '" + name
59                     + "' with on the fly adaptation");
60         }
61
62         // gets an input stream to read the bytecode of the class
63
String JavaDoc resource = name.replace('.', '/') + ".class";
64         InputStream JavaDoc is = getResourceAsStream(resource);
65         byte[] b;
66
67         // adapts the class on the fly
68
try {
69             ClassReader cr = new ClassReader(is);
70             ClassWriter cw = new ClassWriter(false);
71             ClassVisitor cv = new TraceFieldClassAdapter(cw);
72             cr.accept(cv, false);
73             b = cw.toByteArray();
74         } catch (Exception JavaDoc e) {
75             throw new ClassNotFoundException JavaDoc(name, e);
76         }
77
78         // optional: stores the adapted class on disk
79
try {
80             FileOutputStream JavaDoc fos = new FileOutputStream JavaDoc(resource + ".adapted");
81             fos.write(b);
82             fos.close();
83         } catch (Exception JavaDoc e) {
84         }
85
86         // returns the adapted class
87
return defineClass(name, b, 0, b.length);
88     }
89
90     public static void main(final String JavaDoc args[]) throws Exception JavaDoc {
91         // loads the application class (in args[0]) with an Adapt class loader
92
ClassLoader JavaDoc loader = new Adapt();
93         Class JavaDoc c = loader.loadClass(args[0]);
94         // calls the 'main' static method of this class with the
95
// application arguments (in args[1] ... args[n]) as parameter
96
Method JavaDoc m = c.getMethod("main", new Class JavaDoc[] { String JavaDoc[].class });
97         String JavaDoc[] applicationArgs = new String JavaDoc[args.length - 1];
98         System.arraycopy(args, 1, applicationArgs, 0, applicationArgs.length);
99         m.invoke(null, new Object JavaDoc[] { applicationArgs });
100     }
101 }
102
103 class TraceFieldClassAdapter extends ClassAdapter implements Opcodes {
104
105     private String JavaDoc owner;
106
107     public TraceFieldClassAdapter(final ClassVisitor cv) {
108         super(cv);
109     }
110
111     public void visit(
112         final int version,
113         final int access,
114         final String JavaDoc name,
115         final String JavaDoc signature,
116         final String JavaDoc superName,
117         final String JavaDoc[] interfaces)
118     {
119         owner = name;
120         super.visit(version, access, name, signature, superName, interfaces);
121     }
122
123     public FieldVisitor visitField(
124         final int access,
125         final String JavaDoc name,
126         final String JavaDoc desc,
127         final String JavaDoc signature,
128         final Object JavaDoc value)
129     {
130         FieldVisitor fv = super.visitField(access, name, desc, signature, value);
131         if ((access & ACC_STATIC) == 0) {
132             Type t = Type.getType(desc);
133             int size = t.getSize();
134
135             // generates getter method
136
String JavaDoc gDesc = "()" + desc;
137             MethodVisitor gv = cv.visitMethod(ACC_PRIVATE,
138                     "_get" + name,
139                     gDesc,
140                     null,
141                     null);
142             gv.visitFieldInsn(GETSTATIC,
143                     "java/lang/System",
144                     "err",
145                     "Ljava/io/PrintStream;");
146             gv.visitLdcInsn("_get" + name + " called");
147             gv.visitMethodInsn(INVOKEVIRTUAL,
148                     "java/io/PrintStream",
149                     "println",
150                     "(Ljava/lang/String;)V");
151             gv.visitVarInsn(ALOAD, 0);
152             gv.visitFieldInsn(GETFIELD, owner, name, desc);
153             gv.visitInsn(t.getOpcode(IRETURN));
154             gv.visitMaxs(1 + size, 1);
155             gv.visitEnd();
156
157             // generates setter method
158
String JavaDoc sDesc = "(" + desc + ")V";
159             MethodVisitor sv = cv.visitMethod(ACC_PRIVATE,
160                     "_set" + name,
161                     sDesc,
162                     null,
163                     null);
164             sv.visitFieldInsn(GETSTATIC,
165                     "java/lang/System",
166                     "err",
167                     "Ljava/io/PrintStream;");
168             sv.visitLdcInsn("_set" + name + " called");
169             sv.visitMethodInsn(INVOKEVIRTUAL,
170                     "java/io/PrintStream",
171                     "println",
172                     "(Ljava/lang/String;)V");
173             sv.visitVarInsn(ALOAD, 0);
174             sv.visitVarInsn(t.getOpcode(ILOAD), 1);
175             sv.visitFieldInsn(PUTFIELD, owner, name, desc);
176             sv.visitInsn(RETURN);
177             sv.visitMaxs(1 + size, 1 + size);
178             sv.visitEnd();
179         }
180         return fv;
181     }
182
183     public MethodVisitor visitMethod(
184         final int access,
185         final String JavaDoc name,
186         final String JavaDoc desc,
187         final String JavaDoc signature,
188         final String JavaDoc[] exceptions)
189     {
190         MethodVisitor mv = cv.visitMethod(access,
191                 name,
192                 desc,
193                 signature,
194                 exceptions);
195         return mv == null ? null : new TraceFieldCodeAdapter(mv, owner);
196     }
197 }
198
199 class TraceFieldCodeAdapter extends MethodAdapter implements Opcodes {
200
201     private String JavaDoc owner;
202
203     public TraceFieldCodeAdapter(final MethodVisitor mv, final String JavaDoc owner) {
204         super(mv);
205         this.owner = owner;
206     }
207
208     public void visitFieldInsn(
209         final int opcode,
210         final String JavaDoc owner,
211         final String JavaDoc name,
212         final String JavaDoc desc)
213     {
214         if (owner.equals(this.owner)) {
215             if (opcode == GETFIELD) {
216                 // replaces GETFIELD f by INVOKESPECIAL _getf
217
String JavaDoc gDesc = "()" + desc;
218                 visitMethodInsn(INVOKESPECIAL, owner, "_get" + name, gDesc);
219                 return;
220             } else if (opcode == PUTFIELD) {
221                 // replaces PUTFIELD f by INVOKESPECIAL _setf
222
String JavaDoc sDesc = "(" + desc + ")V";
223                 visitMethodInsn(INVOKESPECIAL, owner, "_set" + name, sDesc);
224                 return;
225             }
226         }
227         super.visitFieldInsn(opcode, owner, name, desc);
228     }
229 }
230
Popular Tags