View Javadoc
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