http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/07f5a7de/debugger/src/main/java/flash/tools/debugger/concrete/PlayerSession.java
----------------------------------------------------------------------
diff --git 
a/debugger/src/main/java/flash/tools/debugger/concrete/PlayerSession.java 
b/debugger/src/main/java/flash/tools/debugger/concrete/PlayerSession.java
new file mode 100644
index 0000000..f41ed19
--- /dev/null
+++ b/debugger/src/main/java/flash/tools/debugger/concrete/PlayerSession.java
@@ -0,0 +1,3069 @@
+/*
+ * 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 flash.tools.debugger.concrete;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.io.UnsupportedEncodingException;
+import java.net.Socket;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import flash.tools.debugger.AIRLaunchInfo;
+import flash.tools.debugger.Frame;
+import flash.tools.debugger.IDebuggerCallbacks;
+import flash.tools.debugger.ILauncher;
+import flash.tools.debugger.InProgressException;
+import flash.tools.debugger.Isolate;
+import flash.tools.debugger.IsolateController;
+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.SuspendedException;
+import flash.tools.debugger.SwfInfo;
+import flash.tools.debugger.Value;
+import flash.tools.debugger.ValueAttribute;
+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.concrete.DProtocol.ListenerIndex;
+import flash.tools.debugger.events.DebugEvent;
+import flash.tools.debugger.events.ExceptionFault;
+import flash.tools.debugger.events.FaultEvent;
+import flash.tools.debugger.expression.ECMA;
+import flash.tools.debugger.expression.PlayerFaultException;
+import flash.util.Trace;
+
+
+public class PlayerSession implements Session, DProtocolNotifierIF, Runnable, 
IsolateController
+{
+       public static final int MAX_STACK_DEPTH = 256;
+       public static final long MAX_TERMINATE_WAIT_MILLIS = 10000;
+
+       private Socket                          m_socket;
+       private DProtocol                       m_protocol;
+       private DManager                        m_manager;
+       private IDebuggerCallbacks      m_debuggerCallbacks;
+       private Process                         m_process;
+       private Map<String, Object> m_prefs; // WARNING -- accessed from 
multiple threads
+       private static final String     s_newline = 
System.getProperty("line.separator"); //$NON-NLS-1$
+
+       private volatile boolean m_isConnected; // WARNING -- accessed from 
multiple threads
+       private volatile boolean m_isHalted; // WARNING -- accessed from 
multiple threads
+       private volatile boolean m_incoming; // WARNING -- accessed from 
multiple threads
+       private volatile boolean m_lastResponse;  // whether there was a 
reponse from the last message to the Player
+       private volatile HashMap<Integer, PlayerSessionIsolateStatus> 
m_isolateStatus = new HashMap<Integer, PlayerSessionIsolateStatus>();
+       
+       private int                             m_watchTransactionTag;
+       private Boolean                 m_playerCanCallFunctions;
+       private Boolean                 m_playerSupportsWatchpoints;
+       private Boolean                 m_playerCanBreakOnAllExceptions;
+       private Boolean                 m_playerSupportsConcurrency;
+       private Boolean                 m_playerSupportsWideLine;
+       
+       private ILauncher launcher;
+
+       /**
+        * The URL that was launched, or <code>null</code> if not known.  Note:
+        * This is NOT the value returned by getURI().  getURI() returns the
+        * URL that came from the Player, and is therefore probably the URI of
+        * the SWF; but m_launchedUrl contains the URL that we tried to launch,
+        * which might be an HTML wrapper, e.g. http://localhost/myapp.html
+        */
+       private String                          m_launchUrl;
+
+       private AIRLaunchInfo   m_airLaunchInfo; // null if this is not an AIR 
app
+
+       static volatile boolean m_debugMsgOn;           // debug ONLY; turned 
on with "set $debug_messages = 1"
+       volatile int                    m_debugMsgSize;         // debug ONLY; 
controlled with "set $debug_message_size = NNN"
+       static volatile boolean m_debugMsgFileOn;       // debug ONLY for file 
dump; turned on with "set $debug_message_file = 1"
+       volatile int                    m_debugMsgFileSize;     // debug ONLY 
for file dump; controlled with "set $debug_message_file_size = NNN"
+
+       //FIXME: Make this concurrency aware
+       /**
+        * A simple cache of previous "is" and "instanceof" queries, in order to
+        * avoid having to send redundant messages to the player.
+        */
+       private Map<String, Boolean> m_evalIsAndInstanceofCache = new 
HashMap<String, Boolean>();
+       
+       private volatile int m_lastPreIsolate = Isolate.DEFAULT_ID;
+       
+       private final Map<Integer, IsolateSession> m_isolateSessions;
+
+       private static final String DEBUG_MESSAGES = "$debug_messages"; 
//$NON-NLS-1$
+       private static final String DEBUG_MESSAGE_SIZE = "$debug_message_size"; 
//$NON-NLS-1$
+       private static final String DEBUG_MESSAGE_FILE = "$debug_message_file"; 
//$NON-NLS-1$
+       private static final String DEBUG_MESSAGE_FILE_SIZE = 
"$debug_message_file_size"; //$NON-NLS-1$
+
+       private static final String CONSOLE_ERRORS = "$console_errors"; 
//$NON-NLS-1$
+
+       private static final String FLASH_PREFIX = "$flash_"; //$NON-NLS-1$
+       
+       PlayerSession(Socket s, DProtocol proto, DManager manager, 
IDebuggerCallbacks debuggerCallbacks)
+       {
+               m_isConnected = false;
+               m_isHalted = false;
+               m_socket = s;
+               m_protocol = proto;
+               m_manager = manager;
+               m_prefs = Collections.synchronizedMap(new HashMap<String, 
Object>());
+               m_incoming = false;
+               m_debugMsgOn = false;
+               m_debugMsgSize = 16;
+               m_debugMsgFileOn = false;
+               m_debugMsgFileSize = 128;
+               m_watchTransactionTag = 1;  // number that is sent for each 
watch transaction that occurs
+               m_playerCanCallFunctions = null;
+               m_debuggerCallbacks = debuggerCallbacks;
+               m_isolateSessions = Collections.synchronizedMap(new 
HashMap<Integer, IsolateSession>());
+       }
+       
+       private static PlayerSession createFromSocketHelper(Socket s, 
IDebuggerCallbacks debuggerCallbacks, DProtocol proto) throws IOException
+       {
+               // let the manager hear incoming messages
+               DManager manager = new DManager();
+
+               PlayerSession session = new PlayerSession(s, proto, manager, 
debuggerCallbacks);
+               return session;
+       }
+
+       /**
+        * @deprecated Use createFromSocketWithOptions
+        * @param s
+        * @param debuggerCallbacks
+        * @return
+        * @throws IOException
+        */
+       public static PlayerSession createFromSocket(Socket s, 
IDebuggerCallbacks debuggerCallbacks) throws IOException
+       {
+               DProtocol proto = DProtocol.createFromSocket(s);
+
+               return createFromSocketHelper(s, debuggerCallbacks, proto);
+       }
+       
+       /**
+        * Creates a session from the socket. Sets session specific 
+        * socket settings and stores the callback object.
+        * @param s
+        * @param debuggerCallbacks
+        * @param sessionManager
+        * @return
+        * @throws IOException
+        */
+       public static PlayerSession createFromSocketWithOptions(Socket s, 
IDebuggerCallbacks debuggerCallbacks, SessionManager sessionManager) throws 
IOException
+       {
+               DProtocol proto = DProtocol.createFromSocket(s, sessionManager);
+
+               return createFromSocketHelper(s, debuggerCallbacks, proto);
+       }
+
+       /* getter */
+       public DMessageCounter          getMessageCounter()             { 
return m_protocol.getMessageCounter(); }
+       public String                           getURI()                        
        { return m_manager.getURI(); }
+       public boolean                          playerSupportsGet()             
{ return m_manager.isGetSupported(); }
+    public int                  playerVersion()         { return 
m_manager.getVersion(); }
+    public SourceLocator        getSourceLocator()      { return 
m_manager.getSourceLocator(); }
+
+       /*
+        * @see 
flash.tools.debugger.Session#setSourceLocator(flash.tools.debugger.SourceLocator)
+        */
+       public void setSourceLocator(SourceLocator sourceLocator)
+       {
+               m_manager.setSourceLocator(sourceLocator);
+       }
+
+       /**
+        * If the manager started the process for us, then note it here. We 
will attempt to kill
+        * it when we go down
+        */
+       void setProcess(Process proc)
+       {
+               m_process = proc;
+       }
+
+       /*
+        * @see flash.tools.debugger.Session#getLaunchProcess()
+        */
+       public Process getLaunchProcess()
+       {
+               return m_process;
+       }
+
+       /**
+        * Set preference
+        * If an invalid preference is passed, it will be silently ignored.
+        */
+       public void                     setPreferences(Map<String, ? extends 
Object> map)       { m_prefs.putAll(map); mapBack(); }
+       public Set<String>      keySet()                                        
                        { return m_prefs.keySet(); }
+       public Object           getPreferenceAsObject(String pref)              
{ return m_prefs.get(pref); }
+
+       /**
+        * Set a property. Special logic for debug message boolean
+        */
+       public void setPreference(String pref, int value)
+       {
+               m_prefs.put(pref, new Integer(value));
+               mapBack();
+
+               // change in console messages?
+               if (pref.equals(CONSOLE_ERRORS))
+                       sendConsoleErrorsAsTrace(value == 1);
+
+               // generic message for flash player wherein "$flash_xxx" causes 
"xxx" to be sent
+               if (pref.startsWith(FLASH_PREFIX))
+                       
sendOptionMessage(pref.substring(FLASH_PREFIX.length()), 
Integer.toString(value));
+       }
+
+       // helper for mapBack()
+       private int mapBackOnePreference(String preferenceName, int 
defaultValue)
+       {
+               Object prefValue = getPreferenceAsObject(preferenceName);
+               if (prefValue != null)
+                       return ((Integer)prefValue).intValue();
+               else
+                       return defaultValue;
+       }
+
+       // helper for mapBack()
+       private boolean mapBackOnePreference(String preferenceName, boolean 
defaultValue)
+       {
+               Object prefValue = getPreferenceAsObject(preferenceName);
+               if (prefValue != null)
+                       return ((Integer)prefValue).intValue() != 0 ? true : 
false;
+               else
+                       return defaultValue;
+       }
+
+       // look for preferences, that map back to variables
+       private void mapBack()
+       {
+               m_debugMsgOn = mapBackOnePreference(DEBUG_MESSAGES, 
m_debugMsgOn);
+               m_debugMsgSize = mapBackOnePreference(DEBUG_MESSAGE_SIZE, 
m_debugMsgSize);
+
+               m_debugMsgFileOn = mapBackOnePreference(DEBUG_MESSAGE_FILE, 
m_debugMsgFileOn);
+               m_debugMsgFileSize = 
mapBackOnePreference(DEBUG_MESSAGE_FILE_SIZE, m_debugMsgFileSize);
+       }
+
+       public int getPreference(String pref)
+       {
+               int val = 0;
+               Integer i = (Integer)m_prefs.get(pref);
+               if (i == null)
+                       throw new NullPointerException();
+               else
+                       val = i.intValue();
+               return val;
+       }
+
+
+       /*
+        * @see flash.tools.debugger.Session#isConnected()
+        */
+       public boolean isConnected()
+       {
+               return m_isConnected;
+       }
+
+       /*
+        * @see flash.tools.debugger.Session#isSuspended()
+        */
+       public boolean isSuspended() throws NotConnectedException
+       {
+               if (!isConnected())
+                       throw new NotConnectedException();
+
+               return m_isHalted;
+       }
+       
+       /*
+        * @see flash.tools.debugger.Session#isIsolateSuspended()
+        */
+       public boolean isWorkerSuspended(int isolateId) throws 
NotConnectedException
+       {
+               if (isolateId == Isolate.DEFAULT_ID)
+                       return isSuspended();
+               
+               if (!isConnected())
+                       throw new NotConnectedException();
+               
+               if (m_isolateStatus.containsKey(isolateId)) {
+                       return m_isolateStatus.get(isolateId).m_isHalted;
+               }
+               
+               return false;
+       }
+
+       /**
+        * Start up the session listening for incoming messages on the socket
+        */
+       public boolean bind() throws VersionException
+       {
+               boolean bound = false;
+
+               if (m_isConnected)
+                       return false;
+               
+               // mark that we are connected
+               m_isConnected = true;
+
+               // attach us to the pipe (we are last to ensure that DManager 
and msg counter
+               // get updated first
+               m_protocol.addListener(ListenerIndex.PlayerSession, this);
+
+               // start up the receiving thread
+               bound = m_protocol.bind();
+
+               // transmit our first few adjustment messages
+               sendStopWarning();
+               sendStopOnFault();
+               sendEnumerateOverride();
+               sendFailureNotify();
+               sendInvokeSetters();
+               sendSwfloadNotify();
+               sendGetterTimeout();
+               sendSetterTimeout();
+               boolean responded = sendSquelch(true, Isolate.DEFAULT_ID);
+
+               // now note in our preferences whether get is working or not.
+               setPreference(SessionManager.PLAYER_SUPPORTS_GET, 
playerSupportsGet() ? 1 : 0);
+               if (supportsConcurrency()) {
+                       sendConcurrentDebugger();
+               }
+               
+               if (supportsWideLineNumbers()) {
+                       sendWideLineDebugger();
+               }
+
+               // Spawn a background thread which fetches the SWF and SWD
+               // from the Player and uses them to build function name tables
+               // for each source file
+               Thread t = new Thread(this, "SWF/SWD reader"); //$NON-NLS-1$
+               t.setDaemon(true);
+               t.start();
+
+               // we're probably using a bad version
+               if (!responded)
+                       throw new VersionException();
+
+               return bound;
+       }
+
+       /**
+        * Permanently stops the debugging session and breaks the
+        * connection to the Player
+        */
+       public void unbind()
+       {
+               unbind(false);
+       }
+
+       /**
+        * @param requestTerminate
+        *            if true, and if the player to which we are attached is 
capable
+        *            of terminating itself (e.g. Adobe AIR), then the player 
will
+        *            be told to terminate.
+        * @return true if the player is capable of terminating itself and has 
been
+        *         told to do so
+        */
+       private boolean unbind(boolean requestTerminate)
+       {
+               // If the caller asked us to terminate the player, then we 
first check
+               // whether the player to which we are connected is capable of 
that.
+               // (The web-based players are not; Adobe AIR is.)
+               requestTerminate = requestTerminate && playerCanTerminate();
+               DMessage dm = DMessageCache.alloc(1);
+               dm.setType(DMessage.OutExit);
+               dm.putByte((byte)(requestTerminate ? 1 : 0));
+               sendMessage(dm);
+
+               // unbind from the socket, so that we don't receive any more 
messages
+               m_protocol.unbind();
+
+               // kill the socket
+               try { m_socket.close(); } catch(IOException io) {}
+
+               m_isConnected = false;
+               m_isHalted = false;
+
+               return requestTerminate; // true if player was told to terminate
+       }
+
+       /**
+        * Execute the specified AppleScript by passing it to 
/usr/bin/osascript.
+        *
+        * @param appleScript
+        *            the AppleScript to execute, as a series of lines
+        * @param argv
+        *            any arguments; these can be accessed from within your
+        *            AppleScript via "item 1 or argv", "item 2 of argv", etc.
+        * @return any text which was sent to stdout by /usr/bin/osascript, 
with the
+        *         trailing \n already removed
+        */
+       private String executeAppleScript(String[] appleScript, String[] argv)
+       {
+               StringBuilder retval = new StringBuilder();
+               try
+               {
+                       List<String> execArgs = new LinkedList<String>();
+                       // "osascript" is the command-line way of executing 
AppleScript.
+                       execArgs.add("/usr/bin/osascript"); //$NON-NLS-1$
+                       execArgs.add("-"); //$NON-NLS-1$
+                       if (argv != null)
+                       {
+                               for (int i=0; i<argv.length; ++i)
+                                       execArgs.add(argv[i]);
+                       }
+                       Process osascript = 
Runtime.getRuntime().exec(execArgs.toArray(new String[execArgs.size()]));
+                       // feed our AppleScript code to osascript's stdin
+                       OutputStream outputStream = osascript.getOutputStream();
+                       PrintWriter writer = new PrintWriter(outputStream, 
true);
+                       writer.println("on run argv"); //$NON-NLS-1$ // this 
gives the name "argv" to the command-line args
+                       for (int i=0; i<appleScript.length; ++i)
+                               writer.println(appleScript[i]);
+                       writer.println("end run"); //$NON-NLS-1$
+                       writer.close();
+                       InputStreamReader reader = new 
InputStreamReader(osascript.getInputStream());
+                       int ch;
+                       while ( (ch=reader.read()) != -1 )
+                               retval.append((char)ch);
+               }
+               catch (IOException e)
+               {
+                       // ignore
+               }
+               return retval.toString().replaceAll("\n$", ""); //$NON-NLS-1$ 
//$NON-NLS-2$
+       }
+
+       /**
+        * Execute the specified AppleScript by passing it to 
/usr/bin/osascript.
+        *
+        * @param appleScriptFilename
+        *            The name of the file containing AppleScript to execute.  
This
+        *            must be relative to PlayerSession.java.
+        * @param argv
+        *            any arguments; these can be accessed from within your
+        *            AppleScript via "item 1 or argv", "item 2 of argv", etc.
+        * @return any text which was sent to stdout by /usr/bin/osascript, 
with the
+        *         trailing \n already removed
+        * @throws IOException
+        */
+       private String executeAppleScript(String appleScriptFilename, String[] 
argv) throws IOException
+       {
+               InputStream stm = null;
+               try {
+                       stm = 
PlayerSession.class.getResourceAsStream(appleScriptFilename);
+                       BufferedReader reader = new BufferedReader(new 
InputStreamReader(stm));
+                       String line;
+                       List<String> appleScriptLines = new ArrayList<String>();
+                       while ( (line=reader.readLine()) != null )
+                               appleScriptLines.add(line);
+                       String[] lines = appleScriptLines.toArray(new 
String[appleScriptLines.size()]);
+                       return executeAppleScript(lines, argv);
+               } finally {
+                       if (stm != null) {
+                               stm.close();
+                       }
+               }
+       }
+
+       /**
+        * Checks whether the specified Macintosh web browser is currently
+        * running.  You should only call this function if you have already
+        * checked that you are running on a Mac.
+        *
+        * @param browserName a name, e.g. "Safari", "Firefox", "Camino"
+        * @return true if currently running
+        */
+       private Set<String> runningApplications()
+       {
+               String running = executeAppleScript(
+                       new String[]
+               {
+                               "tell application \"System Events\"", 
//$NON-NLS-1$
+                               "       name of processes", //$NON-NLS-1$
+                               "end tell" //$NON-NLS-1$
+               },
+               null
+               );
+               String[] apps = running.split(", "); //$NON-NLS-1$
+               Set<String> retval = new HashSet<String>();
+               for (int i=0; i<apps.length; ++i)
+                       retval.add(apps[i]);
+               return retval;
+       }
+
+       /**
+        * Destroys all objects related to the connection
+        * including the process that was tied to this
+        * session via SessionManager.launch(), if it
+        * exists.
+        */
+       public void terminate()
+       {
+               boolean playerWillTerminateItself = false;
+
+               // unbind first
+               try
+               {
+                       // Tell player to end session.  Note that this is just 
a hint, and will often
+                       // do nothing.  For example, the Flash player running 
in a browser will
+                       // currently never terminate when you tell it to, but 
the AIR player will
+                       // terminate.
+                       playerWillTerminateItself = unbind(true);
+               } catch(Exception e)
+               {
+               }
+
+               if (!playerWillTerminateItself)
+               {
+                       if 
(System.getProperty("os.name").toLowerCase().startsWith("mac os x")) 
//$NON-NLS-1$ //$NON-NLS-2$
+                       {
+                               if (m_airLaunchInfo != null)
+                               {
+                                       // nothing we need to do -- 
Process.destroy() will kill the AIR app
+                               }
+                               else if (m_launchUrl != null && 
m_launchUrl.length() > 0)
+                               {
+                                       boolean closedAnyWindows = false;
+                                       Set<String> runningApps = 
runningApplications();
+
+                                       if (!closedAnyWindows && 
runningApps.contains("Safari")) //$NON-NLS-1$
+                                       {
+                                               try {
+                                                       String url = 
m_launchUrl.replaceAll(" ", "%20"); //$NON-NLS-1$ //$NON-NLS-2$
+                                                       String 
safariClosedAnyWindows = executeAppleScript("appleScriptCloseSafariWindow.txt", 
new String[] { url }); //$NON-NLS-1$
+                                                       if 
("true".equals(safariClosedAnyWindows)) { //$NON-NLS-1$                         
                                     
+                                                               
closedAnyWindows = true;                                                        
        
+                                                       }
+                                                       else if ( 
"appquit".equals(safariClosedAnyWindows) ) { //$NON-NLS-1$
+                                                               
closedAnyWindows = true;
+                                                               //we closed 
Safari, verify safari was closed
+                                                               runningApps = 
waitForMacAppQuit("Safari"); //$NON-NLS-1$
+                                                       }
+                                               } catch (IOException e) {
+                                                       // ignore
+                                               }
+                                       }
+                                                                               
+                                       if (!closedAnyWindows && 
runningApps.contains("Camino")) //$NON-NLS-1$
+                                       {
+                                               // For local file: URLs, Camino 
uses "file://localhost/..." instead of "file:///..."
+                                               String url = 
m_launchUrl.replaceFirst("^file:///", "file://localhost/"); //$NON-NLS-1$ 
//$NON-NLS-2$
+                                               try {
+                                                       String 
caminoClosedAnyWindows = executeAppleScript("appleScriptCloseCaminoWindow.txt", 
new String[] { url }); //$NON-NLS-1$
+                                                       if 
("true".equals(caminoClosedAnyWindows)) { //$NON-NLS-1$                         
                                     
+                                                               
closedAnyWindows = true;
+                                                       }
+                                                       else if ( 
"appquit".equals(caminoClosedAnyWindows) ) { //$NON-NLS-1$
+                                                               
closedAnyWindows = true;
+                                                               //we closed 
camino, verify camino was closed
+                                                               runningApps = 
waitForMacAppQuit("Camino"); //$NON-NLS-1$
+                                                       }
+                                                               
+                                               } catch (IOException e) {
+                                                       // ignore
+                                               }
+                                       }
+
+                                       // The standalone player on the Mac has 
gone through several name changes,
+                                       // so we have to look for all of these.
+                                       String[] macStandalonePlayerNames =
+                                       {
+                                               "Flash Player Debugger",        
// New name as of Player 10.1   //$NON-NLS-1$
+                                               "Flash Player",                 
        // New name as of 12/4/06               //$NON-NLS-1$
+                                               "SAFlashPlayer",                
        // An older name                                //$NON-NLS-1$
+                                               "standalone"                    
        // Another older name                   //$NON-NLS-1$
+                                       };
+
+                                       for (int i=0; !closedAnyWindows && 
i<macStandalonePlayerNames.length; ++i)
+                                       {
+                                               if 
(runningApps.contains(macStandalonePlayerNames[i]))
+                                               {
+                                                       executeAppleScript(new 
String[] { "tell application \"" + macStandalonePlayerNames[i] + "\" to quit" 
}, null); //$NON-NLS-1$ //$NON-NLS-2$
+                                                       
waitForMacAppQuit(macStandalonePlayerNames[i]);
+                                                       closedAnyWindows = true;
+                                               }
+                                       }
+                               }
+                       }
+
+                       // if we have a process pop it
+                       if (m_process != null)
+                       {
+                               try
+                               {
+                                       //if a launcher is set for handling the 
launcher operations then use it.
+                                       if(null != launcher)
+                                       {
+                                               
m_debuggerCallbacks.terminateDebugTarget(m_process,launcher);
+                                       }
+                                       else
+                                       {
+                                               
m_debuggerCallbacks.terminateDebugTarget(m_process);
+                                       }
+                               }
+                               catch (IOException e)
+                               {
+                                       // ignore
+                               }
+                       }
+               }
+               else if (m_process != null) {
+                       try {
+                               m_process.waitFor();
+                       }
+                       catch (Exception e) {
+                       }
+               }
+
+               // now clear it all
+               m_isConnected = false;
+               m_isHalted = false;
+       }
+
+       /**
+        * Utility function to wait for a mac application to quit.
+        * This waits for a maximum of MAX_TERMINATE_WAIT_MILLIS.
+        * 
+        * Waiting is important because applescript "quit" is not
+        * synchronous and launching a URL while the browser is
+        * quitting is not good. (See FB-21879)
+        * @return Set<String> of running applications.
+        */
+       private Set<String> waitForMacAppQuit(String browser) {
+               Set<String> runningApps;
+               boolean appClosed = true;
+               final long startMillis = System.currentTimeMillis();            
+               final long waitMillis = 100;
+               do {
+                       runningApps = runningApplications();
+                       if ( runningApps.contains(browser) ) {
+                               appClosed = false;
+                               
+                               try {
+                                       Thread.sleep(waitMillis);               
                        
+                               } catch (InterruptedException e) {
+                                       return runningApps;
+                               }
+                               
+                               long currentMillis = System.currentTimeMillis();
+                               
+                               if ( currentMillis - startMillis >= 
MAX_TERMINATE_WAIT_MILLIS )
+                                       break;
+                       }
+                       else {
+                               appClosed = true;
+                       }
+               }
+               while ( !appClosed );
+               return runningApps;
+       }
+
+       /*
+        * @see flash.tools.debugger.Session#resume()
+        */
+       public void resume() throws NotSuspendedException, 
NotConnectedException, NoResponseException
+       {
+               resumeWorker(Isolate.DEFAULT_ID);
+       }
+
+       /*
+        * @see flash.tools.debugger.Session#suspend()
+        */
+       public void suspend() throws SuspendedException, NotConnectedException, 
NoResponseException
+       {
+               suspendWorker(Isolate.DEFAULT_ID);
+       }
+
+       /**
+        * Obtain all the suspend information
+        */
+       public DSuspendInfo getSuspendInfo()
+       {
+               return getSuspendInfoIsolate(Isolate.DEFAULT_ID);
+       }
+
+       /**
+        * Return the reason that the player has suspended itself.
+        */
+       public int suspendReason()
+       {
+               DSuspendInfo info = getSuspendInfo();
+               return info.getReason();
+       }
+
+       /**
+        * Return the offset in which the player has suspended itself.  The 
BreakReason
+        * message contains both reason and offset.
+        */
+       public int getSuspendOffset()
+       {
+               DSuspendInfo info = getSuspendInfo();
+               return info.getOffset();
+       }
+
+       /**
+        * Return the offset in which the player has suspended itself.  The 
BreakReason
+        * message contains both reason and offset.
+        */
+       public int getSuspendActionIndex()
+       {
+               DSuspendInfo info = getSuspendInfo();
+               return info.getActionIndex();
+       }
+
+       /**
+        * Obtain information about the various SWF(s) that have been
+        * loaded into the Player, for this session.
+        *
+        * Note: As SWFs are loaded by the Player a SwfLoadedEvent is
+        * fired.  At this point, a call to getSwfInfo() will provide
+        * updated information.
+        *
+        * @return array of records describing the SWFs
+        */
+       public SwfInfo[] getSwfs() throws NoResponseException
+       {
+               return getSwfsWorker(Isolate.DEFAULT_ID);
+       }
+
+       /**
+        * Request information on a particular swf, used by DSwfInfo
+        * to fill itself correctly
+        */
+       public void requestSwfInfo(int at, int isolateId) throws 
NoResponseException
+       {
+               // nope don't have it...might as well go out and ask for all of 
them.
+               DMessage dm = DMessageCache.alloc(4);
+               dm.setType( DMessage.OutSwfInfo );
+               dm.setTargetIsolate(isolateId);
+               dm.putWord(at);
+               dm.putWord(0);  // rserved
+
+               int to = 
getPreference(SessionManager.PREF_CONTEXT_RESPONSE_TIMEOUT);
+
+               if (!simpleRequestResponseMessage(dm, DMessage.InSwfInfo, to))
+                       throw new NoResponseException(to);
+       }
+
+       /**
+        * Request a set of actions from the player
+        */
+       public byte[] getActions(int which, int at, int len) throws 
NoResponseException
+       {
+               byte[] actions = null;
+
+               // send a actions message
+               DMessage dm = DMessageCache.alloc(12);
+               dm.setType( DMessage.OutGetActions );
+               dm.putWord(which);
+               dm.putWord(0); // rsrvd
+               dm.putDWord(at);
+               dm.putDWord(len);
+
+               // request action bytes
+               int to = 
getPreference(SessionManager.PREF_CONTEXT_RESPONSE_TIMEOUT);
+               if (simpleRequestResponseMessage(dm, DMessage.InGetActions, to))
+                       actions = m_manager.getActions();
+               else
+                       throw new NoResponseException(to);
+
+               return actions;
+       }
+
+       /*
+        * @see flash.tools.debugger.Session#stepInto()
+        */
+       public void stepInto() throws NotSuspendedException, 
NoResponseException, NotConnectedException
+       {
+               stepIntoWorker(Isolate.DEFAULT_ID);
+       }
+
+       /*
+        * @see flash.tools.debugger.Session#stepOut()
+        */
+       public void stepOut() throws NotSuspendedException, 
NoResponseException, NotConnectedException
+       {
+               stepOutWorker(Isolate.DEFAULT_ID);
+       }
+
+       /*
+        * @see flash.tools.debugger.Session#stepOver()
+        */
+       public void stepOver() throws NotSuspendedException, 
NoResponseException, NotConnectedException
+       {
+               stepOverWorker(Isolate.DEFAULT_ID);
+       }
+
+       /*
+        * @see flash.tools.debugger.Session#stepContinue()
+        */
+       public void stepContinue() throws NotSuspendedException, 
NoResponseException, NotConnectedException
+       {
+               if (!isSuspended())
+                       throw new NotSuspendedException();
+
+               // send a step-continue message and then wait for the Flash 
player to tell us that is has
+               // resumed execution
+               if (!simpleRequestResponseMessage(DMessage.OutStepContinue, 
DMessage.InContinue))
+                       throw new 
NoResponseException(getPreference(SessionManager.PREF_RESPONSE_TIMEOUT));
+       }
+
+    /**
+     * Sends a request to the player to obtain function names.
+     * The resultant message end up populating the function name array
+     * for the given DModule.
+     *
+     * @param moduleId
+     * @param lineNbr
+     * @return
+     */
+    public void requestFunctionNames(int moduleId, int lineNbr, int isolateId) 
throws VersionException, NoResponseException
+    {
+        // only player 9 supports this message
+        if (m_manager.getVersion() >= 9)
+        {
+            DMessage dm = DMessageCache.alloc(8);
+            dm.setType(DMessage.OutGetFncNames);
+            dm.setTargetIsolate(isolateId);
+            dm.putDWord(moduleId);
+            dm.putDWord(lineNbr);
+
+            if (!simpleRequestResponseMessage(dm, DMessage.InGetFncNames))
+                throw new NoResponseException(0);
+        }
+        else
+        {
+            throw new VersionException();
+        }
+    }
+
+       /**
+        * From a given file identifier return a source file object
+        */
+       public SourceFile getFile(int fileId, int isolateId)
+       {
+               return m_manager.getSource(fileId, isolateId);
+       }
+
+       /**
+        * Get a list of breakpoints
+        */
+       public Location[] getBreakpointList()
+       {
+               return m_manager.getBreakpoints(Isolate.DEFAULT_ID);
+       }
+
+       /*
+        * @see flash.tools.debugger.Session#setBreakpoint(int, int)
+        */
+       public Location setBreakpoint(int fileId, int lineNum) throws 
NoResponseException, NotConnectedException
+       {
+               return setBreakpointWorker(fileId, lineNum, Isolate.DEFAULT_ID);
+       }
+
+       /*
+        * @see 
flash.tools.debugger.Session#clearBreakpoint(flash.tools.debugger.Location)
+        */
+       public Location clearBreakpoint(Location local)
+       {
+               /* first find it */
+               SourceFile source = local.getFile();
+               int fileId = source.getId();
+               int lineNum = local.getLine();
+               int bp = DLocation.encodeId(fileId, lineNum);
+               int isolateId = local.getIsolateId();
+               Location l = null;
+               l = m_manager.getBreakpoint(bp, isolateId);
+               
+               if (l != null)
+               {
+                       /* send the message */
+                       int wideLineSize = 0;
+                       if (supportsWideLineNumbers())
+                               wideLineSize = 4;
+                       DMessage dm = DMessageCache.alloc(8 + wideLineSize);
+                       dm.setType(DMessage.OutRemoveBreakpoints);
+                       dm.setTargetIsolate(isolateId);
+                       dm.putDWord(1);
+                       if (!supportsWideLineNumbers())
+                               dm.putDWord(bp);
+                       else {
+                               dm.putDWord(fileId);
+                               dm.putDWord(lineNum);
+                       }
+                       sendMessage(dm);
+
+                       /* no callback from the player so we remove it 
ourselves */
+                       m_manager.removeBreakpoint(bp, isolateId);
+               }
+               return l;
+       }
+
+       /*
+        * @see flash.tools.debugger.Session#getWatchList()
+        */
+       public Watch[] getWatchList() throws NoResponseException, 
NotConnectedException
+       {
+               return getWatchListWorker(Isolate.DEFAULT_ID);
+       }
+       
+       /*
+        * @see flash.tools.debugger.Session#getWatchList()
+        */
+       public Watch[] getWatchListWorker(int isolateId) throws 
NoResponseException, NotConnectedException
+       {
+                       return m_manager.getWatchpoints(isolateId);
+       }
+
+       private Watch setWatch(long varId, String memberName, int kind, int 
isolateId) throws NoResponseException, NotConnectedException, 
NotSupportedException
+       {
+               // we really have two cases here, one where we add a completely 
new
+               // watchpoint and the other where we modify an existing one.
+               // In either case the DManager logic is such that the last 
watchpoint
+               // in the list will contain our id if successful.
+               Watch w = null;
+               int tag = m_watchTransactionTag++;
+
+               if (addWatch(varId, memberName, kind, tag, isolateId))
+               {
+                       // good that we got a response now let's check that
+                       // it actually worked.
+                       int count = m_manager.getWatchpointCount(isolateId);
+                       if (count > 0)
+                       {
+                               DWatch lastWatch = 
m_manager.getWatchpoint(count-1, isolateId);
+                               if (lastWatch.getTag() == tag)
+                                       w = lastWatch;
+                       }
+               }
+               return w;
+       }
+       
+       /*
+        * @see 
flash.tools.debugger.Session#setWatch(flash.tools.debugger.Variable, 
java.lang.String, int)
+        */
+       public Watch setWatch(Value v, String memberName, int kind) throws 
NoResponseException, NotConnectedException, NotSupportedException
+       {
+               return setWatch(v.getId(), memberName, kind, v.getIsolateId());
+       }
+
+       public Watch setWatch(Watch watch) throws NoResponseException, 
NotConnectedException, NotSupportedException
+       {
+               return setWatch(watch.getValueId(), watch.getMemberName(), 
watch.getKind(), watch.getIsolateId());
+       }
+
+       /*
+        * @see 
flash.tools.debugger.Session#clearWatch(flash.tools.debugger.Watch)
+        */
+       public Watch clearWatch(Watch watch) throws NoResponseException, 
NotConnectedException
+       {
+               Watch[] list = getWatchListWorker(watch.getIsolateId());
+               Watch w = null;
+               if ( removeWatch(watch.getValueId(), watch.getMemberName(), 
watch.getIsolateId()) )
+               {
+                       // now let's first check the size of the list, it
+                       // should now be one less
+                       if (m_manager.getWatchpointCount(watch.getIsolateId()) 
< list.length)
+                       {
+                               // ok we made a change. So let's compare list 
and see which
+                               // one went away
+                               Watch[] newList = 
getWatchListWorker(watch.getIsolateId());
+                               for(int i=0; i<newList.length; i++)
+                               {
+                                       // where they differ is the missing one
+                                       if (list[i] != newList[i])
+                                       {
+                                               w = list[i];
+                                               break;
+                                       }
+                               }
+
+                               // might be the last one...
+                               if (w == null)
+                                       w = list[list.length-1];
+                       }
+               }
+               return w;
+       }
+
+       /*
+        * @see flash.tools.debugger.Session#getVariableList()
+        */
+       public Variable[] getVariableList() throws NotSuspendedException, 
NoResponseException, NotConnectedException, VersionException
+       {
+               return getVariableListWorker(Isolate.DEFAULT_ID);
+       }
+       
+       public Variable[] getVariableListWorker(int isolateId) throws 
NotSuspendedException, NoResponseException, NotConnectedException, 
VersionException
+       {
+               // make sure the player has stopped and send our message 
awaiting a response
+               if (!isWorkerSuspended(isolateId))
+                       throw new NotSuspendedException();
+
+               requestFrame(0, isolateId);  // our 0th frame gets our local 
context
+
+               // now let's request all of the special variables too
+               getValueWorker(Value.GLOBAL_ID, isolateId);
+               getValueWorker(Value.THIS_ID, isolateId);
+               getValueWorker(Value.ROOT_ID, isolateId);
+
+               // request as many levels as we can get
+               int i = 0;
+               Value v = null;
+               do
+               {
+                       v = getValueWorker(Value.LEVEL_ID-i, isolateId);
+               }
+               while( i++ < 128 && v != null);
+
+               // now that we've primed the DManager we can request the base 
variable whose
+               // children are the variables that are available
+               v = m_manager.getValue(Value.BASE_ID, isolateId);
+               if (v == null)
+                       throw new VersionException();
+               return v.getMembers(this);
+       }
+
+       /*
+        * @see flash.tools.debugger.Session#getFrames()
+        */
+       public Frame[] getFrames() throws NotConnectedException
+       {
+               return m_manager.getFrames(Isolate.DEFAULT_ID);
+       }
+
+       /**
+        * Asks the player to return information regarding our current context 
which includes
+        * this pointer, arguments for current frame, locals, etc.
+        */
+       public void requestFrame(int depth, int isolateId) throws 
NotSuspendedException, NoResponseException, NotConnectedException
+       {
+               if (playerSupportsGet())
+               {
+                       if (!isWorkerSuspended(isolateId))
+                               throw new NotSuspendedException();
+
+                       int timeout = 
getPreference(SessionManager.PREF_CONTEXT_RESPONSE_TIMEOUT);
+
+                       DMessage dm = DMessageCache.alloc(4);
+                       dm.setType(DMessage.OutGetFrame);
+                       dm.setTargetIsolate(isolateId);
+                       dm.putDWord(depth);  // depth of zero
+                       if (!simpleRequestResponseMessage(dm,  
DMessage.InFrame, timeout)) {
+                               throw new NoResponseException(timeout);
+                       }
+
+                       pullUpActivationObjectVariables(depth, isolateId);
+               }
+       }
+       
+       /**
+        * The compiler sometimes creates special local variables called
+        * "activation objects."  When it decides to do this (e.g. if the
+        * current function contains any anonymous functions, try/catch
+        * blocks, complicated E4X expressions, or "with" clauses), then
+        * all locals and arguments are actually stored as children of
+        * this activation object, rather than the usual way.
+        *
+        * We need to hide this implementation detail from the user.  So,
+        * if we find any activation objects among the locals of the current
+        * function, then we will "pull up" its members, and represent them
+        * as if they were actually args/locals of the function itself.
+        *
+        * @param depth the depth of the stackframe we are fixing; 0 is topmost
+        */
+       private void pullUpActivationObjectVariables(int depth, int isolateId) 
throws NotSuspendedException, NoResponseException, NotConnectedException
+       {
+               DValue frame = m_manager.getValue(Value.BASE_ID-depth, 
isolateId);
+               if (frame == null)
+                       return;
+               DStackContext context = m_manager.getFrame(depth, isolateId);   
        
+               DVariable[] frameVars = (DVariable[]) frame.getMembers(this);
+               Map<String, DVariable> varmap = new LinkedHashMap<String, 
DVariable>(frameVars.length); // preserves order
+               List<DVariable> activationObjects = new ArrayList<DVariable>();
+               Pattern activationObjectNamePattern = 
Pattern.compile("^.*\\$\\d+$"); //$NON-NLS-1$
+
+               // loop through all frame variables, and separate them into two
+               // groups: activation objects, and all others (locals and 
arguments)
+               for (int i=0; i<frameVars.length; ++i)
+               {
+                       DVariable member = frameVars[i];
+                       Matcher matcher = 
activationObjectNamePattern.matcher(member.getName());
+                       if (matcher.matches())
+                               activationObjects.add(member);
+                       else
+                               varmap.put(member.getName(), member);
+               }
+
+               // If there are no activation objects, then we don't need to do 
anything
+               if (activationObjects.size() == 0)
+                       return;
+
+               // overwrite existing args and locals with ones pulled from the 
activation objects
+               for (int i=0; i<activationObjects.size(); ++i)
+               {
+                       DVariable activationObject = activationObjects.get(i);
+                       DVariable[] activationMembers = (DVariable[]) 
activationObject.getValue().getMembers(this);
+                       for (int j=0; j<activationMembers.length; ++j)
+                       {
+                               DVariable member = activationMembers[j];
+                               int attributes = member.getAttributes();
+
+                               // For some odd reason, the activation object 
often contains a whole bunch of
+                               // other variables that we shouldn't be 
displaying.  I don't know what they
+                               // are, but I do know that they are all marked 
"static".
+                               if ((attributes & VariableAttribute.IS_STATIC) 
!= 0)
+                                       continue;
+
+                               // No matter what the activation object 
member's scope is, we want all locals
+                               // and arguments to be considered "public"
+                               attributes &= ~(VariableAttribute.PRIVATE_SCOPE 
| VariableAttribute.PROTECTED_SCOPE | VariableAttribute.NAMESPACE_SCOPE);
+                               attributes |= VariableAttribute.PUBLIC_SCOPE;
+                               member.setAttributes(attributes);
+
+                               String name = member.getName();
+                               DVariable oldvar = varmap.get(name);
+                               int vartype;
+                               if (oldvar != null)
+                                       vartype = oldvar.getAttributes() & 
(VariableAttribute.IS_ARGUMENT | VariableAttribute.IS_LOCAL);
+                               else
+                                       vartype = VariableAttribute.IS_LOCAL;
+                               member.setAttributes(member.getAttributes() | 
vartype);
+                               varmap.put(name, member);
+                       }
+
+                       
context.convertLocalToActivationObject(activationObject);
+               }
+
+               for (DVariable var: varmap.values())
+               {
+                       frame.addMember(var);
+                       if (var.isAttributeSet(VariableAttribute.IS_LOCAL))
+                       {
+                               context.addLocal(var);
+                       }
+                       else if 
(var.isAttributeSet(VariableAttribute.IS_ARGUMENT))
+                       {
+                               if (var.getName().equals("this")) //$NON-NLS-1$
+                                       context.setThis(var);
+                               else
+                                       context.addArgument(var);
+                       }
+               }
+       }
+
+       /*
+        * @see flash.tools.debugger.Session#getValue(int)
+        */
+       public Value getValue(long valueId) throws NotSuspendedException, 
NoResponseException, NotConnectedException
+       {
+               return getValueWorker(valueId, Isolate.DEFAULT_ID);
+       }
+       
+       public Value getValueWorker(long valueId, int isolateId) throws 
NotSuspendedException, NoResponseException, NotConnectedException
+       {
+               DValue val = null;
+
+               if (!isWorkerSuspended(isolateId))
+                       throw new NotSuspendedException();
+
+               // get it from cache if we can
+               val = m_manager.getValue(valueId, isolateId);
+
+               if (val == null)
+               {
+                       // if a special variable, then we need to trigger a 
local frame call, otherwise just use id to get it
+                       if (valueId < Value.UNKNOWN_ID)
+                       {
+                               requestFrame(0, isolateId); // force our 
current frame to get populated, BASE_ID will be available
+                       }
+                       else if (valueId > Value.UNKNOWN_ID)
+                       {
+                               requestVariable(valueId, null, isolateId);
+                       }
+
+                       // after all this we should have our variable cache'd 
so try again if it wasn't there the first time
+                       val = m_manager.getValue(valueId, isolateId);
+               }
+
+               return val;
+       }
+
+       /**
+        * Returns the current value object for the given id; never requests it 
from the player.
+        */
+       public Value getRawValue(long valueId, int isolateId)
+       {
+               return m_manager.getValue(valueId, isolateId);
+       }
+
+       /**
+        * Returns the previous value object for the given id -- that is, the 
value that that
+        * object had the last time the player was suspended.  Never requests 
it from the
+        * player (because it can't, of course).  Returns <code>null</code> if 
we don't have
+        * a value for that id.
+        */
+       public Value getPreviousValue(long valueId, int isolateId)
+       {
+               return m_manager.getPreviousValue(valueId, isolateId);
+       }
+
+       /**
+        * Launches a request to obtain all the members of the specified 
variable, and
+        * store them in the variable which would be returned by
+        * {@link DManager#getVariable(long)}.
+        *
+        * @param valueId id of variable whose members we want; underlying 
Variable must
+        * already be known by the PlayerSessionManager.
+        *
+        * @throws NoResponseException
+        * @throws NotConnectedException
+        * @throws NotSuspendedException
+        */
+       void obtainMembers(long valueId, int isolateId) throws 
NoResponseException, NotConnectedException, NotSuspendedException
+       {
+               if (!isWorkerSuspended(isolateId))
+                       throw new NotSuspendedException();
+
+               // Get it from cache.  Normally, this should never fail; 
however, in
+               // the case of Flex Builder, which is multithreaded, it is 
possible
+               // that a thread has called this even after a different thread 
has
+               // single-stepped, so that the original variable is no longer 
valid.
+               // So, we'll check for a null return value.
+               DValue v = m_manager.getValue(valueId, isolateId);
+
+               if (v != null && !v.membersObtained())
+               {
+                       requestVariable(valueId, null, false, true, isolateId);
+               }
+       }
+
+       public Value getGlobal(String name) throws NotSuspendedException, 
NoResponseException, NotConnectedException
+       {
+               return getGlobalWorker(name, Isolate.DEFAULT_ID);
+       }
+       
+       public Value getGlobalWorker(String name, int isolateId) throws 
NotSuspendedException, NoResponseException, NotConnectedException
+       {
+               Value v = getValue(0, name, isolateId);
+
+               if (v==null || v.getType() == VariableType.UNDEFINED)
+                       return null;
+               else
+                       return v;
+       }
+
+       /**
+        * Get the value of the variable named 'name' using varId
+        * as the context id for the Variable.
+        *
+        * This call is used to fire getters, where the id must
+        * be that of the original object and not the object id
+        * of where the getter actually lives.  For example
+        * a getter a() may live under o.__proto__.__proto__
+        * but you must use the id of o and the name of 'a'
+        * in order for the getter to fire correctly.  [Note: This
+        * paragraph was written for AS2; __proto__ doesn't exist
+        * in AS3.  TODO: revise this paragraph]
+        */
+       public Value getValue(long varId, String name, int isolateId) throws 
NotSuspendedException, NoResponseException, NotConnectedException
+       {
+               Value v = null;
+               if (isWorkerSuspended(isolateId))
+               {
+                       int fireGetter = 
getPreference(SessionManager.PREF_INVOKE_GETTERS);
+
+                       // disable children attaching to parent variables and 
clear our
+                       // most recently seen variable
+                       m_manager.clearLastVariable(isolateId);
+                       m_manager.enableChildAttach(false, isolateId);
+
+                       try
+                       {
+                               requestVariable(varId, name, (fireGetter != 0), 
false, isolateId);
+
+                               DVariable lastVariable = 
m_manager.lastVariable(isolateId);
+                               if (lastVariable != null)
+                                       v = lastVariable.getValue();
+                               else
+                                       v = 
DValue.forPrimitive(Value.UNDEFINED, isolateId);
+                       }
+                       catch (NoResponseException e)
+                       {
+                               if (fireGetter != 0)
+                               {
+                                       // We fired a getter -- most likely, 
what happened is that that getter
+                                       // (which is actual code in the user's 
movie) just took too long to
+                                       // calculate its value.  So rather than 
throwing an exception, we store
+                                       // some error text for the value of the 
variable itself.
+                                       //
+                                       // TODO [mmorearty 4/20/06] Even though 
I wrote the below code, I now
+                                       // am wondering if it is incorrect that 
I am calling addVariableMember(),
+                                       // because in every other case, this 
function does not add members to
+                                       // existing objects.  Need to revisit 
this.
+                                       v = new DValue(VariableType.STRING, 
"String", "String", ValueAttribute.IS_EXCEPTION, //$NON-NLS-1$ //$NON-NLS-2$
+                                                       
e.getLocalizedMessage(), isolateId);
+                                       if (varId != 0) {
+                                               DVariable var = new 
DVariable(name, (DValue)v, isolateId);
+                                               
m_manager.enableChildAttach(true, isolateId);
+                                               
m_manager.addVariableMember(varId, var, isolateId);
+                                       }
+                               }
+                               else
+                               {
+                                       throw e; // re-throw
+                               }
+                       }
+                       finally
+                       {
+                               // reset our attach flag, so that children 
attach to parent variables.
+                               m_manager.enableChildAttach(true, isolateId);
+                       }
+               }
+               else
+                       throw new NotSuspendedException();
+
+               return v;
+       }
+
+       private void requestVariable(long id, String name, int isolateId) 
throws NoResponseException, NotConnectedException, NotSuspendedException
+       {
+               requestVariable(id, name, false, false, isolateId);
+       }
+
+       /**
+        * @param thisValue the value of the "this" pointer; meaningless if 
isConstructor is true
+        * @param isConstructor whether we're calling a constructor as opposed 
to a regular function
+        * @param funcname the name of the function to call (or class whose 
constructor we're calling)
+        * @param args the args to the function
+        * @return the return value of the function
+        */
+       private Value callFunction(Value thisValue, boolean isConstructor, 
String funcname, Value[] args, int isolateId) throws PlayerDebugException
+       {
+               if (!isWorkerSuspended(isolateId))
+                       throw new NotSuspendedException();
+
+               if (!playerCanCallFunctions(isolateId))
+                       throw new 
NotSupportedException(PlayerSessionManager.getLocalizationManager().getLocalizedTextString("functionCallsNotSupported"));
 //$NON-NLS-1$
+
+               // name = getRawMemberName(id, name);
+
+               m_manager.clearLastFunctionCall(isolateId);
+
+               DMessage dm = buildCallFunctionMessage(isConstructor, 
thisValue, funcname, args);
+
+               dm.setTargetIsolate(isolateId);
+               
+               // make sure any exception during the setter gets held onto
+               m_manager.beginPlayerCodeExecution(isolateId);
+
+               // TODO wrong timeout
+               int timeout = 
getPreference(SessionManager.PREF_GETVAR_RESPONSE_TIMEOUT);
+               timeout += 500; // give the player enough time to raise its 
timeout exception
+
+               boolean result = simpleRequestResponseMessage(dm, 
DMessage.InCallFunction, timeout);
+
+               // tell manager we're done; ignore returned FaultEvent
+               m_manager.endPlayerCodeExecution(isolateId);
+
+               if (!result)
+                       throw new NoResponseException(timeout);
+
+               DVariable lastFunctionCall = 
m_manager.lastFunctionCall(isolateId);
+               if (lastFunctionCall != null)
+                       return lastFunctionCall.getValue();
+               else
+                       return DValue.forPrimitive(Value.UNDEFINED, isolateId);
+       }
+
+       /*
+        * @see 
flash.tools.debugger.Session#callFunction(flash.tools.debugger.Value, 
java.lang.String, flash.tools.debugger.Value[])
+        */
+       public Value callFunction(Value thisValue, String funcname, Value[] 
args) throws PlayerDebugException
+       {
+               return callFunctionWorker(thisValue, funcname, args, 
Isolate.DEFAULT_ID);
+       }
+       
+       public Value callFunctionWorker(Value thisValue, String funcname, 
Value[] args, int isolateId) throws PlayerDebugException
+       {
+               Value retval = callPseudoFunction(thisValue, funcname, args, 
isolateId);
+               if (retval != null) {
+                       return retval;
+               }
+
+               return callFunction(thisValue, false, funcname, args, 
isolateId);
+       }
+
+       /**
+        * Checks to see if the function being called is a debugger 
pseudofunction such as
+        * $obj(), and if so, handles that directly rather than calling the 
player.  Returns
+        * null if the function being called is not a pseudofunction.
+        */
+       private Value callPseudoFunction(Value thisValue, String funcname, 
Value[] args, int isolateId) throws PlayerDebugException{
+               if (thisValue.getType() == VariableType.UNDEFINED || 
thisValue.getType() == VariableType.NULL) {
+                       if ("$obj".equals(funcname)) { //$NON-NLS-1$
+                               return callObjPseudoFunction(args, isolateId);
+                       }
+               }
+
+               return null;
+       }
+
+       /**
+        * Handles a call to the debugger pseudofunction $obj() -- e.g. 
$obj(1234) returns
+        * a pointer to the object with id 1234.
+        */
+       private Value callObjPseudoFunction(Value[] args, int isolateId) throws 
PlayerDebugException {
+               if (args.length != 1) {
+                       return DValue.forPrimitive(DValue.UNDEFINED, isolateId);
+               }
+               double arg = ECMA.toNumber(this, args[0]);
+               long id = (long) arg;
+               if (id != arg) {
+                       return DValue.forPrimitive(DValue.UNDEFINED, isolateId);
+               }
+               DValue value = m_manager.getValue(id, isolateId);
+               if (value == null) {
+                       return DValue.forPrimitive(DValue.UNDEFINED, isolateId);
+               }
+               return value;
+       }
+
+       public Value callConstructor(String funcname, Value[] args) throws 
PlayerDebugException
+       {
+               return callConstructorWorker(funcname, args, 
Isolate.DEFAULT_ID);
+       }
+       
+       public Value callConstructorWorker(String funcname, Value[] args, int 
isolateId) throws PlayerDebugException
+       {
+               return callFunction(DValue.forPrimitive(null, isolateId), true, 
funcname, args, isolateId);
+       }
+
+       private DMessage buildCallFunctionMessage(boolean isConstructor, Value 
thisValue, String funcname, Value[] args)
+       {
+               funcname = (funcname == null) ? "" : funcname; //$NON-NLS-1$
+
+               int messageSize = 8; // DWORD representing flags + DWORD 
representing frame
+               String thisType = DVariable.typeNameFor(thisValue.getType());
+               String thisValueString = thisValue.getValueAsString();
+               messageSize += DMessage.getStringLength(thisType)+1;
+               messageSize += DMessage.getStringLength(thisValueString)+1;
+               messageSize += DMessage.getStringLength(funcname)+1;
+               messageSize += 4; // DWORD representing the number of args
+               String[] argTypes = new String[args.length];
+               String[] argValues = new String[args.length];
+               for (int i=0; i<args.length; ++i)
+               {
+                       argTypes[i] = DVariable.typeNameFor(args[i].getType());
+                       argValues[i] = args[i].getValueAsString();
+                       messageSize += DMessage.getStringLength(argValues[i])+1;
+                       messageSize += DMessage.getStringLength(argTypes[i])+1;
+               }
+
+               DMessage dm = DMessageCache.alloc(messageSize);
+               dm.setType(DMessage.OutCallFunction);
+               try
+               {
+                       dm.putDWord(isConstructor ? 1 : 0);
+                       dm.putDWord(0); // TODO: the currently active frame 
number
+                       dm.putString(thisType);
+                       dm.putString(thisValueString);
+                       dm.putString(funcname);
+                       dm.putDWord(args.length);
+                       for (int i=0; i<args.length; ++i)
+                       {
+                               dm.putString(argTypes[i]);
+                               dm.putString(argValues[i]);
+                       }
+               }
+               catch(UnsupportedEncodingException uee)
+               {
+                       // couldn't write out the string, so just terminate it 
and complete anyway
+                       dm.putByte((byte)'\0');
+               }
+
+               return dm;
+       }
+
+       private void requestVariable(long id, String name, boolean fireGetter, 
boolean alsoGetChildren, int isolateId) throws NoResponseException, 
NotConnectedException, NotSuspendedException
+       {
+               if (!isWorkerSuspended(isolateId))
+                       throw new NotSuspendedException();
+
+               name = getRawMemberName(id, name, isolateId);
+
+               DMessage dm = buildOutGetMessage(id, name, fireGetter, 
alsoGetChildren);
+
+               dm.setTargetIsolate(isolateId);
+               
+               // make sure any exception during the setter gets held onto
+               m_manager.beginPlayerCodeExecution(isolateId);
+
+               int timeout = 
getPreference(SessionManager.PREF_GETVAR_RESPONSE_TIMEOUT);
+               timeout += 500; // give the player enough time to raise its 
timeout exception
+
+               boolean result = simpleRequestResponseMessage(dm, 
DMessage.InGetVariable, timeout);
+
+               // tell manager we're done; ignore returned FaultEvent
+               m_manager.endPlayerCodeExecution(isolateId);
+
+               if (!result)
+                       throw new NoResponseException(timeout);
+       }
+
+       private DMessage buildOutGetMessage(long id, String name, boolean 
fireGetter, boolean alsoGetChildren)
+       {
+               final int FLAGS_SIZE = 4;
+               name = (name == null) ? "" : name; //$NON-NLS-1$
+
+               DMessage dm = DMessageCache.alloc(DMessage.getSizeofPtr() + 
DMessage.getStringLength(name)+1 + FLAGS_SIZE);
+               dm.setType( (!fireGetter) ? DMessage.OutGetVariable : 
DMessage.OutGetVariableWhichInvokesGetter );
+               dm.putPtr(id);
+               try
+               {
+                       dm.putString(name);
+               }
+               catch(UnsupportedEncodingException uee)
+               {
+                       // couldn't write out the string, so just terminate it 
and complete anyway
+                       dm.putByte((byte)'\0');
+               }
+
+               // as an optimization, newer player builds allow us to tell 
them not to
+               // send all the children of an object along with the object, 
because
+               // frequently we don't care about the children
+               int flags = GetVariableFlag.DONT_GET_FUNCTIONS; // we never 
want functions
+               if (fireGetter)
+                       flags |= GetVariableFlag.INVOKE_GETTER;
+               if (alsoGetChildren)
+                       flags |= GetVariableFlag.ALSO_GET_CHILDREN | 
GetVariableFlag.GET_CLASS_HIERARCHY;
+               dm.putDWord(flags);
+
+               return dm;
+       }
+
+       public FaultEvent setScalarMember(long varId, String memberName, int 
type, String value, int isolateId) throws NotSuspendedException, 
NoResponseException, NotConnectedException
+       {
+               if (!isWorkerSuspended(isolateId))
+                       throw new NotSuspendedException();
+
+               // If the varId is that of a stack frame, then we need to check 
whether that
+               // stack frame has an "activation object".  If it does, then 
all of the
+               // arguments and locals are actually kept as members of that 
activation
+               // object, and so we need to change varId to be the ID of that 
activation
+               // object -- that way, the player will modify the member of the 
activation
+               // object rather than modifying the "regular" argument or 
local.  See bug
+               // 155031.
+               if (varId <= Value.BASE_ID && varId > Value.LEVEL_ID)
+               {
+                       int depth = (int) (Value.BASE_ID - varId);
+                       DStackContext context = 
m_manager.getFrame(depth,isolateId);
+                       DVariable activationObject = 
context.getActivationObject();
+                       if (activationObject != null)
+                               varId = activationObject.getValue().getId();
+               }
+
+               memberName = getRawMemberName(varId, memberName, isolateId);
+
+               // see if it is our any of our special variables
+               FaultEvent faultEvent = requestSetVariable( 
isPseudoVarId(varId) ? 0 : varId, memberName, type, value, isolateId);
+
+               // now that we sent it out, we need to clear our variable cache
+               // if it is our special context then mark the frame as stale.
+               if (isPseudoVarId(varId) && m_manager.getFrameCount(isolateId) 
> 0)
+               {
+                       m_manager.getFrame(0, isolateId).markStale();
+               }
+               else
+               {
+                       DValue parent = m_manager.getValue(varId,isolateId);
+                       if (parent != null)
+                               parent.removeAllMembers();
+               }
+
+               return faultEvent;
+       }
+
+       /**
+        * Returns whether a variable ID is "real" or not.  For example,
+        * Value.THIS_ID is a "pseudo" varId, as are all the other special
+        * hard-coded varIds in the Value class.
+        */
+       private boolean isPseudoVarId(long varId)
+       {
+               /*
+                * Unfortunately, this is actually just taking a guess.  The 
old code
+                * used "varId &lt; 0"; however, the Linux player sometimes has 
real
+                * variable IDs which are less than zero.
+                */
+               return (varId < 0 && varId > -65535);
+       }
+
+       /**
+        * <code>memberName</code> might be just <code>"varname"</code>, or it
+        * might be <code>"namespace::varname"</code>, or it might be
+        * <code>"namespace@hexaddr::varname"</code>.  In the third case, it is
+        * fully resolved, and there is nothing we need to do.  But in the first
+        * and second cases, we may need to fully resolve it so that the Player
+        * will recognize it.
+        */
+       private String getRawMemberName(long parentValueId, String memberName, 
int isolateId)
+       {
+               if (memberName != null)
+               {
+                       DValue parent = m_manager.getValue(parentValueId, 
isolateId);
+                       if (parent != null)
+                       {
+                               int doubleColon = memberName.indexOf("::"); 
//$NON-NLS-1$
+                               String shortName = (doubleColon==-1) ? 
memberName : memberName.substring(doubleColon+2);
+                               DVariable member = parent.findMember(shortName);
+                               if (member != null)
+                                       memberName = member.getRawName();
+                       }
+               }
+               return memberName;
+       }
+
+       /**
+        * @return null for success, or fault event if a setter in the player 
threw an exception
+        */
+       private FaultEvent requestSetVariable(long id, String name, int t, 
String value, int isolateId) throws NoResponseException
+       {
+               // convert type to typeName
+               String type = DVariable.typeNameFor(t);
+               DMessage dm = buildOutSetMessage(id, name, type, value);
+               dm.setTargetIsolate(isolateId);
+               FaultEvent faultEvent = null;
+//             System.out.println("setmsg 
id="+id+",name="+name+",t="+type+",value="+value);
+
+               // make sure any exception during the setter gets held onto
+               m_manager.beginPlayerCodeExecution(isolateId);
+
+               // turn off squelch so we can hear the response
+               sendSquelch(false, isolateId);
+
+               int timeout = 
getPreference(SessionManager.PREF_GETVAR_RESPONSE_TIMEOUT);
+
+               if (!simpleRequestResponseMessage(dm, (t == 
VariableType.STRING) ? DMessage.InSetVariable : DMessage.InSetVariable2, 
timeout))
+                       throw new 
NoResponseException(getPreference(SessionManager.PREF_RESPONSE_TIMEOUT));
+
+               // turn it back on
+               sendSquelch(true, isolateId);
+
+               // tell manager we're done, and get exception if any
+               faultEvent = m_manager.endPlayerCodeExecution(isolateId);
+
+               // hammer the variable cache and context array
+               m_manager.freeValueCache(isolateId);
+               return faultEvent;
+       }
+
+       private DMessage buildOutSetMessage(long id, String name, String type, 
String v)
+       {
+               DMessage dm = DMessageCache.alloc(DMessage.getSizeofPtr()+
+                               DMessage.getStringLength(name)+
+                               DMessage.getStringLength(type)+
+                               DMessage.getStringLength(v)+
+                               3);
+               dm.setType(DMessage.OutSetVariable);
+               dm.putPtr(id);
+               try { dm.putString(name); } catch(UnsupportedEncodingException 
uee) { dm.putByte((byte)'\0'); }
+               try { dm.putString(type); } catch(UnsupportedEncodingException 
uee) { dm.putByte((byte)'\0'); }
+               try { dm.putString(v); } catch(UnsupportedEncodingException 
uee) { dm.putByte((byte)'\0'); }
+               return dm;
+       }
+
+       /*
+        * @see flash.tools.debugger.Session#waitForEvent()
+        */
+       public void waitForEvent() throws NotConnectedException, 
InterruptedException
+       {
+               Object eventNotifier = m_manager.getEventNotifier();
+               synchronized (eventNotifier)
+               {
+                       while (getEventCount() == 0 && isConnected())
+                       {
+                               eventNotifier.wait();
+                       }
+               }
+
+               // We should NOT call isConnected() to test for a broken 
connection!  That
+               // is because we may have received one or more events AND lost 
the connection,
+               // almost simultaneously.  If there are any messages available 
for the
+               // caller to process, we should not throw an exception.
+               if (getEventCount() == 0 && !isConnected())
+                       throw new NotConnectedException();
+       }
+
+       /*
+        * @see flash.tools.debugger.Session#getEventCount()
+        */
+       public int getEventCount()
+       {
+               return m_manager.getEventCount();
+       }
+
+       /*
+        * @see flash.tools.debugger.Session#nextEvent()
+        */
+       public DebugEvent nextEvent()
+       {
+               return m_manager.nextEvent();
+       }
+
+       /**
+        * Adds a watchpoint on the given expression
+        * @throws NotConnectedException
+        * @throws NoResponseException
+        * @throws NotSupportedException
+        * @throws NotSuspendedException
+        */
+       public boolean addWatch(long varId, String varName, int type, int tag, 
int isolateId) throws NoResponseException, NotConnectedException, 
NotSupportedException
+       {
+               // TODO check for NoResponse, NotConnected
+
+               if (!supportsWatchpoints(isolateId))
+                       throw new 
NotSupportedException(PlayerSessionManager.getLocalizationManager().getLocalizedTextString("watchpointsNotSupported"));
 //$NON-NLS-1$
+
+               varName = getRawMemberName(varId, varName, isolateId);
+               DMessage dm = 
DMessageCache.alloc(4+DMessage.getSizeofPtr()+DMessage.getStringLength(varName)+1);
+               dm.setType(DMessage.OutAddWatch2);
+               dm.setTargetIsolate(isolateId);
+               dm.putPtr(varId);
+               try { dm.putString(varName); } 
catch(UnsupportedEncodingException uee) { dm.putByte((byte)'\0'); }
+               dm.putWord(type);
+               dm.putWord(tag);
+
+               int timeout = 
getPreference(SessionManager.PREF_GETVAR_RESPONSE_TIMEOUT);
+               boolean result = simpleRequestResponseMessage(dm, 
DMessage.InWatch2, timeout);
+               return result;
+       }
+
+       /**
+        * Removes a watchpoint on the given expression
+        * @throws NotConnectedException
+        * @throws NoResponseException
+        * @throws NotSuspendedException
+        */
+       public boolean removeWatch(long varId, String memberName, int 
isolateId) throws NoResponseException, NotConnectedException
+       {
+               memberName = getRawMemberName(varId, memberName, isolateId);
+               DMessage dm = 
DMessageCache.alloc(DMessage.getSizeofPtr()+DMessage.getStringLength(memberName)+1);
+               dm.setType(DMessage.OutRemoveWatch2);
+               dm.putPtr(varId);
+               try { dm.putString(memberName); } 
catch(UnsupportedEncodingException uee) { dm.putByte((byte)'\0'); }
+
+               int timeout = 
getPreference(SessionManager.PREF_GETVAR_RESPONSE_TIMEOUT);
+               boolean result = simpleRequestResponseMessage(dm, 
DMessage.InWatch2, timeout);
+               return result;
+       }
+
+       /**
+        * Send a message that contains no data
+        */
+       void sendMessage(int message)
+       {
+               DMessage dm = DMessageCache.alloc(0);
+               dm.setType(message);
+               sendMessage(dm);
+       }
+       
+       /**
+        * Send a message that contains no data
+        */
+       void sendMessageIsolate(int message, int isolateId)
+       {
+               DMessage dm = DMessageCache.alloc(0);
+               dm.setTargetIsolate(isolateId);
+               dm.setType(message);
+               sendMessage(dm);
+       }
+
+       /**
+        * Send a fully formed message and release it when done
+        */
+       synchronized void sendMessage(DMessage dm)
+       {
+               try
+               {
+                       if (dm.getType() != DMessage.OutSetActiveIsolate) {
+                               int isolate = dm.getTargetIsolate();
+                               if (isolate != getActiveIsolate().getId()) {
+                                       DMessage dm1 = DMessageCache.alloc(4);
+                                       dm1.setTargetIsolate(isolate);
+                                       
dm1.setType(DMessage.OutSetActiveIsolate);
+                                       dm1.putDWord(isolate);
+
+                                       /* Use sendMessage here to avoid 
waiting for a response. 
+                                        * The assumption is that once the 
message is sent, subsequent
+                                        * messages are for that isolate 
regardless of the player confirming
+                                        * it. With this change, performance 
has improved considerably; player
+                                        * debugger has not gone out of sync 
since the ProcessTag messages
+                                        * flood issue was resolved. */
+                                       sendMessage(dm1);
+
+                                       
m_manager.setActiveIsolate(m_manager.getIsolate(isolate));
+
+                               }
+                       }
+                       m_protocol.txMessage(dm);
+
+                       if (m_debugMsgOn || m_debugMsgFileOn)
+                               trace(dm, false);
+               }
+               catch(IOException io)
+               {
+                       if (Trace.error)
+                       {
+                               Trace.trace("Attempt to send message 
"+dm.outToString()+" failed"); //$NON-NLS-1$ //$NON-NLS-2$
+                               io.printStackTrace();
+                       }
+               }
+               DMessageCache.free(dm);
+       }
+
+       /**
+        * Tell the player to shut-up
+        */
+       boolean sendSquelch(boolean on, int isolateId)
+       {
+               boolean responded;
+               DMessage dm = DMessageCache.alloc(4);
+               dm.setType(DMessage.OutSetSquelch);
+               dm.setTargetIsolate(isolateId);
+               dm.putDWord( on ? 1 : 0);
+               responded = simpleRequestResponseMessage(dm, 
DMessage.InSquelch);
+               return responded;
+       }
+
+       void sendStopWarning()
+       {
+               // Currently, "disable_script_stuck_dialog" only works for AS2, 
not for AS3.
+               String option = "disable_script_stuck_dialog"; //$NON-NLS-1$
+               String value = "on"; //$NON-NLS-1$
+
+               sendOptionMessage(option, value);
+
+               // HACK: Completely disable the script-stuck notifications, so 
that we can
+               // get AS3 debugging working.
+               option = "disable_script_stuck"; //$NON-NLS-1$
+               value = "on"; //$NON-NLS-1$
+
+               sendOptionMessage(option, value);
+       }
+
+       void sendStopOnFault()
+       {
+               String option = "break_on_fault"; //$NON-NLS-1$
+               String value = "on"; //$NON-NLS-1$
+
+               sendOptionMessage(option, value);
+       }
+
+       void sendEnumerateOverride()
+       {
+               String option = "enumerate_override"; //$NON-NLS-1$
+               String value = "on"; //$NON-NLS-1$
+
+               sendOptionMessage(option, value);
+       }
+
+       void sendFailureNotify()
+       {
+               String option = "notify_on_failure"; //$NON-NLS-1$
+               String value = "on"; //$NON-NLS-1$
+
+               sendOptionMessage(option, value);
+       }
+
+       void sendInvokeSetters()
+       {
+               String option = "invoke_setters"; //$NON-NLS-1$
+               String value = "on"; //$NON-NLS-1$
+
+               sendOptionMessage(option, value);
+       }
+
+       void sendSwfloadNotify()
+       {
+               String option = "swf_load_messages"; //$NON-NLS-1$
+               String value = "on"; //$NON-NLS-1$
+
+               sendOptionMessage(option, value);
+       }
+
+       void sendConsoleErrorsAsTrace(boolean on)
+       {
+               String option = "console_errors"; //$NON-NLS-1$
+               String value = (on) ? "on" : "off"; //$NON-NLS-1$ //$NON-NLS-2$
+
+               sendOptionMessage(option, value);
+       }
+
+       void sendGetterTimeout()
+       {
+               String option = "getter_timeout"; //$NON-NLS-1$
+               String value = "" + 
getPreference(SessionManager.PREF_GETVAR_RESPONSE_TIMEOUT); //$NON-NLS-1$
+
+               sendOptionMessage(option, value);
+       }
+
+       void sendSetterTimeout()
+       {
+               String option = "setter_timeout"; //$NON-NLS-1$
+               String value = "" + 
getPreference(SessionManager.PREF_SETVAR_RESPONSE_TIMEOUT); //$NON-NLS-1$
+
+               sendOptionMessage(option, value);
+       }
+       
+       void sendConcurrentDebugger()
+       {
+               String option = "concurrent_debugger"; //$NON-NLS-1$
+               String value = "on"; //$NON-NLS-1$
+
+               sendOptionMessage(option, value);
+       }
+       
+       void sendWideLineDebugger()
+       {
+               String option = "wide_line_debugger"; //$NON-NLS-1$
+               String value = "on"; //$NON-NLS-1$
+
+               sendOptionMessage(option, value);
+               m_manager.setWideLines(true);
+       }
+
+       void sendOptionMessage(String option, String value)
+       {
+               int msgSize = 
DMessage.getStringLength(option)+DMessage.getStringLength(value)+2;  // add 2 
for trailing nulls of each string
+
+               DMessage dm = DMessageCache.alloc(msgSize);
+               dm.setType(DMessage.OutSetOption);
+               try { dm.putString(option); } 
catch(UnsupportedEncodingException uee) { dm.putByte((byte)'\0'); }
+               try { dm.putString(value); } catch(UnsupportedEncodingException 
uee) { dm.putByte((byte)'\0'); }
+               simpleRequestResponseMessage(dm, DMessage.InOption);
+       }
+
+       public boolean supportsWatchpoints()
+       {
+               return supportsWatchpoints(Isolate.DEFAULT_ID);
+       }
+       
+       public boolean supportsWatchpoints(int isolateId)
+       {
+               if (m_playerSupportsWatchpoints == null)
+                       m_playerSupportsWatchpoints = new 
Boolean(getOption("can_set_watchpoints", false, isolateId)); //$NON-NLS-1$
+               return m_playerSupportsWatchpoints.booleanValue();
+       }
+
+       public boolean playerCanBreakOnAllExceptions()
+       {
+               return playerCanBreakOnAllExceptions(Isolate.DEFAULT_ID);
+       }
+       
+       public boolean playerCanBreakOnAllExceptions(int isolateId)
+       {
+               if (m_playerCanBreakOnAllExceptions == null)
+                       m_playerCanBreakOnAllExceptions = new 
Boolean(getOption("can_break_on_all_exceptions", false, isolateId)); 
//$NON-NLS-1$
+               return m_playerCanBreakOnAllExceptions.booleanValue();
+       }
+       
+       public boolean supportsConcurrency(int isolateId)
+       {
+               if (m_playerSupportsConcurrency == null)
+                       m_playerSupportsConcurrency = new 
Boolean(getOption("concurrent_player", false, isolateId)); //$NON-NLS-1$
+               return m_playerSupportsConcurrency.booleanValue();
+       }
+       
+       public boolean supportsConcurrency()
+       {
+               return supportsConcurrency(Isolate.DEFAULT_ID);
+       }
+       
+       public boolean supportsWideLineNumbers()
+       {
+               return supportsWideLineNumbers(Isolate.DEFAULT_ID);
+       }
+       
+       public boolean supportsWideLineNumbers(int isolateId)
+       {
+               if (m_playerSupportsWideLine == null)
+                       m_playerSupportsWideLine = new 
Boolean(getOption("wide_line_player", false, isolateId)); //$NON-NLS-1$
+               return m_playerSupportsWideLine.booleanValue();
+       }
+
+       public boolean playerCanTerminate()
+       {
+               return getOption("can_terminate", false, Isolate.DEFAULT_ID); 
//$NON-NLS-1$
+       }
+
+       public boolean playerCanCallFunctions()
+       {
+               return playerCanCallFunctions(Isolate.DEFAULT_ID);
+       }
+       
+       public boolean playerCanCallFunctions(int isolateId)
+       {
+               if (m_playerCanCallFunctions == null)
+                       m_playerCanCallFunctions = new 
Boolean(getOption("can_call_functions", false, isolateId)); //$NON-NLS-1$
+               return m_playerCanCallFunctions.booleanValue();
+       }
+
+       /**
+        * Returns the value of a Flash Player boolean option that was 
requested by
+        * OutGetOption and returned by InOption.
+        *
+        * @param optionName
+        *            the name of the option
+        * @return its value, or null
+        */
+       public boolean getOption(String optionName, boolean defaultValue, int 
isolateId)
+       {
+               boolean retval = defaultValue;
+               String optionValue = getOption(optionName, null, isolateId);
+
+               if (optionValue != null)
+                       retval = Boolean.valueOf(optionValue).booleanValue();
+
+               return retval;
+       }
+
+       /**
+        * Returns the value of a Flash Player string option that was requested 
by
+        * OutGetOption and returned by InOption.
+        *
+        * @param optionName
+        *            the name of the option
+        * @return its value, or null
+        */
+       public String getOption(String optionName, String defaultValue, int 
isolateId)
+       {
+               String optionValue = defaultValue;
+
+               int msgSize = DMessage.getStringLength(optionName)+1;  // add 1 
for trailing null of string
+
+               DMessage dm = DMessageCache.alloc(msgSize);
+               dm.setTargetIsolate(isolateId);
+               dm.setType(DMessage.OutGetOption);
+               try { dm.putString(optionName); } 
catch(UnsupportedEncodingException uee) { dm.putByte((byte)'\0'); }
+               if (simpleRequestResponseMessage(dm, DMessage.InOption))
+                       optionValue = m_manager.getOption(optionName);
+               return optionValue;
+       }
+       
+       long getMessageInCount(DMessageCounter counter, long isolate, int 
msgType) {
+               if (isolate == Isolate.DEFAULT_ID) {
+                       return counter.getInCount(msgType);
+               }
+               else {
+                       return counter.getIsolateInCount(isolate, msgType);
+               }
+       }
+       
+       Object getMessageInLock(DMessageCounter counter, long isolate) {
+               if (isolate == Isolate.DEFAULT_ID) {
+                       return counter.getInLock();
+               }
+               else {
+                       return counter.getIsolateInLock(isolate);
+               }
+       }
+
+       /**
+        * Send our message and assume that the next response that is received 
is
+        * ours.  Primitive but there is no use in setting up a full request / 
response
+        * pattern since the player doesn't follow it.
+        *
+        * @return false is no response.
+        */
+       boolean simpleRequestResponseMessage(DMessage msg, int msgType, int 
timeout)
+       {
+               boolean response = false;
+
+               //FIXME: Check if timeout needs to adjust to the isolate 
switching
+               // delay
+               // use default or user supplied timeout
+               timeout = (timeout > 0) ? timeout : 
getPreference(SessionManager.PREF_RESPONSE_TIMEOUT);
+
+               // note the number of messages of this type before our send
+               DMessageCounter msgCounter = getMessageCounter();
+               int isolate = msg.getTargetIsolate();
+               long num = getMessageInCount(msgCounter, isolate, msgType);
+               long expect = num+1;
+
+               // send the message
+               sendMessage(msg);
+
+               long startTime = System.currentTimeMillis();
+//             System.out.println("sending- 
"+DMessage.outTypeName(msg.getType())+",timeout="+timeout+",start="+start);
+
+               // now wait till we see a message come in
+               m_incoming = false;
+               synchronized (getMessageInLock(msgCounter, isolate))
+               {
+                       while( (expect > getMessageInCount(msgCounter, isolate, 
msgType)) &&
+                                       System.currentTimeMillis() < startTime 
+ timeout &&
+                                       isConnected())
+                       {
+                               // block until the message counter tells us 
that some message has been received
+                               try
+                               {
+                                       getMessageInLock(msgCounter, 
isolate).wait(timeout);
+                               }
+                               catch (InterruptedException e)
+                               {
+                                       // this should never happen
+                                       e.printStackTrace();
+                                       //FIXME: Will resetting the interrupted 
status here
+                                       //cause any problems?
+//                         Thread.currentThread().interrupt();
+                               }
+
+                               // if we see incoming messages, then we should 
reset our timeout
+                               synchronized (this)
+                               {
+                                       if (m_incoming)
+                                       {
+                                               startTime = 
System.currentTimeMillis();
+                                               m_incoming = false;
+                                       }
+                               }
+                       }
+               }
+
+               if (getMessageInCount(msgCounter, isolate, msgType) >= expect)
+                       response = true;
+               else if (timeout <= 0 && Trace.error)
+                       Trace.trace("Timed-out waiting for 
"+DMessage.inTypeName(msgType)+" response to message "+msg.outToString()); 
//$NON-NLS-1$ //$NON-NLS-2$
+
+//             long endTime = System.currentTimeMillis();
+//             System.out.println("    response- 
"+response+",timeout="+timeout+",elapsed="+(endTime-startTime));
+               m_lastResponse = response;
+               return response;
+       }
+
+       // use default timeout
+       boolean simpleRequestResponseMessage(DMessage msg, int msgType)         
{ return simpleRequestResponseMessage(msg, msgType, -1);        }
+       
+       boolean simpleRequestResponseMessageIsolate(DMessage msg, int msgType, 
int isolateId)   { 
+               return simpleRequestResponseMessageIsolate(msg, msgType, -1, 
isolateId);                        
+       }
+       
+       boolean simpleRequestResponseMessageIsolate(DMessage msg, int msgType, 
int timeout, int isolateId)
+       {
+               msg.setTargetIsolate(isolateId);
+               return simpleRequestResponseMessage(msg, msgType, timeout);
+       }
+       
+       boolean simpleRequestResponseMessage(int msg, int msgType)              
        { return simpleRequestResponseMessage(msg, msgType, -1);        }
+       
+       boolean simpleRequestResponseMessageIsolate(int msg, int msgType, int 
isolateId) { 
+               return simpleRequestResponseMessageIsolate(msg, msgType, -1, 
isolateId);
+       }
+
+       boolean simpleRequestResponseMessageIsolate(int msg, int msgType, int 
timeout, int isolateId)
+       {
+               DMessage dm = DMessageCache.alloc(0);
+               dm.setType(msg);
+               dm.setTargetIsolate(isolateId);
+               return simpleRequestResponseMessage(dm, msgType, timeout);
+       }
+       
+       // Convenience function
+       boolean simpleRequestResponseMessage(int msg, int msgType, int timeout)
+       {
+               DMessage dm = DMessageCache.alloc(0);
+               dm.setType(msg);
+               return simpleRequestResponseMessage(dm, msgType, timeout);
+       }
+
+       /**
+        * We register ourself as a listener to DMessages from the pipe for the
+        * sole purpose of monitoring the state of the debugger.  All other
+        * object management occurs with DManager
+        */
+       /**
+        * Issued when the socket connection to the player is cut
+        */
+       public void disconnected()
+       {
+               m_isHalted = false;
+               m_isConnected = false;
+               m_manager.disconnected();
+       }
+
+       /**
+        * This is the core routine for decoding incoming messages and deciding 
what should be
+        * done with them.  We have registered ourself with DProtocol to be 
notified when any
+        * incoming messages have been received.
+        *
+        * It is important to note that we should not rely on the contents of 
the message
+        * since it may be reused after we exit this method.
+        */
+       public void messageArrived(DMessage msg, DProtocol which)
+       {
+               preMessageArrived(msg, which);
+               msg.reset(); // allow the message to be re-parsed
+               m_manager.messageArrived(msg, which);
+               msg.reset(); // allow the message to be re-parsed
+               postMessageArrived(msg, which);
+       }
+
+       /**
+        * Processes the message before it is passed to the DManager.
+        */
+       private void preMessageArrived(DMessage msg, DProtocol which)
+       {
+               switch (msg.getType())
+               {
+               case DMessage.InIsolate:
+
+                               m_lastPreIsolate = (int)msg.getDWord();
+                       
+                       break;
+               
+                       case DMessage.InAskBreakpoints:
+                       case DMessage.InBreakAt:
+                       case DMessage.InBreakAtExt:
+                       {
+                               // We need to set m_isHalted to true before the 
DManager processes
+                               // the message, because the DManager may add a 
BreakEvent to the
+                               // event queue, which the host debugger may 
immediately process;
+                               // if the debugger calls back to the Session, 
the Session must be
+                               // correctly marked as halted.
+                               if (m_lastPreIsolate == Isolate.DEFAULT_ID)
+                                       m_isHalted = true;
+                               else
+                                       
updateHaltIsolateStatus(m_lastPreIsolate, true);
+                               break;
+                       }
+               }
+       }
+
+       /**
+        * Processes the message after it has been passed to the DManager.
+        */
+       private void postMessageArrived(DMessage msg, DProtocol which)
+       {
+               if (m_debugMsgOn || m_debugMsgFileOn)
+                       trace(msg, true);
+
+               /* at this point we just open up a big switch statement and 
walk through all possible cases */
+               int type = msg.getType();
+               switch(type)
+               {
+                       case DMessage.InExit:
+                       {
+                               m_isConnected = false;
+                               break;
+                       }
+
+                       case DMessage.InProcessTag:
+                       {
+                               // need to send a response to this message to 
keep the player going
+                               sendMessageIsolate(DMessage.OutProcessedTag, 
msg.getTargetIsolate());
+                               break;
+                       }
+
+                       case DMessage.InContinue:
+                       {
+                               if (msg.getTargetIsolate() == 
Isolate.DEFAULT_ID)
+                                       m_isHalted = false;
+                               else {
+                                       
updateHaltIsolateStatus(msg.getTargetIsolate(), false);
+                               }
+                               break;
+                       }
+
+                       case DMessage.InOption:
+                       {
+                               //workers inherit options, so only store options
+                               //from main thread.
+                               if (msg.getTargetIsolate() == 
Isolate.DEFAULT_ID) {
+                                       String s = msg.getString();
+                                       String v = msg.getString();
+
+                                       // add it to our properties, for DEBUG 
purposes only
+                                       m_prefs.put(s, v);
+                               }
+                               break;
+                       }
+
+                       case DMessage.InSwfInfo:
+                       case DMessage.InScript:
+                       case DMessage.InRemoveScript:
+                       {
+                               //FIXME: Clear this cache only for affected
+                               //workers. Right now, the key contains worker
+                               //id, so we are safe. But we unnecessarily flush
+                               //the queue.
+                               m_evalIsAndInstanceofCache.clear();
+                               
+                               m_incoming = true;
+                               break;
+                       }
+
+                       default:
+                       {
+                               /**
+                                * Simple indicator that we have received a 
message.  We
+                                * put this indicator in default so that 
InProcessTag msgs
+                                * wouldn't generate false triggers.  Mainly, 
we want to
+                                * reset our timeout counter when we receive 
trace messages.
+                                */
+                               m_incoming = true;
+                               break;
+                       }
+               }
+
+               // something came in so assume that we can now talk
+               // to the player
+               m_lastResponse = true;
+       }
+
+    private void updateHaltIsolateStatus(int targetIsolate, boolean value) {
+       if (!m_isolateStatus.containsKey(targetIsolate)) {
+               PlayerSessionIsolateStatus status = new 
PlayerSessionIsolateStatus();
+               status.m_isHalted = value;
+               m_isolateStatus.put(targetIsolate, status);             
+       }
+       else {
+               m_isolateStatus.get(targetIsolate).m_isHalted = value;
+       }
+       }
+
+       /**
+     * A background thread which wakes up periodically and fetches the SWF and 
SWD
+     * from the Player for new movies that have loaded.  It then uses these to 
create
+        * an instance of MovieMetaData (a class shared with the Profiler) from 
which
+        * fdb can cull function names.
+     * This work is done on a background thread because it can take several
+     * seconds, and we want the fdb user to be able to execute other commands
+     * while it is happening.
+     */
+    public void run()
+    {
+       long last = 0;
+       while(isConnected())
+       {
+               // try every 250ms
+               try { Thread.sleep(250); } catch(InterruptedException ie) {}
+
+               try
+               {
+                       // let's make sure that the traffic level is low before
+                       // we do our requests.
+                       long current = m_protocol.messagesReceived();
+                       long delta = last - current;
+                       last = current;
+
+                       // if the last message that went out was not responded 
to
+                       // or we are not suspended and have high traffic
+                       // then wait for later.
+                       if (!m_lastResponse || (!isSuspended() && delta > 5))
+                               throw new NotSuspendedException();
+
+                       // we are either suspended or low enough traffic
+
+                       // get the list of swfs we have
+                       for (Isolate isolate : m_manager.getIsolates()) {
+                               int isolateId = isolate.getId();
+                               if (isolateId != Isolate.DEFAULT_ID && 
!isWorkerSuspended(isolateId) && delta > 5) {
+                                       throw new NotSuspendedException();
+                               }
+                               int count = 
m_manager.getSwfInfoCount(isolateId);
+                               for(int i=0; i<count; i++)
+                               {
+                                       DSwfInfo info = m_manager.getSwfInfo(i, 
isolateId);
+
+                                       // no need to process if it's been 
removed
+                                       if (info == null || info.isUnloaded() 
|| info.isPopulated() || (info.getVmVersion() > 0) )
+                                               continue;
+
+                                       // see if the swd has been loaded, 
throws exception if unable to load it.
+                                       // Also triggers a callback into the 
info object to freshen its contents
+                                       // if successful
+                                       //FIXME: remove sysout
+                                       info.getSwdSize(this);
+                                       // check since our vm version info 
could get updated in between.
+                                       if (info.getVmVersion() > 0)
+                                       {
+                                               // mark it populated if we 
haven't already done so
+                                               info.setPopulated();
+                                               continue;
+                                       }
+
+                                       // so by this point we know that we've 
got good swd data,
+                                       // or we've made too many attempts and 
gave up.
+                                       if (!info.isSwdLoading() && 
!info.isUnloaded())
+                                       {
+                                               // now load the swf, if we 
haven't already got it
+                                               if (info.getSwf() == null && 
!info.isUnloaded())
+                                                       
info.setSwf(requestSwf(i));
+
+                                               // only get the swd if we 
haven't got it
+                                               if (info.getSwd() == null && 
!info.isUnloaded())
+                                                       
info.setSwd(requestSwd(i));
+
+                                               try
+                                               {
+                                                       // now go populate the 
functions tables...
+                                                       if (!info.isUnloaded())
+                                                               
info.parseSwfSwd(m_manager);
+                                               }
+                                               catch(Throwable e)
+                                               {
+                                                       // oh this is not good 
and means that we should probably
+                                                       // give up.
+                                                       if (Trace.error)
+                                                       {
+                                                               
Trace.trace("Error while parsing swf/swd '"+info.getUrl()+"'. Giving up and 
marking it processed"); //$NON-NLS-1$ //$NON-NLS-2$
+                                                               
e.printStackTrace();
+                                                       }
+
+                                                       info.setPopulated();
+                                               }
+                                       }
+                               }
+                       }
+               }
+               catch(InProgressException ipe)
+               {
+                       // swd is still loading so give us a bit of
+                       // time and then come back and try again
+               }
+               catch(NoResponseException nre)
+               {
+                       // timed out on one of our requests so don't bother
+                       // continuing right now,  try again later
+               }
+               catch(NotSuspendedException nse)
+               {
+                       // probably want to wait until we are halted before
+                       // doing this heavy action
+               }
+               catch(Exception e)
+               {
+                       // maybe not good
+                       if (Trace.error)
+                       {
+                               Trace.trace("Exception in background swf/swd 
processing thread"); //$NON-NLS-1$
+                               e.printStackTrace();
+                       }
+               }
+       }
+    }
+
+       byte[] requestSwf(int index) throws NoResponseException
+       {
+               /* send the message */
+               int to = getPreference(SessionManager.PREF_SWFSWD_LOAD_TIMEOUT);
+               byte[] swf = null;
+
+               // the query
+               DMessage dm = DMessageCache.alloc(2);
+               dm.setType(DMessage.OutGetSwf);
+               dm.putWord(index);
+
+               if (simpleRequestResponseMessage(dm, DMessage.InGetSwf, to))
+                       swf = m_manager.getSWF();
+               else
+                       throw new NoResponseException(to);
+
+               return swf;
+       }
+
+       byte[] requestSwd(int index) throws NoResponseException
+       {
+               /* send the message */
+               int to = getPreference(SessionManager.PREF_SWFSWD_LOAD_TIMEOUT);
+               byte[] swd = null;
+
+               // the query
+               DMessage dm = DMessageCache.alloc(2);
+               dm.setType(DMessage.OutGetSwd);
+               dm.putWord(index);
+
+               if (simpleRequestResponseMessage(dm, DMessage.InGetSwd, to))
+                       swd = m_manager.getSWD();
+               else
+                       throw new NoResponseException(to);
+
+               return swd;
+       }
+
+       //
+       // Debug purposes only.  Dump contents of our messages to the screen
+       // and/or file.
+       //
+       synchronized void trace(DMessage dm, boolean in)
+       {
+               try
+               {
+                       if (m_debugMsgOn) {
+                               System.out.println( (in) ? 
dm.inToString(m_debugMsgSize) : dm.outToString(m_debugMsgSize) );
+                       }
+
+                       if (m_debugMsgFileOn)
+                       {
+                               traceFile().write( (in) ? 
dm.inToString(m_debugMsgFileSize) : dm.outToString(m_debugMsgFileSize) );
+                               m_trace.write(s_newline);
+                               m_trace.flush();
+                       }
+               }
+               catch(Exception e) {}
+       }
+
+       // i/o for tracing
+    java.io.Writer m_trace;
+       
+
+       java.io.Writer traceFile() throws IOException
+       {
+               if (m_trace == null)
+               {
+                       m_trace = new 
java.io.FileWriter("mm_debug_api_trace.txt"); //$NON-NLS-1$
+                       try { m_trace.write(new java.util.Date().toString()); } 
catch(Exception e) { m_trace.write("Date unknown"); } //$NON-NLS-1$
+                       try
+                       {
+                               m_trace.write(s_newline);
+
+                               // java properties dump
+                               java.util.Properties props = 
System.getProperties();
+                               props.list(new java.io.PrintWriter(m_trace));
+
+                               m_trace.write(s_newline);
+
+                               // property dump
+                               for (String key: m_prefs.keySet())
+                               {
+                                       Object value = m_prefs.get(key);
+                                       m_trace.write(key);
+                                       m_trace.write(" = "); //$NON-NLS-1$
+                                       m_trace.write(value.toString());
+                                       m_trace.write(s_newline);
+                               }
+                       }
+                       catch(Exception e) { if (Trace.error) 
e.printStackTrace(); }
+                       m_trace.write(s_newline);
+               }
+               return m_trace;
+       }
+
+       public void setLaunchUrl(String url)
+       {
+               if (url.startsWith("/")) { //$NON-NLS-1$
+                       url = "file://" + url; //$NON-NLS-1$
+               }
+               m_launchUrl = url;
+       }
+
+       public void setAIRLaunchInfo(AIRLaunchInfo airLaunchInfo)
+       {
+               m_airLaunchInfo = airLaunchInfo;
+       }
+
+       public void breakOnCaughtExceptions(boolean b) throws 
NotSupportedException, NoResponseException {
+               breakOnCaughtExceptions(b, Isolate.DEFAULT_ID);
+       }
+       
+       public void breakOnCaughtExceptions(boolean b, int isolateId) throws 
NotSupportedException, NoResponseException {
+               if (!playerCanBreakOnAllExceptions(isolateId))
+                       throw new 
NotSupportedException(PlayerSessionManager.getLocalizationManager().getLocalizedTextString("exceptionBreakpointsNotSupported"));
 //$NON-NLS-1$
+
+               DMessage dm = DMessageCache.alloc(1);
+               dm.setType(DMessage.OutPassAllExceptionsToDebugger);
+               dm.putByte((byte)(b ? 1 : 0));
+               dm.setTargetIsolate(isolateId);
+               /* TODO: Verify that sendMessage below is a bug */
+//             sendMessage(dm);
+               if (!simpleRequestResponseMessage(dm, 
DMessage.InPassAllExceptionsToDebugger))
+                       throw new 
NoResponseException(getPreference(SessionManager.PREF_RESPONSE_TIMEOUT));
+       }
+
+
+       public boolean evalIs(Value value, Value type) throws 
PlayerDebugException, PlayerFaultException
+       {
+               return evalIsOrInstanceof(BinaryOp.Is, value, type, 
Isolate.DEFAULT_ID);
+       }
+
+       public boolean evalIs(Value value, String type) throws 
PlayerDebugException, PlayerFaultException
+       {
+               return evalIsOrInstanceof(BinaryOp.Is, value, type, 
Isolate.DEFAULT_ID);
+       }
+
+       public boolean evalInstanceof(Value value, Value type) throws 
PlayerDebugException, PlayerFaultException
+       {
+               return evalIsOrInstanceof(BinaryOp.Instanceof, value, type, 
Isolate.DEFAULT_ID);
+       }
+
+       public boolean evalInstanceof(Value value, String type) throws 
PlayerDebugException, PlayerFaultException
+       {
+               return evalIsOrInstanceof(BinaryOp.Instanceof, value, type, 
Isolate.DEFAULT_ID);
+       }
+       
+       // isolate version
+       
+       public boolean evalIsWorker(Value value, Value type, int isolateId) 
throws PlayerDebugException, PlayerFaultException
+       {
+               return evalIsOrInstanceof(BinaryOp.Is, value, type, isolateId);
+       }
+
+       public boolean evalIsWorker(Value value, String type, int isolateId) 
throws PlayerDebugException, PlayerFaultException
+       {
+               return evalIsOrInstanceof(BinaryOp.Is, value, type, isolateId);
+       }
+
+       public boolean evalInstanceofWorker(Value value, Value type, int 
isolateId) throws PlayerDebugException, PlayerFaultException
+       {
+               return evalIsOrInstanceof(BinaryOp.Instanceof, value, type, 
isolateId);
+       }
+
+       public boolean evalInstanceofWorker(Value value, String type, int 
isolateId) throws PlayerDebugException, PlayerFaultException
+       {
+               return evalIsOrInstanceof(BinaryOp.Instanceof, value, type, 
isolateId);
+       }
+
+       private boolean evalIsOrInstanceof(BinaryOp op, Value value, Value 
type, int isolateId) throws PlayerDebugException, PlayerFaultException
+       {
+               String key = value.getTypeName() + " " + op + " " + 
type.getTypeName() + " " + String.valueOf(isolateId); //$NON-NLS-1$ 
//$NON-NLS-2$ //$NON-NLS-3$
+               Boolean retval = m_evalIsAndInstanceofCache.get(key);
+               if (retval == null)
+               {
+                       retval = new Boolean(ECMA.toBoolean(evalBinaryOp(op, 
value, type, isolateId)));
+                       m_evalIsAndInstanceofCache.put(key, retval);
+               }
+
+               return retval.booleanValue();
+       }
+
+       private boolean evalIsOrInstanceof(BinaryOp op, Value value, String 
type, int isolateId) throws PlayerDebugException, PlayerFaultException
+       {
+               String key = value.getTypeName() + " " + op + " " + type + " " 
+ String.valueOf(isolateId); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+               Boolean retval = m_evalIsAndInstanceofCache.get(key);
+               if (retval == null)
+               {
+                       Value typeval = getGlobalWorker(type, isolateId);
+                       if (typeval == null)
+                               retval = Boolea

<TRUNCATED>

Reply via email to