/*
 * Copyright (c) 1998, 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.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * 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.
 */

/*
 * This source code is provided to illustrate the usage of a given feature
 * or technique and has been deliberately simplified. Additional steps
 * required for a production-quality application, such as security checks,
 * input validation and proper error handling, might not be present in
 * this sample code.
 */


package com.sun.tools.example.debug.bdi;

import com.sun.jdi.*;
import com.sun.jdi.request.*;
import com.sun.jdi.connect.*;
import com.sun.tools.example.debug.expr.ExpressionParser;
import com.sun.tools.example.debug.expr.ParseException;

import java.io.*;
import java.util.*;

import com.sun.tools.example.debug.event.*;

import javax.swing.SwingUtilities;

/**
 * Move this towards being only state and functionality
 * that spans across Sessions (and thus VMs).
 */
public class ExecutionManager {

    private Session session;

    /**
     * Get/set JDI trace mode.
     */
    int traceMode = VirtualMachine.TRACE_NONE;

  //////////////////    Listener registration    //////////////////

  // Session Listeners

    ArrayList<SessionListener> sessionListeners = new ArrayList<SessionListener>();

    public void addSessionListener(SessionListener listener) {
        sessionListeners.add(listener);
    }

    public void removeSessionListener(SessionListener listener) {
        sessionListeners.remove(listener);
    }

  // Spec Listeners

  ArrayList<SpecListener> specListeners = new ArrayList<SpecListener>();

    public void addSpecListener(SpecListener cl) {
        specListeners.add(cl);
    }

    public void removeSpecListener(SpecListener cl) {
        specListeners.remove(cl);
    }

    // JDI Listeners

    ArrayList<JDIListener> jdiListeners = new ArrayList<JDIListener>();

    /**
     * Adds a JDIListener
     */
    public void addJDIListener(JDIListener jl) {
        jdiListeners.add(jl);
    }

    /**
     * Adds a JDIListener - at the specified position
     */
    public void addJDIListener(int index, JDIListener jl) {
        jdiListeners.add(index, jl);
    }

    /**
     * Removes a JDIListener
     */
    public void removeJDIListener(JDIListener jl) {
        jdiListeners.remove(jl);
    }

  // App Echo Listeners

    private ArrayList<OutputListener> appEchoListeners = new ArrayList<OutputListener>();

    public void addApplicationEchoListener(OutputListener l) {
        appEchoListeners.add(l);
    }

    public void removeApplicationEchoListener(OutputListener l) {
        appEchoListeners.remove(l);
    }

  // App Output Listeners

    private ArrayList<OutputListener> appOutputListeners = new ArrayList<OutputListener>();

    public void addApplicationOutputListener(OutputListener l) {
        appOutputListeners.add(l);
    }

    public void removeApplicationOutputListener(OutputListener l) {
        appOutputListeners.remove(l);
    }

  // App Error Listeners

    private ArrayList<OutputListener> appErrorListeners = new ArrayList<OutputListener>();

    public void addApplicationErrorListener(OutputListener l) {
        appErrorListeners.add(l);
    }

    public void removeApplicationErrorListener(OutputListener l) {
        appErrorListeners.remove(l);
    }

  // Diagnostic Listeners

    private ArrayList<OutputListener> diagnosticsListeners = new ArrayList<OutputListener>();

    public void addDiagnosticsListener(OutputListener l) {
        diagnosticsListeners.add(l);
    }

    public void removeDiagnosticsListener(OutputListener l) {
        diagnosticsListeners.remove(l);
    }

  ///////////    End Listener Registration    //////////////

    //### We probably don't want this public
    public VirtualMachine vm() {
        return session == null ? null : session.vm;
    }

    void ensureActiveSession() throws NoSessionException {
        if (session == null) {
         throw new NoSessionException();
      }
    }

    public EventRequestManager eventRequestManager() {
        return vm() == null ? null : vm().eventRequestManager();
    }

    /**
     * Get JDI trace mode.
     */
    public int getTraceMode(int mode) {
        return traceMode;
    }

    /**
     * Set JDI trace mode.
     */
    public void setTraceMode(int mode) {
        traceMode = mode;
        if (session != null) {
            session.setTraceMode(mode);
        }
    }

    /**
     * Determine if VM is interrupted, i.e, present and not running.
     */
    public boolean isInterrupted() /* should: throws NoSessionException */ {
//      ensureActiveSession();
        return session.interrupted;
    }

    /**
     * Return a list of ReferenceType objects for all
     * currently loaded classes and interfaces.
     * Array types are not returned.
     */
    public List<ReferenceType> allClasses() throws NoSessionException {
        ensureActiveSession();
        return vm().allClasses();
    }

    /**
     * Return a ReferenceType object for the currently
     * loaded class or interface whose fully-qualified
     * class name is specified, else return null if there
     * is none.
     *
     * In general, we must return a list of types, because
     * multiple class loaders could have loaded a class
     * with the same fully-qualified name.
     */
    public List<ReferenceType> findClassesByName(String name) throws NoSessionException {
        ensureActiveSession();
        return vm().classesByName(name);
    }

    /**
     * Return a list of ReferenceType objects for all
     * currently loaded classes and interfaces whose name
     * matches the given pattern.  The pattern syntax is
     * open to some future revision, but currently consists
     * of a fully-qualified class name in which the first
     * component may optionally be a "*" character, designating
     * an arbitrary prefix.
     */
    public List<ReferenceType> findClassesMatchingPattern(String pattern)
                                                throws NoSessionException {
        ensureActiveSession();
        List<ReferenceType> result = new ArrayList<ReferenceType>();  //### Is default size OK?
        if (pattern.startsWith("*.")) {
            // Wildcard matches any leading package name.
            pattern = pattern.substring(1);
            for (ReferenceType type : vm().allClasses()) {
                if (type.name().endsWith(pattern)) {
                    result.add(type);
                }
            }
            return result;
        } else {
            // It's a class name.
            return vm().classesByName(pattern);
        }
    }

    /*
     * Return a list of ThreadReference objects corresponding
     * to the threads that are currently active in the VM.
     * A thread is removed from the list just before the
     * thread terminates.
     */

    public List<ThreadReference> allThreads() throws NoSessionException {
        ensureActiveSession();
        return vm().allThreads();
    }

    /*
     * Return a list of ThreadGroupReference objects corresponding
     * to the top-level threadgroups that are currently active in the VM.
     * Note that a thread group may be empty, or contain no threads as
     * descendents.
     */

    public List<ThreadGroupReference> topLevelThreadGroups() throws NoSessionException {
        ensureActiveSession();
        return vm().topLevelThreadGroups();
    }

    /*
     * Return the system threadgroup.
     */

    public ThreadGroupReference systemThreadGroup()
                                                throws NoSessionException {
        ensureActiveSession();
        return vm().topLevelThreadGroups().get(0);
    }

    /*
     * Evaluate an expression.
     */

    public Value evaluate(final StackFrame f, String expr)
        throws ParseException,
                                            InvocationException,
                                            InvalidTypeException,
                                            ClassNotLoadedException,
                                            NoSessionException,
                                            IncompatibleThreadStateException {
        ExpressionParser.GetFrame frameGetter = null;
        ensureActiveSession();
        if (f != null) {
            frameGetter = new ExpressionParser.GetFrame() {
                @Override
                public StackFrame get() /* throws IncompatibleThreadStateException */ {
                    return f;
                }
            };
        }
        return ExpressionParser.evaluate(expr, vm(), frameGetter);
    }


    /*
     * Start a new VM.
     */

    public void run(boolean suspended,
                    String vmArgs,
                    String className,
                    String args) throws VMLaunchFailureException {

        endSession();

        //### Set a breakpoint on 'main' method.
        //### Would be cleaner if we could just bring up VM already suspended.
        if (suspended) {
            //### Set breakpoint at 'main(java.lang.String[])'.
            List<String> argList = new ArrayList<String>(1);
            argList.add("java.lang.String[]");
            createMethodBreakpoint(className, "main", argList);
        }

        String cmdLine = className + " " + args;

        startSession(new ChildSession(this, vmArgs, cmdLine,
                                      appInput, appOutput, appError,
                                      diagnostics));
    }

    /*
     * Attach to an existing VM.
     */
    public void attach(String portName) throws VMLaunchFailureException {
        endSession();

        //### Changes made here for connectors have broken the
        //### the 'Session' abstraction.  The 'Session.attach()'
        //### method is intended to encapsulate all of the various
        //### ways in which session start-up can fail. (maddox 12/18/98)

        /*
         * Now that attaches and launches both go through Connectors,
         * it may be worth creating a new subclass of Session for
         * attach sessions.
         */
        VirtualMachineManager mgr = Bootstrap.virtualMachineManager();
        AttachingConnector connector = mgr.attachingConnectors().get(0);
        Map<String, Connector.Argument> arguments = connector.defaultArguments();
        arguments.get("port").setValue(portName);

        Session newSession = internalAttach(connector, arguments);
        if (newSession != null) {
            startSession(newSession);
        }
    }

