http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/07f5a7de/debugger/src/main/java/flash/tools/debugger/threadsafe/ThreadSafeLocation.java
----------------------------------------------------------------------
diff --git 
a/debugger/src/main/java/flash/tools/debugger/threadsafe/ThreadSafeLocation.java
 
b/debugger/src/main/java/flash/tools/debugger/threadsafe/ThreadSafeLocation.java
new file mode 100644
index 0000000..26d7824
--- /dev/null
+++ 
b/debugger/src/main/java/flash/tools/debugger/threadsafe/ThreadSafeLocation.java
@@ -0,0 +1,90 @@
+/*
+ * 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.threadsafe;
+
+import flash.tools.debugger.Location;
+import flash.tools.debugger.SourceFile;
+
+/**
+ * Thread-safe wrapper for flash.tools.debugger.Location
+ * @author Mike Morearty
+ */
+public class ThreadSafeLocation extends ThreadSafeDebuggerObject implements 
Location {
+
+       private Location fLocation;
+       
+       private ThreadSafeLocation(Object syncObj, Location location) {
+               super(syncObj);
+               fLocation = location;
+       }
+
+       /**
+        * Wraps a Location inside a ThreadSafeLocation.  If the passed-in 
Location
+        * is null, then this function returns null.
+        */
+       public static ThreadSafeLocation wrap(Object syncObj, Location 
location) {
+               if (location != null)
+                       return new ThreadSafeLocation(syncObj, location);
+               else
+                       return null;
+       }
+
+       /**
+        * Wraps an array of Locations inside an array of ThreadSafeLocations.
+        */
+       public static ThreadSafeLocation[] wrapArray(Object syncObj, Location[] 
locations) {
+               ThreadSafeLocation[] threadSafeLocations = new 
ThreadSafeLocation[locations.length];
+               for (int i=0; i<locations.length; ++i) {
+                       threadSafeLocations[i] = wrap(syncObj, locations[i]);
+               }
+               return threadSafeLocations;
+       }
+
+       /**
+        * Returns the raw Location underlying a ThreadSafeLocation.
+        */
+       public static Location getRaw(Location l) {
+               if (l instanceof ThreadSafeLocation)
+                       return ((ThreadSafeLocation)l).fLocation;
+               else
+                       return l;
+       }
+
+       public static Object getSyncObject(Location l) {
+               return ((ThreadSafeLocation)l).getSyncObject();
+       }
+
+       public SourceFile getFile() {
+               synchronized (getSyncObject()) {
+                       return ThreadSafeSourceFile.wrap(getSyncObject(), 
fLocation.getFile());
+               }
+       }
+       
+       public int getLine() {
+               synchronized (getSyncObject()) {
+                       return fLocation.getLine();
+               }
+       }
+
+       @Override
+       public int getIsolateId() {
+               synchronized (getSyncObject()) {
+                       return fLocation.getIsolateId();
+               }
+       }
+}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/07f5a7de/debugger/src/main/java/flash/tools/debugger/threadsafe/ThreadSafePlayer.java
----------------------------------------------------------------------
diff --git 
a/debugger/src/main/java/flash/tools/debugger/threadsafe/ThreadSafePlayer.java 
b/debugger/src/main/java/flash/tools/debugger/threadsafe/ThreadSafePlayer.java
new file mode 100644
index 0000000..ab27e10
--- /dev/null
+++ 
b/debugger/src/main/java/flash/tools/debugger/threadsafe/ThreadSafePlayer.java
@@ -0,0 +1,73 @@
+/*
+ * 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.threadsafe;
+
+import java.io.File;
+
+import flash.tools.debugger.Browser;
+import flash.tools.debugger.Player;
+
+/**
+ * Thread-safe wrapper for flash.tools.debugger.Player
+ * @author Mike Morearty
+ */
+public class ThreadSafePlayer extends ThreadSafeDebuggerObject implements 
Player {
+
+       private Player fPlayer;
+       
+       private ThreadSafePlayer(Object syncObj, Player player) {
+               super(syncObj);
+               fPlayer = player;
+       }
+
+       /**
+        * Wraps a Player inside a ThreadSafePlayer.  If the passed-in Player
+        * is null, then this function returns null.
+        */
+       public static Player wrap(Object syncObj, Player player) {
+               if (player != null)
+                       return new ThreadSafePlayer(syncObj, player);
+               else
+                       return null;
+       }
+
+       /*
+        * @see flash.tools.debugger.Player#getType()
+        */
+       public int getType() {
+               synchronized (getSyncObject()) {
+                       return fPlayer.getType();
+               }
+       }
+
+       /*
+        * @see flash.tools.debugger.Player#getPath()
+        */
+       public File getPath() {
+               synchronized (getSyncObject()) {
+                       return fPlayer.getPath();
+               }
+       }
+
+       public Browser getBrowser() {
+               synchronized (getSyncObject()) {
+                       return fPlayer.getBrowser();
+               }
+       }
+
+}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/07f5a7de/debugger/src/main/java/flash/tools/debugger/threadsafe/ThreadSafeSession.java
----------------------------------------------------------------------
diff --git 
a/debugger/src/main/java/flash/tools/debugger/threadsafe/ThreadSafeSession.java 
b/debugger/src/main/java/flash/tools/debugger/threadsafe/ThreadSafeSession.java
new file mode 100644
index 0000000..4d25e5d
--- /dev/null
+++ 
b/debugger/src/main/java/flash/tools/debugger/threadsafe/ThreadSafeSession.java
@@ -0,0 +1,435 @@
+/*
+ * 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.threadsafe;
+
+import flash.tools.debugger.Frame;
+import flash.tools.debugger.ILauncher;
+import flash.tools.debugger.Isolate;
+import flash.tools.debugger.IsolateSession;
+import flash.tools.debugger.Location;
+import flash.tools.debugger.NoResponseException;
+import flash.tools.debugger.NotConnectedException;
+import flash.tools.debugger.NotSupportedException;
+import flash.tools.debugger.NotSuspendedException;
+import flash.tools.debugger.PlayerDebugException;
+import flash.tools.debugger.Session;
+import flash.tools.debugger.SourceLocator;
+import flash.tools.debugger.SuspendedException;
+import flash.tools.debugger.SwfInfo;
+import flash.tools.debugger.Value;
+import flash.tools.debugger.Variable;
+import flash.tools.debugger.VersionException;
+import flash.tools.debugger.Watch;
+import flash.tools.debugger.events.DebugEvent;
+import flash.tools.debugger.expression.PlayerFaultException;
+
+/**
+ * Thread-safe wrapper for flash.tools.debugger.Session
+ * @author Mike Morearty
+ */
+public class ThreadSafeSession extends ThreadSafeDebuggerObject implements 
Session {
+
+       private Session fSession;
+
+       private ThreadSafeSession(Object syncObj, Session session) {
+               super(syncObj);
+               fSession = session;
+       }
+
+       /**
+        * Wraps a Session inside a ThreadSafeSession.  If the passed-in Session
+        * is null, then this function returns null.
+        */
+       public static ThreadSafeSession wrap(Object syncObj, Session session) {
+               if (session != null)
+                       return new ThreadSafeSession(syncObj, session);
+               else
+                       return null;
+       }
+
+       /**
+        * Returns the raw Session underlying a ThreadSafeSession.
+        */
+       public static Session getRaw(Session s) {
+               if (s instanceof ThreadSafeSession)
+                       return ((ThreadSafeSession)s).fSession;
+               else
+                       return s;
+       }
+
+       public static Object getSyncObject(Session s) {
+               return ((ThreadSafeSession)s).getSyncObject();
+       }
+
+       public boolean bind() throws VersionException {
+               synchronized (getSyncObject()) {
+                       return fSession.bind();
+               }
+       }
+
+       public Location clearBreakpoint(Location location)
+                       throws NoResponseException, NotConnectedException {
+               synchronized (getSyncObject()) {
+                       return ThreadSafeLocation.wrap(getSyncObject(), 
fSession.clearBreakpoint(ThreadSafeLocation.getRaw(location)));
+               }
+       }
+
+       public Watch clearWatch(Watch watch) throws NoResponseException,
+                       NotConnectedException {
+               synchronized (getSyncObject()) {
+                       return ThreadSafeWatch.wrap(getSyncObject(), 
fSession.clearWatch(ThreadSafeWatch.getRaw(watch)));
+               }
+       }
+
+       public Location[] getBreakpointList() throws NoResponseException,
+                       NotConnectedException {
+               synchronized (getSyncObject()) {
+                       return ThreadSafeLocation.wrapArray(getSyncObject(), 
fSession.getBreakpointList());
+               }
+       }
+
+       public int getEventCount() {
+               // Session.getEventCount() is guaranteed to be thread-safe, so 
we
+               // don't have to do a "synchronized" block around this call.
+               return fSession.getEventCount();
+       }
+
+       public Frame[] getFrames() throws NotConnectedException {
+               synchronized (getSyncObject()) {
+                       return ThreadSafeFrame.wrapArray(getSyncObject(), 
fSession.getFrames());
+               }
+       }
+
+       public Process getLaunchProcess() {
+               synchronized (getSyncObject()) {
+                       return fSession.getLaunchProcess();
+               }
+       }
+
+       public int getPreference(String pref) throws NullPointerException {
+               synchronized (getSyncObject()) {
+                       return fSession.getPreference(pref);
+               }
+       }
+
+       public SwfInfo[] getSwfs() throws NoResponseException {
+               synchronized (getSyncObject()) {
+                       return ThreadSafeSwfInfo.wrapArray(getSyncObject(), 
fSession.getSwfs());
+               }
+       }
+
+       public String getURI() {
+               synchronized (getSyncObject()) {
+                       return fSession.getURI();
+               }
+       }
+
+       public Value getValue(long valueId) throws NotSuspendedException,
+                       NoResponseException, NotConnectedException
+       {
+               synchronized (getSyncObject()) {
+                       return ThreadSafeValue.wrap(getSyncObject(), 
fSession.getValue(valueId));
+               }
+       }
+
+       /** @deprecated */
+       public Variable[] getVariableList() throws NotSuspendedException,
+                       NoResponseException, NotConnectedException, 
VersionException {
+               synchronized (getSyncObject()) {
+                       return ThreadSafeVariable.wrapArray(getSyncObject(), 
fSession.getVariableList());
+               }
+       }
+
+       public Watch[] getWatchList() throws NoResponseException,
+                       NotConnectedException {
+               synchronized (getSyncObject()) {
+                       return ThreadSafeWatch.wrapArray(getSyncObject(), 
fSession.getWatchList());
+               }
+       }
+
+       public boolean isConnected() {
+               // Session.isConnected() is guaranteed to be thread-safe, so we
+               // don't have to do a "synchronized" block around this call.
+               return fSession.isConnected();
+       }
+
+       public boolean isSuspended() throws NotConnectedException {
+               // Session.isSuspended() is guaranteed to be thread-safe, so we
+               // don't have to do a "synchronized" block around this call.
+               return fSession.isSuspended();
+       }
+
+       public DebugEvent nextEvent() {
+               synchronized (getSyncObject()) {
+                       return fSession.nextEvent();
+               }
+       }
+
+       public void resume() throws NotSuspendedException, 
NotConnectedException,
+                       NoResponseException {
+               synchronized (getSyncObject()) {
+                       fSession.resume();
+               }
+       }
+
+       public Location setBreakpoint(int fileId, int lineNum)
+                       throws NoResponseException, NotConnectedException {
+               synchronized (getSyncObject()) {
+                       return ThreadSafeLocation.wrap(getSyncObject(), 
fSession.setBreakpoint(fileId, lineNum));
+               }
+       }
+
+       public void setPreference(String pref, int value) {
+               synchronized (getSyncObject()) {
+                       fSession.setPreference(pref, value);
+               }
+       }
+
+       public Watch setWatch(Value v, String memberName, int kind)
+                       throws NoResponseException, NotConnectedException, 
NotSupportedException {
+               synchronized (getSyncObject()) {
+                       return ThreadSafeWatch.wrap(getSyncObject(), 
fSession.setWatch(ThreadSafeValue.getRaw(v), memberName, kind));
+               }
+       }
+
+       public Watch setWatch(Watch watch) throws NoResponseException,
+                       NotConnectedException, NotSupportedException {
+               synchronized (getSyncObject()) {
+                       return ThreadSafeWatch.wrap(getSyncObject(), 
fSession.setWatch(ThreadSafeWatch.getRaw(watch)));
+               }
+       }
+
+       public void stepContinue() throws NotSuspendedException,
+                       NoResponseException, NotConnectedException {
+               synchronized (getSyncObject()) {
+                       fSession.stepContinue();
+               }
+       }
+
+       public void stepInto() throws NotSuspendedException, 
NoResponseException,
+                       NotConnectedException {
+               synchronized (getSyncObject()) {
+                       fSession.stepInto();
+               }
+       }
+
+       public void stepOut() throws NotSuspendedException, NoResponseException,
+                       NotConnectedException {
+               synchronized (getSyncObject()) {
+                       fSession.stepOut();
+               }
+       }
+
+       public void stepOver() throws NotSuspendedException, 
NoResponseException,
+                       NotConnectedException {
+               synchronized (getSyncObject()) {
+                       fSession.stepOver();
+               }
+       }
+
+       public void suspend() throws SuspendedException, NotConnectedException,
+                       NoResponseException {
+               synchronized (getSyncObject()) {
+                       fSession.suspend();
+               }
+       }
+
+       public int suspendReason() throws NotConnectedException {
+               synchronized (getSyncObject()) {
+                       return fSession.suspendReason();
+               }
+       }
+
+       public void terminate() {
+               synchronized (getSyncObject()) {
+                       fSession.terminate();
+               }
+       }
+
+       public void unbind() {
+               synchronized (getSyncObject()) {
+                       fSession.unbind();
+               }
+       }
+
+       public void waitForEvent() throws NotConnectedException, 
InterruptedException {
+               synchronized (getSyncObject()) {
+                       fSession.waitForEvent();
+               }
+       }
+
+       public SourceLocator getSourceLocator()
+       {
+               synchronized (getSyncObject()) {
+                       return ThreadSafeSourceLocator.wrap(getSyncObject(), 
fSession.getSourceLocator());
+               }
+       }
+
+       public void setSourceLocator(SourceLocator sourceLocator)
+       {
+               synchronized (getSyncObject()) {
+                       fSession.setSourceLocator(sourceLocator);
+               }
+       }
+
+       public Value callConstructor(String classname, Value[] args)
+                       throws PlayerDebugException {
+               synchronized (getSyncObject()) {
+                       return ThreadSafeValue.wrap(getSyncObject(), 
fSession.callConstructor(classname, args));
+               }
+       }
+
+       public Value callFunction(Value thisObject, String functionName, 
Value[] args)
+                       throws PlayerDebugException {
+               synchronized (getSyncObject()) {
+                       return ThreadSafeValue.wrap(getSyncObject(), 
fSession.callFunction(thisObject, functionName, args));
+               }
+       }
+
+       public Value getGlobal(String name) throws NotSuspendedException, 
NoResponseException, NotConnectedException
+       {
+               synchronized (getSyncObject())
+               {
+                       return ThreadSafeValue.wrap(getSyncObject(), 
fSession.getGlobal(name));
+               }
+       }
+
+       public void breakOnCaughtExceptions(boolean b) throws 
NotSupportedException, NoResponseException {
+               synchronized (getSyncObject())  {
+                       fSession.breakOnCaughtExceptions(b);
+               }
+       }
+
+       public boolean evalIs(Value value, Value type) throws 
PlayerDebugException, PlayerFaultException {
+               synchronized (getSyncObject()) {
+                       return fSession.evalIs(value, type);
+               }
+       }
+
+       public boolean evalIs(Value value, String type) throws 
PlayerDebugException, PlayerFaultException {
+               synchronized (getSyncObject()) {
+                       return fSession.evalIs(value, type);
+               }
+       }
+
+       public boolean evalInstanceof(Value value, Value type) throws 
PlayerDebugException, PlayerFaultException {
+               synchronized (getSyncObject()) {
+                       return fSession.evalInstanceof(value, type);
+               }
+       }
+
+       public boolean evalInstanceof(Value value, String type) throws 
PlayerDebugException, PlayerFaultException {
+               synchronized (getSyncObject()) {
+                       return fSession.evalInstanceof(value, type);
+               }
+       }
+
+       public boolean evalIn(Value property, Value object) throws 
PlayerDebugException, PlayerFaultException {
+               synchronized (getSyncObject()) {
+                       return fSession.evalIn(property, object);
+               }
+       }
+
+       public Value evalAs(Value value, Value type) throws 
PlayerDebugException, PlayerFaultException {
+               synchronized (getSyncObject()) {
+                       return ThreadSafeValue.wrap(getSyncObject(), 
fSession.evalAs(value, type));
+               }
+       }
+
+       public boolean supportsWatchpoints() {
+               synchronized (getSyncObject()) {
+                       return fSession.supportsWatchpoints();
+               }
+       }
+       
+       public boolean supportsConcurrency() {
+               synchronized (getSyncObject()) {
+                       return fSession.supportsConcurrency();
+               }
+       }
+
+       /* (non-Javadoc)
+        * @see flash.tools.debugger.Session#getDisconnectCause()
+        */
+       public Exception getDisconnectCause() {
+               synchronized (getSyncObject()) {
+                       return fSession.getDisconnectCause();
+               }
+       }
+
+       /* (non-Javadoc)
+        * @see flash.tools.debugger.Session#refreshWorkers()
+        */
+       @Override
+       public Isolate[] refreshWorkers() throws NotSupportedException,
+                       NotSuspendedException, NoResponseException, 
NotConnectedException {
+               synchronized (getSyncObject()) {
+                       return ThreadSafeIsolate.wrapArray(getSyncObject(), 
fSession.getWorkers());
+               }
+       }
+
+       /* (non-Javadoc)
+        * @see flash.tools.debugger.Session#getWorkers()
+        */
+       @Override
+       public Isolate[] getWorkers() {
+               synchronized (getSyncObject()) {
+                       return fSession.getWorkers();
+               }
+       }
+
+       /* (non-Javadoc)
+        * @see flash.tools.debugger.Session#getWorkerSession(int)
+        */
+       @Override
+       public IsolateSession getWorkerSession(int isolateId) {
+               synchronized (getSyncObject()) {
+                       return ThreadSafeIsolateSession.wrap(getSyncObject(), 
fSession.getWorkerSession(isolateId));
+               }
+       }
+
+       /* (non-Javadoc)
+        * @see flash.tools.debugger.Session#setExceptionBreakpoint(String)
+        */
+       @Override
+       public boolean setExceptionBreakpoint(String exceptionClass)
+                       throws NoResponseException, NotConnectedException {
+               synchronized (getSyncObject()) {
+                       return fSession.setExceptionBreakpoint(exceptionClass);
+               }
+       }
+
+       /* (non-Javadoc)
+        * @see flash.tools.debugger.Session#clearExceptionBreakpoint(String)
+        */
+       @Override
+       public boolean clearExceptionBreakpoint(String exceptionClass)
+                       throws NoResponseException, NotConnectedException {
+               synchronized (getSyncObject()) {
+                       return 
fSession.clearExceptionBreakpoint(exceptionClass);
+               }
+       }
+
+       @Override
+       public void setLauncher(ILauncher launcher) {
+               synchronized (getSyncObject()) {
+                       fSession.setLauncher(launcher);
+               }
+       }
+
+}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/07f5a7de/debugger/src/main/java/flash/tools/debugger/threadsafe/ThreadSafeSessionManager.java
----------------------------------------------------------------------
diff --git 
a/debugger/src/main/java/flash/tools/debugger/threadsafe/ThreadSafeSessionManager.java
 
b/debugger/src/main/java/flash/tools/debugger/threadsafe/ThreadSafeSessionManager.java
new file mode 100644
index 0000000..66145fb
--- /dev/null
+++ 
b/debugger/src/main/java/flash/tools/debugger/threadsafe/ThreadSafeSessionManager.java
@@ -0,0 +1,203 @@
+/*
+ * 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.threadsafe;
+
+import java.io.IOException;
+
+import flash.tools.debugger.AIRLaunchInfo;
+import flash.tools.debugger.IDebuggerCallbacks;
+import flash.tools.debugger.ILaunchNotification;
+import flash.tools.debugger.ILauncher;
+import flash.tools.debugger.IProgress;
+import flash.tools.debugger.Player;
+import flash.tools.debugger.Session;
+import flash.tools.debugger.SessionManager;
+import flash.tools.debugger.SessionManager2;
+
+/**
+ * Thread-safe wrapper for flash.tools.debugger.SessionManager
+ * @author Mike Morearty
+ */
+public class ThreadSafeSessionManager extends ThreadSafeDebuggerObject 
implements SessionManager2 {
+
+       private SessionManager fSessionManager;
+       
+       private ThreadSafeSessionManager(SessionManager sessionManager) {
+               super(new Object());
+               fSessionManager = sessionManager;
+       }
+
+       /**
+        * Wraps a SessionManager inside a ThreadSafeSessionManager.  If the 
passed-in SessionManager
+        * is null, then this function returns null.
+        */
+       public static ThreadSafeSessionManager wrap(SessionManager 
sessionManager) {
+               if (sessionManager != null)
+                       return new ThreadSafeSessionManager(sessionManager);
+               else
+                       return null;
+       }
+
+       public static Object getSyncObject(SessionManager sm) {
+               return ((ThreadSafeSessionManager)sm).getSyncObject();
+       }
+
+       public Session accept(IProgress waitReporter) throws IOException {
+               // WARNING: This function is not thread-safe.
+               //
+               // accept() can take a very long time -- e.g. if there is 
something wrong,
+               // then it might hang for two minutes while waiting for the 
Flash player.
+               // So, it is not acceptable to put this in a "synchronized" 
block.
+               return ThreadSafeSession.wrap(getSyncObject(), 
fSessionManager.accept(waitReporter));
+       }
+
+       public int getPreference(String pref) throws NullPointerException {
+               synchronized (getSyncObject()) {
+                       return fSessionManager.getPreference(pref);
+               }
+       }
+
+       public boolean isListening() {
+               synchronized (getSyncObject()) {
+                       return fSessionManager.isListening();
+               }
+       }
+
+       public Session launch(String uri, AIRLaunchInfo airLaunchInfo, boolean 
forDebugging, IProgress waitReporter, ILaunchNotification launchNotification) 
throws IOException {
+               // WARNING: This function is not thread-safe.
+               //
+               // launch() can take a very long time -- e.g. if there is 
something wrong,
+               // then it might hang for two minutes while waiting for the 
Flash player.
+               // So, it is not acceptable to put this in a "synchronized" 
block.
+               return ThreadSafeSession.wrap(getSyncObject(), 
fSessionManager.launch(uri, airLaunchInfo, forDebugging, 
waitReporter,launchNotification));
+       }
+
+       public Player playerForUri(String uri, AIRLaunchInfo airLaunchInfo) {
+               synchronized (getSyncObject()) {
+                       return ThreadSafePlayer.wrap(getSyncObject(), 
fSessionManager.playerForUri(uri, airLaunchInfo));
+               }
+       }
+
+       public boolean supportsLaunch()
+       {
+               synchronized (getSyncObject()) {
+                       return fSessionManager.supportsLaunch();
+               }
+       }
+
+       public void setPreference(String pref, int value) {
+               synchronized (getSyncObject()) {
+                       fSessionManager.setPreference(pref, value);
+               }
+       }
+
+       public void setPreference(String pref, String value) {
+               synchronized (getSyncObject()) {
+                       fSessionManager.setPreference(pref, value);
+               }
+       }
+
+       public void startListening() throws IOException {
+               synchronized (getSyncObject()) {
+                       fSessionManager.startListening();
+               }
+       }
+
+       public void stopListening() throws IOException {
+               synchronized (getSyncObject()) {
+                       fSessionManager.stopListening();
+               }
+       }
+
+       public void setDebuggerCallbacks(IDebuggerCallbacks debuggerCallbacks) {
+               synchronized (getSyncObject()) {
+                       fSessionManager.setDebuggerCallbacks(debuggerCallbacks);
+               }
+       }
+
+       /* (non-Javadoc)
+        * @see flash.tools.debugger.SessionManager#connect(int, 
flash.tools.debugger.IProgress)
+        */
+       public Session connect(int port, IProgress waitReporter) throws 
IOException {
+               // WARNING: This function is not thread-safe.
+               //
+               // connect() can take a very long time -- e.g. if there is 
something wrong,
+               // then it might hang for two minutes while waiting for the 
Flash player.
+               // So, it is not acceptable to put this in a "synchronized" 
block.
+               return ThreadSafeSession.wrap(getSyncObject(), 
fSessionManager.connect(port, waitReporter));            
+       }
+       
+       public void stopConnecting() throws IOException {
+               synchronized (getSyncObject()) {
+                       fSessionManager.stopConnecting();
+               }
+       }
+       
+       public boolean isConnecting() {
+               synchronized (getSyncObject()) {
+                       return fSessionManager.isConnecting();
+               }
+       }
+
+       @Override
+       public Process launchForRun(String uri, AIRLaunchInfo airLaunchInfo,
+                       IProgress waitReporter, ILaunchNotification 
launchNotification)
+                       throws IOException {
+               /*
+                * launch used to return null when the session was null.
+                * The session will be null in this case because this is 
invoked for run launches.
+                * We just return the process to be consistent with 
PlayerSessionManager. 
+                */
+               assert fSessionManager instanceof SessionManager2;
+               
+               Process process = ((SessionManager2) 
fSessionManager).launchForRun(uri, airLaunchInfo, waitReporter, 
launchNotification);
+                       
+               return process; 
+       }
+
+       @Override
+       public Process launchForRun(String uri, AIRLaunchInfo airLaunchInfo,
+                       IProgress waitReporter, ILaunchNotification 
launchNotification,
+                       ILauncher launcher) throws IOException {
+               /*
+                * launch used to return null when the session was null.
+                * The session will be null in this case because this is 
invoked for run launches.
+                * We just return the process to be consistent with 
PlayerSessionManager. 
+                */
+               assert fSessionManager instanceof SessionManager2;
+               
+               Process process = ((SessionManager2) 
fSessionManager).launchForRun(uri, airLaunchInfo, waitReporter, 
launchNotification,launcher);
+                       
+               return process; 
+       }
+
+       @Override
+       public Session launch(String uri, AIRLaunchInfo airLaunchInfo,
+                       boolean forDebugging, IProgress waitReporter,
+                       ILaunchNotification launchNotification, ILauncher 
launcher)
+                       throws IOException {
+               // WARNING: This function is not thread-safe.
+                               //
+                               // launch() can take a very long time -- e.g. 
if there is something wrong,
+                               // then it might hang for two minutes while 
waiting for the Flash player.
+                               // So, it is not acceptable to put this in a 
"synchronized" block.
+                               assert fSessionManager instanceof 
SessionManager2;
+                               
+                               return ThreadSafeSession.wrap(getSyncObject(), 
((SessionManager2) fSessionManager).launch(uri, airLaunchInfo, forDebugging, 
waitReporter,launchNotification,launcher));
+       }
+}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/07f5a7de/debugger/src/main/java/flash/tools/debugger/threadsafe/ThreadSafeSourceFile.java
----------------------------------------------------------------------
diff --git 
a/debugger/src/main/java/flash/tools/debugger/threadsafe/ThreadSafeSourceFile.java
 
