/*
 * Copyright (c) 2005, 2008, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

/**
 * @test
 * @bug 6274264 6274241 5070281
 * @summary test retransformClasses
 * @author Robert Field, Sun Microsystems
 *
 * @run shell/timeout=240 MakeJAR2.sh RetransformAgent RetransformApp 'Can-Retransform-Classes: true'
 * @run main/othervm -javaagent:RetransformAgent.jar RetransformApp
 */

import java.lang.instrument.*;
import java.security.ProtectionDomain;
import java.io.*;

import ilib.*;

class RetransformAgent {

    static ClassFileTransformer t1, t2, t3, t4;
    static Instrumentation inst;
    static boolean succeeded = true;
    static int markCount = 0;
    static int[] markGolden = {30, 40, 20, 30, 40, 20, 30, 40, 20, 30, 40, 20,
                               11, 40, 20, 11, 40, 20, 11, 40, 20, 11, 40, 20};

    static class Tr implements ClassFileTransformer {
        final String trname;
        final boolean onLoad;
        final int loadIndex;
        final boolean onRedef;
        final int redefIndex;
        final String cname;
        final String nname;

        Tr(String trname, boolean onLoad, int loadIndex, boolean onRedef, int redefIndex,
           String cname, String nname) {
            this.trname = trname;
            this.onLoad = onLoad;
            this.loadIndex = loadIndex;
            this.onRedef = onRedef;
            this.redefIndex = redefIndex;
            this.cname = cname;
            this.nname = nname;
        }

        public byte[] transform(ClassLoader loader,
                                String className,
                                Class<?> classBeingRedefined,
                                ProtectionDomain    protectionDomain,
                                byte[] classfileBuffer) {
            boolean redef = classBeingRedefined != null;
            // System.err.println("hook " + trname + ": " + className +
            //                    (redef? " REDEF" : " LOAD"));
            if ((redef? onRedef : onLoad) && className != null && className.equals(cname)) {
                Options opt = new Options();
                opt.shouldInstrumentIndexed = true;
                opt.shouldInstrumentCall = true;
                opt.targetMethod = nname;
                opt.fixedIndex = redef? redefIndex : loadIndex;
                opt.trackerClassName = "RetransformAgent";
                try {
                    byte[] newcf =  Inject.instrumentation(opt, loader, className, classfileBuffer);
                    /*** debugging ...
                         String fname = trname + (redef?"_redef" : "");
                         write_buffer(fname + "_before.class", classfileBuffer);
                         write_buffer(fname + "_instr.class", newcf);
                    ***/
                    System.err.println(trname + ": " + className + " index: " + opt.fixedIndex +
                                       (redef? " REDEF" : " LOAD") +
                                       " len before: " + classfileBuffer.length +
                                       " after: " + newcf.length);
                    return newcf;
                } catch (Throwable ex) {
                    System.err.println("Injection failure: " + ex);
                    ex.printStackTrace();
                }
            }
            return null;
        }
    }

    static void write_buffer(String fname, byte[]buffer) {
        try {
            FileOutputStream outStream = new FileOutputStream(fname);
            outStream.write(buffer, 0, buffer.length);
            outStream.close();
        } catch (Exception ex) {
            System.err.println("EXCEPTION in write_buffer: " + ex);
        }
    }

    public static void premain (String agentArgs, Instrumentation instArg) {
        inst = instArg;
        System.err.println("Premain");

        t1 = new Tr("TR1", false, 10, true, 11, "RetransformApp", "foo");
        inst.addTransformer(t1, true);
        t2 = new Tr("TN2", true,  20, true, 21, "RetransformApp", "foo");
        inst.addTransformer(t2, false);
        t3 = new Tr("TR3", true,  30, true, 31, "RetransformApp", "foo");
        inst.addTransformer(t3, true);
        t4 = new Tr("TN4", true,  40, true, 41, "RetransformApp", "foo");
        inst.addTransformer(t4, false);
    }

    public static void undo() {
        inst.removeTransformer(t3);
        try {
            System.err.println("RETRANSFORM");
            inst.retransformClasses(new RetransformApp().getClass());
        } catch (Exception ex) {
            System.err.println("EXCEPTION on undo: " + ex);
        }
    }

    public static boolean succeeded() {
        return succeeded && markCount == markGolden.length;
    }

    public static void callTracker(int mark) {
        System.err.println("got mark " + mark);
        if (markCount >= markGolden.length || mark != markGolden[markCount++]) {
            succeeded = false;
        }
    }
}
