Example usage for org.objectweb.asm.tree ClassNode accept

List of usage examples for org.objectweb.asm.tree ClassNode accept

Introduction

In this page you can find the example usage for org.objectweb.asm.tree ClassNode accept.

Prototype

public void accept(final ClassVisitor classVisitor) 

Source Link

Document

Makes the given class visitor visit this class.

Usage

From source file:jaspex.speculation.SpeculativeTransformer.java

License:Open Source License

public byte[] insertSpeculationCode(final ClassReader cr) {
    ClassVisitor cv;// w ww . jav a2 s.  co  m

    // 1 Pass: Fazer tentativamente modificaes para especulao, concretizar todos os Futures,
    //       e guardar o resultado num ClassNode
    ClassNode firstPassNode = new ClassNode();
    cv = firstPassNode;

    // Colocao das chamadas ao get do future
    cv = new GenericMethodVisitorAdapter(cv, DelayGetFutureMethodVisitor.class, currentClass);
    // Modificaes para chamar o spawnSpeculation
    cv = new GenericMethodVisitorAdapter(cv, InsertContinuationSpeculationMethodVisitor.class, currentClass);

    cr.accept(cv, ClassReader.EXPAND_FRAMES);

    // 1.5 Pass: Detectar overspeculation -- casos onde a distncia entre a especulao e a sua
    //         concretizao  demasiado pequena
    Map<InfoMethod, UtilList<Integer>> rejectedSpecIdsMap = new HashMap<InfoMethod, UtilList<Integer>>();
    RemoveOverspeculation.scanOverspeculation(currentClass, firstPassNode, rejectedSpecIdsMap);

    ClassNode removeOverspecNode;
    ClassReader finalPassReader;
    // Nota: Originalmente no era efectuado um loop aqui. O loop  feito porque o
    //    RemoveOverspeculation que  executado depois do FixFutureMultipleControlFlows pode
    //    detectar casos adicionais de overspeculation, e portanto temos que repetir o processo
    //    para os excluir.
    //    Alm disso, o processo pode demorar vrias iteraes a convergir, como no caso do
    //    NewSpecExample72.test17() em que na primeira iterao  detectada overspeculation num
    //    dos casos, o cdigo  re-gerado sem essa especulao, e s no final da segunda
    //    iterao  que  detectado que os restantes casos tambm so overspeculation
    //    (e portanto  feita uma terceira iterao que ser a final, naquele caso).
    //    Finalmente, de notar que o RemoveOverspeculation  opcional, ou seja o ciclo at pode
    //    ser comentado, voltando  verso anterior em que o cdigo s fazia uma iterao.
    do {

        // 2 Pass: Repetir modificaes, tomando em conta os resultados do RemoveOverspeculation
        ClassNode secondPassNode = new ClassNode();
        cv = secondPassNode;

        // Adicionar NOPs antes de todas as Labels, para facilitar o trabalho do FixFutureMultipleControlFlows
        cv = new GenericMethodVisitorAdapter(cv, NopAddBeforeLabelMethodVisitor.class);
        // Modificaes para chamar o spawnSpeculation
        cv = new GenericMethodVisitorAdapter(cv, InsertContinuationSpeculationMethodVisitor.class, currentClass,
                rejectedSpecIdsMap);

        cr.accept(cv, ClassReader.EXPAND_FRAMES);

        // 3 Pass: Deteco e resoluo de problemas devido a Futures e mltiplos fluxos de controlo
        //        e gerao de lista de frames do mtodo a usar no DelayGetFutureMethodVisitor

        // Obter verso original dos mtodos antes das alteraes para especulao, para que o
        // computeControlFlowGraph possa fazer revert caso no consiga corrigi-los
        ClassNode origMethods = new ClassNode();
        cr.accept(origMethods, ClassReader.EXPAND_FRAMES);
        FixFutureMultipleControlFlows.computeControlFlowGraph(secondPassNode, origMethods);

        // 4 Pass: Gerar classe final, limpar metadados extra
        ClassWriter cw = new jaspex.util.ClassWriter(ClassWriter.COMPUTE_FRAMES);
        cv = cw;

        // Remover NOPs de novo
        cv = new GenericMethodVisitorAdapter(cv, NopRemoveMethodVisitor.class);
        // Colocao das chamadas ao get do future
        cv = new GenericMethodVisitorAdapter(cv, DelayGetFutureMethodVisitor.class, currentClass);

        // Gerar classe a partir do ClassNode
        secondPassNode.accept(cv);

        finalPassReader = new ClassReader(cw.toByteArray());

        // 4.5 Pass: Re-executar RemoveOverspeculation. Isto pode originar resultados diferentes do
        //         pass original porque esse  executado sem frames correctas e sem o
        //         FixFutureMultipleControlFlows (ver comentrio antes do ciclo acima)
        removeOverspecNode = new ClassNode();
        finalPassReader.accept(removeOverspecNode, 0);

    } while (RemoveOverspeculation.scanOverspeculation(currentClass, removeOverspecNode, rejectedSpecIdsMap));

    // 5 Pass: Hack: Se houverem labels diferentes mas que esto seguidas (como no NewSpecExample8),
    //       o RemoveUnusedTryCatchBlockMethodVisitor no funciona correctamente. Uma nova passagem
    //       por um ClassWriter elimina labels repetidas.
    //       A alternativa a fazer esta passagem seria criar um MethodVisitor que removesse labels
    //       repetidas.
    ClassWriter cw = new jaspex.util.ClassWriter(ClassWriter.COMPUTE_FRAMES);
    cv = cw;

    // Retirar informao extra que  passada dentro do tipo dos futures
    cv = new GenericMethodVisitorAdapter(cv, CleanupFutureTypeInfoMethodVisitor.class);
    // Remover marcadores de inlining da transactificao
    cv = new GenericMethodVisitorAdapter(cv, RemoveInlineMarkerMethodVisitor.class);
    // Remover entradas na exception table no usadas
    cv = new GenericMethodVisitorAdapter(cv, RemoveUnusedTryCatchBlockMethodVisitor.class);
    // (Potencialmente) corrigir problemas com blocos try/catch vazios (BUG/LIMITAO ASM)
    cv = new GenericMethodVisitorAdapter(cv, FixDeadTryCatchBlockMethodVisitor.class);

    finalPassReader.accept(cv, 0);

    return cw.toByteArray();
}