b/debugger/src/main/java/flash/tools/debugger/threadsafe/ThreadSafeSourceFile.java
new file mode 100644
index 0000000..7a1b680
--- /dev/null
+++ 
b/debugger/src/main/java/flash/tools/debugger/threadsafe/ThreadSafeSourceFile.java
@@ -0,0 +1,150 @@
+/*
+ * 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.threadsafe;
+
+import flash.tools.debugger.Session;
+import flash.tools.debugger.SourceFile;
+
+/**
+ * Thread-safe wrapper for flash.tools.debugger.SourceFile
+ * @author Mike Morearty
+ */
+public class ThreadSafeSourceFile extends ThreadSafeDebuggerObject implements 
SourceFile {
+       
+       private SourceFile fSourceFile;
+       
+       private ThreadSafeSourceFile(Object syncObj, SourceFile sourceFile) {
+               super(syncObj);
+               fSourceFile = sourceFile;
+       }
+
+       /**
+        * Wraps a SourceFile inside a ThreadSafeSourceFile.  If the passed-in 
SourceFile
+        * is null, then this function returns null.
+        */
+       public static ThreadSafeSourceFile wrap(Object syncObj, SourceFile 
sourceFile) {
+               if (sourceFile != null)
+                       return new ThreadSafeSourceFile(syncObj, sourceFile);
+               else
+                       return null;
+       }
+
+       /**
+        * Wraps an array of SourceFiles inside an array of 
ThreadSafeSourceFiles.
+        */
+       public static ThreadSafeSourceFile[] wrapArray(Object syncObj, 
SourceFile[] sourceFiles) {
+               ThreadSafeSourceFile[] threadSafeSourceFiles = new 
ThreadSafeSourceFile[sourceFiles.length];
+               for (int i=0; i<sourceFiles.length; ++i) {
+                       threadSafeSourceFiles[i] = wrap(syncObj, 
sourceFiles[i]);
+               }
+               return threadSafeSourceFiles;
+       }
+
+       /**
+        * Returns the raw SourceFile underlying a ThreadSafeSourceFile.
+        */
+       public static SourceFile getRaw(SourceFile f) {
+               if (f instanceof ThreadSafeSourceFile)
+                       return ((ThreadSafeSourceFile)f).fSourceFile;
+               else
+                       return f;
+       }
+
+       public static Object getSyncObject(SourceFile sf) {
+               return ((ThreadSafeSourceFile)sf).getSyncObject();
+       }
+
+       public String getRawName() {
+               synchronized (getSyncObject()) {
+                       return fSourceFile.getRawName();
+               }
+       }
+
+       public String getFunctionNameForLine(Session session, int lineNum) {
+               synchronized (getSyncObject()) {
+                       return fSourceFile.getFunctionNameForLine(session, 
lineNum);
+               }
+       }
+
+       public String[] getFunctionNames(Session session) {
+               synchronized (getSyncObject()) {
+                       return fSourceFile.getFunctionNames(session);
+               }
+       }
+
+       public int getId() {
+               synchronized (getSyncObject()) {
+                       return fSourceFile.getId();
+               }
+       }
+
+       public String getLine(int lineNum) {
+               synchronized (getSyncObject()) {
+                       return fSourceFile.getLine(lineNum);
+               }
+       }
+
+       public int getLineCount() {
+               synchronized (getSyncObject()) {
+                       return fSourceFile.getLineCount();
+               }
+       }
+
+       public int getLineForFunctionName(Session session, String name) {
+               synchronized (getSyncObject()) {
+                       return fSourceFile.getLineForFunctionName(session, 
name);
+               }
+       }
+
+       public String getName() {
+               synchronized (getSyncObject()) {
+                       return fSourceFile.getName();
+               }
+       }
+
+       public int getOffsetForLine(int lineNum) {
+               synchronized (getSyncObject()) {
+                       return fSourceFile.getOffsetForLine(lineNum);
+               }
+       }
+
+       public String getPackageName() {
+               synchronized (getSyncObject()) {
+                       return fSourceFile.getPackageName();
+               }
+       }
+
+       public String getFullPath() {
+               synchronized (getSyncObject()) {
+                       return fSourceFile.getFullPath();
+               }
+       }
+
+       public String getBasePath() {
+               synchronized (getSyncObject()) {
+                       return fSourceFile.getBasePath();
+               }
+       }
+
+       @Override
+       public String toString() {
+               synchronized (getSyncObject()) {
+                       return fSourceFile.toString();
+               }
+       }
+}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/07f5a7de/debugger/src/main/java/flash/tools/debugger/threadsafe/ThreadSafeSourceLocator.java
----------------------------------------------------------------------
diff --git 
a/debugger/src/main/java/flash/tools/debugger/threadsafe/ThreadSafeSourceLocator.java
 
