1 /*
2 * The Apache Software License, Version 1.1
3 *
4 * Copyright (c) 2002 The Apache Software Foundation. All rights
5 * reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 *
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
17 * distribution.
18 *
19 * 3. The end-user documentation included with the redistribution,
20 * if any, must include the following acknowledgment:
21 * "This product includes software developed by the
22 * Apache Software Foundation (http://www.apache.org/)."
23 * Alternately, this acknowledgment may appear in the software itself,
24 * if and wherever such third-party acknowledgments normally appear.
25 *
26 * 4. The names "Apache" and "Apache Software Foundation" must
27 * not be used to endorse or promote products derived from this
28 * software without prior written permission. For written
29 * permission, please contact apache@apache.org.
30 *
31 * 5. Products derived from this software may not be called "Apache",
32 * nor may "Apache" appear in their name, without prior written
33 * permission of the Apache Software Foundation.
34 *
35 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
36 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
37 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
38 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
39 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
42 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
43 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
44 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
45 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
46 * SUCH DAMAGE.
47 * ====================================================================
48 *
49 * This software consists of voluntary contributions made by many
50 * individuals on behalf of the Apache Software Foundation. For more
51 * information on the Apache Software Foundation, please see
52 * <http://www.apache.org/>.
53 */
54 package net.sf.cglib.proxy;
55
56 import java.lang.reflect.*;
57 import java.util.*;
58 import net.sf.cglib.core.*;
59 import org.objectweb.asm.Label;
60 import org.objectweb.asm.Type;
61
62 class MethodInterceptorGenerator
63 implements CallbackGenerator
64 {
65 public static final MethodInterceptorGenerator INSTANCE = new MethodInterceptorGenerator();
66
67 static final String EMPTY_ARGS_NAME = "CGLIB$emptyArgs";
68 static final String FIND_PROXY_NAME = "CGLIB$findMethodProxy";
69 static final Class[] FIND_PROXY_TYPES = { Signature.class };
70
71 private static final Signature FIND_PROXY =
72 new Signature(FIND_PROXY_NAME,
73 TypeUtils.parseType("net.sf.cglib.proxy.MethodProxy"),
74 TypeUtils.getTypes(FIND_PROXY_TYPES));
75
76 private static final Type ABSTRACT_METHOD_ERROR =
77 TypeUtils.parseType("AbstractMethodError");
78 private static final Type METHOD =
79 TypeUtils.parseType("java.lang.reflect.Method");
80 private static final Type METHOD_PROXY =
81 TypeUtils.parseType("net.sf.cglib.proxy.MethodProxy");
82 private static final Type METHOD_INTERCEPTOR =
83 TypeUtils.parseType("net.sf.cglib.proxy.MethodInterceptor");
84 private static final Signature GET_DECLARING_CLASS =
85 TypeUtils.parseSignature("Class getDeclaringClass()");
86 private static final Signature GET_CLASS_LOADER =
87 TypeUtils.parseSignature("ClassLoader getClassLoader()");
88 private static final Signature MAKE_PROXY =
89 TypeUtils.parseSignature("net.sf.cglib.proxy.MethodProxy create(ClassLoader, Class, Class, String, String, String)");
90 private static final Signature INTERCEPT =
91 TypeUtils.parseSignature("Object intercept(Object, java.lang.reflect.Method, Object[], net.sf.cglib.proxy.MethodProxy)");
92 private static final Signature TO_STRING =
93 TypeUtils.parseSignature("String toString()");
94
95 public void generate(ClassEmitter ce, Context context) {
96 Map sigMap = new HashMap();
97 for (Iterator it = context.getMethods(); it.hasNext();) {
98 Method method = (Method)it.next();
99 String accessName = getAccessName(context, method);
100 String fieldName = getFieldName(context, method);
101 sigMap.put(ReflectUtils.getSignature(method).toString(), accessName);
102
103 ce.declare_field(Constants.PRIVATE_FINAL_STATIC, fieldName, METHOD, null, null);
104 ce.declare_field(Constants.PRIVATE_FINAL_STATIC, accessName, METHOD_PROXY, null, null);
105 ce.declare_field(Constants.PRIVATE_FINAL_STATIC, EMPTY_ARGS_NAME, Constants.TYPE_OBJECT_ARRAY, null, null);
106 CodeEmitter e;
107
108 // access method
109 e = ce.begin_method(Constants.ACC_FINAL,
110 new Signature(getAccessName(context, method),
111 ReflectUtils.getSignature(method).getDescriptor()),
112 ReflectUtils.getExceptionTypes(method),
113 null);
114 if (Modifier.isAbstract(method.getModifiers())) {
115 e.throw_exception(ABSTRACT_METHOD_ERROR, method.toString() + " is abstract" );
116 } else {
117 e.load_this();
118 e.load_args();
119 e.super_invoke(ReflectUtils.getSignature(method));
120 }
121 e.return_value();
122 e.end_method();
123
124 // around method
125 e = ce.begin_method(context.getModifiers(method),
126 ReflectUtils.getSignature(method),
127 ReflectUtils.getExceptionTypes(method),
128 null);
129 Label nullInterceptor = e.make_label();
130 context.emitCallback(e, context.getIndex(method));
131 e.dup();
132 e.ifnull(nullInterceptor);
133
134 e.load_this();
135 e.getfield(fieldName);
136
137 if (method.getParameterTypes().length == 0) {
138 e.getfield(EMPTY_ARGS_NAME);
139 } else {
140 e.create_arg_array();
141 }
142
143 e.getfield(accessName);
144 e.invoke_interface(METHOD_INTERCEPTOR, INTERCEPT);
145 e.unbox_or_zero(Type.getType(method.getReturnType()));
146 e.return_value();
147
148 e.mark(nullInterceptor);
149 e.load_this();
150 e.load_args();
151 e.super_invoke(ReflectUtils.getSignature(method));
152 e.return_value();
153 e.end_method();
154 }
155 generateFindProxy(ce, sigMap);
156 }
157
158 private String getFieldName(Context context, Method method) {
159 return "CGLIB$$METHOD_" + context.getUniqueName(method);
160 }
161
162 private String getAccessName(Context context, Method method) {
163 return "CGLIB$$ACCESS_" + context.getUniqueName(method);
164 }
165
166 public void generateStatic(CodeEmitter e, final Context context) {
167 /* generates:
168 static {
169 Class cls = findClass("java.lang.Object");
170 METHOD_1 = cls.getDeclaredMethod("toString", new Class[0]);
171
172 Class thisClass = findClass("NameOfThisClass");
173 CGLIB$ACCESS_0 = MethodProxy.create(thisClass.getClassLoader(), cls, thisClass, "()Ljava/lang/String;", "toString", "CGLIB$ACCESS_0");
174 }
175 */
176
177 Local thisclass = e.make_local();
178 EmitUtils.load_class_this(e);
179 e.dup();
180 e.store_local(thisclass);
181 e.invoke_virtual(Constants.TYPE_CLASS, GET_CLASS_LOADER);
182
183 e.push(0);
184 e.newarray();
185 e.putfield(EMPTY_ARGS_NAME);
186
187 for (Iterator it = context.getMethods(); it.hasNext();) {
188 e.dup();
189 Method method = (Method)it.next();
190 EmitUtils.load_method(e, method);
191 e.dup();
192 e.putfield(getFieldName(context, method));
193
194 String accessName = getAccessName(context, method);
195 Signature sig = ReflectUtils.getSignature(method);
196 e.invoke_virtual(METHOD, GET_DECLARING_CLASS);
197 e.load_local(thisclass);
198 e.push(sig.getDescriptor());
199 e.push(sig.getName());
200 e.push(accessName);
201 e.invoke_static(METHOD_PROXY, MAKE_PROXY);
202 e.putfield(accessName);
203 }
204 }
205
206 public void generateFindProxy(ClassEmitter ce, final Map sigMap) {
207 final CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC | Constants.ACC_STATIC,
208 FIND_PROXY,
209 null,
210 null);
211 e.load_arg(0);
212 e.invoke_virtual(Constants.TYPE_OBJECT, TO_STRING);
213 ObjectSwitchCallback callback = new ObjectSwitchCallback() {
214 public void processCase(Object key, Label end) {
215 e.getfield((String)sigMap.get(key));
216 e.return_value();
217 }
218 public void processDefault() {
219 e.aconst_null();
220 e.return_value();
221 }
222 };
223 EmitUtils.string_switch(e,
224 (String[])sigMap.keySet().toArray(new String[0]),
225 Constants.SWITCH_STYLE_HASH,
226 callback);
227 e.end_method();
228 }
229 }
This page was automatically generated by Maven