package org.coldswap.util;
/**
* (C) Copyright 2013 Faur Ioan-Aurel.
* <p/>
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Lesser General Public License
* (LGPL) version 2.1 which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/lgpl-2.1.html
* <p/>
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
* <p/>
* Contributors:
* faur
* <p/>
* Created at:
* 8:39 PM 5/14/13
*/
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.tree.*;
/**
* Helper class for extracting method return type, method params type, etc...
*/
public class MethodUtil {
public static Type getReturnType(MethodNode methodNode) {
String methodDesc = methodNode.desc;
// get 2 strings one containing the var params and
// the other the return type
String[] descs = methodDesc.split("\\)");
return Type.getReturnType(descs[1]);
}
public static Type[] getParamsType(MethodNode methodNode) {
String methodDesc = methodNode.desc;
// get 2 strings one containing the var params and
// the other the return type
String[] descs = methodDesc.split("\\)");
// get a list of params that this method has
String[] paramType = null;
if (!descs[0].equals("(")) {
paramType = descs[0].substring(1).split(";");
// append ";" if param is not primitive type
for (int i = 0; i < paramType.length; i++) {
if (paramType[i].length() > 1) {
paramType[i] = paramType[i] + ";";
}
}
}
Type[] toRet = new Type[0];
if (paramType != null) {
toRet = new Type[paramType.length];
for (int i = 0; i < toRet.length; i++) {
toRet[i] = Type.getType(paramType[i]);
}
}
return toRet;
}
public static Type classToType(Class<?> aClass) {
return Type.getType(aClass);
}
public static Type[] classToType(Class<?>[] classes) {
Type[] toRet = new Type[classes.length];
for (int i = 0; i < toRet.length; i++) {
toRet[i] = classToType(classes[i]);
}
return toRet;
}
public static MethodNode createObjectHelperMethod(String className, int counter) {
int acc = Opcodes.ACC_PUBLIC;
String methodName = TransformerNameGenerator.getObjectMethodNameWithCounter(className, counter);
MethodNode mn = new MethodNode(acc, methodName, "([Ljava/lang/Object;)Ljava/lang/Object;", null, null);
InsnList insnList = mn.instructions;
LabelNode l0 = new LabelNode();
insnList.add(l0);
insnList.add(new InsnNode(Opcodes.ACONST_NULL));
insnList.add(new InsnNode(Opcodes.ARETURN));
LabelNode l1 = new LabelNode();
insnList.add(l1);
String classLiteral = "L" + className + ";";
mn.localVariables.add(new LocalVariableNode("this", classLiteral, null, l0, l1, 0));
mn.localVariables.add(new LocalVariableNode("args", "[Ljava/lang/Object;", null, l0, l1, 1));
mn.maxStack = 1;
mn.maxLocals = 2;
return mn;
}
public static MethodNode createIntHelperMethod(String className, int counter) {
int acc = Opcodes.ACC_PUBLIC;
String methodName = TransformerNameGenerator.getIntMethodNameWithCounter(className, counter);
MethodNode mn = new MethodNode(acc, methodName, "(I)Ljava/lang/Object;", null, null);
InsnList insnList = mn.instructions;
LabelNode l0 = new LabelNode();
insnList.add(l0);
insnList.add(new InsnNode(Opcodes.ACONST_NULL));
insnList.add(new InsnNode(Opcodes.ARETURN));
LabelNode l1 = new LabelNode();
insnList.add(l1);
String classLiteral = "L" + className + ";";
mn.localVariables.add(new LocalVariableNode("this", classLiteral, null, l0, l1, 0));
mn.localVariables.add(new LocalVariableNode("arg", "I", null, l0, l1, 1));
mn.maxStack = 1;
mn.maxLocals = 2;
return mn;
}
public static MethodNode createLongHelperMethod(String className, int counter) {
int acc = Opcodes.ACC_PUBLIC;
String methodName = TransformerNameGenerator.getLongMethodNameWithCounter(className, counter);
MethodNode mn = new MethodNode(acc, methodName, "(J)Ljava/lang/Object;", null, null);
InsnList insnList = mn.instructions;
LabelNode l0 = new LabelNode();
insnList.add(l0);
insnList.add(new InsnNode(Opcodes.ACONST_NULL));
insnList.add(new InsnNode(Opcodes.ARETURN));
LabelNode l1 = new LabelNode();
insnList.add(l1);
String classLiteral = "L" + className + ";";
mn.localVariables.add(new LocalVariableNode("this", classLiteral, null, l0, l1, 0));
mn.localVariables.add(new LocalVariableNode("arg", "J", null, l0, l1, 1));
mn.maxStack = 1;
mn.maxLocals = 3;
return mn;
}
public static MethodNode createFloatHelperMethod(String className, int counter) {
int acc = Opcodes.ACC_PUBLIC;
String methodName = TransformerNameGenerator.getFloatMethodNameWithCounter(className, counter);
MethodNode mn = new MethodNode(acc, methodName, "(F)Ljava/lang/Object;", null, null);
InsnList insnList = mn.instructions;
LabelNode l0 = new LabelNode();
insnList.add(l0);
insnList.add(new InsnNode(Opcodes.ACONST_NULL));
insnList.add(new InsnNode(Opcodes.ARETURN));
LabelNode l1 = new LabelNode();
insnList.add(l1);
String classLiteral = "L" + className + ";";
mn.localVariables.add(new LocalVariableNode("this", classLiteral, null, l0, l1, 0));
mn.localVariables.add(new LocalVariableNode("arg", "F", null, l0, l1, 1));
mn.maxStack = 1;
mn.maxLocals = 2;
return mn;
}
public static MethodNode createStringHelperMethod(String className, int counter) {
int acc = Opcodes.ACC_PUBLIC;
String methodName = TransformerNameGenerator.getStringMethodNameWithCounter(className, counter);
MethodNode mn = new MethodNode(acc, methodName, "(Ljava/lang/String;)Ljava/lang/Object;", null, null);
InsnList insnList = mn.instructions;
LabelNode l0 = new LabelNode();
insnList.add(l0);
insnList.add(new InsnNode(Opcodes.ACONST_NULL));
insnList.add(new InsnNode(Opcodes.ARETURN));
LabelNode l1 = new LabelNode();
insnList.add(l1);
String classLiteral = "L" + className + ";";
mn.localVariables.add(new LocalVariableNode("this", classLiteral, null, l0, l1, 0));
mn.localVariables.add(new LocalVariableNode("arg", "Ljava/lang/String;", null, l0, l1, 1));
mn.maxStack = 1;
mn.maxLocals = 2;
return mn;
}
public static int getRetOpcodeToReplace(Type retType) {
String retDesc = retType.getDescriptor();
int opcode = Opcodes.IRETURN;
if ("Z".equals(retDesc)) {
opcode = Opcodes.IRETURN;
} else if ("B".equals(retDesc)) {
opcode = Opcodes.IRETURN;
} else if ("C".equals(retDesc)) {
opcode = Opcodes.IRETURN;
} else if ("S".equals(retDesc)) {
opcode = Opcodes.IRETURN;
} else if ("I".equals(retDesc)) {
opcode = Opcodes.IRETURN;
} else if ("J".equals(retDesc)) {
opcode = Opcodes.LRETURN;
} else if ("F".equals(retDesc)) {
opcode = Opcodes.FRETURN;
} else if ("D".equals(retDesc)) {
opcode = Opcodes.DRETURN;
}
return opcode;
}
}