001: /***
002: * ASM Guide
003: * Copyright (c) 2007 Eric Bruneton
004: * All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions
008: * are met:
009: * 1. Redistributions of source code must retain the above copyright
010: * notice, this list of conditions and the following disclaimer.
011: * 2. Redistributions in binary form must reproduce the above copyright
012: * notice, this list of conditions and the following disclaimer in the
013: * documentation and/or other materials provided with the distribution.
014: * 3. Neither the name of the copyright holders nor the names of its
015: * contributors may be used to endorse or promote products derived from
016: * this software without specific prior written permission.
017: *
018: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
019: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
020: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
021: * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
022: * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
023: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
024: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
025: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
026: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
027: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
028: * THE POSSIBILITY OF SUCH DAMAGE.
029: */package ch3.sec2;
030:
031: import static org.objectweb.asm.Opcodes.ACC_PRIVATE;
032: import static org.objectweb.asm.Opcodes.ACC_PUBLIC;
033: import static org.objectweb.asm.Opcodes.ACC_STATIC;
034: import static org.objectweb.asm.Opcodes.V1_5;
035:
036: import java.lang.reflect.InvocationHandler;
037: import java.lang.reflect.Proxy;
038:
039: import org.objectweb.asm.ClassVisitor;
040: import org.objectweb.asm.FieldVisitor;
041: import org.objectweb.asm.MethodVisitor;
042: import org.objectweb.asm.Type;
043: import org.objectweb.asm.commons.GeneratorAdapter;
044: import org.objectweb.asm.commons.Method;
045:
046: /**
047: * ASM Guide example class.
048: *
049: * @author Eric Bruneton
050: */
051: public class ProxyGenerator {
052:
053: private static Type CLASS = Type.getType(Class.class);
054:
055: private static Type METHOD = Type
056: .getType(java.lang.reflect.Method.class);
057:
058: private static Type PROXY = Type.getType(Proxy.class);
059:
060: private static Type HANDLER = Type.getType(InvocationHandler.class);
061:
062: private static Method CLINIT = Method.getMethod("void <clinit>()");
063:
064: private static Method INIT = Method
065: .getMethod("void <init>(java.lang.reflect.InvocationHandler)");
066:
067: private static Method INVOKE = Method
068: .getMethod("java.lang.Object invoke(java.lang.Object, java.lang.reflect.Method, java.lang.Object[])");
069:
070: private static Method GET_METHOD = Method
071: .getMethod("java.lang.reflect.Method getMethod(java.lang.String, java.lang.Class[])");
072:
073: private Class itf;
074:
075: public ProxyGenerator(Class itf) {
076: this .itf = itf;
077: }
078:
079: public void generate(Type type, ClassVisitor cv) {
080: cv.visit(V1_5, ACC_PUBLIC, type.getInternalName(), null, PROXY
081: .getInternalName(), new String[] { Type.getType(itf)
082: .getInternalName() });
083:
084: MethodVisitor mv = cv.visitMethod(ACC_PUBLIC, INIT.getName(),
085: INIT.getDescriptor(), null, null);
086: if (mv != null) {
087: GeneratorAdapter init = new GeneratorAdapter(ACC_PUBLIC,
088: INIT, mv);
089: init.visitCode();
090: init.loadThis();
091: init.loadArg(0);
092: init.invokeConstructor(PROXY, INIT);
093: init.returnValue();
094: init.endMethod();
095: }
096:
097: GeneratorAdapter clinit = null;
098: mv = cv.visitMethod(ACC_STATIC, CLINIT.getName(), CLINIT
099: .getDescriptor(), null, null);
100: if (mv != null) {
101: clinit = new GeneratorAdapter(ACC_STATIC, CLINIT, mv);
102: clinit.visitCode();
103: }
104:
105: for (int i = 0; i < itf.getMethods().length; ++i) {
106: Method m = getMethod(itf.getMethods()[i]);
107:
108: mv = cv.visitMethod(ACC_PUBLIC, m.getName(), m
109: .getDescriptor(), null, null);
110: if (mv != null) {
111: String field = "_M" + i;
112: FieldVisitor fv = cv.visitField(ACC_PRIVATE
113: + ACC_STATIC, field, METHOD.getDescriptor(),
114: null, null);
115: if (fv != null) {
116: fv.visitEnd();
117: }
118:
119: if (clinit != null) {
120: Type[] formals = m.getArgumentTypes();
121: clinit.push(Type.getType(itf));
122: clinit.push(m.getName());
123: clinit.push(formals.length);
124: clinit.newArray(CLASS);
125: for (int j = 0; j < formals.length; ++j) {
126: clinit.dup();
127: clinit.push(j);
128: clinit.push(formals[j]);
129: clinit.arrayStore(CLASS);
130: }
131: clinit.invokeVirtual(CLASS, GET_METHOD);
132: clinit.putStatic(type, field, METHOD);
133: }
134:
135: GeneratorAdapter ga = new GeneratorAdapter(ACC_PUBLIC,
136: m, mv);
137: ga.visitCode();
138: ga.loadThis();
139: ga.getField(PROXY, "h", HANDLER);
140: ga.loadThis();
141: ga.getStatic(type, field, METHOD);
142: ga.loadArgArray();
143: ga.invokeInterface(HANDLER, INVOKE);
144: if (m.getReturnType() != Type.VOID_TYPE) {
145: ga.unbox(m.getReturnType());
146: }
147: ga.returnValue();
148: ga.endMethod();
149: }
150: }
151:
152: if (clinit != null) {
153: clinit.returnValue();
154: clinit.endMethod();
155: }
156:
157: cv.visitEnd();
158: }
159:
160: private static Method getMethod(java.lang.reflect.Method m) {
161: Type returnType = Type.getType(m.getReturnType());
162: Type[] argTypes = new Type[m.getParameterTypes().length];
163: for (int i = 0; i < argTypes.length; ++i) {
164: argTypes[i] = Type.getType(m.getParameterTypes()[i]);
165: }
166: return new Method(m.getName(), returnType, argTypes);
167: }
168: }
|