b/debugger/src/main/java/flash/tools/debugger/threadsafe/ThreadSafeSourceLocator.java
new file mode 100644
index 0000000..a4d6c21
--- /dev/null
+++ 
b/debugger/src/main/java/flash/tools/debugger/threadsafe/ThreadSafeSourceLocator.java
@@ -0,0 +1,70 @@
+/*
+ * 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.threadsafe;
+
+import java.io.InputStream;
+
+import flash.tools.debugger.SourceLocator;
+
+/**
+ * @author Mike Morearty
+ */
+public class ThreadSafeSourceLocator extends ThreadSafeDebuggerObject 
implements SourceLocator
+{
+       private SourceLocator fSourceLocator;
+       
+       /**
+        * @param syncObj
+        */
+       public ThreadSafeSourceLocator(Object syncObj, SourceLocator 
sourceLocator)
+       {
+               super(syncObj);
+               fSourceLocator = sourceLocator;
+       }
+
+       /**
+        * Wraps a SourceLocator inside a ThreadSafeSourceLocator.  If the 
passed-in SourceLocator
+        * is null, then this function returns null.
+        */
+       public static ThreadSafeSourceLocator wrap(Object syncObj, 
SourceLocator sourceLocator) {
+               if (sourceLocator != null)
+                       return new ThreadSafeSourceLocator(syncObj, 
sourceLocator);
+               else
+                       return null;
+       }
+
+       /* (non-Javadoc)
+        * @see 
flash.tools.debugger.SourceLocator#locateSource(java.lang.String, 
java.lang.String, java.lang.String)
+        */
+       public InputStream locateSource(String arg0, String arg1, String arg2)
+       {
+               synchronized (getSyncObject()) {
+                       return fSourceLocator.locateSource(arg0, arg1, arg2);
+               }
+       }
+
+       /* (non-Javadoc)
+        * @see flash.tools.debugger.SourceLocator#getChangeCount()
+        */
+       public int getChangeCount()
+       {
+               synchronized (getSyncObject()) {
+                       return fSourceLocator.getChangeCount();
+               }
+       }
+}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/07f5a7de/debugger/src/main/java/flash/tools/debugger/threadsafe/ThreadSafeSwfInfo.java
----------------------------------------------------------------------
diff --git 
a/debugger/src/main/java/flash/tools/debugger/threadsafe/ThreadSafeSwfInfo.java 
b/debugger/src/main/java/flash/tools/debugger/threadsafe/ThreadSafeSwfInfo.java
new file mode 100644
index 0000000..a3d698c
--- /dev/null
+++ 
b/debugger/src/main/java/flash/tools/debugger/threadsafe/ThreadSafeSwfInfo.java
@@ -0,0 +1,124 @@
+/*
+ * 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.threadsafe;
+
+import flash.tools.debugger.InProgressException;
+import flash.tools.debugger.Session;
+import flash.tools.debugger.SourceFile;
+import flash.tools.debugger.SwfInfo;
+
+/**
+ * Thread-safe wrapper for flash.tools.debugger.SwfInfo
+ * @author Mike Morearty
+ */
+public class ThreadSafeSwfInfo extends ThreadSafeDebuggerObject implements 
SwfInfo {
+       
+       private SwfInfo fSwfInfo;
+       
+       private ThreadSafeSwfInfo(Object syncObj, SwfInfo swfInfo) {
+               super(syncObj);
+               fSwfInfo = swfInfo;
+       }
+
+       /**
+        * Wraps a SwfInfo inside a ThreadSafeSwfInfo.  If the passed-in SwfInfo
+        * is null, then this function returns null.
+        */
+       public static ThreadSafeSwfInfo wrap(Object syncObj, SwfInfo swfInfo) {
+               if (swfInfo != null)
+                       return new ThreadSafeSwfInfo(syncObj, swfInfo);
+               else
+                       return null;
+       }
+
+       /**
+        * Wraps an array of SwfInfos inside an array of ThreadSafeSwfInfos.
+        */
+       public static ThreadSafeSwfInfo[] wrapArray(Object syncObj, SwfInfo[] 
swfinfos) {
+               ThreadSafeSwfInfo[] threadSafeSwfInfos = new 
ThreadSafeSwfInfo[swfinfos.length];
+               for (int i=0; i<swfinfos.length; ++i) {
+                       threadSafeSwfInfos[i] = wrap(syncObj, swfinfos[i]);
+               }
+               return threadSafeSwfInfos;
+       }
+
+       public static Object getSyncObject(SwfInfo swfInfo) {
+               return ((ThreadSafeSwfInfo)swfInfo).getSyncObject();
+       }
+
+       public boolean containsSource(SourceFile f) {
+               synchronized (getSyncObject()) {
+                       return 
fSwfInfo.containsSource(ThreadSafeSourceFile.getRaw(f));
+               }
+       }
+
+       public String getPath() {
+               synchronized (getSyncObject()) {
+                       return fSwfInfo.getPath();
+               }
+       }
+
+       public int getSourceCount(Session s) throws InProgressException {
+               synchronized (getSyncObject()) {
+                       return 
fSwfInfo.getSourceCount(ThreadSafeSession.getRaw(s));
+               }
+       }
+
+       public SourceFile[] getSourceList(Session s) throws InProgressException 
{
+               synchronized (getSyncObject()) {
+                       return ThreadSafeSourceFile.wrapArray(getSyncObject(), 
fSwfInfo.getSourceList(ThreadSafeSession.getRaw(s)));
+               }
+       }
+
+       public int getSwdSize(Session s) throws InProgressException {
+               synchronized (getSyncObject()) {
+                       return fSwfInfo.getSwdSize(ThreadSafeSession.getRaw(s));
+               }
+       }
+
+       public int getSwfSize() {
+               synchronized (getSyncObject()) {
+                       return fSwfInfo.getSwfSize();
+               }
+       }
+
+       public String getUrl() {
+               synchronized (getSyncObject()) {
+                       return fSwfInfo.getUrl();
+               }
+       }
+
+       public boolean isProcessingComplete() {
+               synchronized (getSyncObject()) {
+                       return fSwfInfo.isProcessingComplete();
+               }
+       }
+
+       public boolean isUnloaded() {
+               synchronized (getSyncObject()) {
+                       return fSwfInfo.isUnloaded();
+               }
+       }
+
+       @Override
+       public int getIsolateId() {
+               synchronized (getSyncObject()) {
+                       return fSwfInfo.getIsolateId();
+               }
+       }
+}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/07f5a7de/debugger/src/main/java/flash/tools/debugger/threadsafe/ThreadSafeValue.java
----------------------------------------------------------------------
diff --git 
a/debugger/src/main/java/flash/tools/debugger/threadsafe/ThreadSafeValue.java 
b/debugger/src/main/java/flash/tools/debugger/threadsafe/ThreadSafeValue.java
new file mode 100644
index 0000000..f78414d
--- /dev/null
+++ 
b/debugger/src/main/java/flash/tools/debugger/threadsafe/ThreadSafeValue.java
@@ -0,0 +1,159 @@
+/*
+ * 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.threadsafe;
+
+import flash.tools.debugger.NoResponseException;
+import flash.tools.debugger.NotConnectedException;
+import flash.tools.debugger.NotSuspendedException;
+import flash.tools.debugger.Session;
+import flash.tools.debugger.Value;
+import flash.tools.debugger.Variable;
+
+/**
+ * Thread-safe wrapper for flash.tools.debugger.Value
+ * @author Mike Morearty
+ */
+public class ThreadSafeValue extends ThreadSafeDebuggerObject implements Value 
{
+
+       private Value fVal;
+
+       private ThreadSafeValue(Object syncObj, Value val) {
+               super(syncObj);
+               fVal = val;
+       }
+
+       /**
+        * Wraps a Value inside a ThreadSafeValue.  If the passed-in Value
+        * is null, then this function returns null.
+        */
+       public static ThreadSafeValue wrap(Object syncObj, Value val) {
+               if (val != null)
+                       return new ThreadSafeValue(syncObj, val);
+               else
+                       return null;
+       }
+
+       /**
+        * Wraps an array of Values inside an array of ThreadSafeValues.
+        */
+       public static ThreadSafeValue[] wrapArray(Object syncObj, Value[] 
values) {
+               ThreadSafeValue[] threadSafeValues = new 
ThreadSafeValue[values.length];
+               for (int i=0; i<values.length; ++i) {
+                       threadSafeValues[i] = wrap(syncObj, values[i]);
+               }
+               return threadSafeValues;
+       }
+
+       /**
+        * Returns the raw Value underlying a ThreadSafeValue.
+        */
+       public static Value getRaw(Value v) {
+               if (v instanceof ThreadSafeValue)
+                       return ((ThreadSafeValue)v).fVal;
+               else
+                       return v;
+       }
+
+       public static Object getSyncObject(Value v) {
+               return ((ThreadSafeValue)v).getSyncObject();
+       }
+       
+       @Override
+       public boolean equals(Object other) {
+               if (other instanceof Value)
+                       return fVal.equals(getRaw((Value)other));
+               else
+                       return false;
+       }
+
+       public int getAttributes() {
+               synchronized (getSyncObject()) { return fVal.getAttributes(); }
+       }
+
+       public String getClassName() {
+               synchronized (getSyncObject()) { return fVal.getClassName(); }
+       }
+
+       public long getId() {
+               synchronized (getSyncObject()) { return fVal.getId(); }
+       }
+
+       public int getMemberCount(Session s) throws NotSuspendedException, 
NoResponseException, NotConnectedException {
+               synchronized (getSyncObject()) { return 
fVal.getMemberCount(ThreadSafeSession.getRaw(s)); }
+       }
+
+       public Variable getMemberNamed(Session s, String name) throws 
NotSuspendedException, NoResponseException, NotConnectedException {
+               synchronized (getSyncObject()) {
+                       return ThreadSafeVariable.wrap(getSyncObject(), 
fVal.getMemberNamed(ThreadSafeSession.getRaw(s), name));
+               }
+       }
+
+       public Variable[] getMembers(Session s) throws NotSuspendedException, 
NoResponseException, NotConnectedException {
+               synchronized (getSyncObject()) {
+                       return ThreadSafeVariable.wrapArray(getSyncObject(), 
fVal.getMembers(ThreadSafeSession.getRaw(s)));
+               }
+       }
+
+       public int getType() {
+               synchronized (getSyncObject()) { return fVal.getType(); }
+       }
+
+       public String getTypeName() {
+               synchronized (getSyncObject()) { return fVal.getTypeName(); }
+       }
+
+       public Object getValueAsObject() {
+               synchronized (getSyncObject()) { return 
fVal.getValueAsObject(); }
+       }
+
+       public String getValueAsString() {
+               synchronized (getSyncObject()) { return 
fVal.getValueAsString(); }
+       }
+
+       public boolean isAttributeSet(int variableAttribute) {
+               synchronized (getSyncObject()) { return 
fVal.isAttributeSet(variableAttribute); }
+       }
+
+       public String[] getClassHierarchy(boolean allLevels) {
+               synchronized (getSyncObject()) { return 
fVal.getClassHierarchy(allLevels); }
+       }
+
+       @Override
+       public String toString() {
+               synchronized (getSyncObject()) { return fVal.toString(); }
+       }
+
+       public Variable[] getPrivateInheritedMembers() {
+               synchronized (getSyncObject()) {
+                       return ThreadSafeVariable.wrapArray(getSyncObject(), 
fVal.getPrivateInheritedMembers());
+               }
+       }
+
+       public Variable[] getPrivateInheritedMemberNamed(String name) {
+               synchronized (getSyncObject()) {
+                       return ThreadSafeVariable.wrapArray(getSyncObject(), 
fVal.getPrivateInheritedMemberNamed(name));
+               }
+       }
+
+       @Override
+       public int getIsolateId() {
+               synchronized (getSyncObject()) {
+                       return fVal.getIsolateId();
+               }
+       }
+}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/07f5a7de/debugger/src/main/java/flash/tools/debugger/threadsafe/ThreadSafeValueExp.java
----------------------------------------------------------------------
diff --git 
a/debugger/src/main/java/flash/tools/debugger/threadsafe/ThreadSafeValueExp.java
 