From source file:jpcsp.util.ClassSpecializer.java

License:Open Source License

public Class<?> specialize(String name, Class<?> c, HashMap<String, Object> variables) {
    ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
    ClassVisitor cv = cw;//from w  w w .  j  a  v a 2 s  .  c o  m

    StringWriter debugOutput = null;
    if (log.isTraceEnabled()) {
        // Dump the class to be specialized (only once)
        if (!tracedClasses.contains(c)) {
            StringWriter classTrace = new StringWriter();
            ClassVisitor classTraceCv = new TraceClassVisitor(new PrintWriter(classTrace));
            try {
                ClassReader cr = new ClassReader(c.getName().replace('.', '/'));
                cr.accept(classTraceCv, 0);
                log.trace(String.format("Dump of class to be specialized: %s", c.getName()));
                log.trace(classTrace);
            } catch (IOException e) {
                // Ignore Exception
            }
            tracedClasses.add(c);
        }

        log.trace(String.format("Specializing class %s", name));
        String[] variableNames = variables.keySet().toArray(new String[variables.size()]);
        Arrays.sort(variableNames);
        for (String variableName : variableNames) {
            log.trace(String.format("Variable %s=%s", variableName, variables.get(variableName)));
        }

        debugOutput = new StringWriter();
        PrintWriter debugPrintWriter = new PrintWriter(debugOutput);
        cv = new TraceClassVisitor(cv, debugPrintWriter);
        //cv = new TraceClassVisitor(debugPrintWriter);
    }

    try {
        ClassReader cr = new ClassReader(c.getName().replace('.', '/'));
        ClassNode cn = new SpecializedClassVisitor(name, variables);
        cr.accept(cn, 0);
        cn.accept(cv);
    } catch (IOException e) {
        log.error("Cannot read class", e);
    }

    if (debugOutput != null) {
        log.trace(debugOutput.toString());
    }

    Class<?> specializedClass = null;
    try {
        specializedClass = classLoader.defineClass(name, cw.toByteArray());
    } catch (ClassFormatError e) {
        log.error("Error while defining specialized class", e);
    }

    return specializedClass;
}

From source file:jvstm.atomic.ProcessParNestAnnotations.java

License:Open Source License

protected static void processClassFile(File classFile) {
    alreadyProcessed = new ArrayList<String>();
    callablesCreated = new HashMap<String, String>();
    InputStream is = null;//from w ww . j av  a  2s  .  c om

    try {
        // get an input stream to read the bytecode of the class
        is = new FileInputStream(classFile);
        ClassNode cn = new ClassNode(ASM4);
        ClassReader cr = new ClassReader(is);
        cr.accept(cn, 0);

        List<MethodNode> parNestedMethods = new ArrayList<MethodNode>();
        MethodNode combinerMethod = null;
        MethodNode execMethod = null;

        List<MethodNode> staticMethodsToAdd = new ArrayList<MethodNode>();

        boolean parallelSpawn = extendsParallelSpawn(cn);
        boolean unsafeSpawn = extendsUnsafeSpawn(cn);
        if (parallelSpawn || unsafeSpawn) {
            Iterator<MethodNode> methodIter = cn.methods.iterator();
            while (methodIter.hasNext()) {
                MethodNode mn = methodIter.next();
                if (mn.name.equals("exec") && execMethod == null) {
                    execMethod = mn;
                    continue;
                }
                if (mn.invisibleAnnotations == null) {
                    continue;
                }
                for (AnnotationNode an : mn.invisibleAnnotations) {
                    if (an.desc.equals(PAR_NEST.getDescriptor())) {
                        // Ensure the method can be called from outside
                        mn.access = (mn.access & ~ACC_PRIVATE) | ACC_PUBLIC;
                        parNestedMethods.add(mn);
                        String uniqueMethodName = createUniqueMethodName(mn.name);
                        String callableClass;
                        if (parallelSpawn) {
                            callableClass = cn.name + "$nested$work$unit$" + uniqueMethodName;
                        } else {
                            callableClass = cn.name + "$unsafe$work$unit$" + uniqueMethodName;
                        }
                        callablesCreated.put(mn.name, callableClass);
                        boolean readOnlyCallable = (an.values == null) ? false : (Boolean) an.values.get(1);
                        generateCallable(classFile, cn.name, callableClass, mn, readOnlyCallable, unsafeSpawn);
                        staticMethodsToAdd.add(generateStaticCallableCreation(cn, cn.name, callableClass, mn));
                        break;
                    } else if (an.desc.equals(COMBINER.getDescriptor())) {
                        if (combinerMethod != null) {
                            throw new RuntimeException("Class: " + cn.name + " contains two @Combiner methods: "
                                    + combinerMethod.name + " and " + mn.name);
                        }
                        combinerMethod = mn;
                    }
                }
            }

            // TODO Verify the @Combiner method
            // The return should be of the same type of the parameterization
            // of the ParallelSpawn

            for (MethodNode methodToAdd : staticMethodsToAdd) {
                cn.methods.add(methodToAdd);
            }

            if (alreadyProcessed.size() == 0) {
                throw new RuntimeException(
                        "Class: " + cn.name + " must have at least one method annotated with @ParNested");
            }
            if (combinerMethod == null) {
                throw new RuntimeException(
                        "Class: " + cn.name + " must have one method annotated with @Combiner");
            }

            List<Integer> localVariablesIdx = new ArrayList<Integer>();
            int numberLocalVariables = 0;
            int listIndex = execMethod.maxLocals;
            execMethod.maxLocals++;

            InsnList preamble = new InsnList();
            preamble.add(new TypeInsnNode(NEW, ARRAY_LIST.getInternalName()));
            preamble.add(new InsnNode(DUP));
            preamble.add(new MethodInsnNode(INVOKESPECIAL, ARRAY_LIST.getInternalName(), "<init>", "()V"));
            preamble.add(new VarInsnNode(ASTORE, listIndex));

            Iterator<AbstractInsnNode> execInstIter = execMethod.instructions.iterator();
            while (execInstIter.hasNext()) {
                AbstractInsnNode instr = execInstIter.next();
                // Look out for calls to methods
                if (instr.getOpcode() == INVOKEVIRTUAL || instr.getOpcode() == INVOKESPECIAL) {
                    MethodInsnNode methodInstr = (MethodInsnNode) instr;
                    // Is method being called annotated with @ParNested
                    for (MethodNode parNestedMethod : parNestedMethods) {
                        if (parNestedMethod.name.equals(methodInstr.name)) {
                            numberLocalVariables++;
                        }
                    }
                }
            }

            for (int i = 0; i < numberLocalVariables; i++) {
                localVariablesIdx.add(i, execMethod.maxLocals);
                execMethod.maxLocals++;
            }

            int callablesManipulated = 0;
            execInstIter = execMethod.instructions.iterator();
            while (execInstIter.hasNext()) {
                AbstractInsnNode instr = execInstIter.next();
                // Look out for calls to methods
                if (instr.getOpcode() != INVOKEVIRTUAL && instr.getOpcode() != INVOKESPECIAL) {
                    continue;
                }

                MethodInsnNode methodInstr = (MethodInsnNode) instr;
                // Is method being called annotated with @ParNested
                boolean isParNestedMethod = false;
                for (MethodNode parNestedMethod : parNestedMethods) {
                    if (parNestedMethod.name.equals(methodInstr.name)) {
                        isParNestedMethod = true;
                        break;
                    }
                }
                if (!isParNestedMethod) {
                    continue;
                }

                // Let's change this call
                // If it was a call to: @ParNested public int add(int i1,
                // int i2)
                // add(foo, bar) -> add$static$callable$creator(this, foo,
                // bar)
                // the 'this' will be already in the right place in the
                // stack
                // because the method being called now is static whereas
                // previously
                // it was not
                methodInstr.setOpcode(INVOKESTATIC);
                methodInstr.name = methodInstr.name + "$static$callable$creator";
                for (MethodNode staticCreated : staticMethodsToAdd) {
                    if (staticCreated.name.equals(methodInstr.name)) {
                        methodInstr.desc = staticCreated.desc;
                        break;
                    }
                }

                InsnList midterm = new InsnList();

                // Store the callable instantiated in local variable
                midterm.add(new VarInsnNode(ASTORE, localVariablesIdx.get(callablesManipulated)));
                // Load the list
                midterm.add(new VarInsnNode(ALOAD, listIndex));
                // Load the callable
                midterm.add(new VarInsnNode(ALOAD, localVariablesIdx.get(callablesManipulated)));
                // Add it to the list
                midterm.add(new MethodInsnNode(INVOKEVIRTUAL, ARRAY_LIST.getInternalName(), "add",
                        "(Ljava/lang/Object;)Z"));
                // Pop the boolean that results from the add(Object)
                // May reuse a POP if the previous call had a return
                if (methodInstr.getNext().getOpcode() != POP) {
                    midterm.add(new InsnNode(POP));
                }

                // Add this set of instructions after the call to the
                // constrution of the callable
                execMethod.instructions.insert(methodInstr, midterm);
                callablesManipulated++;

            }

            // Insert the preamble in the start
            execMethod.instructions.insert(preamble);

            InsnList finish = new InsnList();
            // Push 'this' for the call to the combiner method
            finish.add(new VarInsnNode(ALOAD, 0));
            // Call the static method current() of jvstm.Transaction
            finish.add(new MethodInsnNode(INVOKESTATIC, TRANSACTION.getInternalName(), "current",
                    "()Ljvstm/Transaction;"));
            // Load the callables list
            finish.add(new VarInsnNode(ALOAD, listIndex));
            // Call the manage parnested method
            finish.add(new MethodInsnNode(INVOKEVIRTUAL, TRANSACTION.getInternalName(),
                    "manageNestedParallelTxs", "(Ljava/util/List;)Ljava/util/List;"));
            // Call the combiner method
            finish.add(new MethodInsnNode(INVOKEVIRTUAL, cn.name, combinerMethod.name, combinerMethod.desc));
            // Return what the combiner returns
            finish.add(new InsnNode(ARETURN));

            // Remove the "return null" that's supposed to be at the end of
            // the exec method
            execInstIter = execMethod.instructions.iterator();
            while (execInstIter.hasNext()) {
                AbstractInsnNode curNode = execInstIter.next();
                if (!execInstIter.hasNext()) {
                    // Insert the finish in the end
                    execMethod.instructions.insert(curNode.getPrevious().getPrevious(), finish);
                    execMethod.instructions.remove(curNode.getPrevious());
                    execMethod.instructions.remove(curNode);
                    break;
                }
            }

        }

        ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
        cn.accept(cw);
        writeClassFile(classFile, cw.toByteArray());
    } catch (IOException e) {
        throw new Error("Error processing class file", e);
    } finally {
        if (is != null) {
            try {
                is.close();
            } catch (IOException e) {
            }
        }
    }
}