    private Session internalAttach(AttachingConnector connector,
                                   Map<String, Connector.Argument> arguments) {
        try {
            VirtualMachine vm = connector.attach(arguments);
            return new Session(vm, this, diagnostics);
        } catch (IOException ioe) {
            diagnostics.putString("\n Unable to attach to target VM: " +
                                  ioe.getMessage());
        } catch (IllegalConnectorArgumentsException icae) {
            diagnostics.putString("\n Invalid connector arguments: " +
                                  icae.getMessage());
        }
        return null;
    }

    private Session internalListen(ListeningConnector connector,
                                   Map<String, Connector.Argument> arguments) {
        try {
            VirtualMachine vm = connector.accept(arguments);
            return new Session(vm, this, diagnostics);
        } catch (IOException ioe) {
            diagnostics.putString(
                  "\n Unable to accept connection to target VM: " +
                                  ioe.getMessage());
        } catch (IllegalConnectorArgumentsException icae) {
            diagnostics.putString("\n Invalid connector arguments: " +
                                  icae.getMessage());
        }
        return null;
    }

    /*
     * Connect via user specified arguments
     * @return true on success
     */
    public boolean explictStart(Connector connector, Map<String, Connector.Argument> arguments)
                                           throws VMLaunchFailureException {
        Session newSession = null;

        endSession();

        if (connector instanceof LaunchingConnector) {
            // we were launched, use ChildSession
            newSession = new ChildSession(this, (LaunchingConnector)connector,
                                          arguments,
                                          appInput, appOutput, appError,
                                          diagnostics);
        } else if (connector instanceof AttachingConnector) {
            newSession = internalAttach((AttachingConnector)connector,
                                        arguments);
        } else if (connector instanceof ListeningConnector) {
            newSession = internalListen((ListeningConnector)connector,
                                        arguments);
        } else {
            diagnostics.putString("\n Unknown connector: " + connector);
        }
        if (newSession != null) {
            startSession(newSession);
        }
        return newSession != null;
    }

    /*
     * Detach from VM.  If VM was started by debugger, terminate it.
     */
    public void detach() throws NoSessionException {
        ensureActiveSession();
        endSession();
    }

    private void startSession(Session s) throws VMLaunchFailureException {
        if (!s.attach()) {
            throw new VMLaunchFailureException();
        }
        session = s;
        EventRequestManager em = vm().eventRequestManager();
        ClassPrepareRequest classPrepareRequest = em.createClassPrepareRequest();
        //### We must allow the deferred breakpoints to be resolved before
        //### we continue executing the class.  We could optimize if there
        //### were no deferred breakpoints outstanding for a particular class.
        //### Can we do this with JDI?
        classPrepareRequest.setSuspendPolicy(EventRequest.SUSPEND_ALL);
        classPrepareRequest.enable();
        ClassUnloadRequest classUnloadRequest = em.createClassUnloadRequest();
        classUnloadRequest.setSuspendPolicy(EventRequest.SUSPEND_NONE);
        classUnloadRequest.enable();
        ThreadStartRequest threadStartRequest = em.createThreadStartRequest();
        threadStartRequest.setSuspendPolicy(EventRequest.SUSPEND_NONE);
        threadStartRequest.enable();
        ThreadDeathRequest threadDeathRequest = em.createThreadDeathRequest();
        threadDeathRequest.setSuspendPolicy(EventRequest.SUSPEND_NONE);
        threadDeathRequest.enable();
        ExceptionRequest exceptionRequest =
                                em.createExceptionRequest(null, false, true);
        exceptionRequest.setSuspendPolicy(EventRequest.SUSPEND_ALL);
        exceptionRequest.enable();
        validateThreadInfo();
        session.interrupted = true;
        notifySessionStart();
    }

    void endSession() {
        if (session != null) {
            session.detach();
            session = null;
            invalidateThreadInfo();
            notifySessionDeath();
        }
    }

    /*
     * Suspend all VM activity.
     */

    public void interrupt() throws NoSessionException {
        ensureActiveSession();
        vm().suspend();
        //### Is it guaranteed that the interrupt has happened?
        validateThreadInfo();
        session.interrupted = true;
        notifyInterrupted();
    }

    /*
     * Resume interrupted VM.
     */

    public void go() throws NoSessionException, VMNotInterruptedException {
        ensureActiveSession();
        invalidateThreadInfo();
        session.interrupted = false;
        notifyContinued();
        vm().resume();
    }