b/debugger/src/main/java/flash/tools/debugger/threadsafe/ThreadSafeValueExp.java
new file mode 100644
index 0000000..1b5b75c
--- /dev/null
+++ 
b/debugger/src/main/java/flash/tools/debugger/threadsafe/ThreadSafeValueExp.java
@@ -0,0 +1,71 @@
+/*
+ * 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.threadsafe;
+
+import flash.tools.debugger.PlayerDebugException;
+import flash.tools.debugger.expression.Context;
+import flash.tools.debugger.expression.NoSuchVariableException;
+import flash.tools.debugger.expression.PlayerFaultException;
+import flash.tools.debugger.expression.ValueExp;
+
+/**
+ * Thread-safe wrapper for flash.tools.debugger.expression.ValueExp
+ * @author Mike Morearty
+ */
+public class ThreadSafeValueExp extends ThreadSafeDebuggerObject implements 
ValueExp
+{
+       private final ValueExp m_valueExp;
+
+       public ThreadSafeValueExp(Object syncObj, ValueExp valueExp)
+       {
+               super(syncObj);
+               m_valueExp = valueExp;
+       }
+
+       /**
+        * Wraps a ValueExp inside a ThreadSafeValueExp. If the passed-in
+        * ValueExp is null, then this function returns null.
+        */
+       public static ThreadSafeValueExp wrap(Object syncObj, ValueExp 
valueExp) {
+               if (valueExp != null)
+                       return new ThreadSafeValueExp(syncObj, valueExp);
+               else
+                       return null;
+       }
+
+       public Object evaluate(Context context) throws NumberFormatException, 
NoSuchVariableException, PlayerFaultException, PlayerDebugException
+       {
+               synchronized (getSyncObject()) {
+                       return m_valueExp.evaluate(context);
+               }
+       }
+
+       public boolean containsAssignment()
+       {
+               synchronized (getSyncObject()) {
+                       return m_valueExp.containsAssignment();
+               }
+       }
+
+       public boolean isLookupMembers()
+       {
+               synchronized (getSyncObject()) {
+                       return m_valueExp.isLookupMembers();
+               }
+       }
+}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/07f5a7de/debugger/src/main/java/flash/tools/debugger/threadsafe/ThreadSafeVariable.java
----------------------------------------------------------------------
diff --git 
a/debugger/src/main/java/flash/tools/debugger/threadsafe/ThreadSafeVariable.java
 