From source file:me.qmx.jitescript.JiteClass.java

License:Apache License

/**
 * Convert this class representation to JDK bytecode
 *
 * @param version the desired JDK version
 * @return the bytecode representation of this class
 */// w w  w . ja v  a2  s .  c  o m
public byte[] toBytes(JDKVersion version) {
    ClassNode node = new ClassNode();
    node.version = version.getVer();
    node.access = this.access | ACC_SUPER;
    node.name = this.className;
    node.superName = this.superClassName;
    node.sourceFile = this.sourceFile;
    node.sourceDebug = this.sourceDebug;

    if (parentClassName != null) {
        node.visitOuterClass(parentClassName, null, null);
    }

    for (ChildEntry child : childClasses) {
        node.visitInnerClass(child.getClassName(), className, child.getInnerName(), child.getAccess());
    }

    if (!this.interfaces.isEmpty()) {
        node.interfaces.addAll(this.interfaces);
    }

    for (MethodDefinition def : methods) {
        node.methods.add(def.getMethodNode());
    }

    for (FieldDefinition def : fields) {
        node.fields.add(def.getFieldNode());
    }

    if (node.visibleAnnotations == null) {
        node.visibleAnnotations = new ArrayList<AnnotationNode>();
    }

    for (VisibleAnnotation a : annotations) {
        node.visibleAnnotations.add(a.getNode());
    }

    ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
    node.accept(cw);
    return cw.toByteArray();
}

From source file:naftoreiclag.dontdigleft.transformer.ResizePlayerBoudingBox.java

License:Open Source License

@Override
public byte[] transform(String name, String transformedName, byte[] basicClass) {
    if (name.equals("net.minecraft.entity.player.EntityPlayer") || name.equals("xl")) {
        ClassNode classNode = new ClassNode();
        ClassReader classReader = new ClassReader(basicClass);

        classReader.accept(classNode, 0);

        MethodNode mv = new MethodNode(ASM4, ACC_PROTECTED, "setSize", "(FF)V", null, null);

        mv.visitCode();//from  www  .  j  a  v a2  s . co m
        Label l0 = new Label();
        mv.visitLabel(l0);
        mv.visitVarInsn(FLOAD, 1);
        mv.visitLdcInsn(new Float("0.6"));
        mv.visitInsn(FCMPL);
        Label l1 = new Label();
        mv.visitJumpInsn(IFNE, l1);
        mv.visitVarInsn(FLOAD, 2);
        mv.visitLdcInsn(new Float("1.8"));
        mv.visitInsn(FCMPL);
        mv.visitJumpInsn(IFNE, l1);
        Label l2 = new Label();
        mv.visitLabel(l2);
        mv.visitLdcInsn(new Float("0.6"));
        mv.visitVarInsn(FSTORE, 1);
        Label l3 = new Label();
        mv.visitLabel(l3);
        mv.visitLdcInsn(new Float("0.6"));
        mv.visitVarInsn(FSTORE, 2);
        mv.visitLabel(l1);
        mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitVarInsn(FLOAD, 1);
        mv.visitVarInsn(FLOAD, 2);
        mv.visitMethodInsn(INVOKESPECIAL, "net/minecraft/entity/Entity", "setSize", "(FF)V");
        Label l4 = new Label();
        mv.visitLabel(l4);
        mv.visitInsn(RETURN);
        Label l5 = new Label();
        mv.visitLabel(l5);
        mv.visitLocalVariable("this", "Lnet/minecraft/entity/player/EntityPlayer;", null, l0, l5, 0);
        mv.visitLocalVariable("par1", "F", null, l0, l5, 1);
        mv.visitLocalVariable("par2", "F", null, l0, l5, 2);
        mv.visitMaxs(3, 3);
        mv.visitEnd();

        ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
        classNode.accept(cw);
        mv.accept(cw);

        return cw.toByteArray();
    } else {
        return basicClass;
    }
}

From source file:net.afterchat.mocap.MocapClassTransformer.java

License:Open Source License

public byte[] patchClassASM(String name, byte[] bytes) {
    ClassNode classNode = new ClassNode();
    ClassReader classReader = new ClassReader(bytes);
    classReader.accept(classNode, 0);// www.  j  a v a  2 s .c om
    Iterator<MethodNode> methods = classNode.methods.iterator();

    while (methods.hasNext()) {
        MethodNode m = methods.next();

        if ((m.name.equals("onBlockPlacedBy"))
                || (m.name.equals("a") && m.desc.equals("(Lahb;IIILsv;Ladd;)V"))) {
            logger.info("** MOCAP - Patching onBlockPlacedBy: " + m.name);
            AbstractInsnNode currentNode = null;
            Iterator<AbstractInsnNode> iter = m.instructions.iterator();
            int index = -1;

            while (iter.hasNext()) {
                index++;
                currentNode = iter.next();

                /**
                 * Just prior to the original empty function return, inject code to trigger
                 * our custom block place event.
                 */
                if (currentNode.getOpcode() == RETURN) {
                    InsnList toInject = new InsnList();
                    toInject.add(new TypeInsnNode(NEW, "net/afterchat/mocap/LivingPlaceBlockEvent"));
                    toInject.add(new InsnNode(DUP));
                    toInject.add(new VarInsnNode(ALOAD, 5));
                    toInject.add(new VarInsnNode(ALOAD, 6));
                    toInject.add(new VarInsnNode(ILOAD, 2));
                    toInject.add(new VarInsnNode(ILOAD, 3));
                    toInject.add(new VarInsnNode(ILOAD, 4));
                    toInject.add(new MethodInsnNode(INVOKESPECIAL, "net/afterchat/mocap/LivingPlaceBlockEvent",
                            "<init>",
                            "(Lnet/minecraft/entity/EntityLivingBase;Lnet/minecraft/item/ItemStack;III)V"));
                    toInject.add(new VarInsnNode(ASTORE, 7));
                    toInject.add(new FieldInsnNode(GETSTATIC, "net/minecraftforge/common/MinecraftForge",
                            "EVENT_BUS", "Lcpw/mods/fml/common/eventhandler/EventBus;"));
                    toInject.add(new VarInsnNode(ALOAD, 7));
                    toInject.add(new MethodInsnNode(INVOKEVIRTUAL, "cpw/mods/fml/common/eventhandler/EventBus",
                            "post", "(Lcpw/mods/fml/common/eventhandler/Event;)Z"));
                    toInject.add(new InsnNode(POP));

                    m.instructions.insertBefore(currentNode, toInject);
                }
            }
        }
    }

    ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
    classNode.accept(writer);
    return writer.toByteArray();
}

From source file:net.cazzar.corelib.asm.BasicTransformer.java

License:Open Source License

@Override
public final byte[] transform(String name, String transformedName, byte[] bytes) {
    if (!classes.contains(transformedName)) {
        return bytes;
    }//from   ww  w. j  a v  a2s .  co  m

    logger.info("Inserting hooks into {} ({}) for {}", name, transformedName,
            this.getClass().getCanonicalName());
    ClassNode classNode = new ClassNode();
    ClassReader classReader = new ClassReader(bytes);
    classReader.accept(classNode, 0);

    transform(classNode, transformedName);

    ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);
    classNode.accept(writer);
    //        CheckClassAdapter.verify(new ClassReader(writer.toByteArray()), false, new PrintWriter(System.err));
    return writer.toByteArray();

}

From source file:net.doubledoordev.inventorylock.asm.Transformer.java

License:Open Source License

