Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * Copyright 2010 the original author or authors.
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
 package org.callbackparams.internal.template;
 
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import  org.apache.bcel.Constants;
 import  org.apache.bcel.generic.ArrayType;
 import  org.apache.bcel.generic.ClassGen;
 import  org.apache.bcel.generic.ConstantPoolGen;
 import  org.apache.bcel.generic.IFNULL;
 import  org.apache.bcel.generic.IfInstruction;
 import  org.apache.bcel.generic.InstructionFactory;
 import  org.apache.bcel.generic.InstructionList;
 import  org.apache.bcel.generic.MethodGen;
 import  org.apache.bcel.generic.Type;

Author(s):
Henrik Kaipe
 
 public class AdaptiveRulesPackager
 implements java.lang.reflect.InvocationHandler, Constants {

    
Specifies details of a Visitor super-interface for org.callbackparams.internal.CallbackMethodProxyingRebyter.

See also:
 
     public static class VisitorParentGenerator {
         private final String interfaceName;
         private Type enclosingType;
         private List/*Field*/ adaptiveRuleFields;
         private List/*Method*/ testMethods;
 
         public VisitorParentGenerator(Class enclosingClass,
                 List/*Field*/ adaptiveRuleFieldsList/*Method*/ testMethods) {
             this. = Type.getType(enclosingClass);
             this. = adaptiveRuleFields;
             this. = testMethods;
             this. =
                     defineInterfaceNameOfNestedVisitorParent(enclosingClass);
         }
 
         public String getInterfaceName() {
             return ;
         }
 
         public byte[] generateByteCode() {
             return defineNestedVisitorParent(,
                     );
         }
     }

    
Will be rebyted when classes are reloaded for the CallbackParams testrun! As super-interfaces it will get the nested (artificial) VisitorParent_x interfaces of the test-class and its super-classes. It will itself get a single method, which return-type will be the (rebyted) test-class.
 
     public interface Visitor {}
 
     private static final Map/*Method,Method*/ testMethodMap = new HashMap();
     private static final List/*Field*/ adaptiveRuleFields = new ArrayList();
     private static final Class[] proxiedInterfaces = {Visitor.class};
     private static final Class testClass;
 
     private final TestrunCallbacks testInstance;
 
     public AdaptiveRulesPackager(TestrunCallbacks testInstance) {
         this. = testInstance;
     }
 
     static {
         Class tempTestClass = null;
        final Method[] visitorMethods = Visitor.class.getMethods();
        Map/*MethodHashKey,Method*/ hashedVisitorMethods = new HashMap();
        for (int i = 0; i < visitorMethods.length; ++i) {
            final Method m = visitorMethods[i];
            final Class[] params = m.getParameterTypes();
            if (0 == params.length) {
                tempTestClass = m.getReturnType();
            } else if (params[0].isArray()) {//<-Array is code for rule-field
                try {
                    Field f = params[0].getComponentType()
                            .getDeclaredField(m.getName());
                    try {
                        f.setAccessible(true);
                    } catch (SecurityException ignoreAndHopeForTheBest) {}
                    .add(f);
                } catch (Exception x) {
                    throw new Error(x.getMessage());
                }
            } else {
                MethodHashKey key = new MethodHashKey(
                        params[0].getName(),
                        m.getName(),
                        asTestMethodSignature(m.getReturnType(), params));
                hashedVisitorMethods.put(keym);
            }
        }
         = tempTestClass;
        while (false == hashedVisitorMethods.isEmpty()) {
            final Method[] testClassMethods =
                    tempTestClass.getDeclaredMethods();
            for (int i = 0; i < testClassMethods.length; ++i) {
                final Method m = testClassMethods[i];
                final Method visitorMethod = (Method)
                        hashedVisitorMethods.remove(MethodHashKey.getHashKey(m));
                if (null != visitorMethod) {
                    try {
                        m.setAccessible(true);
                    } catch (SecurityException ignoreAndHopeForTheBest) {}
                    .put(
                            MethodHashKey.getHashKey(visitorMethod), m);
                }
            }
            tempTestClass = tempTestClass.getSuperclass();
        }
    }
    private static String asTestMethodSignature(
            Class returnTypeClass[] visitorMethodParams) {
        final Type[] argTypes = new Type[visitorMethodParams.length - 1];
        for (int i = 0; i < argTypes.length; ++i) {
            argTypes[i] = Type.getType(visitorMethodParams[i + 1]);
        }
        return Type.getMethodSignature(Type.getType(returnType), argTypes);
    }
            Class enclosingClass) {
        String interfNamePrefix = enclosingClass.getName() + "$VisitorParent_";
        String interfName = null;
        try {
            for (int suffix = 0; true; ++suffix) {
                interfName = interfNamePrefix + suffix;
                enclosingClass.getClassLoader().loadClass(interfName);
            }
        } catch (ClassNotFoundException x) {
            return interfName;
        }
    }
    private static byte[] defineNestedVisitorParent(
            String interfName, Type enclosingType,
            List/*Field*/ adaptiveRulesList/*Method*/ testMethods) {
        ClassGen cg = new ClassGen(interfNameObject.class.getName(),
                "<generated>", ACC_PUBLIC | ACC_INTERFACE | ACC_ABSTRACT, null);
        ConstantPoolGen cp = cg.getConstantPool();
        if (false == adaptiveRules.isEmpty()) {
            Type[] arg_types = {new ArrayType(enclosingType, 1)};
            for (Iterator/*Field*/ i = adaptiveRules.iterator(); i.hasNext();) {
                final Field ruleField = (Fieldi.next();
                cg.addMethod(new MethodGen(ACC_PUBLIC | ACC_ABSTRACT,
                        Type.VOID, arg_typesnull,
                        ruleField.getName(), interfNamenullcp).getMethod());
            }
        }
        if (false == testMethods.isEmpty()) {
            VisitorMethodArgtypesFactory argsFactory =
                    new VisitorMethodArgtypesFactory(enclosingType);
            for (Iterator/*Method*/ i = testMethods.iterator(); i.hasNext();) {
                final Method m = (Methodi.next();
                MethodGen mg = new MethodGen(ACC_PUBLIC | ACC_ABSTRACT,
                        Type.getType(m.getReturnType()),
                        argsFactory.asVisitorMethodArgtypes(m.getParameterTypes()),
                        nullm.getName(), interfNamenullcp);
                if (0 < m.getExceptionTypes().length) {
                    mg.addException(Throwable.class.getName());
                }
                cg.addMethod(mg.getMethod());
            }
        }
        return cg.getJavaClass().getBytes();
    }
    public static InstructionList defineTestMethodDetourCall(
            InstructionFactory factoryMethod m) {
        final InstructionList il = new InstructionList();
        /* Invoke static method Visitor fetchTestrunVisitor(TestrunCallbacks):*/
        il.append(factory.ALOAD_0);
        il.append(factory.createInvoke(
                AdaptiveRulesPackager.class.getName(),
                "fetchTestrunVisitor",
                Type.getType(Visitor.class),
                new Type[] {Type.getType(TestrunCallbacks.class)},
                INVOKESTATIC));
        /*
         * Duplicate Visitor instance on stack so that
         * it willbe available for both the "ifnull"-check and the
         * following method-invocation.
         */
        il.append(factory.DUP);
        /* Jump to the end of this instruction-list in case the
         * fetchTestrunVisitor-invocation returned null.
         */
        IfInstruction ifNull = new IFNULL(null);
        il.append(ifNull);
        /*
         * Invoke the proper visitor-method.
         */
        Type declaringClassType = Type.getType(m.getDeclaringClass());
        Type[] argTypes = new VisitorMethodArgtypesFactory(declaringClassType)
                .asVisitorMethodArgtypes(m.getParameterTypes());
        il.append(factory.ACONST_NULL);//Detour already knows of test-instance
        for (int i = 1; i < argTypes.length; ++i) {
            il.append(factory.createLoad(argTypes[i], i));
        }
        il.append(factory.createInvoke(
                Visitor.class.getName(), m.getName(),
                Type.getType(m.getReturnType()), argTypes,
                INVOKEINTERFACE));
        /*
         * Return from method - returning the return-value of the
         * preceding interface-invocation (or just return for void-methods).
         */
        il.append(factory.createReturn(Type.getType(m.getReturnType())));
        /*
         * The ifnull-target ...
         * When the ifnull-target reaches here there will be an unused
         * null-reference on the stack because of the Visitor-duplication
         * above, so it could as well be removed ...
         */
        ifNull.setTarget(il.append(factory.POP));
        return il;
    }
    public static Visitor fetchTestrunVisitor(TestrunCallbacks testInstance) {
        if (testInstance.currentlyWrappedWithinAdaptiveRules
                || false == .isInstance(testInstance)
                || .isEmpty()) {
            return null;
        } else {
            return (Visitor) java.lang.reflect.Proxy.newProxyInstance(
                    Visitor.class.getClassLoader(),
                    ,
                    new AdaptiveRulesPackager(testInstance));
        }
    }
    private TestRun wrapTestrunWithRule(
            final AdaptiveRule rulefinal TestRun testRun) {
        return new TestRun() {
            public Object executeTestMethod() throws Throwable {
                return rule.evaluate(testRun);
            }
        };
    }
    private Object executeWithAdaptiveRules(TestRun testRunthrows Throwable {
        for (Iterator i = .iterator(); i.hasNext();) {
            final Field ruleField = (Fieldi.next();
            AdaptiveRule rule = (AdaptiveRuleruleField.get();
            if (null != rule) {
                testRun = wrapTestrunWithRule(ruletestRun);
            }
        }
        return testRun.executeTestMethod();
    }
    public Object invoke(Object proxy,
            final Method mfinal Object[] args)
    throws Throwable {
        try {
            return executeWithAdaptiveRules(new AdaptiveRule.TestRun() {
                public Object executeTestMethod() throws Throwable {
                    try {
                        Method testMethod = (Method)
                                .get(MethodHashKey.getHashKey(m));
                        return testMethod.invoke(
                                asTestMethodArgs(args));
                    } catch (InvocationTargetException ite) {
                        throw ite.getTargetException();
                    }
                }
            });
        } finally {
            . = false;
        }
    }
    private static Object[] asTestMethodArgs(final Object[] args) {
        if (1 == args.length) {
            return null;
        } else {
            final Object[] testMethodArgs = new Object[args.length - 1];
            for (int i = 0; i < testMethodArgs.length; ++i) {
                testMethodArgs[i] = args[i + 1];
            }
            return testMethodArgs;
        }
    }
    public static byte[] generateRebytedVisitor(
            Class testClassSet superInterfaceNames) {
        String[] superInterfaces = (String[]) superInterfaceNames.toArray(
                new String[superInterfaceNames.size()]);
        ClassGen cg = new ClassGen(
                Visitor.class.getName(), Object.class.getName(),
                "<regenerated>", ACC_PUBLIC | ACC_INTERFACE | ACC_ABSTRACT,
                superInterfaces);
        MethodGen mg = new MethodGen(ACC_PUBLIC | ACC_ABSTRACT,
                Type.getType(testClass), new Type[]{}, null"testClass",
                Visitor.class.getName(), nullcg.getConstantPool());
        cg.addMethod(mg.getMethod());
        return cg.getJavaClass().getBytes();
    }
    private static class VisitorMethodArgtypesFactory {
        final Type enclosingType;
        VisitorMethodArgtypesFactory(Type enclosingType) {
            this. = enclosingType;
        }
        Type[] asVisitorMethodArgtypes(final Class[] testMethodParams) {
            final Type[] argTypes = new Type[testMethodParams.length + 1];
            argTypes[0] = ;
            for (int i = 0; i < testMethodParams.length; ++i) {
                argTypes[i + 1] = Type.getType(testMethodParams[i]);
            }
            return argTypes;
        }
    }
New to GrepCode? Check out our FAQ X