Search in sources :

Example 1 with MethodInfo

use of org.springframework.cglib.core.MethodInfo in project spring-framework by spring-projects.

the class Enhancer method emitMethods.

private void emitMethods(final ClassEmitter ce, List methods, List actualMethods) {
    CallbackGenerator[] generators = CallbackInfo.getGenerators(callbackTypes);
    Map groups = new HashMap();
    final Map indexes = new HashMap();
    final Map originalModifiers = new HashMap();
    final Map positions = CollectionUtils.getIndexMap(methods);
    final Map declToBridge = new HashMap();
    Iterator it1 = methods.iterator();
    Iterator it2 = (actualMethods != null) ? actualMethods.iterator() : null;
    while (it1.hasNext()) {
        MethodInfo method = (MethodInfo) it1.next();
        Method actualMethod = (it2 != null) ? (Method) it2.next() : null;
        int index = filter.accept(actualMethod);
        if (index >= callbackTypes.length) {
            throw new IllegalArgumentException("Callback filter returned an index that is too large: " + index);
        }
        originalModifiers.put(method, (actualMethod != null ? actualMethod.getModifiers() : method.getModifiers()));
        indexes.put(method, index);
        List group = (List) groups.get(generators[index]);
        if (group == null) {
            groups.put(generators[index], group = new ArrayList(methods.size()));
        }
        group.add(method);
        // so that we can look up all the bridge methods in one pass for a class.
        if (TypeUtils.isBridge(actualMethod.getModifiers())) {
            Set bridges = (Set) declToBridge.get(actualMethod.getDeclaringClass());
            if (bridges == null) {
                bridges = new HashSet();
                declToBridge.put(actualMethod.getDeclaringClass(), bridges);
            }
            bridges.add(method.getSignature());
        }
    }
    final Map bridgeToTarget = new BridgeMethodResolver(declToBridge, getClassLoader()).resolveAll();
    Set seenGen = new HashSet();
    CodeEmitter se = ce.getStaticHook();
    se.new_instance(THREAD_LOCAL);
    se.dup();
    se.invoke_constructor(THREAD_LOCAL, CSTRUCT_NULL);
    se.putfield(THREAD_CALLBACKS_FIELD);
    final Object[] state = new Object[1];
    CallbackGenerator.Context context = new CallbackGenerator.Context() {

        public ClassLoader getClassLoader() {
            return Enhancer.this.getClassLoader();
        }

        public int getOriginalModifiers(MethodInfo method) {
            return ((Integer) originalModifiers.get(method)).intValue();
        }

        public int getIndex(MethodInfo method) {
            return ((Integer) indexes.get(method)).intValue();
        }

        public void emitCallback(CodeEmitter e, int index) {
            emitCurrentCallback(e, index);
        }

        public Signature getImplSignature(MethodInfo method) {
            return rename(method.getSignature(), ((Integer) positions.get(method)).intValue());
        }

        public void emitLoadArgsAndInvoke(CodeEmitter e, MethodInfo method) {
            // If this is a bridge and we know the target was called from invokespecial,
            // then we need to invoke_virtual w/ the bridge target instead of doing
            // a super, because super may itself be using super, which would bypass
            // any proxies on the target.
            Signature bridgeTarget = (Signature) bridgeToTarget.get(method.getSignature());
            if (bridgeTarget != null) {
                // checkcast each argument against the target's argument types
                for (int i = 0; i < bridgeTarget.getArgumentTypes().length; i++) {
                    e.load_arg(i);
                    Type target = bridgeTarget.getArgumentTypes()[i];
                    if (!target.equals(method.getSignature().getArgumentTypes()[i])) {
                        e.checkcast(target);
                    }
                }
                e.invoke_virtual_this(bridgeTarget);
                Type retType = method.getSignature().getReturnType();
                // method.)
                if (!retType.equals(bridgeTarget.getReturnType())) {
                    e.checkcast(retType);
                }
            } else {
                e.load_args();
                e.super_invoke(method.getSignature());
            }
        }

        public CodeEmitter beginMethod(ClassEmitter ce, MethodInfo method) {
            CodeEmitter e = EmitUtils.begin_method(ce, method);
            if (!interceptDuringConstruction && !TypeUtils.isAbstract(method.getModifiers())) {
                Label constructed = e.make_label();
                e.load_this();
                e.getfield(CONSTRUCTED_FIELD);
                e.if_jump(CodeEmitter.NE, constructed);
                e.load_this();
                e.load_args();
                e.super_invoke();
                e.return_value();
                e.mark(constructed);
            }
            return e;
        }
    };
    for (int i = 0; i < callbackTypes.length; i++) {
        CallbackGenerator gen = generators[i];
        if (!seenGen.contains(gen)) {
            seenGen.add(gen);
            final List fmethods = (List) groups.get(gen);
            if (fmethods != null) {
                try {
                    gen.generate(ce, context, fmethods);
                    gen.generateStatic(se, context, fmethods);
                } catch (RuntimeException x) {
                    throw x;
                } catch (Exception x) {
                    throw new CodeGenerationException(x);
                }
            }
        }
    }
    se.return_value();
    se.end_method();
}
Also used : HashSet(java.util.HashSet) Set(java.util.Set) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) ClassEmitter(org.springframework.cglib.core.ClassEmitter) Label(org.springframework.asm.Label) CodeGenerationException(org.springframework.cglib.core.CodeGenerationException) Iterator(java.util.Iterator) ArrayList(java.util.ArrayList) List(java.util.List) HashSet(java.util.HashSet) Method(java.lang.reflect.Method) CodeGenerationException(org.springframework.cglib.core.CodeGenerationException) InvocationTargetException(java.lang.reflect.InvocationTargetException) CodeEmitter(org.springframework.cglib.core.CodeEmitter) Type(org.springframework.asm.Type) Signature(org.springframework.cglib.core.Signature) MethodInfo(org.springframework.cglib.core.MethodInfo) HashMap(java.util.HashMap) Map(java.util.Map)