    /*
     * Stepping.
     */
    void clearPreviousStep(ThreadReference thread) {
        /*
         * A previous step may not have completed on this thread;
         * if so, it gets removed here.
         */
         EventRequestManager mgr = vm().eventRequestManager();
         for (StepRequest request : mgr.stepRequests()) {
             if (request.thread().equals(thread)) {
                 mgr.deleteEventRequest(request);
                 break;
             }
         }
    }

    private void generalStep(ThreadReference thread, int size, int depth)
                        throws NoSessionException {
        ensureActiveSession();
        invalidateThreadInfo();
        session.interrupted = false;
        notifyContinued();

        clearPreviousStep(thread);
        EventRequestManager reqMgr = vm().eventRequestManager();
        StepRequest request = reqMgr.createStepRequest(thread,
                                                       size, depth);
        // We want just the next step event and no others
        request.addCountFilter(1);
        request.enable();
        vm().resume();
    }

    public void stepIntoInstruction(ThreadReference thread)
                        throws NoSessionException {
        generalStep(thread, StepRequest.STEP_MIN, StepRequest.STEP_INTO);
    }

    public void stepOverInstruction(ThreadReference thread)
                        throws NoSessionException {
        generalStep(thread, StepRequest.STEP_MIN, StepRequest.STEP_OVER);
    }

    public void stepIntoLine(ThreadReference thread)
                        throws NoSessionException,
                        AbsentInformationException {
        generalStep(thread, StepRequest.STEP_LINE, StepRequest.STEP_INTO);
    }

    public void stepOverLine(ThreadReference thread)
                        throws NoSessionException,
                        AbsentInformationException {
        generalStep(thread, StepRequest.STEP_LINE, StepRequest.STEP_OVER);
    }

    public void stepOut(ThreadReference thread)
                        throws NoSessionException {
        generalStep(thread, StepRequest.STEP_MIN, StepRequest.STEP_OUT);
    }

    /*
     * Thread control.
     */

    public void suspendThread(ThreadReference thread) throws NoSessionException {
        ensureActiveSession();
        thread.suspend();
    }

    public void resumeThread(ThreadReference thread) throws NoSessionException {
        ensureActiveSession();
        thread.resume();
    }

    public void stopThread(ThreadReference thread) throws NoSessionException {
        ensureActiveSession();
        //### Need an exception now.  Which one to use?
        //thread.stop();
    }

    /*
     * ThreadInfo objects -- Allow query of thread status and stack.
     */

    private List<ThreadInfo> threadInfoList = new LinkedList<ThreadInfo>();
    //### Should be weak! (in the value, not the key)
    private HashMap<ThreadReference, ThreadInfo> threadInfoMap = new HashMap<ThreadReference, ThreadInfo>();

    public ThreadInfo threadInfo(ThreadReference thread) {
        if (session == null || thread == null) {
            return null;
        }
        ThreadInfo info = threadInfoMap.get(thread);
        if (info == null) {
            //### Should not hardcode initial frame count and prefetch here!
            //info = new ThreadInfo(thread, 10, 10);
            info = new ThreadInfo(thread);
            if (session.interrupted) {
                info.validate();
            }
            threadInfoList.add(info);
            threadInfoMap.put(thread, info);
        }
        return info;
    }

     void validateThreadInfo() {
        session.interrupted = true;
        for (ThreadInfo threadInfo : threadInfoList) {
            threadInfo.validate();
            }
    }

    private void invalidateThreadInfo() {
        if (session != null) {
            session.interrupted = false;
            for (ThreadInfo threadInfo : threadInfoList) {
                threadInfo.invalidate();
            }
        }
    }

    void removeThreadInfo(ThreadReference thread) {
        ThreadInfo info = threadInfoMap.get(thread);
        if (info != null) {
            info.invalidate();
            threadInfoMap.remove(thread);
            threadInfoList.remove(info);
        }
    }

    /*
     * Listen for Session control events.
     */

    private void notifyInterrupted() {
      ArrayList<SessionListener> l = new ArrayList<SessionListener>(sessionListeners);
        EventObject evt = new EventObject(this);
        for (int i = 0; i < l.size(); i++) {
            l.get(i).sessionInterrupt(evt);
        }
    }

    private void notifyContinued() {
        ArrayList<SessionListener> l = new ArrayList<SessionListener>(sessionListeners);
        EventObject evt = new EventObject(this);
        for (int i = 0; i < l.size(); i++) {
            l.get(i).sessionContinue(evt);
        }
    }

    private void notifySessionStart() {
        ArrayList<SessionListener> l = new ArrayList<SessionListener>(sessionListeners);
        EventObject evt = new EventObject(this);
        for (int i = 0; i < l.size(); i++) {
            l.get(i).sessionStart(evt);
        }
    }

