All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.aion.avm.core.ClassToolchain Maven / Gradle / Ivy

There is a newer version: 0.9.6
Show newest version
package org.aion.avm.core;

import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.util.Printer;
import org.objectweb.asm.util.TraceClassVisitor;

import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * @author Roman Katerinenko
 */
public final class ClassToolchain {
    private final ClassReader reader;
    private final ClassWriter writer;
    private final ClassVisitor classVisitor;
    private final int parsingOptions;

    private ClassToolchain(byte[] bytecode, ClassVisitor visitor, ClassWriter writer, int parsingOptions) {
        this.reader = new ClassReader(bytecode);
        this.classVisitor = visitor;
        this.writer = writer;
        this.parsingOptions = parsingOptions;
    }

    public byte[] runAndGetBytecode() {
        reader.accept(classVisitor, parsingOptions);
        return writer.toByteArray();
    }

    public static final class Builder {
        private final byte[] bytecode;
        private final List visitorSequence = new ArrayList<>();
        private final int parsingOptions;

        private ClassWriter writer;

        public Builder(byte[] bytecode, int parsingOptions) {
            Objects.requireNonNull(bytecode);
            this.bytecode = bytecode;
            this.parsingOptions = parsingOptions;
        }

        public Builder addNextVisitor(ToolChainClassVisitor visitor) {
            Objects.requireNonNull(visitor);
            visitorSequence.add(visitor);
            return this;
        }

        public Creator addWriter(ClassWriter writer) {
            Objects.requireNonNull(writer);
            this.writer = writer;
            return new Creator();
        }

        public final class Creator {
            public ClassToolchain build() {
                ClassVisitor prevVisitor = writer;
                for (int i = visitorSequence.size() - 1; i >= 0; i--) {
                    ToolChainClassVisitor curVisitor = visitorSequence.get(i);
                    curVisitor.setDelegate(prevVisitor);
                    prevVisitor = curVisitor;
                }
                return new ClassToolchain(bytecode, visitorSequence.get(0), writer, parsingOptions);
            }
        }
    }

    public static class ToolChainClassVisitor extends ClassVisitor {

        protected ToolChainClassVisitor(int api) {
            super(api, null);
        }

        /**
         * We need to open up access to the setDelegate() so unit tests can still operate on components as though they were part of a
         * standard ASM pipeline for some testing scenarios which are really only possible if we can issue the callbacks, directly,
         * instead of starting with class bytes.
         * NOTE:  Should only be used for testing.
         */
        public void setDelegate(ClassVisitor delegate) {
            this.cv = delegate;
        }

    }

    public static class TraceToolChainClassVisitor extends ToolChainClassVisitor {
        private PrintWriter pw;
        private Printer p;

        public TraceToolChainClassVisitor(Printer p, OutputStream os) {
            super(Opcodes.ASM7);
            this.p = p;
            this.pw = new PrintWriter(os);
        }

        public void setDelegate(ClassVisitor delegate) {
            this.cv = new TraceClassVisitor(delegate, p, pw);
        }

        public void visitEnd() {
            super.visitEnd();
        }
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy