/*
 * Copyright (c) 2002, 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.
 *
 */

import com.sun.jdi.*;
import com.sun.jdi.request.*;
import com.sun.jdi.event.*;
import java.util.*;
import java.io.*;

/**
 * Framework used by all JDI regression tests
 */
abstract public class TestScaffold extends TargetAdapter {
    private boolean shouldTrace = false;
    private VMConnection connection;
    private VirtualMachine vm;
    private EventRequestManager requestManager;
    private List listeners = Collections.synchronizedList(new LinkedList());

    /**
     * We create a VMDeathRequest, SUSPEND_ALL, to sync the BE and FE.
     */
    //private VMDeathRequest ourVMDeathRequest = null;
    Object ourVMDeathRequest = null;

    /**
     * We create an ExceptionRequest, SUSPEND_NONE so that we can
     * catch it and output a msg if an exception occurs in the
     * debuggee.
     */
    private ExceptionRequest ourExceptionRequest = null;

    /**
     * If we do catch an uncaught exception, we set this true
     * so the testcase can find out if it wants to.
     */
    private boolean exceptionCaught = false;
    ThreadReference vmStartThread = null;
    boolean vmDied = false;
    boolean vmDisconnected = false;
    final String[] args;
    protected boolean testFailed = false;

    static private class ArgInfo {
        String targetVMArgs = "";
        String targetAppCommandLine = "";
        String connectorSpec = "com.sun.jdi.CommandLineLaunch:";
        int traceFlags = 0;
    }

    /**
     * An easy way to sleep for awhile
     */
    public void mySleep(int millis) {
        try {
            Thread.sleep(millis);
        } catch (InterruptedException ee) {
        }
    }

    boolean getExceptionCaught() {
        return exceptionCaught;
    }

    void setExceptionCaught(boolean value) {
        exceptionCaught = value;
    }

    /**
     * Return true if eventSet contains the VMDeathEvent for the request in
     * the ourVMDeathRequest ivar.
     */
    private boolean containsOurVMDeathRequest(EventSet eventSet) {
        if (ourVMDeathRequest != null) {
            Iterator myIter = eventSet.iterator();
            while (myIter.hasNext()) {
                Event myEvent = (Event)myIter.next();
                if (!(myEvent instanceof VMDeathEvent)) {
                    // We assume that an EventSet contains only VMDeathEvents
                    // or no VMDeathEvents.
                    break;
                }
                if (ourVMDeathRequest.equals(myEvent.request())) {
                    return true;
                }
            }
        }
        return false;
    }

    /************************************************************************
     * The following methods override those in our base class, TargetAdapter.
     *************************************************************************/

    /**
     * Events handled directly by scaffold always resume (well, almost always)
     */
    public void eventSetComplete(EventSet set) {
        // The listener in connect(..) resumes after receiving our
        // special VMDeathEvent.  We can't also do the resume
        // here or we will probably get a VMDisconnectedException
        if (!containsOurVMDeathRequest(set)) {
            traceln("TS: set.resume() called");
            set.resume();
        }
    }

    /**
     * This method sets up default requests.
     * Testcases can override this to change default behavior.
     */
    protected void createDefaultEventRequests() {
        createDefaultVMDeathRequest();
        createDefaultExceptionRequest();
    }

    /**
     * We want the BE to stop when it issues a VMDeathEvent in order to
     * give the FE time to complete handling events that occured before
     * the VMDeath.  When we get the VMDeathEvent for this request in
     * the listener in connect(), we will do a resume.
     * If a testcase wants to do something special with VMDeathEvent's,
     * then it should override this method with an empty method or
     * whatever in order to suppress the automatic resume.  The testcase
     * will then be responsible for the handling of VMDeathEvents.  It
     * has to be sure that it does a resume if it gets a VMDeathEvent
     * with SUSPEND_ALL, and it has to be sure that it doesn't do a
     * resume after getting a VMDeath with SUSPEND_NONE (the automatically
     * generated VMDeathEvent.)
     */
    protected void createDefaultVMDeathRequest() {
//         ourVMDeathRequest = requestManager.createVMDeathRequest();
//         ourVMDeathRequest.setSuspendPolicy(EventRequest.SUSPEND_ALL);
//         ourVMDeathRequest.enable();
    }

    /**
     * This will allow us to print a warning if a debuggee gets an
     * unexpected exception.  The unexpected exception will be handled in
     * the exceptionThrown method in the listener created in the connect()
     * method.
     * If a testcase does not want an uncaught exception to cause a
     * msg, it must override this method.
     */
    protected void createDefaultExceptionRequest() {
        ourExceptionRequest = requestManager.createExceptionRequest(null,
                                                                false, true);

        // We can't afford to make this be other than SUSPEND_NONE.  Otherwise,
        // it would have to be resumed.  If our connect() listener resumes it,
        // what about the case where the EventSet contains other events with
        // SUSPEND_ALL and there are other listeners who expect the BE to still
        // be suspended when their handlers get called?
        ourExceptionRequest.setSuspendPolicy(EventRequest.SUSPEND_NONE);
        ourExceptionRequest.enable();
    }

    private class EventHandler implements Runnable {
        EventHandler() {
            Thread thread = new Thread(this);
            thread.setDaemon(true);
            thread.start();
        }

        private void notifyEvent(TargetListener listener, Event event) {
            if (event instanceof BreakpointEvent) {
                listener.breakpointReached((BreakpointEvent)event);
            } else if (event instanceof ExceptionEvent) {
                listener.exceptionThrown((ExceptionEvent)event);
            } else if (event instanceof StepEvent) {
                listener.stepCompleted((StepEvent)event);
            } else if (event instanceof ClassPrepareEvent) {
                listener.classPrepared((ClassPrepareEvent)event);
            } else if (event instanceof ClassUnloadEvent) {
                listener.classUnloaded((ClassUnloadEvent)event);
            } else if (event instanceof MethodEntryEvent) {
                listener.methodEntered((MethodEntryEvent)event);
            } else if (event instanceof MethodExitEvent) {
                listener.methodExited((MethodExitEvent)event);
            } else if (event instanceof AccessWatchpointEvent) {
                listener.fieldAccessed((AccessWatchpointEvent)event);
            } else if (event instanceof ModificationWatchpointEvent) {
                listener.fieldModified((ModificationWatchpointEvent)event);
            } else if (event instanceof ThreadStartEvent) {
                listener.threadStarted((ThreadStartEvent)event);
            } else if (event instanceof ThreadDeathEvent) {
                listener.threadDied((ThreadDeathEvent)event);
            } else if (event instanceof VMStartEvent) {
                listener.vmStarted((VMStartEvent)event);
            } else if (event instanceof VMDeathEvent) {
                listener.vmDied((VMDeathEvent)event);
            } else if (event instanceof VMDisconnectEvent) {
                listener.vmDisconnected((VMDisconnectEvent)event);
            } else {
                throw new InternalError("Unknown event type: " + event.getClass());
            }
        }

        private void traceSuspendPolicy(int policy) {
            if (shouldTrace) {
                switch (policy) {
                case EventRequest.SUSPEND_NONE:
                    traceln("TS: eventHandler: suspend = SUSPEND_NONE");
                    break;
                case EventRequest.SUSPEND_ALL:
                    traceln("TS: eventHandler: suspend = SUSPEND_ALL");
                    break;
                case EventRequest.SUSPEND_EVENT_THREAD:
                    traceln("TS: eventHandler: suspend = SUSPEND_EVENT_THREAD");
                    break;
                }
            }
        }

        public void run() {
            boolean connected = true;
            do {
                try {
                    EventSet set = vm.eventQueue().remove();
                    traceSuspendPolicy(set.suspendPolicy());
                    synchronized (listeners) {
                        ListIterator iter = listeners.listIterator();
                        while (iter.hasNext()) {
                            TargetListener listener = (TargetListener)iter.next();
                            traceln("TS: eventHandler: listener = " + listener);
                            listener.eventSetReceived(set);
                            if (listener.shouldRemoveListener()) {
                                iter.remove();
                            } else {
                                Iterator jter = set.iterator();
                                while (jter.hasNext()) {
                                    Event event = (Event)jter.next();
                                    traceln("TS: eventHandler:    event = " + event.getClass());

                                    if (event instanceof VMDisconnectEvent) {
                                        connected = false;
                                    }
                                    listener.eventReceived(event);
                                    if (listener.shouldRemoveListener()) {
                                        iter.remove();
                                        break;
                                    }
                                    notifyEvent(listener, event);
                                    if (listener.shouldRemoveListener()) {
                                        iter.remove();
                                        break;
                                    }
                                }
                                traceln("TS: eventHandler:   end of events loop");
                                if (!listener.shouldRemoveListener()) {
                                    traceln("TS: eventHandler:   calling ESC");
                                    listener.eventSetComplete(set);
                                    if (listener.shouldRemoveListener()) {
                                        iter.remove();
                                    }
                                }
                            }
                            traceln("TS: eventHandler: end of listeners loop");
                        }
                    }
                } catch (InterruptedException e) {
                    traceln("TS: eventHandler: InterruptedException");
                } catch (Exception e) {
                    failure("FAILED: Exception occured in eventHandler: " + e);
                    e.printStackTrace();
                    connected = false;
                    synchronized(TestScaffold.this) {
                        // This will make the waiters such as waitForVMDisconnect
                        // exit their wait loops.
                        vmDisconnected = true;
                        TestScaffold.this.notifyAll();
                    }
                }
                traceln("TS: eventHandler: End of outerloop");
            } while (connected);
            traceln("TS: eventHandler: finished");
        }
    }

    /**
     * Constructor
     */
    public TestScaffold(String[] args) {
        this.args = args;
    }

    public void enableScaffoldTrace() {
        this.shouldTrace = true;
    }

    public void disableScaffoldTrace() {
        this.shouldTrace = false;
    }


    protected void startUp(String targetName) {
        List argList = new ArrayList(Arrays.asList(args));
        argList.add(targetName);
        println("run args: " + argList);
        connect((String[]) argList.toArray(args));
        waitForVMStart();
    }

    protected BreakpointEvent startToMain(String targetName) {
        startUp(targetName);
        traceln("TS: back from startUp");
        BreakpointEvent bpr = resumeTo(targetName, "main", "([Ljava/lang/String;)V");
        waitForInput();
        return bpr;
    }

    protected void waitForInput() {
        if (System.getProperty("jpda.wait") != null) {
            try {
                System.err.println("Press <enter> to continue");
                System.in.read();
                System.err.println("running...");

            } catch(Exception e) {
            }
        }
    }

    /*
     * Test cases should implement tests in runTests and should
     * initiate testing by calling run().
     */
    abstract protected void runTests() throws Exception;

    final public void startTests() throws Exception {
        try {
            runTests();
        } finally {
            shutdown();
        }
    }

    protected void println(String str) {
        System.err.println(str);
    }

    protected void print(String str) {
        System.err.print(str);
    }

    protected void traceln(String str) {
        if (shouldTrace) {
            println(str);
        }
    }

    protected void failure(String str) {
        println(str);
        testFailed = true;
    }

    private ArgInfo parseArgs(String args[]) {
        ArgInfo argInfo = new ArgInfo();
        for (int i = 0; i < args.length; i++) {
            if (args[i].equals("-connect")) {
                i++;
                argInfo.connectorSpec = args[i];
            } else if (args[i].equals("-trace")) {
                i++;
                argInfo.traceFlags = Integer.decode(args[i]).intValue();
            } else if (args[i].startsWith("-J")) {
                argInfo.targetVMArgs += (args[i].substring(2) + ' ');

                /*
                 * classpath can span two arguments so we need to handle
                 * it specially.
                 */
                if (args[i].equals("-J-classpath")) {
                    i++;
                    argInfo.targetVMArgs += (args[i] + ' ');
                }
            } else {
                argInfo.targetAppCommandLine += (args[i] + ' ');
            }
        }
        return argInfo;
    }