Example 2 with MethodInfo

use of org.springframework.cglib.core.MethodInfo in project spring-framework by spring-projects.

the class Enhancer method emitDefaultConstructor.

private void emitDefaultConstructor(ClassEmitter ce) {
    Constructor<Object> declaredConstructor;
    try {
        declaredConstructor = Object.class.getDeclaredConstructor();
    } catch (NoSuchMethodException e) {
        throw new IllegalStateException("Object should have default constructor ", e);
    }
    MethodInfo constructor = (MethodInfo) MethodInfoTransformer.getInstance().transform(declaredConstructor);
    CodeEmitter e = EmitUtils.begin_method(ce, constructor, Constants.ACC_PUBLIC);
    e.load_this();
    e.dup();
    Signature sig = constructor.getSignature();
    e.super_invoke_constructor(sig);
    e.return_value();
    e.end_method();
}
Also used : CodeEmitter(org.springframework.cglib.core.CodeEmitter) Signature(org.springframework.cglib.core.Signature) MethodInfo(org.springframework.cglib.core.MethodInfo)

Example 3 with MethodInfo

use of org.springframework.cglib.core.MethodInfo in project spring-framework by spring-projects.

the class Enhancer method emitNewInstanceMultiarg.

private void emitNewInstanceMultiarg(ClassEmitter ce, List constructors) {
    final CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, MULTIARG_NEW_INSTANCE, null);
    final Type thisType = getThisType(e);
    e.load_arg(2);
    e.invoke_static(thisType, SET_THREAD_CALLBACKS, false);
    e.new_instance(thisType);
    e.dup();
    e.load_arg(0);
    EmitUtils.constructor_switch(e, constructors, new ObjectSwitchCallback() {

        public void processCase(Object key, Label end) {
            MethodInfo constructor = (MethodInfo) key;
            Type[] types = constructor.getSignature().getArgumentTypes();
            for (int i = 0; i < types.length; i++) {
                e.load_arg(1);
                e.push(i);
                e.aaload();
                e.unbox(types[i]);
            }
            e.invoke_constructor(thisType, constructor.getSignature());
            e.goTo(end);
        }

        public void processDefault() {
            e.throw_exception(ILLEGAL_ARGUMENT_EXCEPTION, "Constructor not found");
        }
    });
    e.aconst_null();
    e.invoke_static(thisType, SET_THREAD_CALLBACKS, false);
    e.return_value();
    e.end_method();
}
Also used : CodeEmitter(org.springframework.cglib.core.CodeEmitter) Type(org.springframework.asm.Type) Label(org.springframework.asm.Label) MethodInfo(org.springframework.cglib.core.MethodInfo) ObjectSwitchCallback(org.springframework.cglib.core.ObjectSwitchCallback)

Example 4 with MethodInfo

use of org.springframework.cglib.core.MethodInfo in project spring-framework by spring-projects.

the class Enhancer method emitConstructors.

private void emitConstructors(ClassEmitter ce, List constructors) {
    boolean seenNull = false;
    for (Iterator it = constructors.iterator(); it.hasNext(); ) {
        MethodInfo constructor = (MethodInfo) it.next();
        if (currentData != null && !"()V".equals(constructor.getSignature().getDescriptor())) {
            continue;
        }
        CodeEmitter e = EmitUtils.begin_method(ce, constructor, Constants.ACC_PUBLIC);
        e.load_this();
        e.dup();
        e.load_args();
        Signature sig = constructor.getSignature();
        seenNull = seenNull || sig.getDescriptor().equals("()V");
        e.super_invoke_constructor(sig);
        if (currentData == null) {
            e.invoke_static_this(BIND_CALLBACKS);
            if (!interceptDuringConstruction) {
                e.load_this();
                e.push(1);
                e.putfield(CONSTRUCTED_FIELD);
            }
        }
        e.return_value();
        e.end_method();
    }
    if (!classOnly && !seenNull && arguments == null)
        throw new IllegalArgumentException("Superclass has no null constructors but no arguments were given");
}
Also used : CodeEmitter(org.springframework.cglib.core.CodeEmitter) Signature(org.springframework.cglib.core.Signature) Iterator(java.util.Iterator) MethodInfo(org.springframework.cglib.core.MethodInfo)

Aggregations

CodeEmitter (org.springframework.cglib.core.CodeEmitter)4 MethodInfo (org.springframework.cglib.core.MethodInfo)4 Signature (org.springframework.cglib.core.Signature)3 Iterator (java.util.Iterator)2 Label (org.springframework.asm.Label)2 Type (org.springframework.asm.Type)2 InvocationTargetException (java.lang.reflect.InvocationTargetException)1 Method (java.lang.reflect.Method)1 ArrayList (java.util.ArrayList)1 HashMap (java.util.HashMap)1 HashSet (java.util.HashSet)1 List (java.util.List)1 Map (java.util.Map)1 Set (java.util.Set)1 ClassEmitter (org.springframework.cglib.core.ClassEmitter)1 CodeGenerationException (org.springframework.cglib.core.CodeGenerationException)1 ObjectSwitchCallback (org.springframework.cglib.core.ObjectSwitchCallback)1