    private void notifySessionDeath() {
/*** noop for now
        ArrayList<SessionListener> l = new ArrayList<SessionListener>(sessionListeners);
        EventObject evt = new EventObject(this);
        for (int i = 0; i < l.size(); i++) {
            ((SessionListener)l.get(i)).sessionDeath(evt);
        }
****/
    }

    /*
     * Listen for input and output requests from the application
     * being debugged.  These are generated only when the debuggee
     * is spawned as a child of the debugger.
     */

    private Object inputLock = new Object();
    private LinkedList<String> inputBuffer = new LinkedList<String>();

    private void resetInputBuffer() {
        synchronized (inputLock) {
            inputBuffer = new LinkedList<String>();
        }
    }

    public void sendLineToApplication(String line) {
        synchronized (inputLock) {
            inputBuffer.addFirst(line);
            inputLock.notifyAll();
        }
    }

    private InputListener appInput = new InputListener() {
        @Override
        public String getLine() {
            // Don't allow reader to be interrupted -- catch and retry.
            String line = null;
            while (line == null) {
                synchronized (inputLock) {
                    try {
                        while (inputBuffer.size() < 1) {
                            inputLock.wait();
                        }
                        line = inputBuffer.removeLast();
                    } catch (InterruptedException e) {}
                }
            }
            // We must not be holding inputLock here, as the listener
            // that we call to echo a line might call us re-entrantly
            // to provide another line of input.
            // Run in Swing event dispatcher thread.
            final String input = line;
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    echoInputLine(input);
                }
            });
            return line;
        }
    };

    private static String newline = System.getProperty("line.separator");

    private void echoInputLine(String line) {
        ArrayList<OutputListener> l = new ArrayList<OutputListener>(appEchoListeners);
        for (int i = 0; i < l.size(); i++) {
            OutputListener ol = l.get(i);
            ol.putString(line);
            ol.putString(newline);
        }
    }

    private OutputListener appOutput = new OutputListener() {
      @Override
        public void putString(String string) {
            ArrayList<OutputListener> l = new ArrayList<OutputListener>(appEchoListeners);
            for (int i = 0; i < l.size(); i++) {
                l.get(i).putString(string);
            }
        }
    };

    private OutputListener appError = new OutputListener() {
      @Override
        public void putString(String string) {
            ArrayList<OutputListener> l = new ArrayList<OutputListener>(appEchoListeners);
            for (int i = 0; i < l.size(); i++) {
                l.get(i).putString(string);
            }
        }
    };

   private OutputListener diagnostics = new OutputListener() {
      @Override
        public void putString(String string) {
            ArrayList<OutputListener> l = new ArrayList<OutputListener>(diagnosticsListeners);
            for (int i = 0; i < l.size(); i++) {
                l.get(i).putString(string);
            }
        }
   };

  /////////////    Spec Request Creation/Deletion/Query   ///////////

    private EventRequestSpecList specList = new EventRequestSpecList(this);

    public BreakpointSpec
    createSourceLineBreakpoint(String sourceName, int line) {
        return specList.createSourceLineBreakpoint(sourceName, line);
    }

    public BreakpointSpec
    createClassLineBreakpoint(String classPattern, int line) {
        return specList.createClassLineBreakpoint(classPattern, line);
    }

    public BreakpointSpec
    createMethodBreakpoint(String classPattern,
                           String methodId, List<String> methodArgs) {
        return specList.createMethodBreakpoint(classPattern,
                                                 methodId, methodArgs);
    }

    public ExceptionSpec
    createExceptionIntercept(String classPattern,
                             boolean notifyCaught,
                             boolean notifyUncaught) {
        return specList.createExceptionIntercept(classPattern,
                                                   notifyCaught,
                                                   notifyUncaught);
    }

    public AccessWatchpointSpec
    createAccessWatchpoint(String classPattern, String fieldId) {
        return specList.createAccessWatchpoint(classPattern, fieldId);
    }

    public ModificationWatchpointSpec
    createModificationWatchpoint(String classPattern, String fieldId) {
        return specList.createModificationWatchpoint(classPattern,
                                                       fieldId);
    }

    public void delete(EventRequestSpec spec) {
        specList.delete(spec);
    }

    void resolve(ReferenceType refType) {
        specList.resolve(refType);
    }

    public void install(EventRequestSpec spec) {
        specList.install(spec, vm());
    }

    public List<EventRequestSpec> eventRequestSpecs() {
        return specList.eventRequestSpecs();
    }
}