    /**
     * This is called to connect to a debuggee VM.  It starts the VM and
     * installs a listener to catch VMStartEvent, our default events, and
     * VMDisconnectedEvent.  When these events appear, that is remembered
     * and waiters are notified.
     * This is normally called in the main thread of the test case.
     * It starts up an EventHandler thread that gets events coming in
     * from the debuggee and distributes them to listeners.  That thread
     * keeps running until a VMDisconnectedEvent occurs or some exception
     * occurs during its processing.
     *
     * The 'listenUntilVMDisconnect' method adds 'this' as a listener.
     * This means that 'this's vmDied method will get called.  This has a
     * default impl in TargetAdapter.java which can be overridden in the
     * testcase.
     *
     * waitForRequestedEvent also adds an adaptor listener that listens
     * for the particular event it is supposed to wait for (and it also
     * catches VMDisconnectEvents.)  This listener is removed once
     * its eventReceived method is called.
     * waitForRequestedEvent is called by most of the methods to do bkpts,
     * etc.
     */
    public void connect(String args[]) {
        ArgInfo argInfo = parseArgs(args);

        argInfo.targetVMArgs += VMConnection.getDebuggeeVMOptions();
        connection = new VMConnection(argInfo.connectorSpec,
                                      argInfo.traceFlags);

        addListener(new TargetAdapter() {
                public void eventSetComplete(EventSet set) {
                    if (TestScaffold.this.containsOurVMDeathRequest(set)) {
                        traceln("TS: connect: set.resume() called");
                        set.resume();

                        // Note that we want to do the above resume before
                        // waking up any sleepers.
                        synchronized(TestScaffold.this) {
                            TestScaffold.this.notifyAll();
                        }
                    }
                }

                public void vmStarted(VMStartEvent event) {
                    synchronized(TestScaffold.this) {
                        vmStartThread = event.thread();
                        TestScaffold.this.notifyAll();
                    }
                }
                /**
                 * By default, we catch uncaught exceptions and print a msg.
                 * The testcase must override the createDefaultExceptionRequest
                 * method if it doesn't want this behavior.
                 */
                public void exceptionThrown(ExceptionEvent event) {
                    if (TestScaffold.this.ourExceptionRequest != null &&
                        TestScaffold.this.ourExceptionRequest.equals(
                                                        event.request())) {
                        println("Note: Unexpected Debuggee Exception: " +
                                event.exception().referenceType().name() +
                                " at line " + event.location().lineNumber());
                        TestScaffold.this.exceptionCaught = true;
                    }
                }

                public void vmDied(VMDeathEvent event) {
                    vmDied = true;
                    traceln("TS: vmDied called");
                }

                public void vmDisconnected(VMDisconnectEvent event) {
                    synchronized(TestScaffold.this) {
                        vmDisconnected = true;
                        TestScaffold.this.notifyAll();
                    }
                }
            });
        if (connection.connector().name().equals("com.sun.jdi.CommandLineLaunch")) {
            if (argInfo.targetVMArgs.length() > 0) {
                if (connection.connectorArg("options").length() > 0) {
                    throw new IllegalArgumentException("VM options in two places");
                }
                connection.setConnectorArg("options", argInfo.targetVMArgs);
            }
            if (argInfo.targetAppCommandLine.length() > 0) {
                if (connection.connectorArg("main").length() > 0) {
                    throw new IllegalArgumentException("Command line in two places");
                }
                connection.setConnectorArg("main", argInfo.targetAppCommandLine);
            }
        }

        vm = connection.open();
        requestManager = vm.eventRequestManager();
        createDefaultEventRequests();
        new EventHandler();
    }


    public VirtualMachine vm() {
        return vm;
    }

    public EventRequestManager eventRequestManager() {
        return requestManager;
    }

    public void addListener(TargetListener listener) {
        traceln("TS: Adding listener " + listener);
        listeners.add(listener);
    }

    public void removeListener(TargetListener listener) {
        traceln("TS: Removing listener " + listener);
        listeners.remove(listener);
    }


    protected void listenUntilVMDisconnect() {
        try {
            addListener (this);
        } catch (Exception ex){
            ex.printStackTrace();
            testFailed = true;
        } finally {
            // Allow application to complete and shut down
            resumeToVMDisconnect();
        }
    }

    public synchronized ThreadReference waitForVMStart() {
        while ((vmStartThread == null) && !vmDisconnected) {
            try {
                wait();
            } catch (InterruptedException e) {
            }
        }

        if (vmStartThread == null) {
            throw new VMDisconnectedException();
        }

        return vmStartThread;
    }

    public synchronized void waitForVMDisconnect() {
        traceln("TS: waitForVMDisconnect");
        while (!vmDisconnected) {
            try {
                wait();
            } catch (InterruptedException e) {
            }
        }
        traceln("TS: waitForVMDisconnect: done");
    }

    public Event waitForRequestedEvent(final EventRequest request) {
        class EventNotification {
            Event event;
            boolean disconnected = false;
        }
        final EventNotification en = new EventNotification();

        TargetAdapter adapter = new TargetAdapter() {
            public void eventReceived(Event event) {
                if (request.equals(event.request())) {
                    traceln("TS:Listener2: got requested event");
                    synchronized (en) {
                        en.event = event;
                        en.notifyAll();
                    }
                    removeThisListener();
                } else if (event instanceof VMDisconnectEvent) {
                    traceln("TS:Listener2: got VMDisconnectEvent");
                    synchronized (en) {
                        en.disconnected = true;
                        en.notifyAll();
                    }
                    removeThisListener();
                }
            }
        };

        addListener(adapter);

        try {
            synchronized (en) {
                traceln("TS: waitForRequestedEvent: vm.resume called");
                vm.resume();

                while (!en.disconnected && (en.event == null)) {
                    en.wait();
                }
            }
        } catch (InterruptedException e) {
            return null;
        }

        if (en.disconnected) {
            throw new RuntimeException("VM Disconnected before requested event occurred");
        }
        return en.event;
    }