@Override
public byte[] transform(String name, String transformedName, byte[] basicClass) {
    ClassNode classNode = new ClassNode();
    ClassReader classReader = new ClassReader(basicClass);
    classReader.accept(classNode, READER_FLAGS);

    boolean isPlayer = transformedName.equals(ENTITY_PLAYER_OWNER_NAME);
    if (isPlayer)
        LOGGER.info("Found EntityPlayer");

    for (MethodNode method : classNode.methods) {
        InsnList list = method.instructions;
        if (isPlayer && INSTANCE.mapMethodDesc(method.desc).equals(ENTITY_PLAYER_DESC)
                && INSTANCE.mapMethodName(name, method.name, method.desc).equals(ENTITY_PLAYER_TARGET)) {
            final LabelNode newLabel = new LabelNode();
            LOGGER.info("Found canOpen");
            AbstractInsnNode node = list.getFirst();
            while (node.getOpcode() != IRETURN && node != list.getLast()) {
                if (node.getOpcode() == IFEQ)
                    ((JumpInsnNode) node).label = newLabel;
                node = node.getNext();/*  w w  w  .  j  a v a  2 s .c o  m*/
            }
            if (node.getOpcode() != IRETURN)
                throw new RuntimeException("ASM failed. (return not found)");
            final AbstractInsnNode target = node;
            while (node.getType() != LABEL && node != list.getLast())
                node = node.getNext();
            if (node.getType() != LABEL)
                throw new RuntimeException("ASM failed. (label not found)");
            final LabelNode label = ((LabelNode) node);

            //Adding "else if (code instanceof BetterLockCode) return ((BetterLockCode) code).contains(this.getUniqueID());"
            InsnList inject = new InsnList();

            inject.add(newLabel);
            inject.add(new VarInsnNode(ALOAD, 1));
            inject.add(new TypeInsnNode(INSTANCEOF, BETTER_LOCK_TYPE));
            inject.add(new JumpInsnNode(IFEQ, label));
            inject.add(new VarInsnNode(ALOAD, 1));
            inject.add(new TypeInsnNode(CHECKCAST, BETTER_LOCK_TYPE));
            inject.add(new VarInsnNode(ALOAD, 0));
            //inject.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, ENTITY_PLAYER_OWNER, ENTITY_PLAYER_GET_UUID, ENTITY_PLATER_GET_UUID_DESC, false));
            inject.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, BETTER_LOCK_TYPE, BETTER_LOCK_CONTAINS,
                    BETTER_LOCK_CONTAINS_DESC, false));
            inject.add(new InsnNode(IRETURN));

            list.insert(target, inject);
            LOGGER.info("Injected elseif into EntityPlayer's canOpen");
        }
        for (AbstractInsnNode node = list.getFirst(); node != list.getLast(); node = node.getNext()) {
            if (node.getOpcode() != INVOKESTATIC)
                continue;
            MethodInsnNode methodInsnNode = ((MethodInsnNode) node);
            //                if (transformedName.equals("net.minecraft.tileentity.TileEntityLockable"))
            //                    LOGGER.info("In {} ({}) Method {}.{}{} Translated {}.{}{}", name, transformedName,
            //                            methodInsnNode.owner, methodInsnNode.name, methodInsnNode.desc,
            //                            INSTANCE.map(methodInsnNode.owner), INSTANCE.mapMethodName(methodInsnNode.owner, methodInsnNode.name, methodInsnNode.desc), INSTANCE.mapMethodDesc(methodInsnNode.desc).equals(LOCK_CODE_DESC));
            if (INSTANCE.map(methodInsnNode.owner).equals(LOCK_CODE_OWNER)
                    && INSTANCE.mapMethodDesc(methodInsnNode.desc).equals(LOCK_CODE_DESC)
                    && INSTANCE.mapMethodName(methodInsnNode.owner, methodInsnNode.name, methodInsnNode.desc)
                            .equals(LOCK_CODE_TARGET)) {
                methodInsnNode.owner = LOCK_CODE_OWNER_REPLACE;
                methodInsnNode.name = LOCK_CODE_NAME;
                LOGGER.info("Replaced call in class {} ({}), method {}{}", name, transformedName, method.name,
                        method.desc);
            }
        }
    }

    final ClassWriter writer = new ClassWriter(WRITER_FLAGS);
    classNode.accept(writer);
    return writer.toByteArray();
}

From source file:net.dries007.tfctweaks.asm.FluidContainerRegistryCT.java

License:Open Source License

private byte[] magic(byte[] bytes) {
    FMLLog.info("Found the FluidContainerRegistry class...");
    ClassNode classNode = new ClassNode();
    ClassReader classReader = new ClassReader(bytes);
    classReader.accept(classNode, 0);/*from   w w  w.j ava  2  s  .c  om*/
    for (MethodNode m : classNode.methods) {
        if (m.name.equals("<clinit>") && m.desc.equals("()V")) {
            FMLLog.info("Found the <clinit> method...");

            ListIterator<AbstractInsnNode> i = m.instructions.iterator();
            while (i.hasNext()) {
                AbstractInsnNode node = i.next();
                if (!(node instanceof FieldInsnNode) || node.getOpcode() != GETSTATIC)
                    continue;
                FieldInsnNode fieldInsnNode = ((FieldInsnNode) node);
                if (!fieldInsnNode.owner.equals("net/minecraftforge/fluids/FluidRegistry"))
                    continue;
                if (!fieldInsnNode.name.equals("WATER") && !fieldInsnNode.name.equals("LAVA"))
                    continue;
                if (!fieldInsnNode.desc.equals("Lnet/minecraftforge/fluids/Fluid;"))
                    continue;
                do {
                    i.remove();
                    node = i.next();
                } while (node.getOpcode() != POP);
                i.remove(); // remove last pop
                FMLLog.info("[FluidContainerRegistryCT] Removed the " + fieldInsnNode.name + " registration.");
                done++;
            }
        }
    }

    if (done != DONE) {
        FMLLog.severe(
                "\n######################################################################################\n"
                        + "######################################################################################\n"
                        + "######################################################################################\n"
                        + "OUR ASM FLUID HACK FAILED! PLEASE MAKE AN ISSUE REPORT ON GITHUB WITH A COMPLETE MODLIST! https://github.com/dries007/TFC-Tweaks\n"
                        + "Done %d out of %d ASM tweaks on class FluidContainerRegistry\n"
                        + "########################################################################################\n"
                        + "########################################################################################\n"
                        + "########################################################################################\n\n",
                done, DONE);
    }

    ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
    classNode.accept(writer);
    return writer.toByteArray();
}

