0N/A/*
2362N/A * Copyright (c) 1998, 2008, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
4378N/A/*
4378N/A * This source code is provided to illustrate the usage of a given feature
4378N/A * or technique and has been deliberately simplified. Additional steps
4378N/A * required for a production-quality application, such as security checks,
4378N/A * input validation and proper error handling, might not be present in
4378N/A * this sample code.
4378N/A */
4378N/A
4378N/A
0N/Apackage com.sun.tools.example.debug.bdi;
0N/A
0N/Aimport com.sun.jdi.*;
0N/Aimport com.sun.jdi.request.*;
0N/Aimport com.sun.jdi.connect.*;
0N/Aimport com.sun.tools.example.debug.expr.ExpressionParser;
0N/Aimport com.sun.tools.example.debug.expr.ParseException;
0N/A
0N/Aimport java.io.*;
0N/Aimport java.util.*;
0N/A
0N/Aimport com.sun.tools.example.debug.event.*;
0N/A
0N/Aimport javax.swing.SwingUtilities;
0N/A
0N/A/**
0N/A * Move this towards being only state and functionality
0N/A * that spans across Sessions (and thus VMs).
0N/A */
0N/Apublic class ExecutionManager {
0N/A
0N/A private Session session;
0N/A
0N/A /**
0N/A * Get/set JDI trace mode.
0N/A */
0N/A int traceMode = VirtualMachine.TRACE_NONE;
0N/A
0N/A ////////////////// Listener registration //////////////////
0N/A
0N/A // Session Listeners
0N/A
4123N/A ArrayList<SessionListener> sessionListeners = new ArrayList<SessionListener>();
0N/A
0N/A public void addSessionListener(SessionListener listener) {
0N/A sessionListeners.add(listener);
0N/A }
0N/A
0N/A public void removeSessionListener(SessionListener listener) {
0N/A sessionListeners.remove(listener);
0N/A }
0N/A
0N/A // Spec Listeners
0N/A
4123N/A ArrayList<SpecListener> specListeners = new ArrayList<SpecListener>();
0N/A
0N/A public void addSpecListener(SpecListener cl) {
0N/A specListeners.add(cl);
0N/A }
0N/A
0N/A public void removeSpecListener(SpecListener cl) {
0N/A specListeners.remove(cl);
0N/A }
0N/A
0N/A // JDI Listeners
0N/A
4123N/A ArrayList<JDIListener> jdiListeners = new ArrayList<JDIListener>();
0N/A
0N/A /**
0N/A * Adds a JDIListener
0N/A */
0N/A public void addJDIListener(JDIListener jl) {
0N/A jdiListeners.add(jl);
0N/A }
0N/A
0N/A /**
0N/A * Adds a JDIListener - at the specified position
0N/A */
0N/A public void addJDIListener(int index, JDIListener jl) {
0N/A jdiListeners.add(index, jl);
0N/A }
0N/A
0N/A /**
0N/A * Removes a JDIListener
0N/A */
0N/A public void removeJDIListener(JDIListener jl) {
0N/A jdiListeners.remove(jl);
0N/A }
0N/A
0N/A // App Echo Listeners
0N/A
4123N/A private ArrayList<OutputListener> appEchoListeners = new ArrayList<OutputListener>();
0N/A
0N/A public void addApplicationEchoListener(OutputListener l) {
4123N/A appEchoListeners.add(l);
0N/A }
0N/A
0N/A public void removeApplicationEchoListener(OutputListener l) {
4123N/A appEchoListeners.remove(l);
0N/A }
0N/A
0N/A // App Output Listeners
0N/A
4123N/A private ArrayList<OutputListener> appOutputListeners = new ArrayList<OutputListener>();
0N/A
0N/A public void addApplicationOutputListener(OutputListener l) {
4123N/A appOutputListeners.add(l);
0N/A }
0N/A
0N/A public void removeApplicationOutputListener(OutputListener l) {
4123N/A appOutputListeners.remove(l);
0N/A }
0N/A
0N/A // App Error Listeners
0N/A
4123N/A private ArrayList<OutputListener> appErrorListeners = new ArrayList<OutputListener>();
0N/A
0N/A public void addApplicationErrorListener(OutputListener l) {
4123N/A appErrorListeners.add(l);
0N/A }
0N/A
0N/A public void removeApplicationErrorListener(OutputListener l) {
4123N/A appErrorListeners.remove(l);
0N/A }
0N/A
0N/A // Diagnostic Listeners
0N/A
4123N/A private ArrayList<OutputListener> diagnosticsListeners = new ArrayList<OutputListener>();
0N/A
0N/A public void addDiagnosticsListener(OutputListener l) {
4123N/A diagnosticsListeners.add(l);
0N/A }
0N/A
0N/A public void removeDiagnosticsListener(OutputListener l) {
4123N/A diagnosticsListeners.remove(l);
0N/A }
0N/A
0N/A /////////// End Listener Registration //////////////
0N/A
0N/A //### We probably don't want this public
0N/A public VirtualMachine vm() {
0N/A return session == null ? null : session.vm;
0N/A }
0N/A
0N/A void ensureActiveSession() throws NoSessionException {
4123N/A if (session == null) {
4123N/A throw new NoSessionException();
4123N/A }
0N/A }
0N/A
0N/A public EventRequestManager eventRequestManager() {
0N/A return vm() == null ? null : vm().eventRequestManager();
0N/A }
0N/A
0N/A /**
0N/A * Get JDI trace mode.
0N/A */
0N/A public int getTraceMode(int mode) {
0N/A return traceMode;
0N/A }
0N/A
0N/A /**
0N/A * Set JDI trace mode.
0N/A */
0N/A public void setTraceMode(int mode) {
0N/A traceMode = mode;
0N/A if (session != null) {
0N/A session.setTraceMode(mode);
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Determine if VM is interrupted, i.e, present and not running.
0N/A */
0N/A public boolean isInterrupted() /* should: throws NoSessionException */ {
0N/A// ensureActiveSession();
0N/A return session.interrupted;
0N/A }
0N/A
0N/A /**
0N/A * Return a list of ReferenceType objects for all
0N/A * currently loaded classes and interfaces.
0N/A * Array types are not returned.
0N/A */
0N/A public List<ReferenceType> allClasses() throws NoSessionException {
0N/A ensureActiveSession();
0N/A return vm().allClasses();
0N/A }
0N/A
0N/A /**
0N/A * Return a ReferenceType object for the currently
0N/A * loaded class or interface whose fully-qualified
0N/A * class name is specified, else return null if there
0N/A * is none.
0N/A *
0N/A * In general, we must return a list of types, because
0N/A * multiple class loaders could have loaded a class
0N/A * with the same fully-qualified name.
0N/A */
0N/A public List<ReferenceType> findClassesByName(String name) throws NoSessionException {
0N/A ensureActiveSession();
0N/A return vm().classesByName(name);
0N/A }
0N/A
0N/A /**
0N/A * Return a list of ReferenceType objects for all
0N/A * currently loaded classes and interfaces whose name
0N/A * matches the given pattern. The pattern syntax is
0N/A * open to some future revision, but currently consists
0N/A * of a fully-qualified class name in which the first
0N/A * component may optionally be a "*" character, designating
0N/A * an arbitrary prefix.
0N/A */
0N/A public List<ReferenceType> findClassesMatchingPattern(String pattern)
0N/A throws NoSessionException {
0N/A ensureActiveSession();
0N/A List<ReferenceType> result = new ArrayList<ReferenceType>(); //### Is default size OK?
0N/A if (pattern.startsWith("*.")) {
0N/A // Wildcard matches any leading package name.
0N/A pattern = pattern.substring(1);
28N/A for (ReferenceType type : vm().allClasses()) {
0N/A if (type.name().endsWith(pattern)) {
0N/A result.add(type);
0N/A }
0N/A }
0N/A return result;
0N/A } else {
0N/A // It's a class name.
0N/A return vm().classesByName(pattern);
0N/A }
0N/A }
0N/A
0N/A /*
0N/A * Return a list of ThreadReference objects corresponding
0N/A * to the threads that are currently active in the VM.
0N/A * A thread is removed from the list just before the
0N/A * thread terminates.
0N/A */
0N/A
0N/A public List<ThreadReference> allThreads() throws NoSessionException {
0N/A ensureActiveSession();
0N/A return vm().allThreads();
0N/A }
0N/A
0N/A /*
0N/A * Return a list of ThreadGroupReference objects corresponding
0N/A * to the top-level threadgroups that are currently active in the VM.
0N/A * Note that a thread group may be empty, or contain no threads as
0N/A * descendents.
0N/A */
0N/A
0N/A public List<ThreadGroupReference> topLevelThreadGroups() throws NoSessionException {
0N/A ensureActiveSession();
0N/A return vm().topLevelThreadGroups();
0N/A }
0N/A
0N/A /*
0N/A * Return the system threadgroup.
0N/A */
0N/A
0N/A public ThreadGroupReference systemThreadGroup()
0N/A throws NoSessionException {
0N/A ensureActiveSession();
28N/A return vm().topLevelThreadGroups().get(0);
0N/A }
0N/A
0N/A /*
0N/A * Evaluate an expression.
0N/A */
0N/A
0N/A public Value evaluate(final StackFrame f, String expr)
0N/A throws ParseException,
0N/A InvocationException,
0N/A InvalidTypeException,
0N/A ClassNotLoadedException,
0N/A NoSessionException,
0N/A IncompatibleThreadStateException {
0N/A ExpressionParser.GetFrame frameGetter = null;
0N/A ensureActiveSession();
0N/A if (f != null) {
0N/A frameGetter = new ExpressionParser.GetFrame() {
4123N/A @Override
0N/A public StackFrame get() /* throws IncompatibleThreadStateException */ {
0N/A return f;
0N/A }
0N/A };
0N/A }
0N/A return ExpressionParser.evaluate(expr, vm(), frameGetter);
0N/A }
0N/A
0N/A
0N/A /*
0N/A * Start a new VM.
0N/A */
0N/A
0N/A public void run(boolean suspended,
0N/A String vmArgs,
0N/A String className,
0N/A String args) throws VMLaunchFailureException {
0N/A
0N/A endSession();
0N/A
0N/A //### Set a breakpoint on 'main' method.
0N/A //### Would be cleaner if we could just bring up VM already suspended.
0N/A if (suspended) {
0N/A //### Set breakpoint at 'main(java.lang.String[])'.
0N/A List<String> argList = new ArrayList<String>(1);
0N/A argList.add("java.lang.String[]");
0N/A createMethodBreakpoint(className, "main", argList);
0N/A }
0N/A
0N/A String cmdLine = className + " " + args;
0N/A
0N/A startSession(new ChildSession(this, vmArgs, cmdLine,
0N/A appInput, appOutput, appError,
0N/A diagnostics));
0N/A }
0N/A
0N/A /*
0N/A * Attach to an existing VM.
0N/A */
0N/A public void attach(String portName) throws VMLaunchFailureException {
0N/A endSession();
0N/A
0N/A //### Changes made here for connectors have broken the
0N/A //### the 'Session' abstraction. The 'Session.attach()'
0N/A //### method is intended to encapsulate all of the various
0N/A //### ways in which session start-up can fail. (maddox 12/18/98)
0N/A
0N/A /*
0N/A * Now that attaches and launches both go through Connectors,
0N/A * it may be worth creating a new subclass of Session for
0N/A * attach sessions.
0N/A */
0N/A VirtualMachineManager mgr = Bootstrap.virtualMachineManager();
28N/A AttachingConnector connector = mgr.attachingConnectors().get(0);
0N/A Map<String, Connector.Argument> arguments = connector.defaultArguments();
28N/A arguments.get("port").setValue(portName);
0N/A
0N/A Session newSession = internalAttach(connector, arguments);
0N/A if (newSession != null) {
0N/A startSession(newSession);
0N/A }
0N/A }
0N/A
0N/A private Session internalAttach(AttachingConnector connector,
0N/A Map<String, Connector.Argument> arguments) {
0N/A try {
0N/A VirtualMachine vm = connector.attach(arguments);
0N/A return new Session(vm, this, diagnostics);
0N/A } catch (IOException ioe) {
0N/A diagnostics.putString("\n Unable to attach to target VM: " +
0N/A ioe.getMessage());
0N/A } catch (IllegalConnectorArgumentsException icae) {
0N/A diagnostics.putString("\n Invalid connector arguments: " +
0N/A icae.getMessage());
0N/A }
0N/A return null;
0N/A }
0N/A
0N/A private Session internalListen(ListeningConnector connector,
0N/A Map<String, Connector.Argument> arguments) {
0N/A try {
0N/A VirtualMachine vm = connector.accept(arguments);
0N/A return new Session(vm, this, diagnostics);
0N/A } catch (IOException ioe) {
0N/A diagnostics.putString(
0N/A "\n Unable to accept connection to target VM: " +
0N/A ioe.getMessage());
0N/A } catch (IllegalConnectorArgumentsException icae) {
0N/A diagnostics.putString("\n Invalid connector arguments: " +
0N/A icae.getMessage());
0N/A }
0N/A return null;
0N/A }
0N/A
0N/A /*
0N/A * Connect via user specified arguments
0N/A * @return true on success
0N/A */
0N/A public boolean explictStart(Connector connector, Map<String, Connector.Argument> arguments)
0N/A throws VMLaunchFailureException {
0N/A Session newSession = null;
0N/A
0N/A endSession();
0N/A
0N/A if (connector instanceof LaunchingConnector) {
0N/A // we were launched, use ChildSession
0N/A newSession = new ChildSession(this, (LaunchingConnector)connector,
0N/A arguments,
0N/A appInput, appOutput, appError,
0N/A diagnostics);
0N/A } else if (connector instanceof AttachingConnector) {
0N/A newSession = internalAttach((AttachingConnector)connector,
0N/A arguments);
0N/A } else if (connector instanceof ListeningConnector) {
0N/A newSession = internalListen((ListeningConnector)connector,
0N/A arguments);
0N/A } else {
0N/A diagnostics.putString("\n Unknown connector: " + connector);
0N/A }
0N/A if (newSession != null) {
0N/A startSession(newSession);
0N/A }
0N/A return newSession != null;
0N/A }
0N/A
0N/A /*
0N/A * Detach from VM. If VM was started by debugger, terminate it.
0N/A */
0N/A public void detach() throws NoSessionException {
0N/A ensureActiveSession();
0N/A endSession();
0N/A }
0N/A
0N/A private void startSession(Session s) throws VMLaunchFailureException {
0N/A if (!s.attach()) {
0N/A throw new VMLaunchFailureException();
0N/A }
0N/A session = s;
0N/A EventRequestManager em = vm().eventRequestManager();
0N/A ClassPrepareRequest classPrepareRequest = em.createClassPrepareRequest();
0N/A //### We must allow the deferred breakpoints to be resolved before
0N/A //### we continue executing the class. We could optimize if there
0N/A //### were no deferred breakpoints outstanding for a particular class.
0N/A //### Can we do this with JDI?
0N/A classPrepareRequest.setSuspendPolicy(EventRequest.SUSPEND_ALL);
0N/A classPrepareRequest.enable();
0N/A ClassUnloadRequest classUnloadRequest = em.createClassUnloadRequest();
0N/A classUnloadRequest.setSuspendPolicy(EventRequest.SUSPEND_NONE);
0N/A classUnloadRequest.enable();
0N/A ThreadStartRequest threadStartRequest = em.createThreadStartRequest();
0N/A threadStartRequest.setSuspendPolicy(EventRequest.SUSPEND_NONE);
0N/A threadStartRequest.enable();
0N/A ThreadDeathRequest threadDeathRequest = em.createThreadDeathRequest();
0N/A threadDeathRequest.setSuspendPolicy(EventRequest.SUSPEND_NONE);
0N/A threadDeathRequest.enable();
0N/A ExceptionRequest exceptionRequest =
0N/A em.createExceptionRequest(null, false, true);
0N/A exceptionRequest.setSuspendPolicy(EventRequest.SUSPEND_ALL);
0N/A exceptionRequest.enable();
0N/A validateThreadInfo();
0N/A session.interrupted = true;
0N/A notifySessionStart();
0N/A }
0N/A
0N/A void endSession() {
0N/A if (session != null) {
0N/A session.detach();
0N/A session = null;
0N/A invalidateThreadInfo();
0N/A notifySessionDeath();
0N/A }
0N/A }
0N/A
0N/A /*
0N/A * Suspend all VM activity.
0N/A */
0N/A
0N/A public void interrupt() throws NoSessionException {
0N/A ensureActiveSession();
0N/A vm().suspend();
0N/A //### Is it guaranteed that the interrupt has happened?
0N/A validateThreadInfo();
0N/A session.interrupted = true;
0N/A notifyInterrupted();
0N/A }
0N/A
0N/A /*
0N/A * Resume interrupted VM.
0N/A */
0N/A
0N/A public void go() throws NoSessionException, VMNotInterruptedException {
0N/A ensureActiveSession();
0N/A invalidateThreadInfo();
0N/A session.interrupted = false;
0N/A notifyContinued();
0N/A vm().resume();
0N/A }
0N/A
0N/A /*
0N/A * Stepping.
0N/A */
0N/A void clearPreviousStep(ThreadReference thread) {
0N/A /*
0N/A * A previous step may not have completed on this thread;
0N/A * if so, it gets removed here.
0N/A */
0N/A EventRequestManager mgr = vm().eventRequestManager();
28N/A for (StepRequest request : mgr.stepRequests()) {
0N/A if (request.thread().equals(thread)) {
0N/A mgr.deleteEventRequest(request);
0N/A break;
0N/A }
0N/A }
0N/A }
0N/A
0N/A private void generalStep(ThreadReference thread, int size, int depth)
0N/A throws NoSessionException {
0N/A ensureActiveSession();
0N/A invalidateThreadInfo();
0N/A session.interrupted = false;
0N/A notifyContinued();
0N/A
0N/A clearPreviousStep(thread);
0N/A EventRequestManager reqMgr = vm().eventRequestManager();
0N/A StepRequest request = reqMgr.createStepRequest(thread,
0N/A size, depth);
0N/A // We want just the next step event and no others
0N/A request.addCountFilter(1);
0N/A request.enable();
0N/A vm().resume();
0N/A }
0N/A
0N/A public void stepIntoInstruction(ThreadReference thread)
0N/A throws NoSessionException {
0N/A generalStep(thread, StepRequest.STEP_MIN, StepRequest.STEP_INTO);
0N/A }
0N/A
0N/A public void stepOverInstruction(ThreadReference thread)
0N/A throws NoSessionException {
0N/A generalStep(thread, StepRequest.STEP_MIN, StepRequest.STEP_OVER);
0N/A }
0N/A
0N/A public void stepIntoLine(ThreadReference thread)
0N/A throws NoSessionException,
0N/A AbsentInformationException {
0N/A generalStep(thread, StepRequest.STEP_LINE, StepRequest.STEP_INTO);
0N/A }
0N/A
0N/A public void stepOverLine(ThreadReference thread)
0N/A throws NoSessionException,
0N/A AbsentInformationException {
0N/A generalStep(thread, StepRequest.STEP_LINE, StepRequest.STEP_OVER);
0N/A }
0N/A
0N/A public void stepOut(ThreadReference thread)
0N/A throws NoSessionException {
0N/A generalStep(thread, StepRequest.STEP_MIN, StepRequest.STEP_OUT);
0N/A }
0N/A
0N/A /*
0N/A * Thread control.
0N/A */
0N/A
0N/A public void suspendThread(ThreadReference thread) throws NoSessionException {
0N/A ensureActiveSession();
0N/A thread.suspend();
0N/A }
0N/A
0N/A public void resumeThread(ThreadReference thread) throws NoSessionException {
0N/A ensureActiveSession();
0N/A thread.resume();
0N/A }
0N/A
0N/A public void stopThread(ThreadReference thread) throws NoSessionException {
0N/A ensureActiveSession();
0N/A //### Need an exception now. Which one to use?
0N/A //thread.stop();
0N/A }
0N/A
0N/A /*
0N/A * ThreadInfo objects -- Allow query of thread status and stack.
0N/A */
0N/A
0N/A private List<ThreadInfo> threadInfoList = new LinkedList<ThreadInfo>();
0N/A //### Should be weak! (in the value, not the key)
0N/A private HashMap<ThreadReference, ThreadInfo> threadInfoMap = new HashMap<ThreadReference, ThreadInfo>();
0N/A
0N/A public ThreadInfo threadInfo(ThreadReference thread) {
0N/A if (session == null || thread == null) {
0N/A return null;
0N/A }
28N/A ThreadInfo info = threadInfoMap.get(thread);
0N/A if (info == null) {
0N/A //### Should not hardcode initial frame count and prefetch here!
0N/A //info = new ThreadInfo(thread, 10, 10);
0N/A info = new ThreadInfo(thread);
0N/A if (session.interrupted) {
0N/A info.validate();
0N/A }
0N/A threadInfoList.add(info);
0N/A threadInfoMap.put(thread, info);
0N/A }
0N/A return info;
0N/A }
0N/A
0N/A void validateThreadInfo() {
0N/A session.interrupted = true;
28N/A for (ThreadInfo threadInfo : threadInfoList) {
28N/A threadInfo.validate();
0N/A }
0N/A }
0N/A
0N/A private void invalidateThreadInfo() {
0N/A if (session != null) {
0N/A session.interrupted = false;
28N/A for (ThreadInfo threadInfo : threadInfoList) {
28N/A threadInfo.invalidate();
0N/A }
0N/A }
0N/A }
0N/A
0N/A void removeThreadInfo(ThreadReference thread) {
28N/A ThreadInfo info = threadInfoMap.get(thread);
0N/A if (info != null) {
0N/A info.invalidate();
0N/A threadInfoMap.remove(thread);
0N/A threadInfoList.remove(info);
0N/A }
0N/A }
0N/A
0N/A /*
0N/A * Listen for Session control events.
0N/A */
0N/A
0N/A private void notifyInterrupted() {
4123N/A ArrayList<SessionListener> l = new ArrayList<SessionListener>(sessionListeners);
0N/A EventObject evt = new EventObject(this);
0N/A for (int i = 0; i < l.size(); i++) {
4123N/A l.get(i).sessionInterrupt(evt);
0N/A }
0N/A }
0N/A
0N/A private void notifyContinued() {
4123N/A ArrayList<SessionListener> l = new ArrayList<SessionListener>(sessionListeners);
0N/A EventObject evt = new EventObject(this);
0N/A for (int i = 0; i < l.size(); i++) {
4123N/A l.get(i).sessionContinue(evt);
0N/A }
0N/A }
0N/A
0N/A private void notifySessionStart() {
4123N/A ArrayList<SessionListener> l = new ArrayList<SessionListener>(sessionListeners);
0N/A EventObject evt = new EventObject(this);
0N/A for (int i = 0; i < l.size(); i++) {
4123N/A l.get(i).sessionStart(evt);
0N/A }
0N/A }
0N/A
0N/A private void notifySessionDeath() {
0N/A/*** noop for now
4123N/A ArrayList<SessionListener> l = new ArrayList<SessionListener>(sessionListeners);
0N/A EventObject evt = new EventObject(this);
0N/A for (int i = 0; i < l.size(); i++) {
4123N/A ((SessionListener)l.get(i)).sessionDeath(evt);
0N/A }
0N/A****/
0N/A }
0N/A
0N/A /*
0N/A * Listen for input and output requests from the application
0N/A * being debugged. These are generated only when the debuggee
0N/A * is spawned as a child of the debugger.
0N/A */
0N/A
0N/A private Object inputLock = new Object();
0N/A private LinkedList<String> inputBuffer = new LinkedList<String>();
0N/A
0N/A private void resetInputBuffer() {
0N/A synchronized (inputLock) {
0N/A inputBuffer = new LinkedList<String>();
0N/A }
0N/A }
0N/A
0N/A public void sendLineToApplication(String line) {
0N/A synchronized (inputLock) {
0N/A inputBuffer.addFirst(line);
0N/A inputLock.notifyAll();
0N/A }
0N/A }
0N/A
0N/A private InputListener appInput = new InputListener() {
4123N/A @Override
0N/A public String getLine() {
0N/A // Don't allow reader to be interrupted -- catch and retry.
0N/A String line = null;
0N/A while (line == null) {
0N/A synchronized (inputLock) {
0N/A try {
0N/A while (inputBuffer.size() < 1) {
0N/A inputLock.wait();
0N/A }
28N/A line = inputBuffer.removeLast();
0N/A } catch (InterruptedException e) {}
0N/A }
0N/A }
0N/A // We must not be holding inputLock here, as the listener
0N/A // that we call to echo a line might call us re-entrantly
0N/A // to provide another line of input.
0N/A // Run in Swing event dispatcher thread.
0N/A final String input = line;
0N/A SwingUtilities.invokeLater(new Runnable() {
4123N/A @Override
0N/A public void run() {
0N/A echoInputLine(input);
0N/A }
0N/A });
0N/A return line;
0N/A }
0N/A };
0N/A
0N/A private static String newline = System.getProperty("line.separator");
0N/A
0N/A private void echoInputLine(String line) {
4123N/A ArrayList<OutputListener> l = new ArrayList<OutputListener>(appEchoListeners);
0N/A for (int i = 0; i < l.size(); i++) {
4123N/A OutputListener ol = l.get(i);
0N/A ol.putString(line);
0N/A ol.putString(newline);
0N/A }
0N/A }
0N/A
0N/A private OutputListener appOutput = new OutputListener() {
4123N/A @Override
0N/A public void putString(String string) {
4123N/A ArrayList<OutputListener> l = new ArrayList<OutputListener>(appEchoListeners);
0N/A for (int i = 0; i < l.size(); i++) {
4123N/A l.get(i).putString(string);
0N/A }
0N/A }
0N/A };
0N/A
0N/A private OutputListener appError = new OutputListener() {
4123N/A @Override
0N/A public void putString(String string) {
4123N/A ArrayList<OutputListener> l = new ArrayList<OutputListener>(appEchoListeners);
0N/A for (int i = 0; i < l.size(); i++) {
4123N/A l.get(i).putString(string);
0N/A }
0N/A }
0N/A };
0N/A
0N/A private OutputListener diagnostics = new OutputListener() {
4123N/A @Override
0N/A public void putString(String string) {
4123N/A ArrayList<OutputListener> l = new ArrayList<OutputListener>(diagnosticsListeners);
0N/A for (int i = 0; i < l.size(); i++) {
4123N/A l.get(i).putString(string);
0N/A }
0N/A }
0N/A };
0N/A
0N/A ///////////// Spec Request Creation/Deletion/Query ///////////
0N/A
0N/A private EventRequestSpecList specList = new EventRequestSpecList(this);
0N/A
0N/A public BreakpointSpec
0N/A createSourceLineBreakpoint(String sourceName, int line) {
0N/A return specList.createSourceLineBreakpoint(sourceName, line);
0N/A }
0N/A
0N/A public BreakpointSpec
0N/A createClassLineBreakpoint(String classPattern, int line) {
0N/A return specList.createClassLineBreakpoint(classPattern, line);
0N/A }
0N/A
0N/A public BreakpointSpec
0N/A createMethodBreakpoint(String classPattern,
28N/A String methodId, List<String> methodArgs) {
0N/A return specList.createMethodBreakpoint(classPattern,
0N/A methodId, methodArgs);
0N/A }
0N/A
0N/A public ExceptionSpec
0N/A createExceptionIntercept(String classPattern,
0N/A boolean notifyCaught,
0N/A boolean notifyUncaught) {
0N/A return specList.createExceptionIntercept(classPattern,
0N/A notifyCaught,
0N/A notifyUncaught);
0N/A }
0N/A
0N/A public AccessWatchpointSpec
0N/A createAccessWatchpoint(String classPattern, String fieldId) {
0N/A return specList.createAccessWatchpoint(classPattern, fieldId);
0N/A }
0N/A
0N/A public ModificationWatchpointSpec
0N/A createModificationWatchpoint(String classPattern, String fieldId) {
0N/A return specList.createModificationWatchpoint(classPattern,
0N/A fieldId);
0N/A }
0N/A
0N/A public void delete(EventRequestSpec spec) {
0N/A specList.delete(spec);
0N/A }
0N/A
0N/A void resolve(ReferenceType refType) {
0N/A specList.resolve(refType);
0N/A }
0N/A
0N/A public void install(EventRequestSpec spec) {
0N/A specList.install(spec, vm());
0N/A }
0N/A
28N/A public List<EventRequestSpec> eventRequestSpecs() {
0N/A return specList.eventRequestSpecs();
0N/A }
0N/A}