    private StepEvent doStep(ThreadReference thread, int gran, int depth) {
        final StepRequest sr =
                  requestManager.createStepRequest(thread, gran, depth);

        sr.addClassExclusionFilter("java.*");
        sr.addClassExclusionFilter("sun.*");
        sr.addClassExclusionFilter("com.sun.*");
        sr.addCountFilter(1);
        sr.enable();
        StepEvent retEvent = (StepEvent)waitForRequestedEvent(sr);
        requestManager.deleteEventRequest(sr);
        return retEvent;
    }

    public StepEvent stepIntoInstruction(ThreadReference thread) {
        return doStep(thread, StepRequest.STEP_MIN, StepRequest.STEP_INTO);
    }

    public StepEvent stepIntoLine(ThreadReference thread) {
        return doStep(thread, StepRequest.STEP_LINE, StepRequest.STEP_INTO);
    }

    public StepEvent stepOverInstruction(ThreadReference thread) {
        return doStep(thread, StepRequest.STEP_MIN, StepRequest.STEP_OVER);
    }

    public StepEvent stepOverLine(ThreadReference thread) {
        return doStep(thread, StepRequest.STEP_LINE, StepRequest.STEP_OVER);
    }

    public StepEvent stepOut(ThreadReference thread) {
        return doStep(thread, StepRequest.STEP_LINE, StepRequest.STEP_OUT);
    }

    public BreakpointEvent resumeTo(Location loc) {
        final BreakpointRequest request =
            requestManager.createBreakpointRequest(loc);
        request.addCountFilter(1);
        request.enable();
        return (BreakpointEvent)waitForRequestedEvent(request);
    }

    public ReferenceType findReferenceType(String name) {
        List rts = vm.classesByName(name);
        Iterator iter = rts.iterator();
        while (iter.hasNext()) {
            ReferenceType rt = (ReferenceType)iter.next();
            if (rt.name().equals(name)) {
                return rt;
            }
        }
        return null;
    }

    public Method findMethod(ReferenceType rt, String name, String signature) {
        List methods = rt.methods();
        Iterator iter = methods.iterator();
        while (iter.hasNext()) {
            Method method = (Method)iter.next();
            if (method.name().equals(name) &&
                method.signature().equals(signature)) {
                return method;
            }
        }
        return null;
    }

    public Location findLocation(ReferenceType rt, int lineNumber)
                         throws AbsentInformationException {
        List locs = rt.locationsOfLine(lineNumber);
        if (locs.size() == 0) {
            throw new IllegalArgumentException("Bad line number");
        } else if (locs.size() > 1) {
            throw new IllegalArgumentException("Line number has multiple locations");
        }

        return (Location)locs.get(0);
    }

    public BreakpointEvent resumeTo(String clsName, String methodName,
                                         String methodSignature) {
        ReferenceType rt = findReferenceType(clsName);
        if (rt == null) {
            rt = resumeToPrepareOf(clsName).referenceType();
        }

        Method method = findMethod(rt, methodName, methodSignature);
        if (method == null) {
            throw new IllegalArgumentException("Bad method name/signature");
        }

        return resumeTo(method.location());
    }

    public BreakpointEvent resumeTo(String clsName, int lineNumber) throws AbsentInformationException {
        ReferenceType rt = findReferenceType(clsName);
        if (rt == null) {
            rt = resumeToPrepareOf(clsName).referenceType();
        }

        return resumeTo(findLocation(rt, lineNumber));
    }

    public ClassPrepareEvent resumeToPrepareOf(String className) {
        final ClassPrepareRequest request =
            requestManager.createClassPrepareRequest();
        request.addClassFilter(className);
        request.addCountFilter(1);
        request.enable();
        return (ClassPrepareEvent)waitForRequestedEvent(request);
    }

    public void resumeToVMDisconnect() {
        try {
            traceln("TS: resumeToVMDisconnect: vm.resume called");
            vm.resume();
        } catch (VMDisconnectedException e) {
            // clean up below
        }
        waitForVMDisconnect();
    }

    public void shutdown() {
        shutdown(null);
    }

    public void shutdown(String message) {
        traceln("TS: shutdown: vmDied= " + vmDied +
                 ", vmDisconnected= " + vmDisconnected +
                 ", connection = " + connection);

        if ((connection != null)) {
            try {
                connection.disposeVM();
             } catch (VMDisconnectedException e) {
                // Shutting down after the VM has gone away. This is
                // not an error, and we just ignore it.
            }
        } else {
            traceln("TS: shutdown: disposeVM not called");
        }
        if (message != null) {
            println(message);
        }

        vmDied = true;
        vmDisconnected = true;
    }
}
