/*
 * Copyright 2005 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code 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 General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

package ilib;

import java.io.IOException;
import java.io.File;
import java.io.FileOutputStream;
import java.io.DataOutputStream;
import java.util.List;
import java.util.Iterator;
import java.util.ArrayList;

public class Inject implements RuntimeConstants {

    public static byte[] instrumentation(Options opt,
                                         ClassLoader loader,
                                         String className,
                                         byte[] classfileBuffer) {
        ClassReaderWriter c = new ClassReaderWriter(classfileBuffer);
        (new Inject(className, c, loader == null, opt)).doit();
        return c.result();
    }

    static boolean verbose = false;

    final String className;
    final ClassReaderWriter c;
    final boolean isSystem;
    final Options options;

    int constantPoolCount;
    int methodsCount;
    int methodsCountPos;
    int profiler;
    int wrappedTrackerIndex = 0;
    int thisClassIndex = 0;

    TrackerInjector callInjector;
    TrackerInjector allocInjector;
    TrackerInjector defaultInjector;

    static interface TrackerInjector extends Injector {
        void reinit(int tracker);
        int stackSize(int currentSize);
    }

    static class SimpleInjector implements TrackerInjector {
        byte[] injection;

        public int stackSize(int currentSize) {
            return currentSize;
        }

        public void reinit(int tracker) {
            injection = new byte[3];
            injection[0] = (byte)opc_invokestatic;
            injection[1] = (byte)(tracker >> 8);
            injection[2] = (byte)tracker;
        }

        public byte[] bytecodes(String className, String methodName, int location) {
            return injection;
        }
    }

    static class ObjectInjector implements TrackerInjector {
        byte[] injection;

        public int stackSize(int currentSize) {
            return currentSize + 1;
        }

        public void reinit(int tracker) {
            injection = new byte[4];
            injection[0] = (byte)opc_dup;
            injection[1] = (byte)opc_invokestatic;
            injection[2] = (byte)(tracker >> 8);
            injection[3] = (byte)tracker;
        }

        public byte[] bytecodes(String className, String methodName, int location) {
            return injection;
        }
    }

    class IndexedInjector implements TrackerInjector {
        int counter = 0;
        int tracker;
        List<Info> infoList = new ArrayList<Info>();

        public int stackSize(int currentSize) {
            return currentSize + 1;
        }

        public void reinit(int tracker) {
            this.tracker = tracker;
        }

        void dump(File outDir, String filename) throws IOException {
            FileOutputStream fileOut = new FileOutputStream(new File(outDir, filename));
            DataOutputStream dataOut = new DataOutputStream(fileOut);

            String currentClassName = null;

            dataOut.writeInt(infoList.size());
            for (Iterator<Info> it = infoList.iterator(); it.hasNext(); ) {
                Info info = it.next();
                if (!info.className.equals(currentClassName)) {
                    dataOut.writeInt(123456); // class name marker
                    currentClassName = info.className;
                    dataOut.writeUTF(currentClassName);
                }
                dataOut.writeInt(info.location);
                dataOut.writeUTF(info.methodName);
            }
            dataOut.close();
        }

        public byte[] bytecodes(String className, String methodName, int location) {
            byte[] injection = new byte[6];
            int injectedIndex = options.fixedIndex != 0? options.fixedIndex : ++counter;
            infoList.add(new Info(counter, className, methodName, location));
            injection[0] = (byte)opc_sipush;
            injection[1] = (byte)(injectedIndex >> 8);
            injection[2] = (byte)injectedIndex;
            injection[3] = (byte)opc_invokestatic;
            injection[4] = (byte)(tracker >> 8);
            injection[5] = (byte)tracker;
            return injection;
        }
    }

    Inject(String className, ClassReaderWriter c, boolean isSystem, Options options) {
        this.className = className;
        this.c = c;
        this.isSystem = isSystem;
        this.options = options;
    }

    void doit() {
        int i;
        c.copy(4 + 2 + 2); // magic min/maj version
        int constantPoolCountPos = c.generatedPosition();
        constantPoolCount = c.copyU2();
        // copy old constant pool
        c.copyConstantPool(constantPoolCount);

        if (verbose) {
            System.out.println("ConstantPool expanded from: " +
                               constantPoolCount);
        }

        profiler = addClassToConstantPool(options.trackerClassName);
        if (options.shouldInstrumentNew || options.shouldInstrumentObjectInit) {
            if (options.shouldInstrumentIndexed) {
                if (allocInjector == null) {
                    // first time - create it
                    allocInjector = new IndexedInjector();
                }
                int allocTracker = addMethodToConstantPool(profiler,
                                                           options.allocTrackerMethodName,
                                                           "(I)V");
                allocInjector.reinit(allocTracker);
            } else if (options.shouldInstrumentObject) {
                if (allocInjector == null) {
                    // first time - create it
                    allocInjector = new ObjectInjector();
                }
                int allocTracker = addMethodToConstantPool(profiler,
                                                           options.allocTrackerMethodName,
                                                           "(Ljava/lang/Object;)V");
                allocInjector.reinit(allocTracker);
            } else {
                if (allocInjector == null) {
                    // first time - create it
                    allocInjector = new SimpleInjector();
                }
                int allocTracker = addMethodToConstantPool(profiler,
                                                           options.allocTrackerMethodName,
                                                           "()V");
                allocInjector.reinit(allocTracker);
            }
            defaultInjector = allocInjector;
        }
        if (options.shouldInstrumentCall) {
            if (options.shouldInstrumentIndexed) {
                if (callInjector == null) {
                    // first time - create it
                    callInjector = new IndexedInjector();
                }
                int callTracker = addMethodToConstantPool(profiler,
                                                          options.callTrackerMethodName,
                                                          "(I)V");
                callInjector.reinit(callTracker);
            } else {
                if (callInjector == null) {
                    // first time - create it
                    callInjector = new SimpleInjector();
                }
                int callTracker = addMethodToConstantPool(profiler,
                                                          options.callTrackerMethodName,
                                                          "()V");
                callInjector.reinit(callTracker);
            }
            defaultInjector = callInjector;
        }

        if (verbose) {
            System.out.println("To: " + constantPoolCount);
        }

        c.setSection(1);

        c.copy(2 + 2 + 2);  // access, this, super
        int interfaceCount = c.copyU2();
        if (verbose) {
            System.out.println("interfaceCount: " + interfaceCount);
        }
        c.copy(interfaceCount * 2);
        copyFields(); // fields
        copyMethods(); // methods
        int attrCountPos = c.generatedPosition();
        int attrCount = c.copyU2();
        if (verbose) {
            System.out.println("class attrCount: " + attrCount);
        }
        // copy the class attributes
        copyAttrs(attrCount);

        c.randomAccessWriteU2(constantPoolCountPos, constantPoolCount);
    }


    void copyFields() {
        int count = c.copyU2();
        if (verbose) {
            System.out.println("fields count: " + count);
        }
        for (int i = 0; i < count; ++i) {
            c.copy(6); // access, name, descriptor
            int attrCount = c.copyU2();
            if (verbose) {
                System.out.println("field attr count: " + attrCount);
            }
            copyAttrs(attrCount);
        }
    }

    void copyMethods() {
        methodsCountPos = c.generatedPosition();
        methodsCount = c.copyU2();
        int initialMethodsCount = methodsCount;
        if (verbose) {
            System.out.println("methods count: " + methodsCount);
        }
        for (int i = 0; i < initialMethodsCount; ++i) {
            copyMethod();
        }
    }

    void copyMethod() {
        int accessFlags = c.copyU2();// access flags
        if (options.shouldInstrumentNativeMethods && (accessFlags & ACC_NATIVE) != 0) {
            wrapNativeMethod(accessFlags);
            return;
        }
        int nameIndex = c.copyU2();  // name
        String methodName = c.constantPoolString(nameIndex);
        c.copyU2();                  // descriptor
        int attrCount = c.copyU2();  // attribute count
        if (verbose) {
            System.out.println("methods attr count: " + attrCount);
        }
        for (int i = 0; i < attrCount; ++i) {
            copyAttrForMethod(methodName, accessFlags);
        }
    }

    void wrapNativeMethod(int accessFlags) {
        // first, copy the native method with the name changed
        // accessFlags have already been copied
        int nameIndex = c.readU2();        // name
        String methodName = c.constantPoolString(nameIndex);
        String wrappedMethodName = options.wrappedPrefix + methodName;
        int wrappedNameIndex = writeCPEntryUtf8(wrappedMethodName);
        c.writeU2(wrappedNameIndex);       // change to the wrapped name

        int descriptorIndex = c.copyU2();  // descriptor index

        int attrCount = c.copyU2();        // attribute count
        // need to replicate these attributes (esp Exceptions) in wrapper
        // so mark this location so we can rewind
        c.markLocalPositionStart();
        for (int i = 0; i < attrCount; ++i) {
            copyAttrForMethod(methodName, accessFlags);
        }
        if (true) {
            System.err.println("   wrapped: " + methodName);
        }

        // now write the wrapper method
        c.writeU2(accessFlags & ~ACC_NATIVE);
        c.writeU2(nameIndex);           // original unwrapped name
        c.writeU2(descriptorIndex);     // descriptor is the same

        c.writeU2(attrCount + 1);       // wrapped plus a code attribute
        // rewind to wrapped attributes
        c.rewind();
        for (int i = 0; i < attrCount; ++i) {
            copyAttrForMethod(methodName, accessFlags);
        }

        // generate a Code attribute for the wrapper method
        int wrappedIndex = addMethodToConstantPool(getThisClassIndex(),
                                                   wrappedNameIndex,
                                                   descriptorIndex);
        String descriptor = c.constantPoolString(descriptorIndex);
        createWrapperCodeAttr(nameIndex, accessFlags, descriptor, wrappedIndex);

        // increment method count
        c.randomAccessWriteU2(methodsCountPos, ++methodsCount);
    }

    void copyAttrs(int attrCount) {
        for (int i = 0; i < attrCount; ++i) {
            copyAttr();
        }
    }

    void copyAttr() {
        c.copy(2);             // name
        int len = c.copyU4();  // attr len
        if (verbose) {
            System.out.println("attr len: " + len);
        }
        c.copy(len);           // attribute info
    }

    void copyAttrForMethod(String methodName, int accessFlags) {
        int nameIndex = c.copyU2();   // name
        // check for Code attr
        if (nameIndex == c.codeAttributeIndex) {
            try {
                copyCodeAttr(methodName);
            } catch (IOException exc) {
                System.err.println("Code Exception - " + exc);
                System.exit(1);
            }
        } else {
            int len = c.copyU4();     // attr len
            if (verbose) {
                System.out.println("method attr len: " + len);
            }
            c.copy(len);              // attribute info
        }
    }

    void copyAttrForCode(InjectBytecodes ib) throws IOException {
        int nameIndex = c.copyU2();   // name

        // check for Code attr
        if (nameIndex == c.lineNumberAttributeIndex) {
            ib.copyLineNumberAttr();
        } else if (nameIndex == c.localVarAttributeIndex) {
            ib.copyLocalVarAttr();
        } else {
            int len = c.copyU4();     // attr len
            if (verbose) {
                System.out.println("code attr len: " + len);
            }
            c.copy(len);              // attribute info
        }
    }

    void copyCodeAttr(String methodName) throws IOException {
        if (verbose) {
            System.out.println("Code attr found");
        }
        int attrLengthPos = c.generatedPosition();
        int attrLength = c.copyU4();        // attr len
        int maxStack = c.readU2();          // max stack
        c.writeU2(defaultInjector == null? maxStack :
                  defaultInjector.stackSize(maxStack));  // big enough for injected code
        c.copyU2();                         // max locals
        int codeLengthPos = c.generatedPosition();
        int codeLength = c.copyU4();        // code length
        if (options.targetMethod != null && !options.targetMethod.equals(methodName)) {
            c.copy(attrLength - 8); // copy remainder minus already copied
            return;
        }
        if (isSystem) {
            if (codeLength == 1 && methodName.equals("finalize")) {
                if (verbose) {
                    System.out.println("empty system finalizer not instrumented");
                }
                c.copy(attrLength - 8); // copy remainder minus already copied
                return;
            }
            if (codeLength == 1 && methodName.equals("<init>")) {
                if (verbose) {
                    System.out.println("empty system constructor not instrumented");
                }
                if (!options.shouldInstrumentObjectInit) {
                    c.copy(attrLength - 8); // copy remainder minus already copied
                    return;
                }
            }
            if (methodName.equals("<clinit>")) {
                if (verbose) {
                    System.out.println("system class initializer not instrumented");
                }
                c.copy(attrLength - 8); // copy remainder minus already copied
                return;
            }
        }
        if (options.shouldInstrumentObjectInit
            && (!className.equals("java/lang/Object")
                || !methodName.equals("<init>"))) {
            c.copy(attrLength - 8); // copy remainder minus already copied
            return;
        }

        InjectBytecodes ib = new InjectBytecodes(c, codeLength, className, methodName);

        if (options.shouldInstrumentNew) {
            ib.injectAfter(opc_new, allocInjector);
            ib.injectAfter(opc_newarray, allocInjector);
            ib.injectAfter(opc_anewarray, allocInjector);
            ib.injectAfter(opc_multianewarray, allocInjector);
        }
        if (options.shouldInstrumentCall) {
            ib.inject(0, callInjector.bytecodes(className, methodName, 0));
        }
        if (options.shouldInstrumentObjectInit) {
            ib.inject(0, allocInjector.bytecodes(className, methodName, 0));
        }

        ib.adjustOffsets();

        // fix up code length
        int newCodeLength = c.generatedPosition() - (codeLengthPos + 4);
        c.randomAccessWriteU4(codeLengthPos, newCodeLength);
        if (verbose) {
            System.out.println("code length old: " + codeLength +
                               ", new: " + newCodeLength);
        }

        ib.copyExceptionTable();

        int attrCount = c.copyU2();
        for (int i = 0; i < attrCount; ++i) {
            copyAttrForCode(ib);
        }

        // fix up attr length
        int newAttrLength = c.generatedPosition() - (attrLengthPos + 4);
        c.randomAccessWriteU4(attrLengthPos, newAttrLength);
        if (verbose) {
            System.out.println("attr length old: " + attrLength +
                               ", new: " + newAttrLength);
        }
    }

    int nextDescriptorIndex(String descriptor, int index) {
        switch (descriptor.charAt(index)) {
        case 'B': // byte
        case 'C': // char
        case 'I': // int
        case 'S': // short
        case 'Z': // boolean
        case 'F': // float
        case 'D': // double
        case 'J': // long
            return index + 1;
        case 'L': // object
            int i = index + 1;
            while (descriptor.charAt(i) != ';') {
                ++i;
            }
            return i + 1;
        case '[': // array
            return nextDescriptorIndex(descriptor, index + 1);
        }
        throw new InternalError("should not reach here");
    }

    int getWrappedTrackerIndex() {
        if (wrappedTrackerIndex == 0) {
            wrappedTrackerIndex = addMethodToConstantPool(profiler,
                                                          options.wrappedTrackerMethodName,
                                                          "(Ljava/lang/String;I)V");
        }
        return wrappedTrackerIndex;
    }

    int getThisClassIndex() {
        if (thisClassIndex == 0) {
            thisClassIndex = addClassToConstantPool(className);
        }
        return thisClassIndex;
    }

    int computeMaxLocals(String descriptor, int accessFlags) {
        int index = 1;
        int slot = 0;

        if ((accessFlags & ACC_STATIC) == 0) {
            ++slot;
        }
        char type;
        while ((type = descriptor.charAt(index)) != ')') {
            switch (type) {
            case 'B': // byte
            case 'C': // char
            case 'I': // int
            case 'S': // short
            case 'Z': // boolean
            case 'F': // float
            case 'L': // object
            case '[': // array
                ++slot;
                break;
            case 'D': // double
            case 'J': // long
                slot += 2;
                break;
            }
            index = nextDescriptorIndex(descriptor, index);
        }

        return slot;
    }


    void createWrapperCodeAttr(int methodNameIndex, int accessFlags,
                               String descriptor, int wrappedIndex) {
        int maxLocals = computeMaxLocals(descriptor, accessFlags);

        c.writeU2(c.codeAttributeIndex);        //
        int attrLengthPos = c.generatedPosition();
        c.writeU4(0);                // attr len -- fix up below
        c.writeU2(maxLocals + 4);    // max stack
        c.writeU2(maxLocals);        // max locals
        int codeLengthPos = c.generatedPosition();
        c.writeU4(0);                // code length -- fix up below

        int methodStringIndex = writeCPEntryString(methodNameIndex);

        c.writeU1(opc_ldc_w);
        c.writeU2(methodStringIndex);  // send the method name
        c.writeU1(opc_sipush);
        c.writeU2(options.fixedIndex);
        c.writeU1(opc_invokestatic);
        c.writeU2(getWrappedTrackerIndex());

        // set-up args
        int index = 1;
        int slot = 0;
        if ((accessFlags & ACC_STATIC) == 0) {
            c.writeU1(opc_aload_0);  // this
            ++slot;
        }
        char type;
        while ((type = descriptor.charAt(index)) != ')') {
            switch (type) {
            case 'B': // byte
            case 'C': // char
            case 'I': // int
            case 'S': // short
            case 'Z': // boolean
                c.writeU1(opc_iload);
                c.writeU1(slot);
                ++slot;
                break;
            case 'F': // float
                c.writeU1(opc_fload);
                c.writeU1(slot);
                ++slot;
                break;
            case 'D': // double
                c.writeU1(opc_dload);
                c.writeU1(slot);
                slot += 2;
                break;
            case 'J': // long
                c.writeU1(opc_lload);
                c.writeU1(slot);
                slot += 2;
                break;
            case 'L': // object
            case '[': // array
                c.writeU1(opc_aload);
                c.writeU1(slot);
                ++slot;
                break;
            }
            index = nextDescriptorIndex(descriptor, index);
        }

        // call the wrapped version
        if ((accessFlags & ACC_STATIC) == 0) {
            c.writeU1(opc_invokevirtual);
        } else {
            c.writeU1(opc_invokestatic);
        }
        c.writeU2(wrappedIndex);

        // return correct type
        switch (descriptor.charAt(index+1)) {
        case 'B': // byte
        case 'C': // char
        case 'I': // int
        case 'S': // short
        case 'Z': // boolean
            c.writeU1(opc_ireturn);
            break;
        case 'F': // float
            c.writeU1(opc_freturn);
            break;
        case 'D': // double
            c.writeU1(opc_dreturn);
            break;
        case 'J': // long
            c.writeU1(opc_lreturn);
            break;
        case 'L': // object
        case '[': // array
            c.writeU1(opc_areturn);
            break;
        case 'V': // void
            c.writeU1(opc_return);
            break;
        }

        // end of code

        // fix up code length
        int newCodeLength = c.generatedPosition() - (codeLengthPos + 4);
        c.randomAccessWriteU4(codeLengthPos, newCodeLength);

        c.writeU2(0);                // exception table length
        c.writeU2(0);                // attribute count

        // fix up attr length
        int newAttrLength = c.generatedPosition() - (attrLengthPos + 4);
        c.randomAccessWriteU4(attrLengthPos, newAttrLength);
    }


    int addClassToConstantPool(String className) {
        int prevSection = c.setSection(0);
        int classNameIndex = writeCPEntryUtf8(className);
        int classIndex = writeCPEntryClass(classNameIndex);
        c.setSection(prevSection);
        return classIndex;
    }

    int addMethodToConstantPool(int classIndex,
                                String methodName,
                                String descr) {
        int prevSection = c.setSection(0);
        int methodNameIndex = writeCPEntryUtf8(methodName);
        int descrIndex = writeCPEntryUtf8(descr);
        c.setSection(prevSection);
        return addMethodToConstantPool(classIndex, methodNameIndex, descrIndex);
    }

    int addMethodToConstantPool(int classIndex,
                                int methodNameIndex,
                                int descrIndex) {
        int prevSection = c.setSection(0);
        int nameAndTypeIndex = writeCPEntryNameAndType(methodNameIndex,
                                                       descrIndex);
        int methodIndex = writeCPEntryMethodRef(classIndex, nameAndTypeIndex);
        c.setSection(prevSection);
        return methodIndex;
    }

    int writeCPEntryUtf8(String str) {
        int prevSection = c.setSection(0);
        int len = str.length();
        c.writeU1(CONSTANT_UTF8); // Utf8 tag
        c.writeU2(len);
        for (int i = 0; i < len; ++i) {
            c.writeU1(str.charAt(i));
        }
        c.setSection(prevSection);
        return constantPoolCount++;
    }

    int writeCPEntryString(int utf8Index) {
        int prevSection = c.setSection(0);
        c.writeU1(CONSTANT_STRING);
        c.writeU2(utf8Index);
        c.setSection(prevSection);
        return constantPoolCount++;
    }

    int writeCPEntryClass(int classNameIndex) {
        int prevSection = c.setSection(0);
        c.writeU1(CONSTANT_CLASS);
        c.writeU2(classNameIndex);
        c.setSection(prevSection);
        return constantPoolCount++;
    }

    int writeCPEntryNameAndType(int nameIndex, int descrIndex) {
        int prevSection = c.setSection(0);
        c.writeU1(CONSTANT_NAMEANDTYPE);
        c.writeU2(nameIndex);
        c.writeU2(descrIndex);
        c.setSection(prevSection);
        return constantPoolCount++;
    }

    int writeCPEntryMethodRef(int classIndex, int nameAndTypeIndex) {
        int prevSection = c.setSection(0);
        c.writeU1(CONSTANT_METHOD);
        c.writeU2(classIndex);
        c.writeU2(nameAndTypeIndex);
        c.setSection(prevSection);
        return constantPoolCount++;
    }
}
