
org.jingle.util.dydelegation.DelegationCreator Maven / Gradle / Ivy
package org.jingle.util.dydelegation;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import org.apache.bcel.Constants;
import org.apache.bcel.generic.ArrayType;
import org.apache.bcel.generic.BranchInstruction;
import org.apache.bcel.generic.ClassGen;
import org.apache.bcel.generic.ConstantPoolGen;
import org.apache.bcel.generic.FieldGen;
import org.apache.bcel.generic.INSTANCEOF;
import org.apache.bcel.generic.InstructionConstants;
import org.apache.bcel.generic.InstructionFactory;
import org.apache.bcel.generic.InstructionHandle;
import org.apache.bcel.generic.InstructionList;
import org.apache.bcel.generic.MethodGen;
import org.apache.bcel.generic.ObjectType;
import org.apache.bcel.generic.PUSH;
import org.apache.bcel.generic.ReferenceType;
import org.apache.bcel.generic.Type;
/**
*
* Delegation Creator
*
*
* @author JianLu
* @version 1.0 2004-10-29
* @since 1.0
*/
public class DelegationCreator implements Constants {
static final String DELEGATION_INVOCATION_HANDLER_INTERFACE_NAME = "org.jingle.util.dydelegation.DelegationInvocationHandler";
static long num = 0;
private InstructionFactory _factory;
private ConstantPoolGen _cp;
private ClassGen _cg;
private String className;
private String targetName;
private Method[] methods;
private Constructor[] constructors;
protected Class[] classes;
protected Class[] sourceClasses;
protected Class[] interfaces;
/**
* Constructor
* @param targetClassName The name of the generated delegation class. If it is null, a system generated name will provided.
* @param sourceClasses The classes to be delegated
*/
public DelegationCreator(String targetClassName, Class[] sourceClasses) {
this.sourceClasses = sourceClasses;
analyseSourceClasses();
validate();
this.className = this.classes[0].getName();
this.targetName = getTargetName(targetClassName, this.classes[0], this.interfaces);
String[] interfaceNames = new String[interfaces.length];
for (int i = 1; i <= interfaces.length; i++) {
interfaceNames[i - 1] = interfaces[i - 1].getName();
}
this._cg = new ClassGen(targetName, this.className,
this.targetName + ".java", ACC_PUBLIC | ACC_SUPER,
interfaceNames);
this._cp = this._cg.getConstantPool();
this._factory = new InstructionFactory(this._cg, this._cp);
}
/**
* Constructor
* @param classes The classes to be delegated
*/
public DelegationCreator(Class[] classes) {
this(null, classes);
}
/**
* Analyse the sourceClasses. Divide it into classes and interfaces
*
*/
private void analyseSourceClasses() {
if (sourceClasses != null) {
List interfaceList = new ArrayList();
List classList = new ArrayList();
for (int i = 1; i <= sourceClasses.length; i++) {
if (sourceClasses[i - 1] == null)
throw new NullPointerException();
if (sourceClasses[i - 1].isInterface()) {
if (!interfaceList.contains(sourceClasses[i - 1]))
interfaceList.add(sourceClasses[i - 1]);
}
else
classList.add(sourceClasses[i - 1]);
}
if (classList.size() == 0)
classList.add(Object.class);
if (!interfaceList.contains(Delegation.class))
interfaceList.add(Delegation.class);
classes = (Class[])classList.toArray(new Class[0]);
interfaces = (Class[])interfaceList.toArray(new Class[0]);
}
}
/**
* Get the name of the generated delegation class.
* @param targetClassName The name provided by the creator
* @param clazz The class to be delegated
* @param interfaces The interfaces to be delegated
* @return Name of the generated delegation class.
*/
protected static synchronized String getTargetName(String targetClassName,
Class clazz, Class[] interfaces) {
if (targetClassName == null) {
String name = null;
String classFullName = clazz.getName();
if (classFullName.startsWith("java.")) {
String className = classFullName.substring(classFullName.lastIndexOf('.') + 1);
if (className.equals("Object"))
className = null;
for (int i = 1; i <= interfaces.length; i++) {
Package pac = interfaces[i - 1].getPackage();
if (pac != null) {
if (!pac.getName().startsWith("java.")) {
if (className == null)
name = pac.getName() + "." + "Delegation";
else
name = pac.getName() + "." + className + "_Delegation";
break;
}
}
}
}
else
name = clazz.getName() + "_Delegation";
return name + "_" + (num++);
}
else {
if (targetClassName.startsWith("java.")) {
throw new IllegalArgumentException("Delegation class name can not start with java.");
}
return targetClassName;
}
}
/**
* Validate the arguments pass to creator
*/
protected void validate() {
if (classes == null)
throw new NullPointerException();
if (classes.length != 1)
throw new IllegalArgumentException(
"Can not generate delegation for more than one class");
if (Delegation.class.isAssignableFrom(classes[0]))
throw new IllegalArgumentException(
"Can not generate delegation for Delegation class");
int modifier = classes[0].getModifiers();
if (Modifier.isFinal(modifier))
throw new IllegalArgumentException(
"Can not generate delegation for final class");
try {
Constructor[] allConstructors = classes[0].getDeclaredConstructors();
List constructorList = new ArrayList();
for(int i = 1; i <= allConstructors.length; i++) {
modifier = allConstructors[i - 1].getModifiers();
if (Modifier.isPublic(modifier) || Modifier.isProtected(modifier)) {
constructorList.add(allConstructors[i - 1]);
}
}
constructors = (Constructor[]) constructorList.toArray(new Constructor[0]);
if (constructors.length == 0)
throw new Exception();
} catch (Exception e) {
throw new IllegalArgumentException(
"The class to be delegated should have a public/protected constructor");
}
}
/**
* Create delegation class
* @return Delegation class
*/
public Class create() {
try {
return create(null);
} catch (IOException e) {
throw new IllegalArgumentException(e.toString());
}
}
/**
* Create delegation class
* @param out Output the delegation class to this stream
* @return Delegation class
* @throws IOException If output the class to output stream failed
*/
public Class create(OutputStream out) throws IOException {
Class newClass = null;
getMethods();
createFields();
createStaticBlock();
createConstructors();
createGetHandler();
createSetHandler();
createGetActualObject();
createGetDelegatedObject();
for (int i = 1; i <= methods.length; i++) {
createMethod(methods[i - 1], i - 1);
}
if (out != null)
_cg.getJavaClass().dump(out);
// Repository.addClass(_cg.getJavaClass());
// Verifier.main(new String[] { targetName });
// Class2HTML c2h = new Class2HTML(_cg.getJavaClass(), "c:/temp/code-gen/");
ClassLoader loader = new DelegationClassLoader(Delegation.class.getClassLoader(),
_cg.getJavaClass().getBytes());
try {
newClass = Class.forName(targetName, true, loader);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return newClass;
}
/**
* get All methods to be delegated
*
*/
protected void getMethods() {
Method[] allMethods = classes[0].getMethods();
allMethods = combineMethods(allMethods, getHierachyAbstractProtectedMethods(classes[0]));
for (int i = 1; i <= interfaces.length; i++) {
if (!interfaces[i - 1].equals(Delegation.class))
allMethods = combineMethods(allMethods, interfaces[i -1].getMethods());
}
List qualifiedMethods = new ArrayList();
for (int i = 1; i <= allMethods.length; i++) {
if (allMethods[i - 1].getDeclaringClass() == Object.class) {
String name = allMethods[i - 1].getName();
if (name.equals("toString") || name.equals("hashCode")
|| name.equals("equals"))
qualifiedMethods.add(allMethods[i - 1]);
} else {
int modifier = allMethods[i - 1].getModifiers();
if (!Modifier.isStatic(modifier) && !Modifier.isFinal(modifier))
qualifiedMethods.add(allMethods[i - 1]);
}
}
methods = (Method[]) qualifiedMethods.toArray(new Method[0]);
}
private void createFields() {
FieldGen field;
field = new FieldGen(0, new ObjectType(className), "bean", _cp);
_cg.addField(field.getField());
field = new FieldGen(0, new ObjectType(
DELEGATION_INVOCATION_HANDLER_INTERFACE_NAME), "handler", _cp);
_cg.addField(field.getField());
for (int i = 1; i <= methods.length; i++) {
field = new FieldGen(ACC_STATIC, new ObjectType(
"java.lang.reflect.Method"), "m" + (i - 1), _cp);
_cg.addField(field.getField());
}
}
private void createStaticBlock() {
InstructionList il = new InstructionList();
MethodGen method = new MethodGen(ACC_STATIC, Type.VOID, Type.NO_ARGS,
new String[] {}, "", targetName, il, _cp);
InstructionHandle[] start_pc = new InstructionHandle[methods.length + 1];
InstructionHandle[] end_pc = new InstructionHandle[methods.length];
InstructionHandle[] handler_pc = new InstructionHandle[methods.length];
BranchInstruction[] goto_pc = new BranchInstruction[methods.length];
for (int i = 1; i <= methods.length; i++) {
InstructionHandle ih = il.append(InstructionConstants.ACONST_NULL);
il.append(_factory.createFieldAccess(targetName, "m" + (i - 1),
new ObjectType("java.lang.reflect.Method"),
Constants.PUTSTATIC));
}
for (int i = 1; i <= methods.length; i++) {
start_pc[i - 1] = genForName(il, methods[i - 1].getDeclaringClass().getName());
genGetMethod(il, methods[i - 1]);
il.append(_factory.createFieldAccess(targetName, "m" + (i - 1),
new ObjectType("java.lang.reflect.Method"),
Constants.PUTSTATIC));
genExHandler(il, end_pc, handler_pc, goto_pc, i - 1);
}
start_pc[methods.length] = il.append(InstructionFactory
.createReturn(Type.VOID));
for (int i = 1; i <= methods.length; i++)
goto_pc[i - 1].setTarget(start_pc[i]);
for (int i = 1; i <= methods.length; i++) {
method.addExceptionHandler(start_pc[i - 1], end_pc[i - 1],
handler_pc[i - 1], new ObjectType("java.lang.Exception"));
}
method.setMaxStack();
method.setMaxLocals();
_cg.addMethod(method.getMethod());
il.dispose();
}
private void createConstructors() {
for(int i = 1; i <= constructors.length; i++) {
InstructionList il = new InstructionList();
Class[] paraClass = constructors[i - 1].getParameterTypes();
Class[] exceptClass = constructors[i - 1].getExceptionTypes();
Type[] paraTypes = new Type[paraClass.length + 1];
String[] paraNames = new String[paraClass.length + 1];
int stackIndex = 0;
//method definition
paraTypes[0] = Type.OBJECT;
paraNames[0] = "arg0";
for (int t = 1; t <= paraClass.length; t++) {
paraTypes[t] = getType(paraClass[t - 1]);
paraNames[t] = "arg" + t;
}
MethodGen method = new MethodGen(ACC_PUBLIC, Type.VOID,
paraTypes, paraNames, "", targetName, il, _cp);
for (int t = 1; t <= exceptClass.length; t++) {
method.addException(exceptClass[t - 1].getName());
}
il.append(InstructionFactory.createLoad(Type.OBJECT, stackIndex));
stackIndex = stackIndex + getTypeSize(Type.OBJECT); //Index of first argument
stackIndex = stackIndex + getTypeSize(Type.OBJECT); //Index of second argument
for (int t = 1; t <= paraClass.length; t++) {
if (paraClass[t - 1].isPrimitive())
il.append(InstructionFactory.createLoad(
getEqualType(paraClass[t - 1]), stackIndex));
else {
il.append(InstructionFactory.createLoad(Type.OBJECT, stackIndex));
}
stackIndex = stackIndex + getTypeSize(paraTypes[t]);
}
Type[] superParaTypes = new Type[paraClass.length];
System.arraycopy(paraTypes, 1, superParaTypes, 0, paraClass.length);
il.append(_factory.createInvoke(className, "", Type.VOID,
superParaTypes, Constants.INVOKESPECIAL));
il.append(InstructionFactory.createLoad(Type.OBJECT, 0));
il.append(InstructionConstants.ACONST_NULL);
il.append(_factory.createFieldAccess(targetName, "handler",
new ObjectType(DELEGATION_INVOCATION_HANDLER_INTERFACE_NAME),
Constants.PUTFIELD));
il.append(InstructionFactory.createLoad(Type.OBJECT, 0));
il.append(InstructionFactory.createLoad(Type.OBJECT, 1));
il.append(_factory.createCheckCast(new ObjectType(className)));
il.append(_factory.createFieldAccess(targetName, "bean",
new ObjectType(className), Constants.PUTFIELD));
il.append(InstructionFactory.createReturn(Type.VOID));
method.setMaxStack();
method.setMaxLocals();
_cg.addMethod(method.getMethod());
il.dispose();
}
}
private void createGetHandler() {
InstructionList il = new InstructionList();
MethodGen method = new MethodGen(ACC_PUBLIC, new ObjectType(
DELEGATION_INVOCATION_HANDLER_INTERFACE_NAME), Type.NO_ARGS,
new String[] {}, "_getInvocationHandler", targetName, il, _cp);
InstructionHandle ih_0 = il.append(InstructionFactory.createLoad(
Type.OBJECT, 0));
il.append(_factory.createFieldAccess(targetName, "handler",
new ObjectType(DELEGATION_INVOCATION_HANDLER_INTERFACE_NAME),
Constants.GETFIELD));
InstructionHandle ih_4 = il.append(InstructionFactory
.createReturn(Type.OBJECT));
method.setMaxStack();
method.setMaxLocals();
_cg.addMethod(method.getMethod());
il.dispose();
}
private void createSetHandler() {
InstructionList il = new InstructionList();
MethodGen method = new MethodGen(ACC_PUBLIC, Type.VOID,
new Type[] { new ObjectType(
DELEGATION_INVOCATION_HANDLER_INTERFACE_NAME) },
new String[] { "arg0" }, "_setInvocationHandler", targetName,
il, _cp);
InstructionHandle ih_0 = il.append(InstructionFactory.createLoad(
Type.OBJECT, 0));
il.append(InstructionFactory.createLoad(Type.OBJECT, 1));
il.append(_factory.createFieldAccess(targetName, "handler",
new ObjectType(DELEGATION_INVOCATION_HANDLER_INTERFACE_NAME),
Constants.PUTFIELD));
InstructionHandle ih_5 = il.append(InstructionFactory
.createReturn(Type.VOID));
method.setMaxStack();
method.setMaxLocals();
_cg.addMethod(method.getMethod());
il.dispose();
}
private InstructionHandle genForName(InstructionList il, Class clazz) {
if (clazz.isPrimitive())
return il.append(_factory.createFieldAccess(
getWrapperClassName(clazz), "TYPE", new ObjectType(
"java.lang.Class"), Constants.GETSTATIC));
else {
InstructionHandle ih = il.append(new PUSH(_cp,
getWrapperClassName(clazz)));
il.append(_factory.createInvoke("java.lang.Class", "forName",
new ObjectType("java.lang.Class"),
new Type[] { Type.STRING }, Constants.INVOKESTATIC));
return ih;
}
}
private InstructionHandle genForName(InstructionList il, String className) {
InstructionHandle ih = il.append(new PUSH(_cp, className));
il.append(_factory.createInvoke("java.lang.Class", "forName",
new ObjectType("java.lang.Class"), new Type[] { Type.STRING },
Constants.INVOKESTATIC));
return ih;
}
/**
* Get the given class's wrapper class name
* @param clazz The class to be wrapped
* @return The class name of the wrapper class. If the class is primitive class, return its wrapper class, else return itself.
*/
protected static String getWrapperClassName(Class clazz) {
if (clazz == Boolean.TYPE)
return Boolean.class.getName();
if (clazz == Character.TYPE)
return Character.class.getName();
if (clazz == Byte.TYPE)
return Byte.class.getName();
if (clazz == Short.TYPE)
return Short.class.getName();
if (clazz == Integer.TYPE)
return Integer.class.getName();
if (clazz == Long.TYPE)
return Long.class.getName();
if (clazz == Float.TYPE)
return Float.class.getName();
if (clazz == Double.TYPE)
return Double.class.getName();
return clazz.getName();
}
/**
* Get the method name of wrapper class which is used to change a wrapper object to its primitive value
* @param clazz The primitive class
* @return The method name
*/
protected static String getWrapperClassMethod(Class clazz) {
if (clazz == Boolean.TYPE)
return "booleanValue";
if (clazz == Character.TYPE)
return "charValue";
if (clazz == Byte.TYPE)
return "byteValue";
if (clazz == Short.TYPE)
return "shortValue";
if (clazz == Integer.TYPE)
return "intValue";
if (clazz == Long.TYPE)
return "longValue";
if (clazz == Float.TYPE)
return "floatValue";
if (clazz == Double.TYPE)
return "doubleValue";
return null;
}
private void genSetInitValue(InstructionList il, Class clazz,
float value, int index) {
if (clazz == Boolean.TYPE) {
il.append(new PUSH(_cp, (int) value));
il.append(InstructionFactory.createStore(Type.INT, index));
} else if (clazz == Character.TYPE) {
il.append(new PUSH(_cp, (int) value));
il.append(InstructionFactory.createStore(Type.INT, index));
} else if (clazz == Byte.TYPE) {
il.append(new PUSH(_cp, (int) value));
il.append(InstructionFactory.createStore(Type.INT, index));
} else if (clazz == Short.TYPE) {
il.append(new PUSH(_cp, (int) value));
il.append(InstructionFactory.createStore(Type.INT, index));
} else if (clazz == Integer.TYPE) {
il.append(new PUSH(_cp, (int) value));
il.append(InstructionFactory.createStore(Type.INT, index));
} else if (clazz == Long.TYPE) {
il.append(new PUSH(_cp, (long) value));
il.append(InstructionFactory.createStore(Type.LONG, index));
} else if (clazz == Float.TYPE) {
il.append(new PUSH(_cp, value));
il.append(InstructionFactory.createStore(Type.FLOAT, index));
} else if (clazz == Double.TYPE) {
il.append(new PUSH(_cp, (double) value));
il.append(InstructionFactory.createStore(Type.DOUBLE, index));
} else if (clazz == void.class) {
} else {
il.append(InstructionConstants.ACONST_NULL);
il.append(InstructionFactory.createStore(Type.OBJECT, index));
}
}
private void genGetMethod(InstructionList il, Method method) {
il.append(new PUSH(_cp, method.getName()));
Class[] params = method.getParameterTypes();
il.append(new PUSH(_cp, params.length));
il.append(_factory.createNewArray(new ObjectType("java.lang.Class"),
(short) 1));
for (int i = 1; i <= params.length; i++) {
il.append(InstructionConstants.DUP);
il.append(new PUSH(_cp, i - 1));
genForName(il, params[i - 1]);
il.append(InstructionConstants.AASTORE);
}
il.append(_factory.createInvoke("java.lang.Class", "getMethod",
new ObjectType("java.lang.reflect.Method"), new Type[] {
Type.STRING,
new ArrayType(new ObjectType("java.lang.Class"), 1) },
Constants.INVOKEVIRTUAL));
}
private void genExHandler(InstructionList il, InstructionHandle[] end_pc,
InstructionHandle[] handler_pc, BranchInstruction[] goto_pc,
int index) {
goto_pc[index] = InstructionFactory.createBranchInstruction(
Constants.GOTO, null);
end_pc[index] = il.append(goto_pc[index]);
handler_pc[index] = il.append(InstructionFactory.createStore(
Type.OBJECT, 0));
}
private void createMethod(Method m, int index) {
InstructionList il = new InstructionList();
Class[] paraClass = m.getParameterTypes();
Class[] exceptClass = m.getExceptionTypes();
boolean[] defaultExceptCatch = getDefaultExceptCatch(exceptClass);
Type[] paraTypes = new Type[paraClass.length];
String[] paraNames = new String[paraClass.length];
Class returnClass = m.getReturnType();
Type returnType = getType(returnClass);
InstructionHandle start_pc, end_pc;
InstructionHandle[] handler_pc = new InstructionHandle[exceptClass.length];
BranchInstruction goto_1 = null, goto_2 = null, goto_3 = null;
String m_name = "m" + index;
boolean skipOriginalCall = Modifier.isAbstract(m.getModifiers());
//method definition
for (int i = 1; i <= paraClass.length; i++) {
paraTypes[i - 1] = getType(paraClass[i - 1]);
paraNames[i - 1] = "arg" + (i - 1);
}
int goonIndex = getTypeSize(paraTypes) + 1;
int retIndex = (returnClass == void.class) ? -1 : goonIndex + getTypeSize(Type.BOOLEAN);
int throwableIndex = (retIndex == -1) ? goonIndex + getTypeSize(Type.BOOLEAN) : retIndex
+ getTypeSize(returnType);
int exceptIndex = throwableIndex + getTypeSize(Type.OBJECT);
MethodGen method = new MethodGen(getAccessFlag(m), returnType, paraTypes,
paraNames, m.getName(), targetName, il, _cp);
for (int i = 1; i <= exceptClass.length; i++) {
method.addException(exceptClass[i - 1].getName());
}
//declare the local vars (goon and ret)
genSetInitValue(il, Boolean.TYPE, 1, goonIndex);
genSetInitValue(il, returnClass, 0, retIndex);
genSetInitValue(il, Throwable.class, 0, throwableIndex);
//if handler != null
start_pc = il.append(InstructionFactory.createLoad(Type.OBJECT, 0));
il.append(_factory.createFieldAccess(targetName, "handler",
new ObjectType(DELEGATION_INVOCATION_HANDLER_INTERFACE_NAME),
Constants.GETFIELD));
BranchInstruction ifnull_1 = InstructionFactory
.createBranchInstruction(Constants.IFNULL, null);
il.append(ifnull_1);
//goon = handler.invokeBefore(bean, m0, new Object[] {...});
InstructionHandle ih_11 = il.append(InstructionFactory.createLoad(
Type.OBJECT, 0));
il.append(_factory.createFieldAccess(targetName, "handler",
new ObjectType(DELEGATION_INVOCATION_HANDLER_INTERFACE_NAME),
Constants.GETFIELD));
il.append(InstructionFactory.createLoad(Type.OBJECT, 0));
il.append(_factory.createFieldAccess(targetName, "bean",
new ObjectType(className), Constants.GETFIELD));
il.append(_factory
.createFieldAccess(targetName, m_name, new ObjectType(
"java.lang.reflect.Method"), Constants.GETSTATIC));
genMethodArgumentArray(il, paraClass);
il.append(_factory.createInvoke(
DELEGATION_INVOCATION_HANDLER_INTERFACE_NAME, "invokeBefore",
Type.BOOLEAN, new Type[] { Type.OBJECT,
new ObjectType("java.lang.reflect.Method"),
new ArrayType(Type.OBJECT, 1) },
Constants.INVOKEINTERFACE));
il.append(InstructionFactory.createStore(Type.INT, goonIndex));
//if (goon)
InstructionHandle beyond_ifnull_1 = il.append(InstructionFactory
.createLoad(Type.INT, goonIndex));
BranchInstruction ifeq = InstructionFactory.createBranchInstruction(
Constants.IFEQ, null);
il.append(ifeq);
InstructionHandle sub_start_pc = null;
if (!skipOriginalCall) {
//ret = bean.doMethod(...);
sub_start_pc = il.append(InstructionFactory
.createLoad(Type.OBJECT, 0));
il.append(_factory.createFieldAccess(targetName, "bean",
new ObjectType(className), Constants.GETFIELD));
int stackIndex = getTypeSize(Type.OBJECT);
for (int i = 1; i <= paraClass.length; i++) {
if (paraClass[i - 1].isPrimitive())
il.append(InstructionFactory.createLoad(
getEqualType(paraClass[i - 1]), stackIndex));
else {
//if equals, call bean.equals(getActualObject(obj))
if (m.getName().equals("equals") && (paraClass.length == 1) && (paraClass[0] == Object.class)) {
il.append(InstructionFactory.createLoad(Type.OBJECT, 0));
il.append(InstructionFactory.createLoad(Type.OBJECT, 1));
il.append(_factory.createInvoke(targetName, "getActualObject", Type.OBJECT, new Type[] { Type.OBJECT }, Constants.INVOKESPECIAL));
} else
il.append(InstructionFactory.createLoad(Type.OBJECT, stackIndex));
}
stackIndex = stackIndex + getTypeSize(paraTypes[i - 1]);
}
il.append(_factory.createInvoke(/* className */m.getDeclaringClass()
.getName(), m.getName(), returnType, paraTypes,
Constants.INVOKEVIRTUAL));
if (returnClass != void.class) {
if (returnClass.isPrimitive())
il.append(InstructionFactory.createStore(
getEqualType(returnClass), retIndex));
else
il
.append(InstructionFactory.createStore(Type.OBJECT,
retIndex));
}
} else {
sub_start_pc = il.append(InstructionConstants.ACONST_NULL);
il.append(InstructionFactory.createStore(Type.OBJECT, throwableIndex));
}
goto_1 = InstructionFactory.createBranchInstruction(Constants.GOTO,
null);
InstructionHandle sub_end_pc = il.append(goto_1);
InstructionHandle sub_handler_pc = il.append(InstructionFactory
.createStore(Type.OBJECT, exceptIndex));
il.append(InstructionFactory.createLoad(Type.OBJECT, exceptIndex));
il.append(InstructionFactory.createStore(Type.OBJECT, throwableIndex));
//exception close
method.addExceptionHandler(sub_start_pc, sub_end_pc, sub_handler_pc,
new ObjectType("java.lang.Throwable"));
//if (handler != null)
InstructionHandle beyond_ifeq = il.append(InstructionFactory
.createLoad(Type.OBJECT, 0));
il.append(_factory.createFieldAccess(targetName, "handler",
new ObjectType(DELEGATION_INVOCATION_HANDLER_INTERFACE_NAME),
Constants.GETFIELD));
BranchInstruction ifnull_2 = InstructionFactory
.createBranchInstruction(Constants.IFNULL, null);
il.append(ifnull_2);
//if (t != null)
// ret = ((Integer)handler.invokeAfter(bean, m4, new Object[] {...}, t)).intValue();
il.append(InstructionFactory.createLoad(Type.OBJECT, throwableIndex));
BranchInstruction ifnull_1_5 = InstructionFactory
.createBranchInstruction(Constants.IFNULL, null);
il.append(ifnull_1_5);
il.append(InstructionFactory.createLoad(Type.OBJECT, 0));
il.append(_factory.createFieldAccess(targetName, "handler",
new ObjectType(DELEGATION_INVOCATION_HANDLER_INTERFACE_NAME),
Constants.GETFIELD));
il.append(InstructionFactory.createLoad(Type.OBJECT, 0));
il.append(_factory.createFieldAccess(targetName, "bean",
new ObjectType(className), Constants.GETFIELD));
il.append(_factory
.createFieldAccess(targetName, m_name, new ObjectType(
"java.lang.reflect.Method"), Constants.GETSTATIC));
genMethodArgumentArray(il, paraClass);
il.append(InstructionFactory.createLoad(Type.OBJECT, throwableIndex));
il.append(_factory.createInvoke(
DELEGATION_INVOCATION_HANDLER_INTERFACE_NAME,
"invokeAfterException", Type.OBJECT, new Type[] { Type.OBJECT,
new ObjectType("java.lang.reflect.Method"),
new ArrayType(Type.OBJECT, 1), new ObjectType("java.lang.Throwable") },
Constants.INVOKEINTERFACE));
if (returnClass != void.class) {
if (returnClass.isPrimitive()) {
String wrapperName = getWrapperClassName(returnClass);
String wrapperMethodName = getWrapperClassMethod(returnClass);
il
.append(_factory.createCheckCast(new ObjectType(
wrapperName)));
il.append(_factory.createInvoke(wrapperName, wrapperMethodName,
returnType, Type.NO_ARGS, Constants.INVOKEVIRTUAL));
il.append(InstructionFactory.createStore(
getEqualType(returnClass), retIndex));
} else {
il.append(_factory.createCheckCast((ReferenceType) returnType));
il
.append(InstructionFactory.createStore(Type.OBJECT,
retIndex));
}
} else {
il.append(InstructionConstants.POP);
}
goto_2 = InstructionFactory.createBranchInstruction(Constants.GOTO,
null);
il.append(goto_2);
//else
// ret = ((Integer)handler.invokeAfter(bean, m4, new Object[] {...}, new
// Integer(ret))).intValue();
InstructionHandle else_ih = il.append(InstructionFactory.createLoad(
Type.OBJECT, 0));
il.append(_factory.createFieldAccess(targetName, "handler",
new ObjectType(DELEGATION_INVOCATION_HANDLER_INTERFACE_NAME),
Constants.GETFIELD));
il.append(InstructionFactory.createLoad(Type.OBJECT, 0));
il.append(_factory.createFieldAccess(targetName, "bean",
new ObjectType(className), Constants.GETFIELD));
il.append(_factory
.createFieldAccess(targetName, m_name, new ObjectType(
"java.lang.reflect.Method"), Constants.GETSTATIC));
genMethodArgumentArray(il, paraClass);
if (returnClass == void.class) {
il.append(InstructionConstants.ACONST_NULL);
il.append(_factory.createInvoke(
DELEGATION_INVOCATION_HANDLER_INTERFACE_NAME,
"invokeAfter", Type.OBJECT, new Type[] { Type.OBJECT,
new ObjectType("java.lang.reflect.Method"),
new ArrayType(Type.OBJECT, 1), Type.OBJECT },
Constants.INVOKEINTERFACE));
} else if (returnClass.isPrimitive()) {
String wrapperName = getWrapperClassName(returnClass);
String wrapperMethodName = getWrapperClassMethod(returnClass);
il.append(_factory.createNew(wrapperName));
il.append(InstructionConstants.DUP);
il.append(InstructionFactory.createLoad(getEqualType(returnClass),
retIndex));
il.append(_factory.createInvoke(wrapperName, "", Type.VOID,
new Type[] { returnType }, Constants.INVOKESPECIAL));
il.append(_factory.createInvoke(
DELEGATION_INVOCATION_HANDLER_INTERFACE_NAME,
"invokeAfter", Type.OBJECT, new Type[] { Type.OBJECT,
new ObjectType("java.lang.reflect.Method"),
new ArrayType(Type.OBJECT, 1), Type.OBJECT },
Constants.INVOKEINTERFACE));
il.append(_factory.createCheckCast(new ObjectType(wrapperName)));
il.append(_factory.createInvoke(wrapperName, wrapperMethodName,
returnType, Type.NO_ARGS, Constants.INVOKEVIRTUAL));
il.append(InstructionFactory.createStore(getEqualType(returnClass),
retIndex));
} else {
il.append(InstructionFactory.createLoad(Type.OBJECT, retIndex));
il.append(_factory.createInvoke(
DELEGATION_INVOCATION_HANDLER_INTERFACE_NAME,
"invokeAfter", Type.OBJECT, new Type[] { Type.OBJECT,
new ObjectType("java.lang.reflect.Method"),
new ArrayType(Type.OBJECT, 1), Type.OBJECT },
Constants.INVOKEINTERFACE));
il.append(_factory.createCheckCast((ReferenceType) returnType));
il.append(InstructionFactory.createStore(Type.OBJECT, retIndex));
}
//return ret;
InstructionHandle beyond_ifnull_2 = null;
end_pc = null;
if (returnClass == void.class) {
il.append(InstructionConstants.POP);
goto_3 = InstructionFactory.createBranchInstruction(Constants.GOTO,
null);
end_pc = il.append(goto_3);
} else if (returnClass.isPrimitive()) {
beyond_ifnull_2 = il.append(InstructionFactory.createLoad(
returnType, retIndex));
end_pc = il.append(InstructionFactory.createReturn(returnType));
} else {
beyond_ifnull_2 = il.append(InstructionFactory.createLoad(
Type.OBJECT, retIndex));
end_pc = il.append(InstructionFactory.createReturn(Type.OBJECT));
}
//exception handling
for (int i = 1; i <= exceptClass.length; i++) {
handler_pc[i - 1] = il.append(InstructionFactory.createStore(
Type.OBJECT, exceptIndex));
il.append(InstructionFactory.createLoad(Type.OBJECT, exceptIndex));
il.append(InstructionConstants.ATHROW);
}
InstructionHandle runtime_pc = null;
if (defaultExceptCatch[0]) {
runtime_pc = il.append(InstructionFactory.createStore(Type.OBJECT,
exceptIndex));
il.append(InstructionFactory.createLoad(Type.OBJECT, exceptIndex));
il.append(InstructionConstants.ATHROW);
}
InstructionHandle error_pc = null;
if (defaultExceptCatch[1]) {
error_pc = il.append(InstructionFactory.createStore(Type.OBJECT,
exceptIndex));
il.append(InstructionFactory.createLoad(Type.OBJECT, exceptIndex));
il.append(InstructionConstants.ATHROW);
}
InstructionHandle throwable_pc = null;
if (defaultExceptCatch[2]) {
throwable_pc = il.append(InstructionFactory.createStore(
Type.OBJECT, exceptIndex));
il
.append(_factory
.createNew("java.lang.reflect.UndeclaredThrowableException"));
il.append(InstructionConstants.DUP);
il.append(InstructionFactory.createLoad(Type.OBJECT, exceptIndex));
il.append(_factory.createInvoke(
"java.lang.reflect.UndeclaredThrowableException", "",
Type.VOID, new Type[] { new ObjectType(
"java.lang.Throwable") }, Constants.INVOKESPECIAL));
il.append(InstructionConstants.ATHROW);
}
if (returnClass == void.class) {
beyond_ifnull_2 = il.append(InstructionFactory
.createReturn(Type.VOID));
}
//if statment close
ifnull_1.setTarget(beyond_ifnull_1);
ifeq.setTarget(beyond_ifeq);
ifnull_1_5.setTarget(else_ih);
ifnull_2.setTarget(beyond_ifnull_2);
goto_1.setTarget(beyond_ifeq);
goto_2.setTarget(beyond_ifnull_2);
if (returnClass == void.class) {
goto_3.setTarget(beyond_ifnull_2);
}
//exception close
// method.addExceptionHandler(sub_start_pc, sub_end_pc, sub_handler_pc,
// new ObjectType("java.lang.Throwable"));
for (int i = 1; i <= exceptClass.length; i++) {
method.addExceptionHandler(start_pc, end_pc, handler_pc[i - 1],
(ObjectType) getType(exceptClass[i - 1]));
}
if (defaultExceptCatch[0])
method.addExceptionHandler(start_pc, end_pc, runtime_pc,
new ObjectType("java.lang.RuntimeException"));
if (defaultExceptCatch[1])
method.addExceptionHandler(start_pc, end_pc, error_pc,
new ObjectType("java.lang.Error"));
if (defaultExceptCatch[2])
method.addExceptionHandler(start_pc, end_pc, throwable_pc,
new ObjectType("java.lang.Throwable"));
method.setMaxStack();
method.setMaxLocals();
_cg.addMethod(method.getMethod());
il.dispose();
}
private boolean[] getDefaultExceptCatch(Class[] exceptClasses) {
boolean[] ret = new boolean[] { true, true, true };
for (int i = 1; i <= exceptClasses.length; i++) {
if (exceptClasses[i - 1].equals(RuntimeException.class)) {
ret[0] = false;
} else if (exceptClasses[i - 1].equals(Error.class)) {
ret[1] = false;
} else if (exceptClasses[i - 1].equals(Throwable.class)) {
ret[2] = false;
ret[1] = false;
ret[0] = false;
break;
}
}
return ret;
}
/**
* Get the size of the Type
* @param type BCEL Type
* @return Type size
*/
protected static int getTypeSize(Type type) {
if ((type == Type.LONG) || (type == Type.DOUBLE))
return 2;
if (type == Type.VOID)
return 0;
return 1;
}
/**
* Get the size of the Type array
* @param types Type array
* @return Size of type array
*/
protected static int getTypeSize(Type[] types) {
int ret = 0;
for (int i = 1; i <= types.length; i++) {
ret = ret + getTypeSize(types[i - 1]);
}
return ret;
}
/**
* Change class to BCEL Type
* @param clazz Java class
* @return BCEL Type
*/
protected static Type getType(Class clazz) {
if (clazz == Boolean.TYPE)
return Type.BOOLEAN;
if (clazz == Character.TYPE)
return Type.CHAR;
if (clazz == Byte.TYPE)
return Type.BYTE;
if (clazz == Short.TYPE)
return Type.SHORT;
if (clazz == Integer.TYPE)
return Type.INT;
if (clazz == Long.TYPE)
return Type.LONG;
if (clazz == Float.TYPE)
return Type.FLOAT;
if (clazz == Double.TYPE)
return Type.DOUBLE;
if (clazz == void.class)
return Type.VOID;
if (clazz.isArray())
return getArrayType(clazz);
return new ObjectType(clazz.getName());
}
/**
* Get the array type for a specific class
* @param clazz Java class
* @return BCEL Array type
*/
protected static Type getArrayType(Class clazz) {
Class componentClass = clazz;
int dim = 0;
while (componentClass.isArray()) {
dim++;
componentClass = componentClass.getComponentType();
}
return new ArrayType(getType(componentClass), dim);
}
/**
* Get a specific class's equal type
* @param clazz Java class
* @return BCEL Type
*/
protected static Type getEqualType(Class clazz) {
if (clazz == Boolean.TYPE)
return Type.INT;
if (clazz == Character.TYPE)
return Type.INT;
if (clazz == Byte.TYPE)
return Type.INT;
if (clazz == Short.TYPE)
return Type.INT;
if (clazz == Integer.TYPE)
return Type.INT;
if (clazz == Long.TYPE)
return Type.LONG;
if (clazz == Float.TYPE)
return Type.FLOAT;
if (clazz == Double.TYPE)
return Type.DOUBLE;
if (clazz == void.class)
return Type.VOID;
return new ObjectType(clazz.getName());
}
private void genMethodArgumentArray(InstructionList il, Class[] paraClass) {
il.append(new PUSH(_cp, paraClass.length));
il.append(_factory.createNewArray(Type.OBJECT, (short) 1));
int pos = 1;
for (int i = 1; i <= paraClass.length; i++) {
Type type = getType(paraClass[i - 1]);
il.append(InstructionConstants.DUP);
il.append(new PUSH(_cp, i - 1));
if (paraClass[i - 1].isPrimitive()) {
String wrapperName = getWrapperClassName(paraClass[i - 1]);
il.append(_factory.createNew(wrapperName));
il.append(InstructionConstants.DUP);
il.append(InstructionFactory.createLoad(type, pos));
il.append(_factory
.createInvoke(wrapperName, "", Type.VOID,
new Type[] { type }, Constants.INVOKESPECIAL));
} else {
il.append(InstructionFactory.createLoad(Type.OBJECT, pos));
}
il.append(InstructionConstants.AASTORE);
pos = pos + getTypeSize(type);
}
}
private static Method[] combineMethods(Method[] array1, Method[] array2) {
List methods = new ArrayList();
for (int i = 1; i <= array1.length; i++) {
methods.add(array1[i - 1]);
}
for (int i = 1; i <= array2.length; i++) {
boolean find = false;
for (int j = 1; j <= array1.length; j++) {
if (equals(array1[j - 1], array2[i - 1])) {
find = true;
break;
}
}
if (!find)
methods.add(array2[i - 1]);
}
return (Method[])methods.toArray(new Method[0]);
}
private static Method[] getHierachyAbstractProtectedMethods(Class clazz) {
List ret = new ArrayList();
List superLink = new ArrayList();
while (clazz != null) {
superLink.add(0, clazz);
clazz = clazz.getSuperclass();
}
for (int i = 1; i <= superLink.size(); i++) {
getAbstractProtectedMethods((Class)superLink.get(i - 1), ret);
}
return (Method[]) ret.toArray(new Method[0]);
}
private static void getAbstractProtectedMethods(Class clazz, List abMethods) {
Method[] methods = clazz.getDeclaredMethods();
for (int i = 1; i <= methods.length; i++) {
int modifier = methods[i - 1].getModifiers();
if (Modifier.isAbstract(modifier) && Modifier.isProtected(modifier))
abMethods.add(methods[i - 1]);
else if (!Modifier.isAbstract(modifier) && !Modifier.isStatic(modifier) && !Modifier.isPrivate(modifier)) {
Iterator it = abMethods.iterator();
while(it.hasNext()) {
Method m = (Method)it.next();
if (equals(methods[i - 1], m)) {
it.remove();
break;
}
}
}
}
}
private static boolean equals(Method m1, Method m2) {
if (m1.getName().equals(m2.getName()) && Arrays.equals(m1.getParameterTypes(), m2.getParameterTypes()))
return true;
return false;
}
private void createGetActualObject() {
InstructionList il = new InstructionList();
MethodGen method = new MethodGen(ACC_PRIVATE, Type.OBJECT, new Type[] { Type.OBJECT }, new String[] { "arg0" }, "getActualObject", targetName, il, _cp);
InstructionHandle ih_0 = il.append(InstructionFactory.createLoad(Type.OBJECT, 1));
il.append(new INSTANCEOF(_cp.addClass(new ObjectType("org.jingle.util.dydelegation.Delegation"))));
BranchInstruction ifeq_4 = InstructionFactory.createBranchInstruction(Constants.IFEQ, null);
il.append(ifeq_4);
InstructionHandle ih_7 = il.append(InstructionFactory.createLoad(Type.OBJECT, 1));
il.append(_factory.createCheckCast(new ObjectType("org.jingle.util.dydelegation.Delegation")));
il.append(_factory.createInvoke("org.jingle.util.dydelegation.Delegation", "_getDelegatedObject", Type.OBJECT, Type.NO_ARGS, Constants.INVOKEINTERFACE));
il.append(InstructionFactory.createReturn(Type.OBJECT));
InstructionHandle ih_17 = il.append(InstructionFactory.createLoad(Type.OBJECT, 1));
InstructionHandle ih_18 = il.append(InstructionFactory.createReturn(Type.OBJECT));
ifeq_4.setTarget(ih_17);
method.setMaxStack();
method.setMaxLocals();
_cg.addMethod(method.getMethod());
il.dispose();
}
private void createGetDelegatedObject() {
InstructionList il = new InstructionList();
MethodGen method = new MethodGen(ACC_PUBLIC, Type.OBJECT, Type.NO_ARGS, new String[] { }, "_getDelegatedObject", targetName, il, _cp);
InstructionHandle ih_0 = il.append(InstructionFactory.createLoad(Type.OBJECT, 0));
il.append(_factory.createFieldAccess(targetName, "bean", new ObjectType(className), Constants.GETFIELD));
InstructionHandle ih_4 = il.append(InstructionFactory.createReturn(Type.OBJECT));
method.setMaxStack();
method.setMaxLocals();
_cg.addMethod(method.getMethod());
il.dispose();
}
private static short getAccessFlag(Method m) {
int modifier = m.getModifiers();
if (Modifier.isPublic(modifier))
return ACC_PUBLIC;
else if (Modifier.isProtected(modifier))
return ACC_PROTECTED;
else
return ACC_PRIVATE;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy