/*
 * Copyright (c) 1999, 2001, 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 JDIScaffold {
    private boolean shouldTrace = false;
    private VMConnection connection;
    private VirtualMachine vm;
    private EventRequestManager requestManager;
    private List listeners = Collections.synchronizedList(new LinkedList());
    ThreadReference vmStartThread = null;
    boolean vmDied = false;
    boolean vmDisconnected = false;

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

    static public interface TargetListener {
        boolean eventSetReceived(EventSet set);
        boolean eventSetComplete(EventSet set);
        boolean eventReceived(Event event);
        boolean breakpointReached(BreakpointEvent event);
        boolean exceptionThrown(ExceptionEvent event);
        boolean stepCompleted(StepEvent event);
        boolean classPrepared(ClassPrepareEvent event);
        boolean classUnloaded(ClassUnloadEvent event);
        boolean methodEntered(MethodEntryEvent event);
        boolean methodExited(MethodExitEvent event);
        boolean fieldAccessed(AccessWatchpointEvent event);
        boolean fieldModified(ModificationWatchpointEvent event);
        boolean threadStarted(ThreadStartEvent event);
        boolean threadDied(ThreadDeathEvent event);
        boolean vmStarted(VMStartEvent event);
        boolean vmDied(VMDeathEvent event);
        boolean vmDisconnected(VMDisconnectEvent event);
    }

    static public class TargetAdapter implements TargetListener {
        public boolean eventSetReceived(EventSet set) {
            return false;
        }
        public boolean eventSetComplete(EventSet set) {
            return false;
        }
        public boolean eventReceived(Event event) {
            return false;
        }
        public boolean breakpointReached(BreakpointEvent event) {
            return false;
        }
        public boolean exceptionThrown(ExceptionEvent event) {
            return false;
        }
        public boolean stepCompleted(StepEvent event) {
            return false;
        }
        public boolean classPrepared(ClassPrepareEvent event) {
            return false;
        }
        public boolean classUnloaded(ClassUnloadEvent event) {
            return false;
        }
        public boolean methodEntered(MethodEntryEvent event) {
            return false;
        }
        public boolean methodExited(MethodExitEvent event) {
            return false;
        }
        public boolean fieldAccessed(AccessWatchpointEvent event) {
            return false;
        }
        public boolean fieldModified(ModificationWatchpointEvent event) {
            return false;
        }
        public boolean threadStarted(ThreadStartEvent event) {
            return false;
        }
        public boolean threadDied(ThreadDeathEvent event) {
            return false;
        }
        public boolean vmStarted(VMStartEvent event) {
            return false;
        }
        public boolean vmDied(VMDeathEvent event) {
            return false;
        }
        public boolean vmDisconnected(VMDisconnectEvent event) {
            return false;
        }
    }

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

        private boolean notifyEvent(TargetListener listener, Event event) {
            if (listener.eventReceived(event) == true) {
                return true;
            } else if (event instanceof BreakpointEvent) {
                return listener.breakpointReached((BreakpointEvent)event);
            } else if (event instanceof ExceptionEvent) {
                return listener.exceptionThrown((ExceptionEvent)event);
            } else if (event instanceof StepEvent) {
                return listener.stepCompleted((StepEvent)event);
            } else if (event instanceof ClassPrepareEvent) {
                return listener.classPrepared((ClassPrepareEvent)event);
            } else if (event instanceof ClassUnloadEvent) {
                return listener.classUnloaded((ClassUnloadEvent)event);
            } else if (event instanceof MethodEntryEvent) {
                return listener.methodEntered((MethodEntryEvent)event);
            } else if (event instanceof MethodExitEvent) {
                return listener.methodExited((MethodExitEvent)event);
            } else if (event instanceof AccessWatchpointEvent) {
                return listener.fieldAccessed((AccessWatchpointEvent)event);
            } else if (event instanceof ModificationWatchpointEvent) {
                return listener.fieldModified((ModificationWatchpointEvent)event);
            } else if (event instanceof ThreadStartEvent) {
                return listener.threadStarted((ThreadStartEvent)event);
            } else if (event instanceof ThreadDeathEvent) {
                return listener.threadDied((ThreadDeathEvent)event);
            } else if (event instanceof VMStartEvent) {
                return listener.vmStarted((VMStartEvent)event);
            } else if (event instanceof VMDeathEvent) {
                return listener.vmDied((VMDeathEvent)event);
            } else if (event instanceof VMDisconnectEvent) {
                return 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("JDI: runloop: suspend = SUSPEND_NONE");
                    break;
                case EventRequest.SUSPEND_ALL:
                    traceln("JDI: runloop: suspend = SUSPEND_ALL");
                    break;
                case EventRequest.SUSPEND_EVENT_THREAD:
                    traceln("JDI: runloop: 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("JDI: runloop: listener = " + listener);
                            if (listener.eventSetReceived(set) == true) {
                                iter.remove();
                            } else {
                                Iterator jter = set.iterator();
                                while (jter.hasNext()) {
                                    Event event = (Event)jter.next();
                                    traceln("JDI: runloop:    event = " + event.getClass());
                                    if (event instanceof VMDisconnectEvent) {
                                        connected = false;
                                    }
                                    if (notifyEvent(listener, event) == true) {
                                        iter.remove();
                                        break;
                                    }
                                }
                                traceln("JDI: runloop:   end of events loop");
                                if (listener.eventSetComplete(set) == true) {
                                    iter.remove();
                                }
                            }
                        traceln("JDI: runloop: end of listener");
                        }
                    }
                } catch (InterruptedException e) {
                }
                traceln("JDI: runloop: end of outer loop");
            } while (connected);
        }
    }

    /**
     * Constructor
     */
    public JDIScaffold() {
    }

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

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


    /*
     * 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 traceln(String str) {
        if (shouldTrace) {
            println(str);
        }
    }

    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;
    }

    public void connect(String args[]) {
        ArgInfo argInfo = parseArgs(args);

        argInfo.targetVMArgs += VMConnection.getDebuggeeVMOptions();
        connection = new VMConnection(argInfo.connectorSpec,
                                      argInfo.traceFlags);
        if (!connection.isLaunch()) {
            throw new UnsupportedOperationException(
                                 "Listening and Attaching not yet supported");
        }

        /*
         * Add a listener to track VM start/death/disconnection and
         * to update status fields accordingly.
         */
        addListener(new TargetAdapter() {
                        public boolean vmStarted(VMStartEvent event) {
                            traceln("JDI: listener1:  got VMStart");
                            synchronized(JDIScaffold.this) {
                                vmStartThread = event.thread();
                                JDIScaffold.this.notifyAll();
                            }
                            return false;
                        }

                        public boolean vmDied(VMDeathEvent event) {
                            traceln("JDI: listener1:  got VMDeath");
                            synchronized(JDIScaffold.this) {
                                vmDied = true;
                                JDIScaffold.this.notifyAll();
                            }
                            return false;
                        }

                        public boolean vmDisconnected(VMDisconnectEvent event) {
                            traceln("JDI: listener1:  got VMDisconnectedEvent");
                            synchronized(JDIScaffold.this) {
                                vmDisconnected = true;
                                JDIScaffold.this.notifyAll();
                            }
                            return false;
                        }
                    });

        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();
        new EventHandler();
    }


    public VirtualMachine vm() {
        return vm;
    }

    public EventRequestManager eventRequestManager() {
        return requestManager;
    }

    public void addListener(TargetListener listener) {
        listeners.add(listener);
    }

    public void removeListener(TargetListener listener) {
        listeners.remove(listener);
    }

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

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

        return vmStartThread;
    }

    public synchronized void waitForVMDeath() {
        while (!vmDied && !vmDisconnected) {
            try {
                traceln("JDI: waitForVMDeath:  waiting");
                wait();
            } catch (InterruptedException e) {
            }
        }
        traceln("JDI: waitForVMDeath:  done waiting");

        if (!vmDied) {
            throw new VMDisconnectedException();
        }
    }

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

        TargetAdapter adapter = new TargetAdapter() {
            public boolean eventReceived(Event event) {
                if (request.equals(event.request())) {
                    synchronized (en) {
                        en.event = event;
                        en.notifyAll();
                    }
                    return true;
                } else if (event instanceof VMDisconnectEvent) {
                    synchronized (en) {
                        en.disconnected = true;
                        en.notifyAll();
                    }
                    return true;
                } else {
                    return false;
                }
            }
        };

        addListener(adapter);

        try {
            synchronized (en) {
                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 resumeToVMDeath() {
        // If we are very close to VM death, we might get a VM disconnect
        // before resume is complete. In that case ignore any VMDisconnectException
        // and let the waitForVMDeath to clean up.
        try {
            traceln("JDI: resumeToVMDeath:  resuming");
            vm.resume();
            traceln("JDI: resumeToVMDeath:  resumed");
        } catch (VMDisconnectedException e) {
            // clean up below
        }
        waitForVMDeath();
    }

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

    public void shutdown(String message) {
        if ((connection != null) && !vmDied) {
            try {
                connection.disposeVM();
            } catch (VMDisconnectedException e) {
                // Shutting down after the VM has gone away. This is
                // not an error, and we just ignore it.
            }
        }
        if (message != null) {
            System.out.println(message);
        }
    }
}