b/debugger/src/main/java/flash/tools/debugger/threadsafe/ThreadSafeVariable.java
new file mode 100644
index 0000000..126a224
--- /dev/null
+++ 
b/debugger/src/main/java/flash/tools/debugger/threadsafe/ThreadSafeVariable.java
@@ -0,0 +1,142 @@
+/*
+ * 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.threadsafe;
+
+import flash.tools.debugger.NoResponseException;
+import flash.tools.debugger.NotConnectedException;
+import flash.tools.debugger.NotSuspendedException;
+import flash.tools.debugger.Session;
+import flash.tools.debugger.Value;
+import flash.tools.debugger.Variable;
+import flash.tools.debugger.events.FaultEvent;
+
+/**
+ * Thread-safe wrapper for flash.tools.debugger.Variable
+ * @author Mike Morearty
+ */
+public class ThreadSafeVariable extends ThreadSafeDebuggerObject implements 
Variable {
+
+       private Variable fVar;
+
+       private ThreadSafeVariable(Object syncObj, Variable var) {
+               super(syncObj);
+               fVar = var;
+       }
+
+       /**
+        * Wraps a Variable inside a ThreadSafeVariable.  If the passed-in 
Variable
+        * is null, then this function returns null.
+        */
+       public static ThreadSafeVariable wrap(Object syncObj, Variable 
variable) {
+               if (variable != null)
+                       return new ThreadSafeVariable(syncObj, variable);
+               else
+                       return null;
+       }
+
+       /**
+        * Wraps an array of Variables inside an array of ThreadSafeVariables.
+        */
+       public static ThreadSafeVariable[] wrapArray(Object syncObj, Variable[] 
variables) {
+               ThreadSafeVariable[] threadSafeVariables = new 
ThreadSafeVariable[variables.length];
+               for (int i=0; i<variables.length; ++i) {
+                       threadSafeVariables[i] = wrap(syncObj, variables[i]);
+               }
+               return threadSafeVariables;
+       }
+
+       /**
+        * Returns the raw Variable underlying a ThreadSafeVariable.
+        */
+       public static Variable getRaw(Variable v) {
+               if (v instanceof ThreadSafeVariable)
+                       return ((ThreadSafeVariable)v).fVar;
+               else
+                       return v;
+       }
+
+       public static Object getSyncObject(Variable v) {
+               return ((ThreadSafeVariable)v).getSyncObject();
+       }
+
+       public String getName() {
+               synchronized (getSyncObject()) { return fVar.getName(); }
+       }
+
+       public int getAttributes() {
+               synchronized (getSyncObject()) { return fVar.getAttributes(); }
+       }
+
+       public boolean isAttributeSet(int variableAttribute) {
+               synchronized (getSyncObject()) { return 
fVar.isAttributeSet(variableAttribute); }
+       }
+
+       public Value getValue() {
+               synchronized (getSyncObject()) {
+                       return ThreadSafeValue.wrap(getSyncObject(), 
fVar.getValue());
+               }
+       }
+
+       public boolean hasValueChanged(Session s) {
+               synchronized (getSyncObject()) {
+                       return 
fVar.hasValueChanged(ThreadSafeSession.getRaw(s));
+               }
+       }
+
+       public boolean needsToInvokeGetter() {
+               synchronized (getSyncObject()) { return 
fVar.needsToInvokeGetter(); }
+       }
+
+       public void invokeGetter(Session s) throws NotSuspendedException, 
NoResponseException, NotConnectedException {
+               synchronized (getSyncObject()) { 
fVar.invokeGetter(ThreadSafeSession.getRaw(s)); }
+       }
+
+       public String getQualifiedName() {
+               synchronized (getSyncObject()) { return 
fVar.getQualifiedName(); }
+       }
+
+       public String getNamespace() {
+               synchronized (getSyncObject()) { return fVar.getNamespace(); }
+       }
+       
+       public int getScope() {
+               synchronized (getSyncObject()) { return fVar.getScope(); }
+       }
+
+       public FaultEvent setValue(Session s, int type, String value) throws 
NotSuspendedException, NoResponseException, NotConnectedException {
+               synchronized (getSyncObject()) { return 
fVar.setValue(ThreadSafeSession.getRaw(s), type, value); }
+       }
+
+       public String getDefiningClass() {
+               synchronized (getSyncObject()) { return 
fVar.getDefiningClass(); }
+       }
+
+       public int getLevel() {
+               synchronized (getSyncObject()) { return fVar.getLevel(); }
+       }
+
+       @Override
+       public String toString() {
+               synchronized (getSyncObject()) { return fVar.toString(); }
+       }
+
+       @Override
+       public int getIsolateId() {
+               synchronized (getSyncObject()) { return fVar.getIsolateId(); }
+       }
+}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/07f5a7de/debugger/src/main/java/flash/tools/debugger/threadsafe/ThreadSafeWatch.java
----------------------------------------------------------------------
diff --git 
a/debugger/src/main/java/flash/tools/debugger/threadsafe/ThreadSafeWatch.java 
b/debugger/src/main/java/flash/tools/debugger/threadsafe/ThreadSafeWatch.java
new file mode 100644
index 0000000..276a0c5
--- /dev/null
+++ 
b/debugger/src/main/java/flash/tools/debugger/threadsafe/ThreadSafeWatch.java
@@ -0,0 +1,95 @@
+/*
+ * 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.threadsafe;
+
+import flash.tools.debugger.Watch;
+
+/**
+ * Thread-safe wrapper for flash.tools.debugger.Watch
+ * @author Mike Morearty
+ */
+public class ThreadSafeWatch extends ThreadSafeDebuggerObject implements Watch 
{
+       
+       private Watch fWatch;
+       
+       private ThreadSafeWatch(Object syncObj, Watch watch) {
+               super(syncObj);
+               fWatch = watch;
+       }
+
+       /**
+        * Wraps a Watch inside a ThreadSafeWatch.  If the passed-in Watch
+        * is null, then this function returns null.
+        */
+       public static ThreadSafeWatch wrap(Object syncObj, Watch watch) {
+               if (watch != null)
+                       return new ThreadSafeWatch(syncObj, watch);
+               else
+                       return null;
+       }
+
+       /**
+        * Wraps an array of Watches inside an array of ThreadSafeWatches.
+        */
+       public static ThreadSafeWatch[] wrapArray(Object syncObj, Watch[] 
watchs) {
+               ThreadSafeWatch[] threadSafeWatches = new 
ThreadSafeWatch[watchs.length];
+               for (int i=0; i<watchs.length; ++i) {
+                       threadSafeWatches[i] = wrap(syncObj, watchs[i]);
+               }
+               return threadSafeWatches;
+       }
+
+       /**
+        * Returns the raw Watch underlying a ThreadSafeWatch.
+        */
+       public static Watch getRaw(Watch w) {
+               if (w instanceof ThreadSafeWatch)
+                       return ((ThreadSafeWatch)w).fWatch;
+               else
+                       return w;
+       }
+
+       public static Object getSyncObject(Watch w) {
+               return ((ThreadSafeWatch)w).getSyncObject();
+       }
+
+       public int getKind() {
+               synchronized (getSyncObject()) {
+                       return fWatch.getKind();
+               }
+       }
+
+       public String getMemberName() {
+               synchronized (getSyncObject()) {
+                       return fWatch.getMemberName();
+               }
+       }
+
+       public long getValueId() {
+               synchronized (getSyncObject()) {
+                       return fWatch.getValueId();
+               }
+       }
+
+       @Override
+       public int getIsolateId() {
+               synchronized (getSyncObject()) {
+                       return fWatch.getIsolateId();
+               }
+       }
+}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/07f5a7de/debugger/src/main/java/flash/util/URLEncoder.java
----------------------------------------------------------------------
diff --git a/debugger/src/main/java/flash/util/URLEncoder.java 
b/debugger/src/main/java/flash/util/URLEncoder.java
new file mode 100644
index 0000000..52afb29
--- /dev/null
+++ b/debugger/src/main/java/flash/util/URLEncoder.java
@@ -0,0 +1,150 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.util;
+
+import java.io.*;
+
+public final class URLEncoder
+{
+       public static final String charset = "UTF8"; //$NON-NLS-1$
+
+       private URLEncoder()
+       {
+       }
+
+       public static final String encode(String s)
+       {
+               try
+               {
+                       return encode(s, charset);
+               }
+               catch (UnsupportedEncodingException ex)
+               {
+                       throw new IllegalArgumentException(charset);
+               }
+       }
+
+       public static final String encode(String s, String enc) throws 
UnsupportedEncodingException
+       {
+               if (!needsEncoding(s))
+               {
+                       return s;
+               }
+
+               int length = s.length();
+
+               StringBuilder out = new StringBuilder(length);
+
+               ByteArrayOutputStream buf = new ByteArrayOutputStream(10); // 
why 10? w3c says so.
+
+               BufferedWriter writer = new BufferedWriter(new 
OutputStreamWriter(buf, enc));
+
+               for (int i = 0; i < length; i++)
+               {
+                       int c = s.charAt(i);
+                       if (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c 
>= '0' && c <= '9' || c == ' ')
+                       {
+                               if (c == ' ')
+                               {
+                                       c = '+';
+                               }
+
+                               toHex(out, buf.toByteArray());
+                               buf.reset();
+
+                               out.append((char) c);
+                       }
+                       else
+                       {
+                               try
+                               {
+                                       writer.write(c);
+
+                                       if (c >= 0xD800 && c <= 0xDBFF && i < 
length - 1)
+                                       {
+                                               int d = s.charAt(i + 1);
+                                               if (d >= 0xDC00 && d <= 0xDFFF)
+                                               {
+                                                       writer.write(d);
+                                                       i++;
+                                               }
+                                       }
+
+                                       writer.flush();
+                               }
+                               catch (IOException ex)
+                               {
+                                       throw new IllegalArgumentException(s);
+                               }
+                       }
+               }
+
+               toHex(out, buf.toByteArray());
+
+               return out.toString();
+       }
+
+       private static final void toHex(StringBuilder buffer, byte[] b)
+       {
+               for (int i = 0; i < b.length; i++)
+               {
+                       buffer.append('%');
+
+                       char ch = Character.forDigit((b[i] >> 4) & 0xF, 16);
+                       if (Character.isLetter(ch))
+                       {
+                               ch -= 32;
+                       }
+                       buffer.append(ch);
+
+                       ch = Character.forDigit(b[i] & 0xF, 16);
+                       if (Character.isLetter(ch))
+                       {
+                               ch -= 32;
+                       }
+                       buffer.append(ch);
+               }
+       }
+
+       private static final boolean needsEncoding(String s)
+       {
+               if (s == null)
+               {
+                       return false;
+               }
+
+               int length = s.length();
+
+               for (int i = 0; i < length; i++)
+               {
+                       int c = s.charAt(i);
+                       if (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c 
>= '0' && c <= '9')
+                       {
+                               // keep going
+                       }
+                       else
+                       {
+                               return true;
+                       }
+               }
+
+               return false;
+       }
+}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/07f5a7de/debugger/src/main/java/flash/util/URLHelper.java
----------------------------------------------------------------------
diff --git a/debugger/src/main/java/flash/util/URLHelper.java 
b/debugger/src/main/java/flash/util/URLHelper.java
new file mode 100644
index 0000000..a3b3f60
--- /dev/null
+++ b/debugger/src/main/java/flash/util/URLHelper.java
@@ -0,0 +1,283 @@
+/*
+ * 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.util;
+
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.StringTokenizer;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class URLHelper
+{
+       private static Pattern URL_PATTERN = 
Pattern.compile("^(.*?)(\\?.*?)?(#.*)?$"); //$NON-NLS-1$
+
+       /**
+        * Everything before the "query" part of the URL.  E.g. for
+        * "http://www.example.com/file?firstname=Bob&lastname=Smith#foo";
+        * this would be "http://www.example.com/file";.
+        */
+       private String m_everythingBeforeQuery;
+       
+       /**
+        * The "query" in a URL is the "?firstname=Bob&lastname=Smith" part.
+        * m_query contains the query (including "?"), or contains "" if the
+        * URL has no query.  Never null.
+        */
+       private String m_query;
+       
+       /**
+        * The "fragment" in a URL is the "#foo" part at the end of a URL.
+        * m_fragment contains the fragment (including "#"), or contains "" if 
the
+        * URL has no fragment. Never null.
+        */
+       private String m_fragment;
+
+       public URLHelper(String url)
+       {
+               Matcher matcher = URL_PATTERN.matcher(url);
+
+               if (!matcher.matches())
+                       throw new IllegalArgumentException(url);
+
+               if (matcher.matches())
+               {
+                       m_everythingBeforeQuery = matcher.group(1);
+
+                       m_query = matcher.group(2);
+                       if (m_query == null) m_query = ""; //$NON-NLS-1$
+
+                       m_fragment = matcher.group(3);
+                       if (m_fragment == null) m_fragment = ""; //$NON-NLS-1$
+               }
+       }
+
+       /**
+        * Everything before the "query" part of the URL.  E.g. for
+        * "http://www.example.com/file?firstname=Bob&lastname=Smith#foo";
+        * this would be "http://www.example.com/file";.
+        */
+       public String getEverythingBeforeQuery()
+       {
+               return m_everythingBeforeQuery;
+       }
+
+       public void setEverythingBeforeQuery(String everythingBeforeQuery)
+       {
+               assertValidArguments(everythingBeforeQuery, getQuery(), 
getFragment());
+               m_everythingBeforeQuery = everythingBeforeQuery;
+       }
+
+       /**
+        * Rturns the "query" portion of the URL, e.g. the
+        * "?firstname=Bob&lastname=Smith" part. m_query contains the query
+        * (including "?"), or "" if the URL has no query. Never null.
+        */
+       public String getQuery()
+       {
+               return m_query;
+       }
+
+       /**
+        * Sets the "query" portion of the URL.  This must be either the
+        * empty string or a string that begins with "?".
+        */
+       public void setQuery(String query)
+       {
+               // if there is a query, make sure it starts with "?"
+               if (query.length() > 0 && query.charAt(0) != '?')
+                       query = "?" + query; //$NON-NLS-1$
+
+               assertValidArguments(getEverythingBeforeQuery(), query, 
getFragment());
+
+               m_query = query;
+       }
+
+       /**
+        * Returns the "fragment" portion of the URL, e.g. the "#foo" part, or
+        * "" if the URL has no fragment. Never null.
+        */
+       public String getFragment()
+       {
+               return m_fragment;
+       }
+
+       /**
+        * Sets the "fragment" portion of the URL.  This must be either the
+        * empty string or a string that begins with "#".
+        * @param fragment
+        */
+       public void setFragment(String fragment)
+       {
+               // if there is a fragment, make sure it starts with "#"
+               if (fragment.length() > 0 && fragment.charAt(0) != '#')
+                       fragment = "#" + fragment; //$NON-NLS-1$
+
+               assertValidArguments(getEverythingBeforeQuery(), getQuery(), 
fragment);
+               m_fragment = fragment;
+       }
+
+       private static void assertValidArguments(String everythingBeforeQuery, 
String query, String fragment)
+       {
+               assert areArgumentsValid(everythingBeforeQuery, query, 
fragment);
+       }
+
+       /**
+        * This will test for various error conditions, e.g. a query string that
+        * contains "#" or has incorrect contents.
+        */
+       private static boolean areArgumentsValid(String everythingBeforeQuery, 
String query, String fragment)
+       {
+               if (everythingBeforeQuery == null || query == null || fragment 
== null)
+                       return false;
+
+               URLHelper newHelper = new URLHelper(everythingBeforeQuery + 
query + fragment);
+               if 
(!newHelper.getEverythingBeforeQuery().equals(everythingBeforeQuery) ||
+                       !newHelper.getQuery().equals(query) ||
+                       !newHelper.getFragment().equals(fragment))
+               {
+                       return false;
+               }
+               
+               return true;
+       }
+
+       /**
+        * Returns the entire URL.
+        */
+       public String getURL()
+       {
+               return m_everythingBeforeQuery + m_query + m_fragment;
+       }
+
+       /**
+        * Returns the query portion of the URL, broken up into individual 
key/value
+        * pairs. Does NOT unescape the keys and values.
+        */
+    public LinkedHashMap<String, String> getParameterMap()
+       {
+               LinkedHashMap<String, String> map;
+
+               StringTokenizer tokens = new StringTokenizer(getQuery(), "?&"); 
//$NON-NLS-1$
+               // multiply by 2 to create a sufficiently large HashMap
+               map = new LinkedHashMap<String, String>(tokens.countTokens() * 
2);
+
+               while (tokens.hasMoreElements())
+               {
+                       String nameValuePair = tokens.nextToken();
+                       String name = nameValuePair;
+                       String value = ""; //$NON-NLS-1$
+                       int equalsIndex = nameValuePair.indexOf('=');
+                       if (equalsIndex != -1)
+                       {
+                               name = nameValuePair.substring(0, equalsIndex);
+                               if (name.length() > 0)
+                               {
+                                       value = 
nameValuePair.substring(equalsIndex + 1);
+                               }
+                       }
+                       map.put(name, value);
+               }
+
+               return map;
+       }
+
+    /**
+        * Sets the query portion of the URL.
+        * 
+        * @param parameterMap
+        *            a key/value mapping; these must already be escaped!
+        */
+    public void setParameterMap(Map<String,String> parameterMap)
+       {
+               if ((parameterMap != null) && (!parameterMap.isEmpty()))
+               {
+                       StringBuilder queryString = new StringBuilder();
+
+                       Iterator<Map.Entry<String,String>> it = 
parameterMap.entrySet().iterator();
+                       while (it.hasNext())
+                       {
+                               Map.Entry<String,String> entry = it.next();
+                               String name = (String) entry.getKey();
+                               String value = String.valueOf(entry.getValue());
+                               queryString.append(name);
+                               if ((value != null) && (!value.equals(""))) 
//$NON-NLS-1$
+                               {
+                                       queryString.append('=');
+                                       queryString.append(value);
+                               }
+                               if (it.hasNext())
+                               {
+                                       queryString.append('&');
+                               }
+                       }
+
+                       setQuery(queryString.toString());
+               } else
+               {
+                       setQuery(""); //$NON-NLS-1$
+               }
+       }
+
+       // shortcut for converting spaces to %20 in URIs
+       public static String escapeSpace(String uri)
+       {
+               return escapeCharacter(uri, ' ', "%20"); //$NON-NLS-1$
+       }
+
+       /**
+        * Locates characters 'c' in the scheme specific portion of a URI and
+        * translates them into 'to'
+        */
+       public static String escapeCharacter(String uri, char c, String to)
+       {
+               StringBuilder sb = new StringBuilder();
+
+               int size = uri.length();
+               int at = uri.indexOf(':');
+               int lastAt = 0;
+
+               // skip the scheme
+               if (at > -1)
+               {
+                       for(int i=0; i<=at; i++)
+                               sb.append(uri.charAt(i));
+                       lastAt = ++at;
+               }
+
+               // while we have 'c's in uri
+               while( (at = uri.indexOf(c, at)) > -1)
+               {
+                       // original portion
+                       for(int i=lastAt; i<at; i++)
+                               sb.append(uri.charAt(i));
+
+                       // conversion
+                       sb.append(to);
+                       lastAt = ++at;  // advance to char after conversion
+               }
+
+               if (lastAt < size)
+               {
+                       for(int i=lastAt; i<size; i++)
+                               sb.append(uri.charAt(i));
+               }
+               return sb.toString();
+       }
+}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/07f5a7de/debugger/src/main/java/flex/tools/debugger/cli/AmbiguousException.java
----------------------------------------------------------------------
diff --git 
a/debugger/src/main/java/flex/tools/debugger/cli/AmbiguousException.java 
b/debugger/src/main/java/flex/tools/debugger/cli/AmbiguousException.java
new file mode 100644
index 0000000..d670b3d
--- /dev/null
+++ b/debugger/src/main/java/flex/tools/debugger/cli/AmbiguousException.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package flex.tools.debugger.cli;
+
+/**
+ * An exception that is thrown when some ambiguous condition or state
+ * was encountered.  It is usually not fatal, and normally caused
+ * by some user interaction which can be overcome. 
+ */
+public class AmbiguousException extends Exception
+{
+    private static final long serialVersionUID = -1627900831637441719L;
+    
+    public AmbiguousException() {}
+    public AmbiguousException(String s) { super(s); }
+}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/07f5a7de/debugger/src/main/java/flex/tools/debugger/cli/BreakAction.java
----------------------------------------------------------------------
diff --git a/debugger/src/main/java/flex/tools/debugger/cli/BreakAction.java 
b/debugger/src/main/java/flex/tools/debugger/cli/BreakAction.java
new file mode 100644
index 0000000..3899a70
--- /dev/null
+++ b/debugger/src/main/java/flex/tools/debugger/cli/BreakAction.java
@@ -0,0 +1,154 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package flex.tools.debugger.cli;
+
+import java.util.Vector;
+import java.util.Iterator;
+
+import flash.tools.debugger.Location;
+import flash.tools.debugger.expression.ValueExp;
+
+
+/**
+ * An object that relates a CLI debugger breakpoint with an associated set
+ * of CLI commands to perform.
+ * 
+ * A breakpoint can be enabled or disabled.  It can be set such
+ * that it disabled or deletes itself after being hit N times.
+ */
+public class BreakAction
+{
+       // return values for getStatus()
+       public final static int         RESOLVED = 1;
+       public final static int         UNRESOLVED = 2;
+       public final static int         AMBIGUOUS = 3;
+       public final static int         NOCODE = 4;     // there is no 
executable code at the specified line
+
+       /**
+        * This will be null if the user typed in a breakpoint expression which
+        * did not match any currently loaded location, but we have saved it
+        * (with status == UNRESOLVED) in case it gets resolved later when 
another
+        * SWF or ABC gets loaded.
+        */
+       private LocationCollection      m_where;                                
// may be null
+
+       /**
+        * This will be null if the breakpoint was created via the
+        * <code>BreakAction(String unresolvedLocation)</code> constructor.
+        */
+       private String                          m_breakpointExpression; // may 
be null
+
+       private Vector<String>          m_commands;
+       private boolean                         m_enabled;
+       private boolean                         m_autoDelete;
+       private boolean                         m_autoDisable;
+       private boolean                         m_silent;
+       private boolean                         m_singleSwf;                    
// is breakpoint meant for a single swf only
+       private int                                     m_id;
+       private int                                     m_hits;
+       private ValueExp                        m_condition;
+       private String                          m_conditionString;
+       private int                                     m_status;
+    private boolean             m_propagable;
+    
+       public BreakAction(LocationCollection c) throws NullPointerException
+       {
+               m_where = c;
+               m_where.first().getFile();  // force NullPointerException if l 
== null
+               m_status = RESOLVED;
+               init();
+       }
+
+       public BreakAction(String unresolvedLocation)
+       {
+               m_breakpointExpression = unresolvedLocation;
+               m_status = UNRESOLVED;
+               init();
+       }
+
+       private void init()
+       {
+               m_id = BreakIdentifier.next();
+               m_commands = new Vector<String>();
+               m_propagable = true;
+       }
+
+       /* getters */
+       public int                                      getCommandCount()       
                        { return m_commands.size(); }
+       public String                           commandAt(int i)                
                { return m_commands.elementAt(i); }
+       public Location                         getLocation()                   
                { return (m_where != null) ? m_where.first() : null; }
+    public LocationCollection  getLocations()                                  
{ return m_where; }
+       public int                                      getId()                 
                                { return m_id; }
+       public int                                      getHits()               
                                { return m_hits; }
+       public boolean                          isEnabled()                     
                        { return m_enabled; }
+       public boolean                          isAutoDisable()                 
                { return m_autoDisable; }
+       public boolean                          isAutoDelete()                  
                { return m_autoDelete; }
+       public boolean                          isSilent()                      
                        { return m_silent; }
+       public boolean                          isSingleSwf()                   
                { return m_singleSwf; }
+       public ValueExp                         getCondition()                  
                { return m_condition; }
+       public String                           getConditionString()            
        { return m_conditionString; }
+       public String                           getBreakpointExpression()       
        { return m_breakpointExpression; }
+       public int                                      getStatus()             
                                { return m_status; }
+    public boolean              isPropagable()                  { return 
m_propagable; }
+    
+       /* setters */
+       public void addCommand(String cmd)                                      
{ m_commands.add(cmd); }
+       public void clearCommands()                                             
        { m_commands.clear(); }
+       public void addLocation(Location l)                                     
{ m_where.add(l); }
+       public void setEnabled(boolean enable)                          { 
m_enabled = enable; }
+       public void setAutoDisable(boolean disable)                     { 
m_autoDisable = disable; }
+       public void setAutoDelete(boolean delete)                       { 
m_autoDelete = delete; }
+       public void setSilent(boolean silent)                           { 
m_silent = silent; }
+       public void setCondition(ValueExp c, String s)          { m_condition = 
c;  m_conditionString = s; }
+       public void clearCondition()                                            
{ setCondition(null, ""); } //$NON-NLS-1$
+       public void hit()                                                       
                { m_hits++; }
+       public void clearHits()                                                 
        { m_hits = 0; }
+       public void setSingleSwf(boolean singleSwf)                     { 
m_singleSwf = singleSwf; }
+       public void setBreakpointExpression(String expr)        { 
m_breakpointExpression = expr; }
+       public void setStatus(int status)                                       
{ m_status = status; }
+    public void setPropagable(boolean propagable)       { m_propagable = 
propagable; }
+    
+       public void setLocations(LocationCollection loc)
+       {
+               m_where = loc;
+               if (loc != null)
+                       setStatus(RESOLVED);
+       }
+
+       /*
+        * Check to see if our location matches the requested one
+        */
+    public boolean locationMatches(int fileId, int line, int isolateId)
+    {
+               boolean match = false;
+               LocationCollection col = getLocations();
+               if (col != null)
+               {
+                       Iterator itr = col.iterator();
+               
+                       // probe all locations looking for a match
+                       while(!match && itr.hasNext())
+                       {
+                               Location l = (Location)itr.next();
+                if (l != null && l.getFile().getId() == fileId && l.getLine() 
== line && (isolateId == -1 || l.getIsolateId() == isolateId))
+                       match = true;
+                       }
+               }
+               return match;
+       }
+}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/07f5a7de/debugger/src/main/java/flex/tools/debugger/cli/BreakIdentifier.java
----------------------------------------------------------------------
diff --git 
a/debugger/src/main/java/flex/tools/debugger/cli/BreakIdentifier.java 
b/debugger/src/main/java/flex/tools/debugger/cli/BreakIdentifier.java
new file mode 100644
index 0000000..9a32cca
--- /dev/null
+++ b/debugger/src/main/java/flex/tools/debugger/cli/BreakIdentifier.java
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package flex.tools.debugger.cli;
+
+/**
+ * An singleton object that doles out unique identifiers to breakpoints and 
watchpoints
+ */
+public class BreakIdentifier
+{
+       private static int s_uniqueIdentifier  = 1;
+
+       public static int next() { return s_uniqueIdentifier++; }
+}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/07f5a7de/debugger/src/main/java/flex/tools/debugger/cli/CatchAction.java
----------------------------------------------------------------------
diff --git a/debugger/src/main/java/flex/tools/debugger/cli/CatchAction.java 
b/debugger/src/main/java/flex/tools/debugger/cli/CatchAction.java
new file mode 100644
index 0000000..6dac5e9
--- /dev/null
+++ b/debugger/src/main/java/flex/tools/debugger/cli/CatchAction.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package flex.tools.debugger.cli;
+
+/**
+ * 
+ * An object that relates a CLI debugger catchpoint with the
+ * actual Catch obtained from the Session
+ * 
+ * @author Mike Morearty
+ */
+public class CatchAction
+{
+       private final int m_id;
+       private final String m_typeToCatch;
+
+       /**
+        * @param typeToCatch
+        *            the type, e.g. "ReferenceError" or "com.example.MyError". 
If
+        *            typeToCatch is <code>null</code>, that means to halt on 
any
+        *            exception.
+        */
+       public CatchAction(String typeToCatch)
+       {
+               m_typeToCatch = typeToCatch;
+               m_id = BreakIdentifier.next();
+       }
+
+       public int getId()
+       {
+               return m_id;
+       }
+
+       /**
+        * Returns the type being caught, or <code>null</code> to catch all
+        * exceptions.
+        */
+       public String getTypeToCatch()
+       {
+               return m_typeToCatch;
+       }
+}

Reply via email to