package me.lpk.util; import static org.objectweb.asm.Opcodes.ACC_PUBLIC; import static org.objectweb.asm.Opcodes.ALOAD; import static org.objectweb.asm.Opcodes.GETFIELD; import static org.objectweb.asm.Opcodes.ILOAD; import static org.objectweb.asm.Opcodes.IRETURN; import static org.objectweb.asm.Opcodes.PUTFIELD; import static org.objectweb.asm.Opcodes.RETURN; import org.objectweb.asm.ClassReader; import org.objectweb.asm.ClassWriter; import org.objectweb.asm.Type; import org.objectweb.asm.tree.ClassNode; import org.objectweb.asm.tree.FieldInsnNode; import org.objectweb.asm.tree.InsnNode; import org.objectweb.asm.tree.MethodNode; import org.objectweb.asm.tree.VarInsnNode; public class ASMUtils { /** * Gets the bytes of a given ClassNode. * * @param cn * @param useMaxs * @return */ public static byte[] getNodeBytes(ClassNode cn, boolean useMaxs) { ClassWriter cw = new ClassWriter(useMaxs ? ClassWriter.COMPUTE_MAXS : ClassWriter.COMPUTE_FRAMES); cn.accept(cw); byte[] b = cw.toByteArray(); return b; } public static byte[] getNodeBytes0(ClassNode cn) { ClassWriter cw = new ClassWriter(0); cn.accept(cw); byte[] b = cw.toByteArray(); return b; } /** * Gets a ClassNode based on given bytes * * @param bytez * @return */ public static ClassNode getNode(final byte[] bytez) { ClassReader cr = new ClassReader(bytez); ClassNode cn = new ClassNode(); try { cr.accept(cn, ClassReader.EXPAND_FRAMES); } catch (Exception e) { try { cr.accept(cn, ClassReader.SKIP_FRAMES | ClassReader.SKIP_DEBUG); } catch (Exception e2) { // e2.printStackTrace(); } } cr = null; return cn; } /** * Generates a getter method for the specified field * * @author Xerces * @param fieldName * the name of the field * @param className * the internal class name * @param fieldDesc * the field descriptor * @param methodName * the name of the method to create * @return the method as a {@link org.objectweb.asm.tree.MethodNode} */ public static MethodNode generateGetter(String methodName, String fieldName, String className, String fieldDesc) { MethodNode methodNode = new MethodNode(ACC_PUBLIC, methodName, "()" + fieldDesc, null, null); methodNode.instructions.insert(new VarInsnNode(ALOAD, 0)); methodNode.instructions.insert(new FieldInsnNode(GETFIELD, className, fieldName, fieldDesc)); methodNode.instructions.insert(new InsnNode(Type.getType(fieldDesc).getOpcode(IRETURN))); return methodNode; } /** * Generates a setter method for the specified field * * @author Xerces * @param fieldName * the name of the field * @param className * the internal class name * @param fieldDesc * the field descriptor * @param methodName * the name of the method to create * @return the method as a {@link org.objectweb.asm.tree.MethodNode} */ public static MethodNode generateSetter(String methodName, String fieldName, String className, String fieldDesc) { MethodNode methodNode = new MethodNode(ACC_PUBLIC, methodName, "(" + fieldDesc + ")V", null, null); methodNode.instructions.insert(new VarInsnNode(ALOAD, 0)); methodNode.instructions.insert(new VarInsnNode(Type.getType(fieldDesc).getOpcode(ILOAD), 1)); methodNode.instructions.insert(new FieldInsnNode(PUTFIELD, className, fieldName, fieldDesc)); methodNode.instructions.insert(new InsnNode(RETURN)); return methodNode; } /** * Adds interfaces to a class * * @author Xerces * @param classNode * the {@link org.objectweb.asm.tree.ClassNode} to add the interfaces * too * @param interfaces * a {@link java.lang.Class} array of the interfaces to add */ public static void addInterfaces(ClassNode classNode, Class<?>[] interfaces) { for (Class<?> interfaceClass : interfaces) { if (interfaceClass.isInterface()) { classNode.interfaces.add(interfaceClass.getName().replaceAll(".", "/")); } } } }