KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > logicalcobwebs > cglib > proxy > MethodInterceptorGenerator


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 org.logicalcobwebs.cglib.proxy;
55
56 import java.lang.reflect.*;
57 import java.util.*;
58 import org.logicalcobwebs.cglib.core.*;
59 import org.logicalcobwebs.asm.Label;
60 import org.logicalcobwebs.asm.Type;
61
62 class MethodInterceptorGenerator
63 implements CallbackGenerator
64 {
65     public static final MethodInterceptorGenerator INSTANCE = new MethodInterceptorGenerator();
66
67     static final String JavaDoc FIND_PROXY_NAME = "CGLIB$findMethodProxy";
68     static final Class JavaDoc[] FIND_PROXY_TYPES = { Signature.class };
69
70     private static final Signature FIND_PROXY =
71       new Signature(FIND_PROXY_NAME,
72                     TypeUtils.parseType("org.logicalcobwebs.cglib.proxy.MethodProxy"),
73                     TypeUtils.getTypes(FIND_PROXY_TYPES));
74
75     private static final Type ABSTRACT_METHOD_ERROR =
76       TypeUtils.parseType("AbstractMethodError");
77     private static final Type METHOD =
78       TypeUtils.parseType("java.lang.reflect.Method");
79     private static final Type METHOD_PROXY =
80       TypeUtils.parseType("org.logicalcobwebs.cglib.proxy.MethodProxy");
81     private static final Type METHOD_INTERCEPTOR =
82       TypeUtils.parseType("org.logicalcobwebs.cglib.proxy.MethodInterceptor");
83     private static final Signature GET_DECLARING_CLASS =
84       TypeUtils.parseSignature("Class getDeclaringClass()");
85     private static final Signature GET_CLASS_LOADER =
86       TypeUtils.parseSignature("ClassLoader getClassLoader()");
87     private static final Signature MAKE_PROXY =
88       TypeUtils.parseSignature("org.logicalcobwebs.cglib.proxy.MethodProxy create(ClassLoader, Class, Class, String, String, String)");
89     private static final Signature INTERCEPT =
90       TypeUtils.parseSignature("Object intercept(Object, java.lang.reflect.Method, Object[], org.logicalcobwebs.cglib.proxy.MethodProxy)");
91     private static final Signature TO_STRING =
92       TypeUtils.parseSignature("String toString()");
93
94     public void generate(ClassEmitter ce, Context context) {
95         Map sigMap = new HashMap();
96         for (Iterator it = context.getMethods(); it.hasNext();) {
97             Method method = (Method)it.next();
98             String JavaDoc accessName = getAccessName(context, method);
99             String JavaDoc fieldName = getFieldName(context, method);
100             sigMap.put(ReflectUtils.getSignature(method).toString(), accessName);
101
102             ce.declare_field(Constants.PRIVATE_FINAL_STATIC, fieldName, METHOD, null, null);
103             ce.declare_field(Constants.PRIVATE_FINAL_STATIC, accessName, METHOD_PROXY, null, null);
104             CodeEmitter e;
105
106             // access method
107
e = ce.begin_method(Constants.ACC_FINAL,
108                                 new Signature(getAccessName(context, method),
109                                               ReflectUtils.getSignature(method).getDescriptor()),
110                                 ReflectUtils.getExceptionTypes(method),
111                                 null);
112             if (Modifier.isAbstract(method.getModifiers())) {
113                 e.throw_exception(ABSTRACT_METHOD_ERROR, method.toString() + " is abstract" );
114             } else {
115                 e.load_this();
116                 e.load_args();
117                 e.super_invoke(ReflectUtils.getSignature(method));
118             }
119             e.return_value();
120             e.end_method();
121
122             // around method
123
e = ce.begin_method(context.getModifiers(method),
124                                 ReflectUtils.getSignature(method),
125                                 ReflectUtils.getExceptionTypes(method),
126                                 null);
127             Label nullInterceptor = e.make_label();
128             context.emitCallback(e, context.getIndex(method));
129             e.dup();
130             e.ifnull(nullInterceptor);
131
132             e.load_this();
133             e.getfield(fieldName);
134             e.create_arg_array();
135             e.getfield(accessName);
136             e.invoke_interface(METHOD_INTERCEPTOR, INTERCEPT);
137             e.unbox_or_zero(Type.getType(method.getReturnType()));
138             e.return_value();
139
140             e.mark(nullInterceptor);
141             e.load_this();
142             e.load_args();
143             e.super_invoke(ReflectUtils.getSignature(method));
144             e.return_value();
145             e.end_method();
146         }
147         generateFindProxy(ce, sigMap);
148     }
149
150     private String JavaDoc getFieldName(Context context, Method method) {
151         return "CGLIB$$METHOD_" + context.getUniqueName(method);
152     }
153     
154     private String JavaDoc getAccessName(Context context, Method method) {
155         return "CGLIB$$ACCESS_" + context.getUniqueName(method);
156     }
157
158     public void generateStatic(CodeEmitter e, final Context context) {
159         /* generates:
160            static {
161              Class cls = findClass("java.lang.Object");
162              METHOD_1 = cls.getDeclaredMethod("toString", new Class[0]);
163
164              Class thisClass = findClass("NameOfThisClass");
165              CGLIB$ACCESS_0 = MethodProxy.create(thisClass.getClassLoader(), cls, thisClass, "()Ljava/lang/String;", "toString", "CGLIB$ACCESS_0");
166            }
167         */

168
169         Local thisclass = e.make_local();
170         EmitUtils.load_class_this(e);
171         e.dup();
172         e.store_local(thisclass);
173         e.invoke_virtual(Constants.TYPE_CLASS, GET_CLASS_LOADER);
174         
175         for (Iterator it = context.getMethods(); it.hasNext();) {
176             e.dup();
177             Method method = (Method)it.next();
178             EmitUtils.load_method(e, method);
179             e.dup();
180             e.putfield(getFieldName(context, method));
181
182             String JavaDoc accessName = getAccessName(context, method);
183             Signature sig = ReflectUtils.getSignature(method);
184             e.invoke_virtual(METHOD, GET_DECLARING_CLASS);
185             e.load_local(thisclass);
186             e.push(sig.getDescriptor());
187             e.push(sig.getName());
188             e.push(accessName);
189             e.invoke_static(METHOD_PROXY, MAKE_PROXY);
190             e.putfield(accessName);
191         }
192     }
193
194     public void generateFindProxy(ClassEmitter ce, final Map sigMap) {
195         final CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC | Constants.ACC_STATIC,
196                                               FIND_PROXY,
197                                               null,
198                                               null);
199         e.load_arg(0);
200         e.invoke_virtual(Constants.TYPE_OBJECT, TO_STRING);
201         ObjectSwitchCallback callback = new ObjectSwitchCallback() {
202             public void processCase(Object JavaDoc key, Label end) {
203                 e.getfield((String JavaDoc)sigMap.get(key));
204                 e.return_value();
205             }
206             public void processDefault() {
207                 e.aconst_null();
208                 e.return_value();
209             }
210         };
211         EmitUtils.string_switch(e,
212                                 (String JavaDoc[])sigMap.keySet().toArray(new String JavaDoc[0]),
213                                 Constants.SWITCH_STYLE_HASH,
214                                 callback);
215         e.end_method();
216     }
217 }
218
Popular Tags