From source file:net.dries007.tfctweaks.asm.FluidRegistryCT.java

License:Open Source License

private byte[] magic(byte[] bytes) {
    FMLLog.info("Found the FluidRegistry class...");
    ClassNode classNode = new ClassNode();
    ClassReader classReader = new ClassReader(bytes);
    classReader.accept(classNode, 0);//w  w w  .j  av  a2  s . c  o  m
    for (MethodNode m : classNode.methods) {
        if (m.name.equals("<clinit>") && m.desc.equals("()V")) {
            FMLLog.info("Found the <clinit> method...");

            ListIterator<AbstractInsnNode> i = m.instructions.iterator();
            while (i.hasNext()) {
                AbstractInsnNode node = i.next();
                if (!(node instanceof FieldInsnNode) || node.getOpcode() != GETSTATIC)
                    continue;
                FieldInsnNode fieldInsnNode = ((FieldInsnNode) node);
                if (!fieldInsnNode.owner.equals("net/minecraftforge/fluids/FluidRegistry"))
                    continue;
                if (!fieldInsnNode.name.equals("WATER") && !fieldInsnNode.name.equals("LAVA"))
                    continue;
                if (!fieldInsnNode.desc.equals("Lnet/minecraftforge/fluids/Fluid;"))
                    continue;
                node = i.next();
                if (!(node instanceof MethodInsnNode) || node.getOpcode() != INVOKESTATIC)
                    continue;
                MethodInsnNode methodInsnNode = ((MethodInsnNode) node);
                if (!methodInsnNode.owner.equals("net/minecraftforge/fluids/FluidRegistry"))
                    continue;
                if (!methodInsnNode.name.equals("registerFluid"))
                    continue;
                if (!methodInsnNode.desc.equals("(Lnet/minecraftforge/fluids/Fluid;)Z"))
                    continue;
                node = i.next();
                if (!(node instanceof InsnNode) || node.getOpcode() != POP)
                    continue;
                InsnNode insnNode = ((InsnNode) node);
                m.instructions.remove(fieldInsnNode);
                m.instructions.remove(methodInsnNode);
                m.instructions.remove(insnNode);
                FMLLog.info("[FluidRegistryCT] Removed the " + fieldInsnNode.name + " registration.");
                done++;
            }
        } else if (m.name.equals("getFluid")
                && m.desc.equals("(Ljava/lang/String;)Lnet/minecraftforge/fluids/Fluid;")) {
            FMLLog.info("Found the getFluid method...");
            InsnList insnList = new InsnList();
            {
                LabelNode labelFirstIf = new LabelNode();
                insnList.add(new FieldInsnNode(GETSTATIC, "net/dries007/tfctweaks/util/FluidHacks",
                        "makeAllWaterFTCWater", "Z"));
                insnList.add(new JumpInsnNode(IFEQ, labelFirstIf));
                insnList.add(new VarInsnNode(ALOAD, 0));
                insnList.add(new LdcInsnNode("water"));
                insnList.add(new MethodInsnNode(INVOKEVIRTUAL, "java/lang/String", "equals",
                        "(Ljava/lang/Object;)Z", false));
                insnList.add(new JumpInsnNode(IFEQ, labelFirstIf));
                insnList.add(new FieldInsnNode(GETSTATIC, "com/bioxx/tfc/api/TFCFluids", "FRESHWATER",
                        "Lnet/minecraftforge/fluids/Fluid;"));
                insnList.add(new InsnNode(ARETURN));
                insnList.add(labelFirstIf);
            }
            {
                LabelNode lableSecondIf = new LabelNode();
                insnList.add(new FieldInsnNode(GETSTATIC, "net/dries007/tfctweaks/util/FluidHacks",
                        "makeAllLavaFTCLava", "Z"));
                insnList.add(new JumpInsnNode(IFEQ, lableSecondIf));
                insnList.add(new VarInsnNode(ALOAD, 0));
                insnList.add(new LdcInsnNode("lava"));
                insnList.add(new MethodInsnNode(INVOKEVIRTUAL, "java/lang/String", "equals",
                        "(Ljava/lang/Object;)Z", false));
                insnList.add(new JumpInsnNode(IFEQ, lableSecondIf));
                insnList.add(new FieldInsnNode(GETSTATIC, "com/bioxx/tfc/api/TFCFluids", "LAVA",
                        "Lnet/minecraftforge/fluids/Fluid;"));
                insnList.add(new InsnNode(ARETURN));
                insnList.add(lableSecondIf);
            }
            m.instructions.insertBefore(m.instructions.getFirst(), insnList);

            FMLLog.info("[FluidRegistryCT] Edited getFluid(String) : Fluid.");
            done++;
        } else if (m.name.equals("isFluidRegistered")) {
            if (m.desc.equals("(Lnet/minecraftforge/fluids/Fluid;)Z")) {
                InsnList insnList = new InsnList();
                LabelNode falseLabel = new LabelNode();
                LabelNode trueLabel = new LabelNode();
                insnList.add(new VarInsnNode(ALOAD, 0));
                insnList.add(new JumpInsnNode(IFNULL, falseLabel));
                insnList.add(new VarInsnNode(ALOAD, 0));
                insnList.add(new MethodInsnNode(INVOKEVIRTUAL, "net/minecraftforge/fluids/Fluid", "getName",
                        "()Ljava/lang/String;", false));
                insnList.add(new MethodInsnNode(INVOKESTATIC, "net/minecraftforge/fluids/FluidRegistry",
                        "isFluidRegistered", "(Ljava/lang/String;)Z", false));
                insnList.add(new JumpInsnNode(IFEQ, falseLabel));
                insnList.add(new InsnNode(ICONST_1));
                insnList.add(new JumpInsnNode(GOTO, trueLabel));
                insnList.add(falseLabel);
                insnList.add(new InsnNode(ICONST_0));
                insnList.add(trueLabel);
                insnList.add(new InsnNode(IRETURN));
                // replace entire method
                m.instructions.clear();
                m.instructions.add(insnList);

                FMLLog.info("[FluidRegistryCT] Edited isFluidRegistered(Fluid) : bool.");
                done++;
            } else if (m.desc.equals("(Ljava/lang/String;)Z")) {
                InsnList insnList = new InsnList();
                LabelNode trueLabel = new LabelNode();
                insnList.add(new LdcInsnNode("water"));
                insnList.add(new VarInsnNode(ALOAD, 0));
                insnList.add(new MethodInsnNode(INVOKEVIRTUAL, "java/lang/String", "equals",
                        "(Ljava/lang/Object;)Z", false));
                insnList.add(new JumpInsnNode(IFNE, trueLabel));
                insnList.add(new LdcInsnNode("lava"));
                insnList.add(new VarInsnNode(ALOAD, 0));
                insnList.add(new MethodInsnNode(INVOKEVIRTUAL, "java/lang/String", "equals",
                        "(Ljava/lang/Object;)Z", false));
                insnList.add(new JumpInsnNode(IFNE, trueLabel));
                insnList.add(new FieldInsnNode(GETSTATIC, "net/minecraftforge/fluids/FluidRegistry", "fluids",
                        "Lcom/google/common/collect/BiMap;"));
                insnList.add(new VarInsnNode(ALOAD, 0));
                insnList.add(new MethodInsnNode(INVOKEINTERFACE, "com/google/common/collect/BiMap",
                        "containsKey", "(Ljava/lang/Object;)Z", true));
                LabelNode falseLabel = new LabelNode();
                insnList.add(new JumpInsnNode(IFEQ, falseLabel));
                insnList.add(trueLabel);
                insnList.add(new InsnNode(ICONST_1));
                LabelNode returnLabel = new LabelNode();
                insnList.add(new JumpInsnNode(GOTO, returnLabel));
                insnList.add(falseLabel);
                insnList.add(new InsnNode(ICONST_0));
                insnList.add(returnLabel);
                insnList.add(new InsnNode(IRETURN));

                // replace entire method
                m.instructions.clear();
                m.instructions.add(insnList);

                FMLLog.info("[FluidRegistryCT] Edited isFluidRegistered(String) : bool.");
                done++;
            }
        } else if (m.name.equals("getFluidStack")) {
            LabelNode notNullNode = null;
            { // Grab first jump node label
                ListIterator<AbstractInsnNode> i = m.instructions.iterator();
                while (i.hasNext()) {
                    AbstractInsnNode node = i.next();
                    if (node.getOpcode() == IFNE) {
                        notNullNode = ((JumpInsnNode) node).label;
                        break;
                    }
                }
            }

            InsnList insnList = new InsnList();
            insnList.add(new LdcInsnNode("water"));
            insnList.add(new VarInsnNode(ALOAD, 0));
            insnList.add(new MethodInsnNode(INVOKEVIRTUAL, "java/lang/String", "equals",
                    "(Ljava/lang/Object;)Z", false));
            insnList.add(new JumpInsnNode(IFNE, notNullNode));
            insnList.add(new LdcInsnNode("lava"));
            insnList.add(new VarInsnNode(ALOAD, 0));
            insnList.add(new MethodInsnNode(INVOKEVIRTUAL, "java/lang/String", "equals",
                    "(Ljava/lang/Object;)Z", false));
            insnList.add(new JumpInsnNode(IFNE, notNullNode));

            // add to the beginning of the list, leave the rest of the method in place.
            m.instructions.insert(insnList);

            FMLLog.info("[FluidRegistryCT] Edited getFluidStack(String, int) : FluidStack.");
            done++;
        }
    }

    if (done != DONE) {
        FMLLog.severe(
                "\n######################################################################################\n"
                        + "######################################################################################\n"
                        + "######################################################################################\n"
                        + "OUR ASM FLUID HACK FAILED! PLEASE MAKE AN ISSUE REPORT ON GITHUB WITH A COMPLETE MODLIST! https://github.com/dries007/TFC-Tweaks\n"
                        + "Done %d out of %d ASM tweaks on class FluidRegistry\n"
                        + "########################################################################################\n"
                        + "########################################################################################\n"
                        + "########################################################################################\n\n",
                done, DONE);
    }

    ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
    classNode.accept(writer);
    return writer.toByteArray();
}