You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@flex.apache.org by ah...@apache.org on 2015/06/02 19:05:17 UTC
[14/50] [abbrv] git commit: [flex-falcon] [refs/heads/develop] - get
donated fdbworkers to work,
including integration with latest falcon compiler for expression evaluation
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/00c0bf63/debugger/src/flex/tools/debugger/cli/DebugCLI.java
----------------------------------------------------------------------
diff --git a/debugger/src/flex/tools/debugger/cli/DebugCLI.java b/debugger/src/flex/tools/debugger/cli/DebugCLI.java
new file mode 100644
index 0000000..588a977
--- /dev/null
+++ b/debugger/src/flex/tools/debugger/cli/DebugCLI.java
@@ -0,0 +1,7567 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package flex.tools.debugger.cli;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayOutputStream;
+import java.io.EOFException;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.LineNumberReader;
+import java.io.PrintStream;
+import java.io.StringReader;
+import java.net.SocketException;
+import java.net.SocketTimeoutException;
+import java.text.NumberFormat;
+import java.text.ParseException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Properties;
+import java.util.Set;
+import java.util.Stack;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+import flash.localization.LocalizationManager;
+import flash.tools.debugger.Bootstrap;
+import flash.tools.debugger.DebuggerLocalizer;
+import flash.tools.debugger.Frame;
+import flash.tools.debugger.InProgressException;
+import flash.tools.debugger.Isolate;
+import flash.tools.debugger.IsolateSession;
+import flash.tools.debugger.Location;
+import flash.tools.debugger.NoResponseException;
+import flash.tools.debugger.NotConnectedException;
+import flash.tools.debugger.NotSupportedException;
+import flash.tools.debugger.NotSuspendedException;
+import flash.tools.debugger.PlayerDebugException;
+import flash.tools.debugger.Session;
+import flash.tools.debugger.SessionManager;
+import flash.tools.debugger.SourceFile;
+import flash.tools.debugger.SourceLocator;
+import flash.tools.debugger.SuspendReason;
+import flash.tools.debugger.SuspendedException;
+import flash.tools.debugger.SwfInfo;
+import flash.tools.debugger.Value;
+import flash.tools.debugger.Variable;
+import flash.tools.debugger.VariableAttribute;
+import flash.tools.debugger.VariableType;
+import flash.tools.debugger.VersionException;
+import flash.tools.debugger.Watch;
+import flash.tools.debugger.WatchKind;
+import flash.tools.debugger.concrete.DProtocol;
+import flash.tools.debugger.events.BreakEvent;
+import flash.tools.debugger.events.ConsoleErrorFault;
+import flash.tools.debugger.events.DebugEvent;
+import flash.tools.debugger.events.ExceptionFault;
+import flash.tools.debugger.events.FaultEvent;
+import flash.tools.debugger.events.FileListModifiedEvent;
+import flash.tools.debugger.events.FunctionMetaDataAvailableEvent;
+import flash.tools.debugger.events.IsolateCreateEvent;
+import flash.tools.debugger.events.IsolateExitEvent;
+import flash.tools.debugger.events.SwfLoadedEvent;
+import flash.tools.debugger.events.SwfUnloadedEvent;
+import flash.tools.debugger.events.TraceEvent;
+import flash.tools.debugger.expression.ECMA;
+import flash.tools.debugger.expression.NoSuchVariableException;
+import flash.tools.debugger.expression.PlayerFaultException;
+import flash.tools.debugger.expression.ValueExp;
+import flash.util.FieldFormat;
+import flash.util.Trace;
+import flex.tools.debugger.cli.ExpressionCache.EvaluationResult;
+import flex.tools.debugger.cli.FaultActions.FaultActionsBuilder;
+
+/**
+ * This is a front end command line interface to the Flash Debugger
+ * Player.
+ *<p>
+ * This tool utilizes the Debugger Java API (DJAPI) for Flash
+ * Player that exists in flash.tools.debuggger.
+ *<p>
+ * This tool is not completely compliant with the API, since
+ * some commands expose implementation specific information for
+ * debugging purposes. Instances where this occurs are kept to a
+ * minimum and are isolated in a special class called Extensions.
+ * If you wish to build a version that is completely API
+ * compatible. Replace Extensions with ExtensionsDisabled in
+ * the static method calls at the end of this file.
+ */
+public class DebugCLI implements Runnable, SourceLocator
+{
+ public static final String VERSION = "82"; //$NON-NLS-1$
+
+ public static final int CMD_UNKNOWN = 0;
+ public static final int CMD_QUIT = 1;
+ public static final int CMD_CONTINUE = 2;
+ public static final int CMD_STEP = 3;
+ public static final int CMD_NEXT = 4;
+ public static final int CMD_FINISH = 5;
+ public static final int CMD_BREAK = 6;
+ public static final int CMD_SET = 7;
+ public static final int CMD_LIST = 8;
+ public static final int CMD_PRINT = 9;
+ public static final int CMD_TUTORIAL = 10;
+ public static final int CMD_INFO = 11;
+ public static final int CMD_HOME = 12;
+ public static final int CMD_RUN = 13;
+ public static final int CMD_FILE = 14;
+ public static final int CMD_DELETE = 15;
+ public static final int CMD_SOURCE = 16;
+ public static final int CMD_COMMENT = 17;
+ public static final int CMD_CLEAR = 18;
+ public static final int CMD_HELP = 19;
+ public static final int CMD_SHOW = 20;
+ public static final int CMD_KILL = 21;
+ public static final int CMD_HANDLE = 22;
+ public static final int CMD_ENABLE = 23;
+ public static final int CMD_DISABLE = 24;
+ public static final int CMD_DISPLAY = 25;
+ public static final int CMD_UNDISPLAY = 26;
+ public static final int CMD_COMMANDS = 27;
+ public static final int CMD_PWD = 28;
+ public static final int CMD_CF = 29;
+ public static final int CMD_CONDITION = 30;
+ public static final int CMD_AWATCH = 31;
+ public static final int CMD_WATCH = 32;
+ public static final int CMD_RWATCH = 33;
+ public static final int CMD_WHAT = 34;
+ public static final int CMD_DISASSEMBLE = 35;
+ public static final int CMD_HALT = 36;
+ public static final int CMD_MCTREE = 37;
+ public static final int CMD_VIEW_SWF = 38;
+ public static final int CMD_DOWN = 39;
+ public static final int CMD_UP = 40;
+ public static final int CMD_FRAME = 41;
+ public static final int CMD_DIRECTORY = 42;
+ public static final int CMD_CATCH = 43;
+ public static final int CMD_CONNECT = 44;
+ public static final int CMD_WORKER = 45;
+
+ /* info sub commands */
+ public static final int INFO_UNKNOWN_CMD = 100;
+ public static final int INFO_ARGS_CMD = 101;
+ public static final int INFO_BREAK_CMD = 102;
+ public static final int INFO_FILES_CMD = 103;
+ public static final int INFO_HANDLE_CMD = 104;
+ public static final int INFO_FUNCTIONS_CMD = 105;
+ public static final int INFO_LOCALS_CMD = 106;
+ public static final int INFO_SCOPECHAIN_CMD = 107;
+ public static final int INFO_SOURCES_CMD = 108;
+ public static final int INFO_STACK_CMD = 109;
+ public static final int INFO_VARIABLES_CMD = 110;
+ public static final int INFO_DISPLAY_CMD = 111;
+ public static final int INFO_TARGETS_CMD = 112;
+ public static final int INFO_SWFS_CMD = 113;
+ public static final int INFO_WORKERS_CMD = 114;
+
+ /* show subcommands */
+ public static final int SHOW_UNKNOWN_CMD = 200;
+ public static final int SHOW_NET_CMD = 201;
+ public static final int SHOW_FUNC_CMD = 202;
+ public static final int SHOW_URI_CMD = 203;
+ public static final int SHOW_PROPERTIES_CMD = 204;
+ public static final int SHOW_FILES_CMD = 205;
+ public static final int SHOW_BREAK_CMD = 206;
+ public static final int SHOW_VAR_CMD = 207;
+ public static final int SHOW_MEM_CMD = 208;
+ public static final int SHOW_LOC_CMD = 209;
+ public static final int SHOW_DIRS_CMD = 210;
+
+ /* misc subcommands */
+ public static final int ENABLE_ONCE_CMD = 301;
+
+ // default metadata retry count 8 attempts per waitForMetadata() call * 5 calls
+ public static final int METADATA_RETRIES = 8*5;
+
+ /* Enum for the state of the initial prompt shown when a swf is loaded */
+ public static enum InitialPromptState { NEVER_SHOWN, SHOWN_ONCE, DONE }
+
+ Stack<LineNumberReader> m_readerStack = new Stack<LineNumberReader>();
+ public PrintStream m_err;
+ public PrintStream m_out;
+ Session m_session;
+ String m_launchURI;
+ boolean m_fullnameOption; // emacs mode
+ String m_cdPath;
+ String m_mruURI;
+ String m_connectPort;
+ public final static String m_newline = System.getProperty("line.separator"); //$NON-NLS-1$
+
+ private final static LocalizationManager m_localizationManager = new LocalizationManager();
+ private final static FaultActionsBuilder faultActionsBuilder = new FaultActionsBuilder(m_localizationManager);
+
+ List<String> m_sourceDirectories; // List of String
+ int m_sourceDirectoriesChangeCount;
+ private File m_flexHomeDirectory; // <application.home>/frameworks/projects/*/src always goes in m_sourceDirectories
+ private boolean m_initializedFlexHomeDirectory;
+
+ // context information for our current session
+ FileInfoCache m_fileInfo;
+ FaultActions m_faultTable;
+ Vector<Integer> m_breakIsolates;
+ ExpressionCache m_exprCache;
+ Vector<BreakAction> m_breakpoints;
+ Vector<WatchAction> m_watchpoints;
+ Vector<CatchAction> m_catchpoints;
+ ArrayList<DisplayAction> m_displays;
+// boolean m_requestResume;
+// boolean m_requestHalt;
+// boolean m_stepResume;
+ int m_activeIsolate;
+ DebugCLIIsolateState m_mainState;
+
+ /* This indicates the isolate for which we have been showing prompts for setting
+ * breakpoints( so that we don't switch worker while the user is setting breakpoints) */
+ int m_lastPromptIsolate;
+
+ private HashMap<Integer, DebugCLIIsolateState> m_isolateState;
+
+ class DebugCLIIsolateState
+ {
+// public FileInfoCache m_fileInfo;
+// public ExpressionCache m_exprCache;
+ public boolean m_requestResume;
+ public boolean m_requestHalt;
+ public boolean m_stepResume;
+ /* Indicates whether the prompt for setting initial breakpoints has been displayed for this isolate */
+ public InitialPromptState m_promptState;
+// public Vector<BreakAction> m_breakpoints;
+// public Vector<WatchAction> m_watchpoints;
+// public Vector<CatchAction> m_catchpoints;
+// public ArrayList<DisplayAction> m_displays;
+
+
+ public DebugCLIIsolateState(DebugCLI debugcli) {
+// m_exprCache = new ExpressionCache(debugcli);
+ m_faultTable = faultActionsBuilder.build();//new FaultActions();
+// m_breakpoints = new Vector<BreakAction>();
+// m_watchpoints = new Vector<WatchAction>();
+// m_catchpoints = new Vector<CatchAction>();
+// m_displays = new ArrayList<DisplayAction>();
+ }
+ }
+
+ private DebugCLIIsolateState getIsolateState(int isolateId) {
+ if (isolateId == Isolate.DEFAULT_ID)
+ return m_mainState;
+ DebugCLIIsolateState isolateState = null;
+ if (!m_isolateState.containsKey(isolateId)) {
+ isolateState = new DebugCLIIsolateState(this);
+ m_isolateState.put(isolateId, isolateState);
+ }
+ else
+ isolateState = m_isolateState.get(isolateId);
+ return isolateState;
+ }
+
+ public int getActiveIsolateId() {
+ return m_activeIsolate;
+ }
+
+ private boolean getRequestResume(int isolateId) {
+ return getIsolateState(isolateId).m_requestResume;
+ }
+
+ private void setRequestResume(boolean value, int isolateId) {
+ getIsolateState(isolateId).m_requestResume = value;
+ }
+
+ private boolean getStepResume(int isolateId) {
+ return getIsolateState(isolateId).m_stepResume;
+ }
+
+ private void setStepResume(boolean value, int isolateId) {
+ getIsolateState(isolateId).m_stepResume = value;
+ }
+
+ private boolean getRequestHalt(int isolateId) {
+ return getIsolateState(isolateId).m_requestHalt;
+ }
+
+ private void setRequestHalt(boolean value, int isolateId) {
+ getIsolateState(isolateId).m_requestHalt = value;
+ }
+
+ private InitialPromptState getPromptState(int isolateId) {
+ return getIsolateState(isolateId).m_promptState;
+ }
+
+ private void setPromptState(InitialPromptState value, int isolateId) {
+ getIsolateState(isolateId).m_promptState = value;
+ }
+
+ /* our current input processing context */
+ LineNumberReader m_in;
+ public LineNumberReader m_keyboardStream;
+ Vector<String> m_keyboardInput;
+ boolean m_keyboardReadRequest;
+ StringTokenizer m_currentTokenizer;
+ String m_currentToken;
+ String m_currentLine;
+ public String m_repeatLine;
+
+ /**
+ * The module that the next "list" command should display if no
+ * module is explicitly specified.
+ */
+ public static final String LIST_MODULE = "$listmodule"; //$NON-NLS-1$
+
+ /**
+ * The line number at which the next "list" command should begin if no
+ * line number is explicitly specified.
+ */
+ public static final String LIST_LINE = "$listline"; //$NON-NLS-1$
+
+ public static final String LIST_WORKER = "$listworker"; //$NON-NLS-1$
+
+ /**
+ * The number of lines displayed by the "list" command.
+ */
+ private static final String LIST_SIZE = "$listsize"; //$NON-NLS-1$
+
+ private static final String COLUMN_WIDTH = "$columnwidth"; //$NON-NLS-1$
+
+ private static final String UPDATE_DELAY = "$updatedelay"; //$NON-NLS-1$
+
+ private static final String HALT_TIMEOUT = "$halttimeout"; //$NON-NLS-1$
+
+ /**
+ * Current breakpoint number.
+ */
+ private static final String BPNUM = "$bpnum"; //$NON-NLS-1$
+
+ /**
+ * Used to determine how much context information should be displayed.
+ */
+ private static final String LAST_FRAME_DEPTH = "$lastframedepth"; //$NON-NLS-1$
+
+ /**
+ * Used to determine how much context information should be displayed.
+ */
+ private static final String CURRENT_FRAME_DEPTH = "$currentframedepth"; //$NON-NLS-1$
+
+ /**
+ * The current frame we are viewing -- controlled by the "up", "down", and "frame" commands.
+ */
+ public static final String DISPLAY_FRAME_NUMBER = "$displayframenumber"; //$NON-NLS-1$
+
+ private static final String FILE_LIST_WRAP = "$filelistwrap"; //$NON-NLS-1$
+
+ private static final String NO_WAITING = "$nowaiting"; //$NON-NLS-1$
+
+ /**
+ * Show this pointer for info stack.
+ */
+ private static final String INFO_STACK_SHOW_THIS = "$infostackshowthis"; //$NON-NLS-1$
+
+ /**
+ * Number of milliseconds to wait for metadata.
+ */
+ private static final String METADATA_ATTEMPTS_PERIOD = "$metadataattemptsperiod"; //$NON-NLS-1$
+
+ private static final String METADATA_NOT_AVAILABLE = "$metadatanotavailable"; //$NON-NLS-1$
+
+ /**
+ * How many times we should try to get metadata.
+ */
+ private static final String METADATA_ATTEMPTS = "$metadataattempts"; //$NON-NLS-1$
+
+ private static final String PLAYER_FULL_SUPPORT = "$playerfullsupport"; //$NON-NLS-1$
+
+ /**
+ * Whether the "print" command will display attributes of members.
+ */
+ public static final String DISPLAY_ATTRIBUTES = "$displayattributes"; //$NON-NLS-1$
+
+ /* class's static init */
+ static
+ {
+ // set up for localizing messages
+ m_localizationManager.addLocalizer( new DebuggerLocalizer("flex.tools.debugger.cli.fdb.") ); //$NON-NLS-1$
+ }
+
+ public static void main(String[] args)
+ {
+ DebugCLI cli = new DebugCLI();
+
+ /* attach our 'main' input method and out/err*/
+ cli.m_err = System.err;
+ cli.m_out = System.out;
+
+ // get the default <application.home>/projects/frameworks/*/src entries into the source path
+ cli.initSourceDirectoriesList();
+
+ // a big of wrangling for our keyboard input stream since its special
+ cli.m_keyboardStream = new LineNumberReader(new InputStreamReader(System.in));
+ cli.pushStream(cli.m_keyboardStream);
+
+ /* iterate through the args list */
+ cli.processArgs(args);
+
+ /* figure out $HOME and the current directory */
+ String userHome = System.getProperty("user.home"); //$NON-NLS-1$
+ String userDir = System.getProperty("user.dir"); //$NON-NLS-1$
+
+ /*
+ * If the current directory is not $HOME, and a .fdbinit file exists in the current directory,
+ * then push it onto the stack of files to read.
+ *
+ * Note, we want ./.fdbinit to be read AFTER $HOME/.fdbinit, but we push them in reverse
+ * order, because they're going onto a stack. If we push them in reverse order, then they
+ * will be read in the correct order (last one pushed is the first one read).
+ */
+ if (userDir != null && !userDir.equals(userHome))
+ {
+ try
+ {
+ FileReader sr = new FileReader(new File(userDir, ".fdbinit")); //$NON-NLS-1$
+ cli.pushStream( new LineNumberReader(sr) );
+ }
+ catch(FileNotFoundException fnf) {}
+ }
+
+ /*
+ * If a .fdbinit file exists in the $HOME directory, then push it onto the stack of files
+ * to read.
+ *
+ * Note, we want ./.fdbinit to be read AFTER $HOME/.fdbinit, but we push them in reverse
+ * order, because they're going onto a stack. If we push them in reverse order, then they
+ * will be read in the correct order (last one pushed is the first one read).
+ */
+ if (userHome != null)
+ {
+ try
+ {
+ FileReader sr = new FileReader(new File(userHome, ".fdbinit")); //$NON-NLS-1$
+ cli.pushStream( new LineNumberReader(sr) );
+ }
+ catch(FileNotFoundException fnf) {}
+ }
+
+ cli.execute();
+ }
+
+ public DebugCLI()
+ {
+ m_fullnameOption = false;
+ m_faultTable = faultActionsBuilder.build();
+ m_exprCache = new ExpressionCache(this);
+ m_breakpoints = new Vector<BreakAction>();
+ m_watchpoints = new Vector<WatchAction>();
+ m_catchpoints = new Vector<CatchAction>();
+ m_displays = new ArrayList<DisplayAction>();
+ m_keyboardInput = new Vector<String>();
+ m_mruURI = null;
+ m_sourceDirectories = new LinkedList<String>();
+
+ initProperties();
+ m_mainState = new DebugCLIIsolateState(this);
+ m_lastPromptIsolate = -1;
+ initIsolateState();
+ }
+
+ public static LocalizationManager getLocalizationManager() { return m_localizationManager; }
+ public Session getSession() { return m_session; }
+
+ public FileInfoCache getFileCache() {
+ return m_fileInfo;
+ }
+
+ /**
+ * Convert a module to class name. This is used
+ * by the ExpressionCache to find variables
+ * that live at royale package scope. That
+ * is variables such as mx.core.Component.
+ */
+ public String module2ClassName(int moduleId)
+ {
+ String pkg = null;
+ try
+ {
+ SourceFile file = m_fileInfo.getFile(moduleId);
+ pkg = file.getPackageName();
+ }
+ catch(Exception npe)
+ {
+ // didn't work ignore it.
+ }
+ return pkg;
+ }
+
+ LineNumberReader popStream() { return m_readerStack.pop(); }
+ public void pushStream(LineNumberReader r) { m_readerStack.push(r); }
+ boolean haveStreams() { return !m_readerStack.empty(); }
+
+ public void processArgs(String[] args)
+ {
+ for(int i=0; i<args.length; i++)
+ {
+ String arg = args[i];
+// System.out.println("arg["+i+"]= '"+arg+"'");
+ if (arg.charAt(0) == '-')
+ {
+ // its an option
+ if (arg.equals("-unit")) // unit-testing mode //$NON-NLS-1$
+ {
+ System.setProperty("fdbunit", ""); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ else if (arg.equals("-fullname") || arg.equals("-f")) //$NON-NLS-1$ //$NON-NLS-2$
+ {
+ m_fullnameOption = true; // emacs mode
+ }
+ else if (arg.equals("-cd")) //$NON-NLS-1$
+ {
+ // consume the path
+ if (i+1 < args.length)
+ m_cdPath = args[i++];
+ }
+ else if (arg.equals("-p")) //$NON-NLS-1$
+ {
+ // consume the port
+ if (i+1 < args.length)
+ m_connectPort = args[++i];
+ }
+ else
+ {
+ err("Unknown command-line argument: " + arg); //$NON-NLS-1$
+ }
+ }
+ else
+ {
+ // its a URI to run
+ StringReader sr = new StringReader("run "+arg+m_newline); //$NON-NLS-1$
+ pushStream( new LineNumberReader(sr) );
+ }
+ }
+ }
+
+ /**
+ * Dispose of the current line and read the next from the current stream, if its an empty
+ * line and we are console then repeat last line.
+ */
+ protected String readLine() throws IOException
+ {
+ String line = null;
+ if (haveStreams())
+ line = m_in.readLine();
+ else
+ line = keyboardReadLine();
+
+ setCurrentLine(line);
+ return line;
+ }
+
+ /**
+ * The reader portion of our keyboard input routine
+ * Block until input arrives.
+ */
+ synchronized String keyboardReadLine()
+ {
+ // enable a request then block on the queue
+ m_keyboardReadRequest = true;
+ try { wait(); } catch(InterruptedException ie) {}
+
+ // pull from the front of the queue
+ return m_keyboardInput.remove(0);
+ }
+
+ /**
+ * A seperate thread collects our input so that we can
+ * block in the doContinue on the main thread and then
+ * allow the user to interrupt us via keyboard input
+ * on this thread.
+ *
+ * We built the stupid thing in this manner, since readLine()
+ * will block no matter what and if we 'quit' we can't
+ * seem to kill this thread. .close() doesn't work
+ * and Thread.stop(), etc. all fail to do the job.
+ *
+ * Thus we needed to take a request response approach
+ * so that we only block when requested to do so.
+ */
+ public void run()
+ {
+ // while we have this stream
+ while(m_keyboardStream != null)
+ {
+ try
+ {
+ // only if someone is requesting us to read do we do so...
+ if (m_keyboardReadRequest)
+ {
+ // block on keyboard input and put it onto the end of the queue
+ String s = m_keyboardStream.readLine();
+ m_keyboardInput.add(s);
+
+ // fullfilled request, now notify blocking thread.
+ m_keyboardReadRequest = false;
+ synchronized(this) { notifyAll(); }
+ }
+ else
+ try { Thread.sleep(50); } catch(InterruptedException ie) {}
+ }
+ catch(IOException io)
+ {
+// io.printStackTrace();
+ }
+ }
+ }
+
+ public void setCurrentLine(String s)
+ {
+ m_currentLine = s;
+ if (m_currentLine == null)
+ m_currentTokenizer = null; /* eof */
+ else
+ {
+ m_currentLine = m_currentLine.trim();
+
+ /* if nothing provided on this command then pull our 'repeat' command */
+ if (m_repeatLine != null && !haveStreams() && m_currentLine.length() == 0)
+ m_currentLine = m_repeatLine;
+
+ m_currentTokenizer = new StringTokenizer(m_currentLine, " \n\r\t"); //$NON-NLS-1$
+ }
+ }
+
+ /* Helpers for extracting tokens from the current line */
+ public boolean hasMoreTokens() { return m_currentTokenizer.hasMoreTokens(); }
+ public String nextToken() { m_currentToken = m_currentTokenizer.nextToken(); return m_currentToken; }
+ public int nextIntToken() throws NumberFormatException { nextToken(); return Integer.parseInt(m_currentToken); }
+ public long nextLongToken() throws NumberFormatException { nextToken(); return Long.parseLong(m_currentToken); }
+ public String restOfLine() { return m_currentTokenizer.nextToken("").trim(); } //$NON-NLS-1$
+
+ public void execute()
+ {
+ /* dump console message */
+ displayStartMessage();
+
+ /* now fire our keyboard input thread */
+ Thread t = new Thread(this, "Keyboard input"); //$NON-NLS-1$
+ t.start();
+
+ /* keep processing streams until we have no more to do */
+ while(haveStreams())
+ {
+ try
+ {
+ m_in = popStream();
+ process();
+ }
+ catch(EOFException eof)
+ {
+ ; /* quite allright */
+ }
+ catch(IOException io)
+ {
+ Map<String, Object> args = new HashMap<String, Object>();
+ args.put("exceptionMessage", io); //$NON-NLS-1$
+ err(getLocalizationManager().getLocalizedTextString("errorWhileProcessingFile", args)); //$NON-NLS-1$
+ }
+ }
+
+ /* we done kill everything */
+ exitSession();
+
+ // clear this thing, which also halts our other thread.
+ m_keyboardStream = null;
+ }
+
+ public PrintStream getOut() { return m_out; }
+
+ private void displayStartMessage()
+ {
+ String build = getLocalizationManager().getLocalizedTextString("defaultBuildName"); //$NON-NLS-1$
+
+ try
+ {
+ Properties p = new Properties();
+ p.load(this.getClass().getResourceAsStream("version.properties")); //$NON-NLS-1$
+ String buildString = p.getProperty("build"); //$NON-NLS-1$
+ if ((buildString != null) && (! buildString.equals(""))) //$NON-NLS-1$
+ {
+ build = buildString;
+ }
+ }
+ catch (Throwable t)
+ {
+ // ignore
+ }
+
+ Map<String, Object> aboutMap = new HashMap<String, Object>(); aboutMap.put("build", build); //$NON-NLS-1$
+ out(getLocalizationManager().getLocalizedTextString("about", aboutMap)); //$NON-NLS-1$
+ out(getLocalizationManager().getLocalizedTextString("copyright")); //$NON-NLS-1$
+ }
+
+ void displayPrompt()
+ {
+ m_out.print("(fdb) "); //$NON-NLS-1$
+ }
+
+ void displayCommandPrompt()
+ {
+ m_out.print(">"); //$NON-NLS-1$
+ }
+
+ // add the given character n times to sb
+ void repeat(StringBuilder sb, char c, int n)
+ {
+ while(n-- > 0)
+ sb.append(c);
+ }
+
+ // Prompt the user to respond to a yes or no type question
+ boolean yesNoQuery(String prompt) throws IOException
+ {
+ boolean result = false;
+ m_out.print(prompt);
+ m_out.print(getLocalizationManager().getLocalizedTextString("yesOrNoAppendedToAllQuestions")); //$NON-NLS-1$
+
+ String in = readLine();
+ if (in != null && in.equals(getLocalizationManager().getLocalizedTextString("singleCharacterUserTypesForYes"))) //$NON-NLS-1$
+ result = true;
+ else if (in != null && in.equals("escape")) //$NON-NLS-1$
+ throw new IllegalArgumentException("escape"); //$NON-NLS-1$
+ else
+ out(getLocalizationManager().getLocalizedTextString("yesNoQueryNotConfirmed")); //$NON-NLS-1$
+ return result;
+ }
+
+ public void err(String s)
+ {
+ // Doesn't make sense to send messages to stderr, because this is
+ // an interactive application; and besides that, sending a combination
+ // of interwoven but related messages to both stdout and stderr causes
+ // the output to be in the wrong order sometimes.
+ out(s);
+ }
+
+ public void out(String s)
+ {
+ if (s.length() > 0 && (s.charAt(s.length()-1) == '\n') )
+ m_out.print(s);
+ else
+ m_out.println(s);
+ }
+
+ static String uft()
+ {
+ Runtime rt = Runtime.getRuntime();
+ long free = rt.freeMemory(), total = rt.totalMemory(), used = total - free;
+// long max = rt.maxMemory();
+ java.text.NumberFormat nf = java.text.NumberFormat.getInstance() ;
+// System.out.println("used: "+nf.format(used)+" free: "+nf.format(free)+" total: "+nf.format(total)+" max: "+nf.format(max));
+ return "Used "+nf.format(used)+" - free "+nf.format(free)+" - total "+nf.format(total); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ }
+
+ /**
+ * Add all properties that we know about
+ */
+ void initProperties()
+ {
+ propertyPut(LIST_SIZE, 10);
+ propertyPut(LIST_LINE, 1);
+ propertyPut(LIST_MODULE, 1); // default to module #1
+ propertyPut(LIST_WORKER, Isolate.DEFAULT_ID);
+ propertyPut(COLUMN_WIDTH, 70);
+ propertyPut(UPDATE_DELAY, 25);
+ propertyPut(HALT_TIMEOUT, 7000);
+ propertyPut(BPNUM, 0); // set current breakpoint number as something bad
+ propertyPut(LAST_FRAME_DEPTH, 0); // used to determine how much context information should be displayed
+ propertyPut(CURRENT_FRAME_DEPTH, 0); // used to determine how much context information should be displayed
+ propertyPut(DISPLAY_FRAME_NUMBER, 0); // houses the current frame we are viewing
+ propertyPut(FILE_LIST_WRAP, 999999); // default 1 file name per line
+ propertyPut(NO_WAITING, 0);
+ propertyPut(INFO_STACK_SHOW_THIS, 1); // show this pointer for info stack
+ }
+
+ // getter/setter for properties; in the expression cache, so that they can be used in expressions!
+ public void propertyPut(String k, int v) { m_exprCache.put(k,v); }
+ public int propertyGet(String k) { return ((Integer)m_exprCache.get(k)).intValue(); }
+ public Set<String> propertyKeys() { return m_exprCache.keySet(); }
+
+ /**
+ * Process this reader until its done
+ */
+ void process() throws IOException
+ {
+ boolean done = false;
+ while(!done)
+ {
+ try
+ {
+ /**
+ * Now if we are in a session and that session is suspended then we go
+ * into a state where we wait for some user interaction to get us out
+ */
+ runningLoop();
+
+ /* if we are in the stdin then put out a prompt */
+ if (!haveStreams())
+ displayPrompt();
+
+ /* now read in the next line */
+ readLine();
+ if (m_currentLine == null)
+ break;
+
+ done = processLine();
+ }
+ catch(NoResponseException nre)
+ {
+ err(getLocalizationManager().getLocalizedTextString("noResponseException")); //$NON-NLS-1$
+ }
+ catch(NotSuspendedException nse)
+ {
+ err(getLocalizationManager().getLocalizedTextString("notSuspendedException")); //$NON-NLS-1$
+ }
+ catch(AmbiguousException ae)
+ {
+ // we already put up a warning for the user
+ }
+ catch(IllegalStateException ise)
+ {
+ err(getLocalizationManager().getLocalizedTextString("illegalStateException")); //$NON-NLS-1$
+ }
+ catch(IllegalMonitorStateException ime)
+ {
+ err(getLocalizationManager().getLocalizedTextString("illegalMonitorStateException")); //$NON-NLS-1$
+ }
+ catch(NoSuchElementException nse)
+ {
+ err(getLocalizationManager().getLocalizedTextString("noSuchElementException")); //$NON-NLS-1$
+ }
+ catch(NumberFormatException nfe)
+ {
+ err(getLocalizationManager().getLocalizedTextString("numberFormatException")); //$NON-NLS-1$
+ }
+ catch(SocketException se)
+ {
+ Map<String, Object> socketArgs = new HashMap<String, Object>();
+ socketArgs.put("message", se.getMessage()); //$NON-NLS-1$
+ err(getLocalizationManager().getLocalizedTextString("socketException", socketArgs)); //$NON-NLS-1$
+ }
+ catch(VersionException ve)
+ {
+ err(getLocalizationManager().getLocalizedTextString("versionException")); //$NON-NLS-1$
+ }
+ catch(NotConnectedException nce)
+ {
+ // handled by isConnectionLost()
+ }
+ catch(Exception e)
+ {
+ err(getLocalizationManager().getLocalizedTextString("unexpectedError")); //$NON-NLS-1$
+ err(getLocalizationManager().getLocalizedTextString("stackTraceFollows")); //$NON-NLS-1$
+ e.printStackTrace();
+ }
+
+ // check for a lost connection and if it is clean-up!
+ if (isConnectionLost())
+ {
+ try
+ {
+ dumpHaltState(false);
+ }
+ catch(PlayerDebugException pde)
+ {
+ err(getLocalizationManager().getLocalizedTextString("sessionEndedAbruptly")); //$NON-NLS-1$
+ }
+ }
+ }
+ }
+
+ // check if we have lost the connect without our help...
+ boolean isConnectionLost()
+ {
+ boolean lost = false;
+
+ if (m_session != null && !m_session.isConnected())
+ lost = true;
+
+ return lost;
+ }
+
+ boolean haveConnection()
+ {
+ boolean have = false;
+
+ if (m_session != null && m_session.isConnected())
+ have = true;
+
+ return have;
+ }
+
+ void doShow() throws AmbiguousException, PlayerDebugException
+ {
+ /* show without any args brings up help */
+ if (!hasMoreTokens())
+ out( getHelpTopic("show") ); //$NON-NLS-1$
+ else
+ {
+ /* otherwise we have a boatload of options */
+ String subCmdString = nextToken();
+ int subCmd = showCommandFor(subCmdString);
+ switch(subCmd)
+ {
+ case SHOW_NET_CMD:
+ doShowStats();
+ break;
+
+ case SHOW_FUNC_CMD:
+ doShowFuncs();
+ break;
+
+ case SHOW_URI_CMD:
+ doShowUri();
+ break;
+
+ case SHOW_PROPERTIES_CMD:
+ doShowProperties();
+ break;
+
+ case SHOW_FILES_CMD:
+ doShowFiles();
+ break;
+
+ case SHOW_BREAK_CMD:
+ doShowBreak();
+ break;
+
+ case SHOW_VAR_CMD:
+ doShowVariable();
+ break;
+
+ case SHOW_MEM_CMD:
+ doShowMemory();
+ break;
+
+ case SHOW_LOC_CMD:
+ doShowLocations();
+ break;
+
+ case SHOW_DIRS_CMD:
+ doShowDirectories();
+ break;
+
+ default:
+ doUnknown("show", subCmdString); //$NON-NLS-1$
+ break;
+ }
+ }
+ }
+
+ void doShowUri()
+ {
+ // dump the URI that the player has sent us
+ try
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.append("URI = "); //$NON-NLS-1$
+ sb.append( m_session.getURI() );
+ out( sb.toString() );
+ }
+ catch(Exception e)
+ {
+ err(getLocalizationManager().getLocalizedTextString("noUriReceived")); //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * Dump the content of files in a raw format
+ */
+ void doShowFiles()
+ {
+ try
+ {
+ StringBuilder sb = new StringBuilder();
+ for (Isolate isolate : m_session.getWorkers()) {
+
+ Iterator itr = m_fileInfo.getAllFiles(isolate.getId());
+
+ while(itr.hasNext())
+ {
+ SourceFile m = (SourceFile) ((Map.Entry)itr.next()).getValue();
+
+ String name = m.getName();
+ int id = m.getId();
+ String path = m.getFullPath();
+
+ sb.append(id);
+ sb.append(' ');
+ sb.append(path);
+ sb.append(", "); //$NON-NLS-1$
+ sb.append(name);
+ sb.append(" ("); //$NON-NLS-1$
+ if (isolate.getId() == Isolate.DEFAULT_ID) {
+ sb.append(getLocalizationManager().getLocalizedTextString("mainThread")); //$NON-NLS-1$
+ }
+ else {
+ HashMap<String, Object> wArgs = new HashMap<String, Object>();
+ wArgs.put("worker", isolate.getId() - 1); //$NON-NLS-1$
+ sb.append(getLocalizationManager().getLocalizedTextString("inWorker", wArgs)); //$NON-NLS-1$
+ }
+ sb.append(")"); //$NON-NLS-1$
+ sb.append(m_newline);
+ }
+ }
+ out( sb.toString() );
+ }
+ catch(NullPointerException npe)
+ {
+ err(getLocalizationManager().getLocalizedTextString("noSourceFilesFound")); //$NON-NLS-1$
+ }
+ }
+
+ void doShowMemory()
+ {
+ out(uft());
+ }
+
+ void doShowLocations()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.append("Num Type Disp Enb Address What"+m_newline); //$NON-NLS-1$
+
+ // our list of breakpoints
+ int count = breakpointCount();
+ for(int i=0; i<count; i++)
+ {
+ BreakAction b = breakpointAt(i);
+ int num = b.getId();
+
+ FieldFormat.formatLong(sb, num, 3);
+ sb.append(" breakpoint "); //$NON-NLS-1$
+
+ if (b.isAutoDisable())
+ sb.append("dis "); //$NON-NLS-1$
+ else if (b.isAutoDelete())
+ sb.append("del "); //$NON-NLS-1$
+ else
+ sb.append("keep "); //$NON-NLS-1$
+
+ if (b.isEnabled())
+ sb.append("y "); //$NON-NLS-1$
+ else
+ sb.append("n "); //$NON-NLS-1$
+
+ Iterator<Location> itr = b.getLocations().iterator();
+ while(itr.hasNext())
+ {
+ Location l = itr.next();
+ SourceFile file = l.getFile();
+ String funcName = (file == null)
+ ? getLocalizationManager().getLocalizedTextString("unknownBreakpointLocation") //$NON-NLS-1$
+ : file.getFunctionNameForLine(m_session, l.getLine()) ;
+ int offset = adjustOffsetForUnitTests((file == null) ? 0 : file.getOffsetForLine(l.getLine()));
+
+ sb.append("0x"); //$NON-NLS-1$
+ FieldFormat.formatLongToHex(sb, offset, 8);
+ sb.append(' ');
+
+ if (funcName != null)
+ {
+ Map<String, Object> funcArgs = new HashMap<String, Object>();
+ funcArgs.put("functionName", funcName); //$NON-NLS-1$
+ sb.append(getLocalizationManager().getLocalizedTextString("inFunctionAt", funcArgs)); //$NON-NLS-1$
+ }
+
+ sb.append(file.getName());
+ if (file != null)
+ {
+ sb.append("#"); //$NON-NLS-1$
+ sb.append(file.getId());
+ }
+ sb.append(':');
+ sb.append(l.getLine());
+
+ try
+ {
+ SwfInfo info = m_fileInfo.swfForFile(file, l.getIsolateId());
+ Map<String, Object> swfArgs = new HashMap<String, Object>();
+ swfArgs.put("swf", FileInfoCache.shortNameOfSwf(info)); //$NON-NLS-1$
+ sb.append(getLocalizationManager().getLocalizedTextString("inSwf", swfArgs)); //$NON-NLS-1$
+ if (l.getIsolateId() == Isolate.DEFAULT_ID) {
+ sb.append(" ("); //$NON-NLS-1$
+ sb.append(getLocalizationManager().getLocalizedTextString("mainThread")); //$NON-NLS-1$
+ sb.append(")"); //$NON-NLS-1$
+ }
+ else {
+ swfArgs = new HashMap<String, Object>();
+ swfArgs.put("worker", l.getIsolateId() - 1); //$NON-NLS-1$
+ sb.append(" ("); //$NON-NLS-1$
+ sb.append(getLocalizationManager().getLocalizedTextString("inWorker", swfArgs)); //$NON-NLS-1$
+ sb.append(")"); //$NON-NLS-1$
+ }
+ }
+ catch(NullPointerException npe)
+ {
+ // can't find the swf
+ sb.append(getLocalizationManager().getLocalizedTextString("nonRestorable")); //$NON-NLS-1$
+ }
+ sb.append(m_newline);
+ if (itr.hasNext())
+ sb.append(" "); //$NON-NLS-1$
+ }
+ }
+ out(sb.toString());
+ }
+
+ /**
+ * When running unit tests, we want byte offsets into the file to
+ * always be displayed as zero, so that the unit test expected
+ * results will match up with the actual results. This is just a
+ * simple helper function that deals with that.
+ */
+ private int adjustOffsetForUnitTests(int offset)
+ {
+ if (System.getProperty("fdbunit")==null) //$NON-NLS-1$
+ return offset;
+ else
+ return 0;
+ }
+
+ void doShowDirectories()
+ {
+ out(getLocalizationManager().getLocalizedTextString("sourceDirectoriesSearched")); //$NON-NLS-1$
+ Iterator<String> iter = m_sourceDirectories.iterator();
+ while (iter.hasNext())
+ {
+ String dir = iter.next();
+ out(" " + dir); //$NON-NLS-1$
+ }
+ }
+
+ void doHalt() throws SuspendedException, NotConnectedException, NoResponseException
+ {
+ out(getLocalizationManager().getLocalizedTextString("attemptingToSuspend")); //$NON-NLS-1$
+ IsolateSession session = m_session.getWorkerSession(getActiveIsolateId());
+ if (!session.isSuspended())
+ session.suspend();
+ if (session.isSuspended())
+ out(getLocalizationManager().getLocalizedTextString("playerStopped")); //$NON-NLS-1$
+ else
+ out(getLocalizationManager().getLocalizedTextString("playerRunning")); //$NON-NLS-1$
+ }
+
+ public void appendReason(StringBuilder sb, int reason)
+ {
+ switch(reason)
+ {
+ case SuspendReason.Unknown:
+ sb.append(getLocalizationManager().getLocalizedTextString("suspendReason_Unknown")); //$NON-NLS-1$
+ break;
+
+ case SuspendReason.Breakpoint:
+ sb.append(getLocalizationManager().getLocalizedTextString("suspendReason_HitBreakpoint")); //$NON-NLS-1$
+ break;
+
+ case SuspendReason.Watch:
+ sb.append(getLocalizationManager().getLocalizedTextString("suspendReason_HitWatchpoint")); //$NON-NLS-1$
+ break;
+
+ case SuspendReason.Fault:
+ sb.append(getLocalizationManager().getLocalizedTextString("suspendReason_ProgramThrewException")); //$NON-NLS-1$
+ break;
+
+ case SuspendReason.StopRequest:
+ sb.append(getLocalizationManager().getLocalizedTextString("suspendReason_StopRequest")); //$NON-NLS-1$
+ break;
+
+ case SuspendReason.Step:
+ sb.append(getLocalizationManager().getLocalizedTextString("suspendReason_ProgramFinishedStepping")); //$NON-NLS-1$
+ break;
+
+ case SuspendReason.HaltOpcode:
+ sb.append(getLocalizationManager().getLocalizedTextString("suspendReason_HaltOpcode")); //$NON-NLS-1$
+ break;
+
+ case SuspendReason.ScriptLoaded:
+ sb.append(getLocalizationManager().getLocalizedTextString("suspendReason_ScriptHasLoadedIntoFlashPlayer")); //$NON-NLS-1$
+ break;
+ }
+ }
+
+ /**
+ * The big ticket item, where all your questions are answered.
+ *
+ */
+ void doInfo() throws AmbiguousException, PlayerDebugException
+ {
+ /* info without any args brings up help */
+ if (!hasMoreTokens())
+ out( getHelpTopic("info") ); //$NON-NLS-1$
+ else
+ {
+ /* otherwise we have a boatload of options */
+ String subCmdString = nextToken();
+ int subCmd = infoCommandFor(subCmdString);
+ switch(subCmd)
+ {
+ case INFO_ARGS_CMD:
+ doInfoArgs();
+ break;
+
+ case INFO_BREAK_CMD:
+ doInfoBreak();
+ break;
+
+ case INFO_FILES_CMD:
+ doInfoFiles();
+ break;
+
+ case INFO_FUNCTIONS_CMD:
+ doInfoFuncs();
+ break;
+
+ case INFO_HANDLE_CMD:
+ doInfoHandle();
+ break;
+
+ case INFO_LOCALS_CMD:
+ doInfoLocals();
+ break;
+
+ case INFO_SCOPECHAIN_CMD:
+ doInfoScopeChain();
+ break;
+
+ case INFO_SOURCES_CMD:
+ doInfoSources();
+ break;
+
+ case INFO_STACK_CMD:
+ doInfoStack();
+ break;
+
+ case INFO_VARIABLES_CMD:
+ doInfoVariables();
+ break;
+
+ case INFO_DISPLAY_CMD:
+ doInfoDisplay();
+ break;
+
+ case INFO_TARGETS_CMD:
+ doInfoTargets();
+ break;
+
+ case INFO_SWFS_CMD:
+ doInfoSwfs();
+ break;
+
+ case INFO_WORKERS_CMD:
+ doInfoWorkers();
+ break;
+
+ default:
+ doUnknown("info", subCmdString); //$NON-NLS-1$
+ break;
+ }
+ }
+ }
+
+ void doInfoWorkers() throws NotConnectedException, NotSupportedException, NotSuspendedException, NoResponseException
+ {
+// waitTilHalted();
+ Isolate[] isolates = m_session.getWorkers();
+ if (isolates == null || isolates.length == 0) {
+ out(getLocalizationManager().getLocalizedTextString("noWorkersRunning")); //$NON-NLS-1$
+ return;
+ }
+ StringBuilder sb = new StringBuilder();
+ for (Isolate t : isolates) {
+ String status = getLocalizationManager().getLocalizedTextString("workerRunning"); //$NON-NLS-1$
+ if (m_session.getWorkerSession(t.getId()).isSuspended()) {
+ status = getLocalizationManager().getLocalizedTextString("workerSuspended"); //$NON-NLS-1$
+ }
+ if (m_activeIsolate == t.getId()) {
+ status += " " + getLocalizationManager().getLocalizedTextString("workerSelected"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ if (t.getId() == Isolate.DEFAULT_ID) {
+ sb.append(getLocalizationManager().getLocalizedTextString("mainThread")); //$NON-NLS-1$
+ sb.append(" "); //$NON-NLS-1$
+ sb.append(Isolate.DEFAULT_ID - 1);
+ }
+ else {
+ HashMap<String, Object> workArgs = new HashMap<String, Object>();
+ workArgs.put("worker", (t.getId() - 1)); //$NON-NLS-1$
+ sb.append(getLocalizationManager().getLocalizedTextString("inWorker", workArgs)); //$NON-NLS-1$
+ }
+ sb.append(" - " + status + m_newline); //$NON-NLS-1$
+ }
+ out(sb.toString());
+ }
+
+
+ void doInfoStack() throws PlayerDebugException
+ {
+ waitTilHalted(m_activeIsolate);
+
+ StringBuilder sb = new StringBuilder();
+ Frame[] stack = m_session.getWorkerSession(m_activeIsolate).getFrames();
+ if (stack == null || stack.length == 0)
+ sb.append(getLocalizationManager().getLocalizedTextString("noStackAvailable")); //$NON-NLS-1$
+ else
+ {
+ boolean showThis = propertyGet(INFO_STACK_SHOW_THIS) == 1;
+ for(int i=0; i<stack.length; i++)
+ {
+ // keep spitting out frames until we can't
+ Frame frame = stack[i];
+ boolean valid = appendFrameInfo(sb, frame, i, showThis, false);
+ sb.append(m_newline);
+ if (!valid)
+ break;
+ }
+ }
+
+ /* dump it out */
+ out(sb.toString());
+ }
+
+ /**
+ * Spit out frame information for a given frame number
+ */
+ boolean appendFrameInfo(StringBuilder sb, Frame ctx, int frameNumber, boolean showThis, boolean showFileId) throws PlayerDebugException
+ {
+ boolean validFrame = true;
+
+ // some formatting properties
+ int i = frameNumber;
+
+ Location loc = ctx.getLocation();
+ SourceFile file = loc.getFile();
+ int line = loc.getLine();
+ String name = (file == null) ? "<null>" : file.getName(); //$NON-NLS-1$
+ String sig = ctx.getCallSignature();
+ String func = extractFunctionName(sig);
+
+ // file == null or line < 0 appears to be a terminator for stack info
+ if (file == null && line < 0)
+ {
+ validFrame = false;
+ }
+ else
+ {
+ Variable[] var = ctx.getArguments(m_session);
+ Variable dis = ctx.getThis(m_session);
+ boolean displayArgs = (func != null) || (var != null);
+
+ sb.append('#');
+ FieldFormat.formatLong(sb, i, 3);
+ sb.append(' ');
+
+ if (showThis && dis != null)
+ {
+ ExpressionCache.appendVariable(sb, dis, ctx.getIsolateId());
+ sb.append("."); //$NON-NLS-1$
+ }
+
+ if (func != null)
+ sb.append(func);
+
+ if (displayArgs)
+ {
+ sb.append('(');
+ for (int j=0; j<var.length; j++)
+ {
+ Variable v = var[j];
+ sb.append(v.getName());
+ sb.append('=');
+ ExpressionCache.appendVariableValue(sb, v.getValue(), ctx.getIsolateId());
+ if ((j+1)<var.length)
+ sb.append(", "); //$NON-NLS-1$
+ }
+ sb.append(")"); //$NON-NLS-1$
+ sb.append(getLocalizationManager().getLocalizedTextString("atFilename")); //$NON-NLS-1$
+ }
+
+ sb.append(name);
+
+ // if this file is currently being filtered put the source file id after it
+ if (file != null && (showFileId || !m_fileInfo.inFileList(file)))
+ {
+ sb.append('#');
+ sb.append( file.getId() );
+
+ }
+ sb.append(':');
+ sb.append(line);
+ }
+ return validFrame;
+ }
+
+ /** extract the function name from a signature */
+ public static String extractFunctionName(String sig)
+ {
+ // strip everything after the leading (
+ int at = sig.indexOf('(');
+ if (at > -1)
+ sig = sig.substring(0, at);
+
+ // trim the leading [object_name::] since it doesn't seem to add much
+ if (sig != null && (at = sig.indexOf("::")) > -1) //$NON-NLS-1$
+ sig = sig.substring(at+2);
+
+ return sig;
+ }
+
+ void doInfoVariables() throws PlayerDebugException
+ {
+ waitTilHalted(m_activeIsolate);
+
+ // dump a set of locals
+ StringBuilder sb = new StringBuilder();
+
+ // use our expression cache formatting routine
+ try
+ {
+ Variable[] vars = m_session.getWorkerSession(m_activeIsolate).getVariableList();
+ for(int i=0; i<vars.length; i++)
+ {
+ Variable v = vars[i];
+
+ // all non-local and non-arg variables
+ if ( !v.isAttributeSet(VariableAttribute.IS_LOCAL) &&
+ !v.isAttributeSet(VariableAttribute.IS_ARGUMENT) )
+ {
+ ExpressionCache.appendVariable(sb, vars[i], m_activeIsolate);
+ sb.append(m_newline);
+ }
+ }
+ }
+ catch(NullPointerException npe)
+ {
+ sb.append(getLocalizationManager().getLocalizedTextString("noVariables")); //$NON-NLS-1$
+ }
+
+ out(sb.toString());
+ }
+
+ void doInfoDisplay()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.append("Num Enb Expression"+m_newline); //$NON-NLS-1$
+
+ // our list of displays
+ int count = displayCount();
+ for(int i=0; i<count; i++)
+ {
+ DisplayAction b = displayAt(i);
+ int num = b.getId();
+ String exp = b.getContent();
+
+ sb.append(':');
+ FieldFormat.formatLong(sb, num, 3);
+
+ if (b.isEnabled())
+ sb.append(" y "); //$NON-NLS-1$
+ else
+ sb.append(" n "); //$NON-NLS-1$
+
+ sb.append(exp);
+ sb.append(m_newline);
+ }
+
+ out(sb.toString());
+ }
+
+ void doInfoArgs() throws PlayerDebugException
+ {
+ waitTilHalted(m_activeIsolate);
+
+ // dump a set of locals
+ StringBuilder sb = new StringBuilder();
+
+ // use our expression cache formatting routine
+ try
+ {
+ int num = propertyGet(DISPLAY_FRAME_NUMBER);
+ Frame[] frames = m_session.getWorkerSession(m_activeIsolate).getFrames();
+ Variable[] vars = frames[num].getArguments(m_session);
+ for(int i=0; i<vars.length; i++)
+ {
+ ExpressionCache.appendVariable(sb, vars[i], m_activeIsolate);
+ sb.append(m_newline);
+ }
+ }
+ catch(NullPointerException npe)
+ {
+ sb.append(getLocalizationManager().getLocalizedTextString("noArguments")); //$NON-NLS-1$
+ }
+ catch(ArrayIndexOutOfBoundsException aix)
+ {
+ sb.append(getLocalizationManager().getLocalizedTextString("notInValidFrame")); //$NON-NLS-1$
+ }
+
+ out(sb.toString());
+ }
+
+ void doInfoLocals() throws PlayerDebugException
+ {
+ waitTilHalted(m_activeIsolate);
+
+ // dump a set of locals
+ StringBuilder sb = new StringBuilder();
+
+ // use our expression cache formatting routine
+ try
+ {
+ // get the variables from the requested frame
+ int num = propertyGet(DISPLAY_FRAME_NUMBER);
+ Frame[] ar = m_session.getWorkerSession(m_activeIsolate).getFrames();
+ Frame ctx = ar[num];
+ Variable[] vars = ctx.getLocals(m_session);
+
+ for(int i=0; i<vars.length; i++)
+ {
+ Variable v = vars[i];
+
+ // see if variable is local
+ if ( v.isAttributeSet(VariableAttribute.IS_LOCAL) )
+ {
+ ExpressionCache.appendVariable(sb, v, m_activeIsolate);
+ sb.append(m_newline);
+ }
+ }
+ }
+ catch(NullPointerException npe)
+ {
+ sb.append(getLocalizationManager().getLocalizedTextString("noLocals")); //$NON-NLS-1$
+ }
+ catch(ArrayIndexOutOfBoundsException aix)
+ {
+ sb.append(getLocalizationManager().getLocalizedTextString("notInValidFrame")); //$NON-NLS-1$
+ }
+
+ out(sb.toString());
+ }
+
+ void doInfoScopeChain() throws PlayerDebugException
+ {
+ waitTilHalted(m_activeIsolate);
+
+ // dump the scope chain
+ StringBuilder sb = new StringBuilder();
+
+ // use our expression cache formatting routine
+ try
+ {
+ // get the scope chainfrom the requested frame
+ int num = propertyGet(DISPLAY_FRAME_NUMBER);
+ Frame[] ar = m_session.getWorkerSession(m_activeIsolate).getFrames();
+ Frame ctx = ar[num];
+ Variable[] scopes = ctx.getScopeChain(m_session);
+
+ for(int i=0; i<scopes.length; i++)
+ {
+ Variable scope = scopes[i];
+ ExpressionCache.appendVariable(sb, scope, m_activeIsolate);
+ sb.append(m_newline);
+ }
+ }
+ catch(NullPointerException npe)
+ {
+ sb.append(getLocalizationManager().getLocalizedTextString("noScopeChain")); //$NON-NLS-1$
+ }
+ catch(ArrayIndexOutOfBoundsException aix)
+ {
+ sb.append(getLocalizationManager().getLocalizedTextString("notInValidFrame")); //$NON-NLS-1$
+ }
+
+ out(sb.toString());
+ }
+
+ void doInfoTargets()
+ {
+ if (!haveConnection())
+ {
+ out(getLocalizationManager().getLocalizedTextString("noActiveSession")); //$NON-NLS-1$
+ if (m_launchURI != null)
+ {
+ Map<String, Object> args = new HashMap<String, Object>();
+ args.put("uri", m_launchURI); //$NON-NLS-1$
+ out(getLocalizationManager().getLocalizedTextString("runWillLaunchUri", args)); //$NON-NLS-1$
+ }
+ }
+ else
+ {
+ String uri = m_session.getURI();
+ if (uri == null || uri.length() < 1)
+ err(getLocalizationManager().getLocalizedTextString("targetUnknown")); //$NON-NLS-1$
+ else
+ out(uri);
+ }
+ }
+
+ /**
+ * Dump some stats about our currently loaded swfs.
+ */
+ void doInfoSwfs()
+ {
+ try
+ {
+ StringBuilder sb = new StringBuilder();
+ SwfInfo[] swfs = m_fileInfo.getSwfs(m_activeIsolate);
+ for(int i=0; i<swfs.length; i++)
+ {
+ SwfInfo e = swfs[i];
+ if (e == null || e.isUnloaded())
+ continue;
+
+ Map<String, Object> args = new HashMap<String, Object>();
+ args.put("swfName", FileInfoCache.nameOfSwf(e)); //$NON-NLS-1$
+ args.put("size", NumberFormat.getInstance().format(e.getSwfSize())); //$NON-NLS-1$
+
+ try
+ {
+ int size = e.getSwdSize(m_session);
+
+ // our swd is loaded so let's comb through our
+ // list of scripts and locate the range of ids.
+ SourceFile[] files = e.getSourceList(m_session);
+ int max = Integer.MIN_VALUE;
+ int min = Integer.MAX_VALUE;
+ for(int j=0; j<files.length; j++)
+ {
+ SourceFile f = files[j];
+ int id = f.getId();
+ max = (id > max) ? id : max;
+ min = (id < min) ? id : min;
+ }
+
+ args.put("scriptCount", Integer.toString(e.getSourceCount(m_session))); //$NON-NLS-1$
+ args.put("min", Integer.toString(min)); //$NON-NLS-1$
+ args.put("max", Integer.toString(max)); //$NON-NLS-1$
+ args.put("plus", (e.isProcessingComplete()) ? "+" : ""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ args.put("moreInfo", (size==0) ? getLocalizationManager().getLocalizedTextString("remainingSourceBeingLoaded") : ""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ }
+ catch(InProgressException ipe)
+ {
+ sb.append(getLocalizationManager().getLocalizedTextString("debugInfoBeingLoaded")); //$NON-NLS-1$
+ }
+ args.put("url", e.getUrl()); //$NON-NLS-1$
+ sb.append(getLocalizationManager().getLocalizedTextString("swfInfo", args)); //$NON-NLS-1$
+ sb.append(m_newline);
+ }
+ out( sb.toString() );
+ }
+ catch(NullPointerException npe)
+ {
+ err(getLocalizationManager().getLocalizedTextString("noSWFs")); //$NON-NLS-1$
+ }
+ }
+
+ private static final int AUTHORED_FILE = 1; // a file that was created by the end user, e.g. MyApp.mxml
+ private static final int FRAMEWORK_FILE = 2; // a file from the Flex framework, e.g. mx.controls.Button.as, see FRAMEWORK_FILE_PACKAGES
+ private static final int SYNTHETIC_FILE = 3; // e.g. "<set up XML utilities.1>"
+ private static final int ACTIONS_FILE = 4; // e.g. "Actions for UIComponent: Frame 1 of Layer Name Layer 1"
+
+ private static final String[] FRAMEWORK_FILE_PACKAGES // package prefixes that we consider FRAMEWORK_FILEs
+ = new String[] {"mx","flex","text"}; // 'text' is Vellum (temporary) //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+
+ /**
+ * Given a file, guesses what type it is -- e.g. a file created by the end user,
+ * or a file from the Flex framework, etc.
+ */
+ private int getFileType(SourceFile sourceFile)
+ {
+ String name = sourceFile.getName();
+ String pkg = sourceFile.getPackageName();
+
+ if (name.startsWith("<") && name.endsWith(">") || name.equals("GeneratedLocale")) //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ return SYNTHETIC_FILE;
+
+ for (final String frameworkPkg : FRAMEWORK_FILE_PACKAGES )
+ {
+ // look for packages starting with pkgName
+ if (pkg.startsWith(frameworkPkg + '\\') ||
+ pkg.startsWith(frameworkPkg + '/') ||
+ pkg.equals(frameworkPkg))
+ {
+ return FRAMEWORK_FILE;
+ }
+ }
+
+ if (name.startsWith("Actions for")) //$NON-NLS-1$
+ return ACTIONS_FILE;
+
+ return AUTHORED_FILE;
+}
+
+ void buildFileList(StringBuilder sb, boolean authoredFilesOnly)
+ {
+ SourceFile[] ar = m_fileInfo.getFileList(m_activeIsolate);
+ if (ar == null)
+ {
+ err(getLocalizationManager().getLocalizedTextString("noSourceFilesFound")); //$NON-NLS-1$
+ return;
+ }
+
+ Vector<String> authoredFiles = new Vector<String>();
+ Vector<String> frameworkFiles = new Vector<String>();
+ Vector<String> syntheticFiles = new Vector<String>();
+ Vector<String> actionsFiles = new Vector<String>();
+
+ for (int i = 0; i < ar.length; i++)
+ {
+ SourceFile m = ar[i];
+ int fileType = getFileType(m);
+ int id = m.getId();
+// int fakeId = m_fileInfo.getFakeId(m);
+ String entry = m.getName() + "#" + id; //$NON-NLS-1$
+
+ switch (fileType)
+ {
+ case SYNTHETIC_FILE:
+ syntheticFiles.add(entry);
+ break;
+ case FRAMEWORK_FILE:
+ frameworkFiles.add(entry);
+ break;
+ case ACTIONS_FILE:
+ actionsFiles.add(entry);
+ break;
+ case AUTHORED_FILE:
+ authoredFiles.add(entry);
+ break;
+ }
+ }
+
+ int wrapAt = propertyGet(FILE_LIST_WRAP);
+
+ if (!authoredFilesOnly)
+ {
+ if (actionsFiles.size() > 0)
+ {
+ appendStrings(sb, actionsFiles, (actionsFiles.size() > wrapAt) );
+ }
+
+ if (frameworkFiles.size() > 0)
+ {
+ sb.append("---"+m_newline); //$NON-NLS-1$
+ appendStrings(sb, frameworkFiles, (frameworkFiles.size() > wrapAt) );
+ }
+
+ if (syntheticFiles.size() > 0)
+ {
+ sb.append("---"+m_newline); //$NON-NLS-1$
+ appendStrings(sb, syntheticFiles, (syntheticFiles.size() > wrapAt) );
+ }
+
+ sb.append("---"+m_newline); //$NON-NLS-1$
+ }
+
+ appendStrings(sb, authoredFiles, (authoredFiles.size() > wrapAt) );
+ }
+
+ /**
+ * Dump a list of strings contained a vector
+ * If flow is set then the strings are placed
+ * on a single line and wrapped at $columnwidth
+ */
+ void appendStrings(StringBuilder sb, Vector<String> v, boolean flow)
+ {
+ int count = v.size();
+ int width = 0;
+ int maxCol = propertyGet(COLUMN_WIDTH);
+
+ for (int i = 0; i < count; i++)
+ {
+ String s = v.get(i);
+ sb.append(s);
+
+ // too many of them, then wrap according to columnwidth
+ if (flow)
+ {
+ width += (s.length() + 2);
+ if (width >= maxCol)
+ {
+ sb.append(m_newline);
+ width = 0;
+ }
+ else
+ sb.append(", "); //$NON-NLS-1$
+ }
+ else
+ sb.append(m_newline);
+ }
+
+ // add a line feed for flow based
+ if (flow && width > 0)
+ sb.append(m_newline);
+ }
+
+ void doInfoFiles()
+ {
+ try
+ {
+ StringBuilder sb = new StringBuilder();
+ if (hasMoreTokens())
+ {
+ String arg = nextToken();
+ listFilesMatching(sb, arg);
+ }
+ else
+ {
+ buildFileList(sb, false);
+ }
+ out(sb.toString());
+ }
+ catch(NullPointerException npe)
+ {
+ throw new IllegalStateException();
+ }
+ }
+
+ public void waitForMetaData() throws InProgressException
+ {
+ // perform a query to see if our metadata has loaded
+ int metadatatries = propertyGet(METADATA_ATTEMPTS);
+ int maxPerCall = 8; // cap on how many attempt we make per call
+
+ int tries = Math.min(maxPerCall, metadatatries);
+ if (tries > 0)
+ {
+ int remain = metadatatries - tries; // assume all get used up
+
+ // perform the call and then update our remaining number of attempts
+ try
+ {
+ tries = waitForMetaData(tries);
+ remain = metadatatries - tries; // update our used count
+ }
+ catch(InProgressException ipe)
+ {
+ propertyPut(METADATA_ATTEMPTS, remain);
+ throw ipe;
+ }
+ }
+ }
+
+ /**
+ * Wait for the API to load function names, which
+ * exist in the form of external meta-data.
+ *
+ * Only do this tries times, then give up
+ *
+ * We wait period * attempts
+ */
+ public int waitForMetaData(int attempts) throws InProgressException
+ {
+ int start = attempts;
+ int period = propertyGet(METADATA_ATTEMPTS_PERIOD);
+ while(attempts > 0)
+ {
+ // are we done yet?
+ if (isMetaDataAvailable())
+ break;
+ else
+ try { attempts--; Thread.sleep(period); } catch(InterruptedException ie) {}
+ }
+
+ // throw exception if still not ready
+ if (!isMetaDataAvailable())
+ throw new InProgressException();
+
+ return start-attempts; // remaining number of tries
+ }
+
+ /**
+ * Ask each swf if metadata processing is complete
+ */
+ public boolean isMetaDataAvailable()
+ {
+ boolean allLoaded = true;
+ try
+ {
+ // we need to ask the session since our fileinfocache will hide the exception
+ SwfInfo[] swfs = m_session.getSwfs();
+ for(int i=0; i<swfs.length; i++)
+ {
+ // check if our processing is finished.
+ SwfInfo swf = swfs[i];
+ if (swf != null && !swf.isProcessingComplete())
+ {
+ allLoaded = false;
+ break;
+ }
+ }
+ }
+ catch(NoResponseException nre)
+ {
+ // ok we still need to wait for player to read the swd in
+ allLoaded = false;
+ }
+
+ // count the number of times we checked and it wasn't there
+ if (!allLoaded)
+ {
+ int count = propertyGet(METADATA_NOT_AVAILABLE);
+ count++;
+ propertyPut(METADATA_NOT_AVAILABLE, count);
+ }
+ else
+ {
+ // success so we reset our attempt counter
+ propertyPut(METADATA_ATTEMPTS, METADATA_RETRIES);
+ }
+ return allLoaded;
+ }
+
+ void doInfoHandle()
+ {
+ if (hasMoreTokens())
+ {
+ // user specified a fault
+ String faultName = nextToken();
+
+ // make sure we know about this one
+ if (!m_faultTable.exists(faultName))
+ err(getLocalizationManager().getLocalizedTextString("unrecognizedFault")); //$NON-NLS-1$
+ else
+ listFault(faultName);
+ }
+ else
+ {
+ // dump them all
+ StringBuilder sb = new StringBuilder();
+
+ appendFaultTitles(sb);
+
+ Object names[] = m_faultTable.names();
+ Arrays.sort(names);
+
+ for(int i=0; i<names.length; i++)
+ appendFault(sb, (String)names[i]);
+
+ out ( sb.toString() );
+ }
+ }
+
+ void doInfoFuncs()
+ {
+ StringBuilder sb = new StringBuilder();
+
+ String arg = null;
+
+ // we take an optional single arg which specifies a module
+ try
+ {
+ // let's wait a bit for the background load to complete
+ waitForMetaData();
+
+ if (hasMoreTokens())
+ {
+ arg = nextToken();
+ int id = arg.equals(".") ? propertyGet(LIST_MODULE) : parseFileArg(-1, arg); //$NON-NLS-1$
+
+ SourceFile m = m_fileInfo.getFile(id, m_activeIsolate);
+ listFunctionsFor(sb, m);
+ }
+ else
+ {
+ SourceFile[] ar = m_fileInfo.getFileList(m_activeIsolate);
+ if (ar == null)
+ err(getLocalizationManager().getLocalizedTextString("noSourceFilesFound")); //$NON-NLS-1$
+ else
+ {
+ for(int i = 0; ar != null && i < ar.length; i++)
+ {
+ SourceFile m = ar[i];
+ listFunctionsFor(sb, m);
+ }
+ }
+ }
+
+ out(sb.toString());
+ }
+ catch(NullPointerException npe)
+ {
+ err(getLocalizationManager().getLocalizedTextString("noFunctionsFound")); //$NON-NLS-1$
+ }
+ catch(ParseException pe)
+ {
+ err(pe.getMessage());
+ }
+ catch(NoMatchException nme)
+ {
+ err(nme.getMessage());
+ }
+ catch(AmbiguousException ae)
+ {
+ err(ae.getMessage());
+ }
+ catch(InProgressException ipe)
+ {
+ err(getLocalizationManager().getLocalizedTextString("functionListBeingPrepared")); //$NON-NLS-1$
+ }
+ }
+
+ void listFunctionsFor(StringBuilder sb, SourceFile m)
+ {
+ String[] names = m.getFunctionNames(m_session);
+ if (names == null)
+ return;
+
+ Arrays.sort(names);
+
+ Map<String, Object> args = new HashMap<String, Object>();
+ args.put("sourceFile", m.getName() + "#" + m.getId()); //$NON-NLS-1$ //$NON-NLS-2$
+ sb.append(getLocalizationManager().getLocalizedTextString("functionsInSourceFile", args)); //$NON-NLS-1$
+ sb.append(m_newline);
+
+ for (int j = 0; j < names.length; j++)
+ {
+ String fname = names[j];
+ sb.append(' ');
+ sb.append(fname);
+ sb.append(' ');
+ sb.append(m.getLineForFunctionName(m_session, fname));
+ sb.append(m_newline);
+ }
+ }
+
+ void listFilesMatching(StringBuilder sb, String match)
+ {
+ SourceFile[] sourceFiles = m_fileInfo.getFiles(match);
+
+ for (int j = 0; j < sourceFiles.length; j++)
+ {
+ SourceFile sourceFile = sourceFiles[j];
+ sb.append(sourceFile.getName());
+ sb.append('#');
+ sb.append(sourceFile.getId());
+ sb.append(m_newline);
+ }
+ }
+
+ void doInfoSources()
+ {
+ try
+ {
+ StringBuilder sb = new StringBuilder();
+ buildFileList(sb, true);
+ out(sb.toString());
+ }
+ catch(NullPointerException npe)
+ {
+ throw new IllegalStateException();
+ }
+ }
+
+ void doInfoBreak() throws NotConnectedException
+ {
+// waitTilHalted();
+
+ StringBuilder sb = new StringBuilder();
+ sb.append("Num Type Disp Enb Address What"+m_newline); //$NON-NLS-1$
+
+ int count = breakpointCount();
+ for(int i=0; i<count; i++)
+ {
+ BreakAction b = breakpointAt(i);
+ int status = b.getStatus();
+ boolean isResolved = (status == BreakAction.RESOLVED);
+ Location l = b.getLocation();
+ SourceFile file = (l != null) ? l.getFile() : null;
+ String funcName = (file == null) ? null : file.getFunctionNameForLine(m_session, l.getLine()) ;
+ boolean singleSwf = b.isSingleSwf();
+ int cmdCount = b.getCommandCount();
+ int hits = b.getHits();
+ String cond = b.getConditionString();
+ boolean silent = b.isSilent();
+ int offset = adjustOffsetForUnitTests((file == null) ? 0 : file.getOffsetForLine(l.getLine()));
+
+ int num = b.getId();
+ FieldFormat.formatLong(sb, num, 3);
+ sb.append(" breakpoint "); //$NON-NLS-1$
+
+ if (b.isAutoDisable())
+ sb.append("dis "); //$NON-NLS-1$
+ else if (b.isAutoDelete())
+ sb.append("del "); //$NON-NLS-1$
+ else
+ sb.append("keep "); //$NON-NLS-1$
+
+ if (b.isEnabled())
+ sb.append("y "); //$NON-NLS-1$
+ else
+ sb.append("n "); //$NON-NLS-1$
+
+ sb.append("0x"); //$NON-NLS-1$
+ FieldFormat.formatLongToHex(sb, offset, 8);
+ sb.append(' ');
+
+ if (funcName != null)
+ {
+ Map<String, Object> args = new HashMap<String, Object>();
+ args.put("functionName", funcName); //$NON-NLS-1$
+ sb.append(getLocalizationManager().getLocalizedTextString("inFunctionAt", args)); //$NON-NLS-1$
+ }
+
+ if (file != null)
+ {
+ sb.append(file.getName());
+ if (isResolved && singleSwf)
+ {
+ sb.append("#"); //$NON-NLS-1$
+ sb.append(file.getId());
+ }
+ sb.append(':');
+ sb.append(l.getLine());
+ }
+ else
+ {
+ String expr = b.getBreakpointExpression();
+ if (expr != null)
+ sb.append(expr);
+ }
+
+ switch (status)
+ {
+ case BreakAction.UNRESOLVED:
+ sb.append(getLocalizationManager().getLocalizedTextString("breakpointNotYetResolved")); //$NON-NLS-1$
+ break;
+ case BreakAction.AMBIGUOUS:
+ sb.append(getLocalizationManager().getLocalizedTextString("breakpointAmbiguous")); //$NON-NLS-1$
+ break;
+ case BreakAction.NOCODE:
+ sb.append(getLocalizationManager().getLocalizedTextString("breakpointNoCode")); //$NON-NLS-1$
+ break;
+ }
+
+ // if a single swf break action then append more info
+ if (singleSwf && isResolved)
+ {
+ try
+ {
+ SwfInfo info = m_fileInfo.swfForFile(file, l.getIsolateId());
+ Map<String, Object> swfArgs = new HashMap<String, Object>();
+ swfArgs.put("swf", FileInfoCache.nameOfSwf(info)); //$NON-NLS-1$
+ sb.append(getLocalizationManager().getLocalizedTextString("inSwf", swfArgs)); //$NON-NLS-1$
+ }
+ catch(NullPointerException npe)
+ {
+ // can't find the swf
+ sb.append(getLocalizationManager().getLocalizedTextString("nonRestorable")); //$NON-NLS-1$
+ }
+ }
+ sb.append(m_newline);
+
+ final String INDENT = " "; //$NON-NLS-1$
+
+ // state our condition if we have one
+ if (cond != null && cond.length() > 0)
+ {
+ sb.append(INDENT);
+ Map<String, Object> args = new HashMap<String, Object>();
+ args.put("breakpointCondition", cond ); //$NON-NLS-1$
+ sb.append(getLocalizationManager().getLocalizedTextString(getLocalizationManager().getLocalizedTextString("stopOnlyIfConditionMet", args))); //$NON-NLS-1$
+ sb.append(m_newline);
+ }
+
+ // now if its been hit, lets state the fact
+ if (hits > 0)
+ {
+ sb.append(INDENT);
+ Map<String, Object> args = new HashMap<String, Object>();
+ args.put("count", Integer.toString(hits)); //$NON-NLS-1$
+ sb.append(getLocalizationManager().getLocalizedTextString("breakpointAlreadyHit", args)); //$NON-NLS-1$
+ sb.append(m_newline);
+ }
+
+ // silent?
+ if (silent)
+ {
+ sb.append(INDENT);
+ sb.append(getLocalizationManager().getLocalizedTextString("silentBreakpoint")+m_newline); //$NON-NLS-1$
+ }
+
+ // now if any commands are trailing then we pump them out
+ for(int j=0; j<cmdCount; j++)
+ {
+ sb.append(INDENT);
+ sb.append(b.commandAt(j));
+ sb.append(m_newline);
+ }
+ }
+// }
+
+ int wcount = watchpointCount();
+ for(int k = 0; k < wcount; k++)
+ {
+ WatchAction b = watchpointAt(k);
+ int id = b.getId();
+ FieldFormat.formatLong(sb, id, 4);
+
+ int flags = b.getKind();
+ switch(flags)
+ {
+ case WatchKind.READ:
+ sb.append("rd watchpoint "); //$NON-NLS-1$
+ break;
+ case WatchKind.WRITE:
+ sb.append("wr watchpoint "); //$NON-NLS-1$
+ break;
+ case WatchKind.READWRITE:
+ default:
+ sb.append("watchpoint "); //$NON-NLS-1$
+ break;
+ }
+
+ sb.append("keep "); //$NON-NLS-1$
+ sb.append("y "); //$NON-NLS-1$
+ sb.append(" "); //$NON-NLS-1$
+ sb.append(b.getExpr());
+ sb.append(m_newline);
+ }
+
+ int ccount = catchpointCount();
+ for (int k = 0; k < ccount; k++)
+ {
+ CatchAction c = catchpointAt(k);
+ int id = c.getId();
+ FieldFormat.formatLong(sb, id, 4);
+
+ String typeToCatch = c.getTypeToCatch();
+ if (typeToCatch == null)
+ typeToCatch = "*"; //$NON-NLS-1$
+
+ sb.append("catch "); //$NON-NLS-1$
+ sb.append("keep "); //$NON-NLS-1$
+ sb.append("y "); //$NON-NLS-1$
+ sb.append(" "); //$NON-NLS-1$
+ sb.append(typeToCatch);
+ sb.append(m_newline);
+ }
+
+ out(sb.toString());
+ }
+
+ /**
+ * Dump out the state of the execution, either the fact we are running
+ * or the breakpoint we hit.
+ */
+ void dumpHaltState(boolean postStep) throws NotConnectedException
+ {
+ // spit out any event output, if we are to resume after a fault and we're not stepping then we're done.
+ processEvents();
+// System.out.println("processEvents = "+m_requestResume);
+
+ //if (m_requestResume && !postStep)
+ if (hasAnyPendingResumes() != -1 && !postStep)
+ return;
+
+ if (!m_session.isConnected())
+ {
+ // session is kaput
+ out(getLocalizationManager().getLocalizedTextString("sessionTerminated")); //$NON-NLS-1$
+ exitSession();
+ }
+ else
+ {
+ if (hasAnythingSuspended())
+ {
+ // capture our break location / information
+ StringBuilder sbLine = new StringBuilder();
+ dumpBreakLine(postStep, sbLine);
+
+ // Process our breakpoints.
+ // Since we can have conditional breakpoints, which the
+ // player always breaks for, but we may not want to, the variable
+ // m_requestResume may be set after this call. Additionally,
+ // silent may be set for one of two reasons; 1) m_requestResume
+ // was set to true in the call or one or more breakpoints that
+ // hit contained the keyword silent in their command list.
+ //
+ StringBuilder sbBreak = new StringBuilder();
+ boolean silent = processBreak(postStep, sbBreak, m_activeIsolate);
+
+ StringBuilder sb = new StringBuilder();
+ if (silent)
+ {
+ // silent means we only spit out our current location
+ dumpBreakLine(postStep, sb);
+ }
+ else
+ {
+ // not silent means we append things like normal
+ sb.append(sbLine);
+ if (sbLine.length() > 0 && sbLine.charAt(sbLine.length()-1) != '\n')
+ sb.append(m_newline);
+ sb.append(sbBreak);
+ }
+
+ // output whatever was generated
+ if (sb.length() > 0)
+ out( sb.toString() );
+
+// System.out.println("processbreak = "+m_requestResume+",silent="+silent+",reason="+m_session.suspendReason());
+ }
+ else
+ {
+ // very bad, set stepping so that we don't trigger a continue on a breakpoint or fault
+ out(getLocalizationManager().getLocalizedTextString("playerDidNotStop")); //$NON-NLS-1$
+ }
+ }
+ }
+
+ Location getCurrentLocation()
+ {
+ return getCurrentLocationIsolate(Isolate.DEFAULT_ID);
+ }
+
+ Location getCurrentLocationIsolate(int isolateId)
+ {
+ Location where = null;
+ try
+ {
+ Frame[] ar = m_session.getWorkerSession(isolateId).getFrames();
+ propertyPut(CURRENT_FRAME_DEPTH, (ar.length > 0) ? ar.length : 0);
+ where = ( (ar.length > 0) ? ar[0].getLocation() : null);
+ }
+ catch(PlayerDebugException pde)
+ {
+ // where == null
+ }
+ return where;
+ }
+
+ void dumpBreakLine(boolean postStep, StringBuilder sb) throws NotConnectedException
+ {
+ int bp = -1;
+ String name = getLocalizationManager().getLocalizedTextString("unknownFilename"); //$NON-NLS-1$
+ int line = -1;
+
+ // clear our current frame display
+ propertyPut(DISPLAY_FRAME_NUMBER, 0);
+
+ int targetIsolate = getLastStoppedIsolate();
+ boolean activeIsolateChanged = (m_activeIsolate != targetIsolate);
+ m_activeIsolate = targetIsolate;
+ propertyPut(LIST_WORKER, targetIsolate);
+
+ /* dump a context line to the console */
+ Location l = getCurrentLocationIsolate(targetIsolate);
+
+ // figure out why we stopped
+ int reason = SuspendReason.Unknown;
+ try { reason = m_session.getWorkerSession(targetIsolate).suspendReason(); } catch(PlayerDebugException pde) {}
+
+ // then see if it because of a swfloaded event
+ if( reason == SuspendReason.ScriptLoaded)
+ {
+ // since the player takes a long time to provide swf/swd, try 80 * 250ms = ~20s
+ if (propertyGet(METADATA_ATTEMPTS) > 0)
+ try { waitForMetaData(80); } catch(InProgressException ipe) { }
+
+ m_fileInfo.setDirty();
+ m_fileInfo.getSwfsIsolate(targetIsolate);
+ //propertyPut(LIST_MODULE, m_fileInfo.getFakeId(m_fileInfo.getFile(1, targetIsolate)));
+ processEvents();
+ propagateBreakpoints(targetIsolate);
+ propertyPut(LIST_LINE, 1);
+ propertyPut(LIST_WORKER, targetIsolate);
+ propertyPut(LIST_MODULE, 1);
+ sb.append(getLocalizationManager().getLocalizedTextString("additionalCodeLoaded")); //$NON-NLS-1$
+ if ( activeIsolateChanged ) {
+ sb.append(m_newline + getLocalizationManager().getLocalizedTextString("workerChanged")+ " " + (targetIsolate - 1) + m_newline); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ sb.append(m_newline);
+
+ if (resolveBreakpoints(sb))
+ sb.append(getLocalizationManager().getLocalizedTextString("setAdditionalBreakpoints")+m_newline); //$NON-NLS-1$
+ else
+ sb.append(getLocalizationManager().getLocalizedTextString("fixBreakpoints")+m_newline); //$NON-NLS-1$
+
+ setPromptState(InitialPromptState.SHOWN_ONCE, targetIsolate);
+ }
+ else if ( l == null || l.getFile() == null )
+ {
+
+ if ( activeIsolateChanged ) {
+ sb.append(m_newline + getLocalizationManager().getLocalizedTextString("workerChanged")+ " " + (targetIsolate - 1) + m_newline);
+ }
+
+ // no idea where we are ?!?
+ propertyPut(LAST_FRAME_DEPTH, 0);
+ sb.append(getLocalizationManager().getLocalizedTextString("executionHalted")); //$NON-NLS-1$
+ sb.append(' ');
+
+ /** disable this line (and enable the one after) if implementation Extensions are not provided */
+ appendBreakInfo(sb, m_activeIsolate);
+ //sb.append("unknown location");
+ }
+ else
+ {
+ if ( activeIsolateChanged ) {
+ sb.append(m_newline + getLocalizationManager().getLocalizedTextString("workerChanged")+ " " + (targetIsolate - 1) + m_newline);
+ }
+
+ SourceFile file = l.getFile();
+ name = file.getName();
+ line = l.getLine();
+ String funcName = file.getFunctionNameForLine(m_session, line) ;
+
+ // where were we last time
+ int lastModule = propertyGet(LIST_MODULE);
+ int lastDepth = propertyGet(LAST_FRAME_DEPTH);
+
+ int thisModule = file.getId();
+ int thisDepth = propertyGet(CURRENT_FRAME_DEPTH); // triggered via getCurrentLocation()
+
+ // mark where we stopped
+ propertyPut(LAST_FRAME_DEPTH, thisDepth);
+
+ // if we have changed our context or we are not spitting out source then dump our location
+ if (!postStep || lastModule != thisModule || lastDepth != thisDepth )
+ {
+ // is it a fault?
+ String reasonForHalting;
+ if ( reason == SuspendReason.Fault || reason == SuspendReason.StopRequest)
+ {
+ StringBuilder s = new StringBuilder();
+ appendReason(s, reason);
+ reasonForHalting = s.toString();
+ }
+ // if its a breakpoint add that information
+ else if ( (bp = enabledBreakpointIndexOf(l)) > -1 )
+ {
+ Map<String, Object> args = new HashMap<String, Object>();
+ args.put("breakpointNumber", Integer.toString(breakpointAt(bp).getId())); //$NON-NLS-1$
+ reasonForHalting = getLocalizationManager().getLocalizedTextString("hitBreakpoint", args); //$NON-NLS-1$
+ }
+ else
+ {
+ reasonForHalting = getLocalizationManager().getLocalizedTextString("executionHalted"); //$NON-NLS-1$
+ }
+
+ Map<String, Object> args = new HashMap<String, Object>();
+ args.put("reasonForHalting", reasonForHalting); //$NON-NLS-1$
+ args.put("fileAndLine", name + ':' + line); //$NON-NLS-1$
+ String formatString;
+ if (funcName != null)
+ {
+ args.put("functionName", funcName); //$NON-NLS-1$
+ formatString = "haltedInFunction"; //$NON-NLS-1$
+ }
+ else
+ {
+ formatString = "haltedInFile"; //$NON-NLS-1$
+ }
+ sb.append(getLocalizationManager().getLocalizedTextString(formatString, args));
+
+ if (!m_fullnameOption)
+ sb.append(m_newline);
+ }
+
+ // set current listing poistion and emit emacs trigger
+ setListingPosition(thisModule, line, targetIsolate);
+
+ // dump our source line if not in emacs mode
+ if (!m_fullnameOption)
+ appendSource(sb, file.getId(), line, file.getLine(line), false);
+ }
+ }
+
+ private int getLastStoppedIsolate() {
+ int targetIsolate = Isolate.DEFAULT_ID;
+
+ if (m_breakIsolates.size() > 0) {
+ targetIsolate = m_breakIsolates.get(m_breakIsolates.size() - 1);
+ }
+ return targetIsolate;
+ }
+
+ void appendFullnamePosition(StringBuilder sb, SourceFile file, int lineNbr)
+ {
+ // fullname option means we dump 'path:line:col?:offset', which is used for emacs !
+ String name = file.getFullPath();
+ if (name.startsWith("file:/")) //$NON-NLS-1$
+ name = name.substring(6);
+
+ // Ctrl-Z Ctrl-Z
+ sb.append('\u001a');
+ sb.append('\u001a');
+
+ sb.append(name);
+ sb.append(':');
+ sb.append(lineNbr);
+ sb.append(':');
+ sb.append('0');
+ sb.append(':');
+ sb.append("beg"); //$NON-NLS-1$
+ sb.append(':');
+ sb.append('0');
+ }
+
+ // pretty print a trace statement to the console
+ void dumpTraceLine(String s)
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.append("[trace] "); //$NON-NLS-1$
+ sb.append(s);
+ out(sb.toString());
+ }
+
+ // pretty print a fault statement to the console
+ void dumpFaultLine(FaultEvent e)
+ {
+ StringBuilder sb = new StringBuilder();
+
+ // use a slightly different format for ConsoleErrorFaults
+ if (e instanceof ConsoleErrorFault)
+ {
+ sb.append(getLocalizationManager().getLocalizedTextString("linePrefixWhenDisplayingConsoleError")); //$NON-NLS-1$
+ sb.append(' ');
+ sb.append(e.information);
+ }
+ else
+ {
+ String name = e.name();
+ sb.append(getLocalizationManager().getLocalizedTextString("linePrefixWhenDisplayingFault")); //$NON-NLS-1$
+ sb.append(' ');
+ sb.append(name);
+ if (e.information != null && e.information.length() > 0)
+ {
+ sb.append(getLocalizationManager().getLocalizedTextString("informationAboutFault")); //$NON-NLS-1$
+ sb.append(e.information);
+ }
+ }
+ out( sb.toString() );
+ }
+
+ /**
+ * Called when a swf has been loaded by the player
+ * @param e event documenting the load
+ */
+ void handleSwfLoadedEvent(SwfLoadedEvent e)
+ {
+ // first we dump out a message that displays we have loaded a swf
+ dumpSwfLoadedLine(e);
+ }
+
+ // pretty print a SwfLoaded statement to the console
+ void dumpSwfLoadedLine(SwfLoadedEvent e)
+ {
+ // now rip off any trailing ? options
+ int at = e.path.lastIndexOf('?');
+ String name = (at > -1) ? e.path.substring(0, at) : e.path;
+
+ StringBuilder sb = new StringBuilder();
+ sb.append(getLocalizationManager().getLocalizedTextString("linePrefixWhenSwfLoaded")); //$NON-NLS-1$
+ sb.append(' ');
+ sb.append(name);
+ sb.append(" - "); //$NON-NLS-1$
+
+ Map<String, Object> args = new HashMap<String, Object>();
+ args.put("size", NumberFormat.getInstance().format(e.swfSize)); //$NON-NLS-1$
+ sb.append(getLocalizationManager().getLocalizedTextString("sizeAfterDecompression", args)); //$NON-NLS-1$
+ out(sb.toString());
+ }
+
+ /**
+ * Propagate current breakpoints to the newly loaded swf.
+ */
+ void propagateBreakpoints(int isolateId) throws NotConnectedException
+ {
+ // get the newly added swf, which lands at the end list
+ SwfInfo[] swfs = m_fileInfo.getSwfsIsolate(isolateId);
+ SwfInfo swf = (swfs.length > 1) ? swfs[swfs.length-1] : null;
+
+ // now walk through all breakpoints propagating the
+ // the break for each source and line number we
+ // find in the new swf
+ int size = m_breakpoints.size();
+ for (int i = 0; (swf != null) && i < size; i++)
+ {
+ // dont do this for single swf breakpoints
+ BreakAction bp = breakpointAt(i);
+ if (bp.isSingleSwf())
+ continue;
+ if (bp.getStatus() != BreakAction.RESOLVED)
+ continue;
+
+ try
+ {
+ Location l = bp.getLocation();
+ int line = l.getLine();
+ SourceFile f = l.getFile();
+ Location newLoc = findAndEnableBreak(swf, f, line);
+ if (newLoc != null)
+ bp.addLocation(newLoc);
+ }
+ catch(InProgressException ipe)
+ {
+ if (breakpointCount() > 0)
+ {
+ Map<String, Object> args = new HashMap<String, Object>();
+ args.put("breakpointNumber", Integer.toString(bp.getId())); //$NON-NLS-1$
+ out(getLocalizationManager().getLocalizedTextString("breakpointNotPropagated", args)); //$NON-NLS-1$
+ }
+ }
+ }
+ }
+
+ /**
+ * Perform the tasks need for when a swf is unloaded
+ * the player
+ */
+ void handleSwfUnloadedEvent(SwfUnloadedEvent e)
+ {
+ // print out the notification
+ dumpSwfUnloadedLine(e);
+ }
+
+ // pretty print a SwfUnloaded statement to the console
+ void dumpSwfUnloadedLine(SwfUnloadedEvent e)
+ {
+ // now rip off any trailing ? options
+ int at = e.path.lastIndexOf('?');
+ String name = (at > -1) ? e.path.substring(0, at) : e.path;
+
+ StringBuilder sb = new StringBuilder();
+ sb.append(getLocalizationManager().getLocalizedTextString("linePrefixWhenSwfUnloaded")); //$NON-NLS-1$
+ sb.append(' ');
+ sb.append(name);
+ out(sb.toString());
+ }
+
+ void doContinue() throws NotConnectedException
+ {
+ //int stoppedIsolate = getLastStoppedIsolate();
+ int stoppedIsolate = m_activeIsolate;
+ waitTilHalted(stoppedIsolate);
+
+ // this will trigger a resume when we get back to the main loop
+ //m_requestResume = true;
+ setRequestResume(true, stoppedIsolate);
+ m_repeatLine = m_currentLine;
+ }
+
+ boolean hasAnythingSuspended() throws NotConnectedException {
+ boolean hasAnythingSuspended = false;
+ for (Integer id : m_breakIsolates) {
+ if (m_session.getWorkerSession(id).isSuspended()) {
+ hasAnythingSuspended = true;
+ break;
+ }
+ }
+ return hasAnythingSuspended;
+ }
+
+ int hasAnyPendingResumes() throws NotConnectedException {
+ int rid = -1;
+ if (m_mainState.m_requestResume)
+ return Isolate.DEFAULT_ID;
+ for (Integer id : m_breakIsolates) {
+ if (getIsolateState(id).m_requestResume) {
+ rid = id;
+ break;
+ }
+ }
+ return rid;
+ }
+
+ /**
+ * Returns the first isolate's id for which we need to keep showing prompts.
+ *
+ * @return The isolate id
+ * @throws NotConnectedException
+ */
+ int hasPendingInitialPrompts() throws NotConnectedException {
+ int rid = -1;
+ for (Integer id : m_breakIsolates) {
+ if (getPromptState(id) != InitialPromptState.DONE) {
+ rid = id;
+ break;
+ }
+ }
+ return rid;
+ }
+
+ /**
+ * Our main loop when the player is off running
+ */
+ public void runningLoop() throws NoResponseException, NotConnectedException
+ {
+ int update = propertyGet(UPDATE_DELAY);
+ boolean nowait = (propertyGet(NO_WAITING) == 1) ? true : false; // DEBUG ONLY; do not document
+ boolean stop = false;
+ boolean noConnection = !haveConnection();
+ boolean hasAnythingSuspended = false;
+ int targetIsolate = Isolate.DEFAULT_ID;
+ if (!noConnection) {
+ hasAnythingSuspended = hasAnythingSuspended();
+ }
+
+ if (hasAnythingSuspended) {
+ if (m_breakIsolates.size() > 0) {
+ targetIsolate = m_breakIsolates.get(m_breakIsolates.size() - 1);
+ }
+ }
+ // not there, not connected or already halted and no pending resume requests => we are done
+ //if (noConnection || (hasAnythingSuspended && !m_requestResume) )
+ if (noConnection || (hasAnythingSuspended && hasAnyPendingResumes() == -1) )
+ {
+ processEvents();
+ stop = true;
+
+ if(!noConnection) {
+ /** At this point, some isolate is in suspended state and will be until a resume
+ * is requested via the prompt. We thus check for any pending prompts to be displayed
+ * for freshly loaded swfs. If any, we switch to that worker and prompt the user to set
+ * any break points. */
+ int pendingPromptIsolate = -1;
+ if ( m_lastPromptIsolate != -1 && ( getPromptState(m_lastPromptIsolate) != InitialPromptState.DONE ) ) {
+ pendingPromptIsolate = m_lastPromptIsolate;
+ } else {
+ pendingPromptIsolate = hasPendingInitialPrompts();
+ }
+ if ( pendingPromptIsolate != -1) {
+ dumpInitialPrompt(pendingPromptIsolate);
+ }
+ }
+ }
+
+ while(!stop)
+ {
+ // allow keyboard input
+ if (!nowait)
+ m_keyboardReadRequest = true;
+ int pendingResumeId = hasAnyPendingResumes();
+ if (pendingResumeId != -1)
+ {
+ // resume execution (request fulfilled) and look for keyboard input
+ try
+ {
+ IsolateSession workerSession = m_session.getWorkerSession(pendingResumeId);
+ //if (m_stepResume)
+ if (getStepResume(pendingResumeId))
+ workerSession.stepContinue();
+ else {
+ workerSession.resume();
+ }
+ /** The user is done setting initial breakpoints for this isolate,
+ * clear any pending initial prompts */
+ setPromptState(InitialPromptState.DONE, pendingResumeId);
+ removeBreakIsolate(pendingResumeId);
+ }
+ catch(NotSuspendedException nse)
+ {
+ err(getLocalizationManager().getLocalizedTextString("playerAlreadyRunning")); //$NON-NLS-1$
+ }
+
+ setRequestResume(false, pendingResumeId);
+ setRequestHalt(false, pendingResumeId);
+ setStepResume(false, pendingResumeId);
+// m_requestResume = false;
+// m_requestHalt = false;
+// m_stepResume = false;
+ }
+
+ // sleep for a bit, then process our events.
+ try { Thread.sleep(update); } catch(InterruptedException ie) {}
+ processEvents();
+
+ // lost connection?
+ if (!haveConnection())
+ {
+ stop = true;
+ dumpHaltState(false);
+ }
+ else if (hasAnythingSuspended())
+ {
+ /**
+ * We have stopped for some reason. Now for all cases, but conditional
+ * breakpoints, we should be done. For conditional breakpoints it
+ * may be that the condition has turned out to be false and thus
+ * we need to continue
+ */
+
+ /**
+ * Now before we do this see, if we have a valid break reason, since
+ * we could be still receiving incoming messages, even though we have halted.
+ * This is definately the case with loading of multiple SWFs. After the load
+ * we get info on the swf.
+ */
+ if (m_breakIsolates.size() > 0) {
+ targetIsolate = m_breakIsolates.get(m_breakIsolates.size() - 1);
+ }
+ else {
+ targetIsolate = Isolate.DEFAULT_ID;
+ }
+ int tries = 3;
+ IsolateSession workerSession = m_session.getWorkerSession(targetIsolate);
+ while (tries-- > 0 && workerSession.suspendReason() == SuspendReason.Unknown)
+ try { Thread.sleep(100); processEvents(); } catch(InterruptedException ie) {}
+
+ dumpHaltState(false);
+ //if (!m_requestResume)
+ if (!getRequestResume(targetIsolate))
+ stop = true;
+ }
+ else if (nowait)
+ {
+ stop = true; // for DEBUG only
+ }
+ else
+ {
+ /**
+ * We are still running which is fine. But let's see if the user has
+ * tried to enter something on the keyboard. If so, then we need to
+ * stop
+ */
+ if (!m_keyboardInput.isEmpty() && System.getProperty("fdbunit")==null) //$NON-NLS-1$
+ {
+ // flush the queue and prompt the user if they want us to halt
+ m_keyboardInput.clear();
+ try
+ {
+ if (yesNoQuery(getLocalizationManager().getLocalizedTextString("doYouWantToHalt"))) //$NON-NLS-1$
+ {
+ out(getLocalizationManager().getLocalizedTextString("attemptingToHalt")); //$NON-NLS-1$
+ IsolateSession workerSession = m_session.getWorkerSession(m_activeIsolate);
+ workerSession.suspend();
+// m_session.suspend();
+ getIsolateState(m_activeIsolate).m_requestHalt = true;
+
+ // no connection => dump state and end
+ if (!haveConnection())
+ {
+ dumpHaltState(false);
+ stop = true;
+ }
+ else if (!workerSession.isSuspended())
+ err(getLocalizationManager
<TRUNCATED>