You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@flex.apache.org by ah...@apache.org on 2016/04/26 06:29:03 UTC

[11/63] [abbrv] [partial] git commit: [flex-falcon] [refs/heads/develop] - move stuff to where I think Maven wants it

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/07f5a7de/debugger/src/main/java/flex/tools/debugger/cli/DisplayAction.java
----------------------------------------------------------------------
diff --git a/debugger/src/main/java/flex/tools/debugger/cli/DisplayAction.java b/debugger/src/main/java/flex/tools/debugger/cli/DisplayAction.java
new file mode 100644
index 0000000..d8612d5
--- /dev/null
+++ b/debugger/src/main/java/flex/tools/debugger/cli/DisplayAction.java
@@ -0,0 +1,62 @@
+/*
+ * 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 flash.tools.debugger.expression.ValueExp;
+
+/**
+ * An object that relates a CLI debugger 'display' command
+ * with the contents of the display 
+ */
+public class DisplayAction
+{
+	private static int s_uniqueIdentifier  = 1;
+
+	boolean		m_enabled;
+	int			m_id;
+	ValueExp	m_expression;
+	String		m_content;
+	int m_isolateId;
+
+	public DisplayAction(ValueExp expr, String content, int isolateId)
+	{
+		init();
+		m_expression = expr;
+		m_content = content;
+		m_isolateId = isolateId;
+	}
+
+	void init()
+	{
+		m_enabled = true;
+		m_id = s_uniqueIdentifier++;
+	}
+
+	/* getters */
+	public String		getContent()					{ return m_content; }
+	public int			getId()							{ return m_id; }
+	
+	public int getIsolateId() {
+		return m_isolateId;
+	}
+	public boolean		isEnabled()						{ return m_enabled; }
+	public ValueExp		getExpression()					{ return m_expression; }
+
+	/* setters */
+	public void setEnabled(boolean enable)				{ m_enabled = enable; }
+}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/07f5a7de/debugger/src/main/java/flex/tools/debugger/cli/ExpressionCache.java
----------------------------------------------------------------------
diff --git a/debugger/src/main/java/flex/tools/debugger/cli/ExpressionCache.java b/debugger/src/main/java/flex/tools/debugger/cli/ExpressionCache.java
new file mode 100644
index 0000000..95698d5
--- /dev/null
+++ b/debugger/src/main/java/flex/tools/debugger/cli/ExpressionCache.java
@@ -0,0 +1,596 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package flex.tools.debugger.cli;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.text.ParseException;
+import java.util.NoSuchElementException;
+import java.util.Set;
+import java.util.Vector;
+
+import flash.localization.LocalizationManager;
+import flash.tools.debugger.Bootstrap;
+import flash.tools.debugger.NoResponseException;
+import flash.tools.debugger.NotConnectedException;
+import flash.tools.debugger.NotSuspendedException;
+import flash.tools.debugger.PlayerDebugException;
+import flash.tools.debugger.Session;
+import flash.tools.debugger.Value;
+import flash.tools.debugger.ValueAttribute;
+import flash.tools.debugger.Variable;
+import flash.tools.debugger.VariableAttribute;
+import flash.tools.debugger.VariableType;
+import flash.tools.debugger.concrete.DValue;
+import flash.tools.debugger.expression.ASTBuilder;
+import flash.tools.debugger.expression.IASTBuilder;
+import flash.tools.debugger.expression.NoSuchVariableException;
+import flash.tools.debugger.expression.PlayerFaultException;
+import flash.tools.debugger.expression.ValueExp;
+
+public class ExpressionCache
+{
+	Session				m_session;
+	IASTBuilder			m_builder;
+	Vector<Object>		m_expressions;
+	IntProperties		m_props;
+	DebugCLI			m_cli;
+
+	/**
+	 * Returned by evaluate().
+	 */
+	public static class EvaluationResult
+	{
+		/**
+		 * The value to which the expression evaluated.
+		 */
+		public Object value;
+
+		/**
+		 * The context that was used to evaluate the expression. Sometimes used
+		 * to convert the <code>value</code> field to a <code>Value</code>
+		 * with <code>context.toValue()</code>.
+		 */
+		public ExpressionContext context;
+	}
+
+	/**
+	 * We can get at files by name or module id, eventually we will put functions in here too
+	 */
+
+	public ExpressionCache(DebugCLI cli)
+	{
+		m_builder = new ASTBuilder(true); // allow fdb's "*x" and "x." indirection operators
+		m_expressions = new Vector<Object>();
+		m_props = new IntProperties();
+		m_cli = cli;
+	}
+
+	public void			clear()			{ m_expressions.clear(); }
+	public void			unbind()		{ m_session = null; }
+	public int			size()			{ return m_expressions.size(); }
+	public Object		at(int i)		{ return m_expressions.elementAt(i); }
+
+	void setSession(Session s)	{ m_session = s; }
+
+	public Session		getSession()			{ return m_session; }
+	public String		getPackageName(int id)	{ return m_cli.module2ClassName(id); }
+
+	public void bind(Session s)
+	{ 
+		setSession(s); 
+
+		// propagates our properties to the session / non-critical if fails
+		try { ((flash.tools.debugger.concrete.PlayerSession)s).setPreferences(m_props.map()); } catch(Exception e) {}
+	}
+
+	public EvaluationResult evaluate(ValueExp e, int isolateId) throws NumberFormatException, NoSuchVariableException, PlayerFaultException, PlayerDebugException
+	{
+		EvaluationResult result = new EvaluationResult();
+		result.context = new ExpressionContext(this);
+		result.context.setIsolateId(isolateId);
+		result.value = e.evaluate(result.context);
+		return result;
+	}
+
+	public ValueExp parse(String s) throws IOException, ParseException
+	{
+		return m_builder.parse(new StringReader(s));
+	}
+
+	public int add(Object e)
+	{
+		int at = m_expressions.size();
+		m_expressions.add(e);
+		return at+1;
+	}
+
+	//
+	// Interface for accessing previous expression values and also the properties
+	//
+	public boolean propertyEnabled(String which)
+	{
+		boolean enabled = false;
+		try
+		{
+			Number number = (Number) get(which);
+			if (number != null)
+				enabled = (number.intValue() != 0);
+		}
+		catch (Exception e)
+		{
+			// nothing; leave 'enabled' as false
+		}
+		return enabled;
+	}
+
+	// this goes in properties
+	public void put(String s, int value) { m_props.put(s, value); setSessionProperty(s, value); }
+	public Set<String>  keySet() { return m_props.keySet(); }
+
+	/**
+	 * Allow the session to receive property updates 
+	 */
+	void setSessionProperty(String s, int value)
+	{
+		Session sess = getSession();
+	    if (sess != null)
+			sess.setPreference(s, value);
+		Bootstrap.sessionManager().setPreference(s, value);
+	}
+
+	/**
+	 * We are able to fetch properties or expressions (i.e previous expression)
+	 * using this single call, despite the fact that each of these types of 
+	 * results lie in different data structures m_expressions and m_props.
+	 * This allows us to easily perform expression evaluation without
+	 * need or concern over which 'type' of $ reference we are dealing with
+	 */
+	public Object get(String s) throws NumberFormatException, ArrayIndexOutOfBoundsException, NoSuchElementException
+	{
+		Object exp = null;
+
+		// should be of form '$n' where n is a number 0..size()
+		if (s.charAt(0) != '$')
+			throw new NoSuchElementException(s);
+
+	    String num = s.substring(1);
+		if (num == null || num.length() == 0)
+			exp = at(size()-1);
+		else if (num.equals("$")) //$NON-NLS-1$
+			exp = at(size()-2);
+		else
+		{
+			try
+			{
+				int index = Integer.parseInt(num);
+				exp = at(index-1);
+			}
+			catch(NumberFormatException nfe)
+			{
+				// must be in the property list 
+				exp = m_props.getInteger(s);
+			}
+		}
+		return exp;
+	}
+
+	//
+	// Statics for formatting stuff
+	//
+
+	/**
+	 * Formatting function for variable
+	 */
+	public void appendVariable(StringBuilder sb, Variable v, int isolateId)
+	{
+		//sb.append('\'');
+		String name = v.getName();
+		sb.append(name);
+		//sb.append('\'');
+		sb.append(" = "); //$NON-NLS-1$
+		appendVariableValue(sb, v.getValue(), name, isolateId);
+		//appendVariableAttributes(sb, v);
+	}
+
+	/**
+	 * Given any arbitrary constant value, such as a Double, a String, etc.,
+	 * format its value appropriately. For example, strings will be quoted.
+	 * 
+	 * @param sb
+	 *            a StringBuilder to which the formatted value will be appended.
+	 * @param o
+	 *            the value to format.
+	 */
+	public void appendVariableValue(StringBuilder sb, final Object o, final int isolateId)
+	{
+		Value v;
+
+		if (o instanceof Value) {
+			v = (Value) o;
+		} else {
+			v = new Value() {
+				public int getAttributes() {
+					return 0;
+				}
+
+				public String[] getClassHierarchy(boolean allLevels) {
+					return new String[0];
+				}
+
+				public String getClassName() {
+					return ""; //$NON-NLS-1$
+				}
+
+				public long getId() {
+					return UNKNOWN_ID;
+				}
+
+				public int getMemberCount(Session s) throws NotSuspendedException,
+						NoResponseException, NotConnectedException {
+					return 0;
+				}
+
+				public Variable getMemberNamed(Session s, String name)
+						throws NotSuspendedException, NoResponseException,
+						NotConnectedException {
+					return null;
+				}
+
+				public Variable[] getMembers(Session s)
+						throws NotSuspendedException, NoResponseException,
+						NotConnectedException {
+					return new Variable[0];
+				}
+
+				public int getType() {
+					if (o instanceof Number)
+						return VariableType.NUMBER;
+					else if (o instanceof Boolean)
+						return VariableType.BOOLEAN;
+					else if (o instanceof String)
+						return VariableType.STRING;
+					else if (o == Value.UNDEFINED)
+						return VariableType.UNDEFINED;
+					else if (o == null)
+						return VariableType.NULL;
+
+					assert false;
+					return VariableType.UNKNOWN;
+				}
+
+				public String getTypeName() {
+					return ""; //$NON-NLS-1$
+				}
+
+				public Object getValueAsObject() {
+					return o;
+				}
+
+				public String getValueAsString() {
+					return DValue.getValueAsString(o);
+				}
+
+				public boolean isAttributeSet(int variableAttribute) {
+					return false;
+				}
+
+				public Variable[] getPrivateInheritedMembers() {
+					return new Variable[0];
+				}
+
+				public Variable[] getPrivateInheritedMemberNamed(String name) {
+					return new Variable[0];
+				}
+				
+				public int getIsolateId() {
+					return isolateId;
+				}
+			};
+		}
+
+		appendVariableValue(sb, v, isolateId);
+	}
+
+	public void appendVariableValue(StringBuilder sb, Value val, final int isolateId) { appendVariableValue(sb,val,"", isolateId); } //$NON-NLS-1$
+
+	public void appendVariableValue(StringBuilder sb, Value val, String variableName, final int isolateId)
+	{
+		int type = val.getType();
+		String typeName = val.getTypeName();
+		String className = val.getClassName();
+
+		// if no string or empty then typeName is blank
+		if (typeName != null && typeName.length() == 0)
+			typeName = null;
+
+        switch (type)
+        {
+            case VariableType.NUMBER:
+            {
+				double value = ((Number)val.getValueAsObject()).doubleValue();
+				long longValue = (long) value;
+				// The value is stored as a double; however, in practice most values are
+				// actually integers.  Check to see if this is the case, and if it is,
+				// then display it:
+				//    - without a fraction, and
+				//    - with its hex equivalent in parentheses.
+				// Note, we use 'long' instead of 'int', in order to deal with the
+				// ActionScript type 'uint'.
+				if (longValue == value)
+				{
+					sb.append(longValue);
+					sb.append(" (0x"); //$NON-NLS-1$
+					sb.append(Long.toHexString(longValue));
+					sb.append(")"); //$NON-NLS-1$
+				}
+				else
+				{
+					sb.append(value);
+				}
+                break;
+            }
+
+            case VariableType.BOOLEAN:
+            {
+                Boolean b = (Boolean)val.getValueAsObject();
+                if (b.booleanValue())
+                    sb.append("true"); //$NON-NLS-1$
+                else
+                    sb.append("false"); //$NON-NLS-1$
+                break;
+            }
+
+            case VariableType.STRING:
+            {
+            	// Exceptions are displayed in angle brackets, e.g.
+            	//     foo = <Text of exception here>
+            	// Strings are displayed quoted:
+            	//     foo = "Value of string here"
+            	//
+            	// Note that quotation marks within the string are not escaped.  This
+            	// is sort of weird, but it's what we want to do, at least for now;
+            	// the debugger's output is intended to be human-readable, not
+            	// machine-readable, and it's easier for a person to read the string
+            	// if there is no escaping of quotation marks.
+            	//
+            	// As a small step in the direction of avoiding that weirdness, if
+            	// the string contains double-quotes but no single-quotes, we will
+            	// quote it in single quotes.
+            	String s = val.getValueAsString();
+            	char start, end;
+
+				if (val.isAttributeSet(ValueAttribute.IS_EXCEPTION))
+				{
+					start = '<';
+					end = '>';
+				}
+				else if (s.indexOf('"') != -1 && s.indexOf('\'') == -1)
+				{
+					start = end = '\'';
+				}
+				else
+				{
+					start = end = '"';
+				}
+
+                sb.append(start);
+                sb.append(escapeIfIde(s));
+                sb.append(end);
+                break;
+            }
+
+            case VariableType.OBJECT:
+            {
+                sb.append("["); //$NON-NLS-1$
+				sb.append(className);
+
+				// Normally, we include the object id after the class name.
+				// However, when running fdbunit, don't show object IDs, so that
+				// results can reproduce consistently from one run to the next.
+				if (System.getProperty("fdbunit") == null) //$NON-NLS-1$
+				{
+					sb.append(" "); //$NON-NLS-1$
+					sb.append(escapeIfIde(String.valueOf(val.getValueAsObject()))); // object id
+				}
+                if (typeName != null && !typeName.equals(className))
+                {
+                    sb.append(", class='"); //$NON-NLS-1$
+
+					// Often the typename is of the form 'classname@hexaddress',
+					// but the hex address is the same as the object id which
+					// is returned by getValue() -- we don't want to display it
+					// here.
+					int at = typeName.indexOf('@');
+					if (at != -1)
+						typeName = typeName.substring(0, at);
+
+                    sb.append(typeName);
+                    sb.append('\'');
+                }
+                sb.append(']');
+                break;
+            }
+
+            case VariableType.FUNCTION:
+            {
+				// here we have a special case for getters/setters which 
+				// look like functions to us, except the attribute is set.
+				sb.append('[');
+				if (val.isAttributeSet(VariableAttribute.HAS_GETTER))
+					sb.append(getLocalizationManager().getLocalizedTextString("getterFunction")); //$NON-NLS-1$
+				else if (val.isAttributeSet(VariableAttribute.HAS_SETTER))
+					sb.append(getLocalizationManager().getLocalizedTextString("setterFunction")); //$NON-NLS-1$
+				else
+					sb.append(getLocalizationManager().getLocalizedTextString("function")); //$NON-NLS-1$
+				sb.append(' ');
+
+				sb.append(escapeIfIde(String.valueOf(val.getValueAsObject())));
+                if (typeName != null && !typeName.equals(variableName))
+                {
+                    sb.append(", name='"); //$NON-NLS-1$
+                    sb.append(typeName);
+                    sb.append('\'');
+                }
+                sb.append(']');
+                break;
+            }
+
+            case VariableType.MOVIECLIP:
+            {
+                sb.append("["); //$NON-NLS-1$
+				sb.append(className);
+				sb.append(" "); //$NON-NLS-1$
+				sb.append(escapeIfIde(String.valueOf(val.getValueAsObject())));
+                if (typeName != null && !typeName.equals(className))
+                {
+                    sb.append(", named='"); //$NON-NLS-1$
+                    sb.append(typeName);
+                    sb.append('\'');
+                }
+                sb.append(']');
+                break;
+            }
+
+            case VariableType.NULL:
+            {
+                sb.append("null"); //$NON-NLS-1$
+                break;
+            }
+
+            case VariableType.UNDEFINED:
+            {
+                sb.append("undefined"); //$NON-NLS-1$
+                break;
+            }
+
+            case VariableType.UNKNOWN:
+            {
+                sb.append(getLocalizationManager().getLocalizedTextString("unknownVariableType")); //$NON-NLS-1$
+                break;
+            }
+        }
+	}
+
+	private static LocalizationManager getLocalizationManager()
+	{
+		return DebugCLI.getLocalizationManager();
+	}
+
+	public static void appendVariableAttributes(StringBuilder sb, Variable v)
+	{
+		if (v.getAttributes() == 0)
+			return;
+
+		sb.append("  "); //$NON-NLS-1$
+
+		if (v.isAttributeSet(VariableAttribute.DONT_ENUMERATE))
+			sb.append(", " + getLocalizationManager().getLocalizedTextString("variableAttribute_dontEnumerate")); //$NON-NLS-1$ //$NON-NLS-2$
+
+		if (v.isAttributeSet(VariableAttribute.READ_ONLY))
+			sb.append(", " + getLocalizationManager().getLocalizedTextString("variableAttribute_readOnly")); //$NON-NLS-1$ //$NON-NLS-2$
+
+		if (v.isAttributeSet(VariableAttribute.IS_LOCAL))
+			sb.append(", " + getLocalizationManager().getLocalizedTextString("variableAttribute_localVariable")); //$NON-NLS-1$ //$NON-NLS-2$
+
+		if (v.isAttributeSet(VariableAttribute.IS_ARGUMENT))
+			sb.append(", " + getLocalizationManager().getLocalizedTextString("variableAttribute_functionArgument")); //$NON-NLS-1$ //$NON-NLS-2$
+
+		if (v.isAttributeSet(VariableAttribute.HAS_GETTER))
+			sb.append(", " + getLocalizationManager().getLocalizedTextString("variableAttribute_getterFunction")); //$NON-NLS-1$ //$NON-NLS-2$
+
+		if (v.isAttributeSet(VariableAttribute.HAS_SETTER))
+			sb.append(", " + getLocalizationManager().getLocalizedTextString("variableAttribute_setterFunction")); //$NON-NLS-1$ //$NON-NLS-2$
+
+		if (v.isAttributeSet(VariableAttribute.IS_DYNAMIC))
+			sb.append(", dynamic"); //$NON-NLS-1$
+		
+		if (v.isAttributeSet(VariableAttribute.IS_STATIC))
+			sb.append(", static"); //$NON-NLS-1$
+
+		if (v.isAttributeSet(VariableAttribute.IS_CONST))
+			sb.append(", const"); //$NON-NLS-1$
+
+		if (v.isAttributeSet(VariableAttribute.PRIVATE_SCOPE))
+			sb.append(", private"); //$NON-NLS-1$
+
+		if (v.isAttributeSet(VariableAttribute.PUBLIC_SCOPE))
+			sb.append(", public"); //$NON-NLS-1$
+
+		if (v.isAttributeSet(VariableAttribute.PROTECTED_SCOPE))
+			sb.append(", protected"); //$NON-NLS-1$
+
+		if (v.isAttributeSet(VariableAttribute.INTERNAL_SCOPE))
+			sb.append(", internal"); //$NON-NLS-1$
+
+		if (v.isAttributeSet(VariableAttribute.NAMESPACE_SCOPE))
+			sb.append(", " + getLocalizationManager().getLocalizedTextString("variableAttribute_hasNamespace")); //$NON-NLS-1$ //$NON-NLS-2$
+	}
+	
+    private String escapeIfIde(String s)
+    {
+        return m_cli != null && m_cli.isIde() ? escape(s) : s;
+    }
+
+    public static String escape(final String str) {
+        final StringBuilder buffer = new StringBuilder();
+
+        for (int idx = 0; idx < str.length(); idx++) {
+            char ch = str.charAt(idx);
+            switch (ch) {
+                case '\b':
+                    buffer.append("\\b");
+                    break;
+
+                case '\t':
+                    buffer.append("\\t");
+                    break;
+
+                case '\n':
+                    buffer.append("\\n");
+                    break;
+
+                case '\f':
+                    buffer.append("\\f");
+                    break;
+
+                case '\r':
+                    buffer.append("\\r");
+                    break;
+
+                case '\\':
+                    buffer.append("\\\\");
+                    break;
+
+                default:
+                    if (Character.isISOControl(ch)) {
+                        String hexCode = Integer.toHexString(ch).toUpperCase();
+                        buffer.append("\\u");
+                        int paddingCount = 4 - hexCode.length();
+                        while (paddingCount-- > 0) {
+                            buffer.append(0);
+                        }
+                        buffer.append(hexCode);
+                    } else {
+                        buffer.append(ch);
+                    }
+            }
+        }
+        return buffer.toString();
+    }
+}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/07f5a7de/debugger/src/main/java/flex/tools/debugger/cli/ExpressionContext.java
----------------------------------------------------------------------
diff --git a/debugger/src/main/java/flex/tools/debugger/cli/ExpressionContext.java b/debugger/src/main/java/flex/tools/debugger/cli/ExpressionContext.java
new file mode 100644
index 0000000..2bed5ee
--- /dev/null
+++ b/debugger/src/main/java/flex/tools/debugger/cli/ExpressionContext.java
@@ -0,0 +1,653 @@
+/*
+ * 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.StringTokenizer;
+import java.util.Vector;
+
+import flash.tools.debugger.Isolate;
+import flash.tools.debugger.PlayerDebugException;
+import flash.tools.debugger.Session;
+import flash.tools.debugger.SessionManager;
+import flash.tools.debugger.Value;
+import flash.tools.debugger.ValueAttribute;
+import flash.tools.debugger.Variable;
+import flash.tools.debugger.VariableType;
+import flash.tools.debugger.concrete.DValue;
+import flash.tools.debugger.events.ExceptionFault;
+import flash.tools.debugger.events.FaultEvent;
+import flash.tools.debugger.expression.Context;
+import flash.tools.debugger.expression.ExpressionEvaluatorException;
+import flash.tools.debugger.expression.NoSuchVariableException;
+import flash.tools.debugger.expression.PlayerFaultException;
+
+public class ExpressionContext implements Context
+{
+	ExpressionCache		m_cache;
+	Object				m_current;
+	boolean				m_createIfMissing;  // set if we need to create a variable if it doesn't exist
+	Vector<String>		m_namedPath;
+	boolean				m_nameLocked;
+	String				m_newline = System.getProperty("line.separator"); //$NON-NLS-1$
+	int m_isolateId;
+
+	// used when evaluating an expression
+	public ExpressionContext(ExpressionCache cache)
+	{
+		m_cache = cache;
+		m_current = null;
+		m_createIfMissing = false;
+		m_namedPath = new Vector<String>();
+		m_nameLocked = false;
+		m_isolateId = Isolate.DEFAULT_ID;
+	}
+	
+	public void setIsolateId(int id) {
+		m_isolateId = id;
+	}
+
+	void		setContext(Object o)	{ m_current = o; }
+
+	void		pushName(String name)	{ if (m_nameLocked || name.length() < 1) return; m_namedPath.add(name);  }
+	boolean		setName(String name)	{ if (m_nameLocked) return true; m_namedPath.clear(); pushName(name); return true; }
+	void		lockName()				{ m_nameLocked = true; }
+
+	public String getName()
+	{
+		int size = m_namedPath.size();
+		StringBuilder sb = new StringBuilder();
+		for(int i=0; i<size; i++)
+		{
+			String s = m_namedPath.get(i);
+			if (i > 0)
+				sb.append('.');
+			sb.append(s);
+		}
+		return ( sb.toString() );
+	}
+
+	String getCurrentPackageName()
+	{ 
+		String s = null;
+		try
+		{
+			Integer o = (Integer)m_cache.get(DebugCLI.LIST_MODULE);
+			s = m_cache.getPackageName(o.intValue());
+		}
+		catch(NullPointerException npe)
+		{
+		}
+		catch(ClassCastException cce)
+		{
+		}
+		return s; 
+	}
+
+	//
+	//
+	// Start of Context API implementation
+	//
+	//
+	public void createPseudoVariables(boolean oui) { m_createIfMissing = oui; }
+
+	// create a new context object by combining the current one and o 
+	public Context createContext(Object o)
+	{
+		ExpressionContext c = new ExpressionContext(m_cache);
+		c.setContext(o);
+		c.createPseudoVariables(m_createIfMissing);
+		c.m_namedPath.addAll(m_namedPath);
+		c.setIsolateId(m_isolateId);
+		return c;
+	}
+
+	// assign the object o, the value v
+	public void assign(Object o, Value v) throws NoSuchVariableException, PlayerFaultException
+	{
+		try
+		{
+			// first see if it is an internal property (avoids player calls)
+			InternalProperty prop = resolveToInternalProperty(o);
+
+			// we expect that o is a variable that can be resolved or is a specially marked internal variable
+			if (prop != null)
+			{
+				assignInternal(prop, v);
+			}
+			else
+			{
+				boolean wasCreateIfMissing = m_createIfMissing;
+				createPseudoVariables(true);
+				Variable var = null;
+				try {
+					var = resolveToVariable(o);
+				} finally {
+					createPseudoVariables(wasCreateIfMissing);
+				}
+
+				if (var == null)
+					throw new NoSuchVariableException((var == null) ? m_current : var.getName());
+
+				// set the value, for the case of a variable that does not exist it will not have a type
+				// so we try to glean one from v.
+				FaultEvent faultEvent = var.setValue(getSession(), v.getType(), v.getValueAsString());
+				if (faultEvent != null)
+					throw new PlayerFaultException(faultEvent);
+			}
+		}
+		catch(PlayerDebugException pde)
+		{
+			throw new ExpressionEvaluatorException(pde);
+		}
+	}
+
+	/**
+	 * The Context interface which goes out and gets values from the session
+	 * Expressions use this interface as a means of evaluation.
+	 * 
+	 * We also use this to create a reference to internal variables.
+	 */
+	public Object lookup(Object o) throws NoSuchVariableException, PlayerFaultException
+	{
+		Object result = null;
+		try
+		{
+			// first see if it is an internal property (avoids player calls)
+			if ( (result = resolveToInternalProperty(o)) != null)
+				;
+
+			// attempt to resolve to a player variable
+			else if ( (result = resolveToVariable(o)) != null)
+				;
+
+			// or value
+			else if ( (result = resolveToValue(o)) != null)
+				;
+
+			else
+				throw new NoSuchVariableException(o);
+
+			// take on the path to the variable; so 'what' command prints something nice
+			if ((result != null) && result instanceof VariableFacade)
+			{
+				((VariableFacade)result).setPath(getName());
+			}
+
+			// if the attempt to get the variable's value threw an exception inside the
+			// player (most likely because the variable is actually a getter, and the
+			// getter threw something), then throw something here
+			Value resultValue = null;
+
+			if (result instanceof Variable)
+			{
+				if (result instanceof VariableFacade && ((VariableFacade)result).getVariable() == null)
+					resultValue = null;
+				else
+					resultValue = ((Variable)result).getValue();
+			}
+			else if (result instanceof Value)
+			{
+				resultValue = (Value) result;
+			}
+
+			if (resultValue != null)
+			{
+				if (resultValue.isAttributeSet(ValueAttribute.IS_EXCEPTION))
+				{
+					String value = resultValue.getValueAsString();
+					throw new PlayerFaultException(new ExceptionFault(value, false, resultValue, resultValue.getIsolateId()));
+				}
+			}
+		}
+		catch(PlayerDebugException pde)
+		{
+			result = Value.UNDEFINED;
+		}
+		return result;
+	}
+
+	/* returns a string consisting of formatted member names and values */
+	public Object lookupMembers(Object o) throws NoSuchVariableException
+	{
+		Variable var = null;
+		Value val = null;
+  		Variable[] mems = null;
+		try
+		{
+			var = resolveToVariable(o);
+			if (var != null)
+				val = var.getValue();
+			else
+				val = resolveToValue(o);
+			mems = val.getMembers(getSession());
+		}
+		catch(NullPointerException npe)
+		{
+			throw new NoSuchVariableException(o);
+		}
+		catch(PlayerDebugException pde)
+		{
+			throw new NoSuchVariableException(o); // not quite right...
+		}
+
+  		StringBuilder sb = new StringBuilder();
+
+  		if (var != null)
+  			m_cache.appendVariable(sb, var, m_isolateId);
+  		else
+  			m_cache.appendVariableValue(sb, val, m_isolateId);
+
+		boolean attrs = m_cache.propertyEnabled(DebugCLI.DISPLAY_ATTRIBUTES);
+		if (attrs && var != null)
+			ExpressionCache.appendVariableAttributes(sb, var);
+
+		// [mmorearty] experimenting with hierarchical display of members
+		String[] classHierarchy = val.getClassHierarchy(false);
+		if (classHierarchy != null && getSession().getPreference(SessionManager.PREF_HIERARCHICAL_VARIABLES) != 0)
+		{
+			for (int c=0; c<classHierarchy.length; ++c)
+			{
+				String classname = classHierarchy[c];
+				sb.append(m_newline + "(Members of " + classname + ")"); //$NON-NLS-1$ //$NON-NLS-2$
+				for (int i=0; i<mems.length; ++i)
+				{
+					if (classname.equals(mems[i].getDefiningClass()))
+					{
+			  			sb.append(m_newline + " "); //$NON-NLS-1$
+			  			m_cache.appendVariable(sb, mems[i], m_isolateId);
+						if (attrs)
+							ExpressionCache.appendVariableAttributes(sb, mems[i]);
+					}
+				}
+			}
+		}
+		else
+		{
+	  		for(int i=0; i<mems.length; i++)
+	  		{
+	  			sb.append(m_newline + " "); //$NON-NLS-1$
+	  			m_cache.appendVariable(sb, mems[i], m_isolateId);
+				if (attrs)
+					ExpressionCache.appendVariableAttributes(sb, mems[i]);
+	  		}
+		}
+
+  		return sb.toString();
+  	}
+
+	//
+	//
+	// End of Context API implementation 
+	//
+	//
+
+	// used to assign a value to an internal variable 
+	private void assignInternal(InternalProperty var, Value v) throws NoSuchVariableException, NumberFormatException, PlayerDebugException
+	{
+		// otherwise set it
+		if (v.getType() != VariableType.NUMBER)
+			throw new NumberFormatException(v.getValueAsString());
+		long l = Long.parseLong(v.getValueAsString());
+		m_cache.put(var.getName(), (int)l);
+	}
+
+	InternalProperty resolveToInternalProperty(Object o)
+	{
+		if (o instanceof String && ((String)o).charAt(0) == '$')
+		{
+			String key = (String)o;
+			Object value = null;
+
+			try { value = m_cache.get(key); } catch(Exception e) {}
+			return new InternalProperty(key, value);
+		}
+
+		return null;
+	}
+
+	/**
+	 * Resolve the object into a variable by various means and 
+	 * using the current context.
+	 * @return variable, or <code>null</code>
+	 */
+	Variable resolveToVariable(Object o) throws PlayerDebugException
+	{
+		Variable v = null;
+
+		// if o is a variable already, then we're done!
+		if (o instanceof Variable)
+			return (Variable)o;
+
+		/**
+		 * Resolve the name to something
+		 */
+		{
+			// not an id so try as name 
+			String name = o.toString();
+			long id = nameAsId(name);
+
+			/**
+			 * if #N was used just pick up the variable, otherwise
+			 * we need to use the current context to resolve 
+			 * the name to a member
+			 */
+			if (id != Value.UNKNOWN_ID)
+			{
+				// TODO what here?
+			}
+			else
+			{
+				// try to resolve as a member of current context (will set context if null)
+				id = determineContext(name);
+				v = locateForNamed(id, name, true);
+				if (v != null)
+					v = new VariableFacade(v, id, m_isolateId);
+				else if (v == null && m_createIfMissing && name.charAt(0) != '$')
+					v = new VariableFacade(id, name, m_isolateId);
+			}
+		}
+
+		/* return the variable */
+		return v;
+	}
+
+	/*
+	 * Resolve the object into a variable by various means and 
+	 * using the current context.
+	 */
+	Value resolveToValue(Object o) throws PlayerDebugException
+	{
+		Value v = null;
+
+		// if o is a variable or a value already, then we're done!
+		if (o instanceof Value)
+			return (Value)o;
+		else if (o instanceof Variable)
+			return ((Variable)o).getValue();
+		else if (o instanceof InternalProperty)
+			return DValue.forPrimitive(((InternalProperty)o).m_value, m_isolateId);
+
+		/**
+		 * Resolve the name to something
+		 */
+		if (m_current == null)
+		{
+			// not an id so try as name 
+			String name = o.toString();
+			long id = nameAsId(name);
+
+			/**
+			 * if #N was used just pick up the variable, otherwise
+			 * we need to use the current context to resolve 
+			 * the name to a member
+			 */
+			if (id != Value.UNKNOWN_ID)
+			{
+				v = getSession().getWorkerSession(m_isolateId).getValue((int)id);
+			}
+			else if (name.equals("undefined")) //$NON-NLS-1$
+			{
+				v = DValue.forPrimitive(Value.UNDEFINED, m_isolateId);
+			}
+			else
+			{
+				// Ask the player to find something, anything, on the scope chain
+				// with this name.  We'll end up here, for example, when resolving
+				// things like MyClass, String, Number, etc.
+				v = getSession().getWorkerSession(m_isolateId).getGlobal(name);
+			}
+		}
+
+		/* return the value */
+		return v;
+	}
+
+	// special code for #N support. I.e. naming a variable via an ID
+	long nameAsId(String name)
+	{
+		long id = Value.UNKNOWN_ID;
+		try
+		{
+			if (name.charAt(0) == '#')
+				id = Long.parseLong(name.substring(1));
+		}
+		catch(Exception e) 
+		{
+			id = Value.UNKNOWN_ID;
+		}
+		return id;
+	}
+
+	/**
+	 * Using the given id as a parent find the member named
+	 * name.
+	 * @throws NoSuchVariableException if id is UNKNOWN_ID
+	 */
+	Variable memberNamed(long id, String name) throws NoSuchVariableException, PlayerDebugException
+	{
+		Variable v = null;
+		Value parent = getSession().getWorkerSession(m_isolateId).getValue(id);
+
+		if (parent == null)
+			throw new NoSuchVariableException(name);
+
+		/* got a variable now return the member if any */
+		v = parent.getMemberNamed(getSession(), name);
+
+		return v;
+	}
+
+	/**
+	 * All the really good stuff about finding where name exists goes here!
+	 * 
+	 * If name is not null, then it implies that we use the existing
+	 * m_current to find a member of m_current.  If m_current is null
+	 * Then we need to probe variable context points attempting to locate
+	 * name.  When we find a match we set the m_current to this context
+	 *
+	 * If name is null then we simply return the current context.
+	 */
+	long determineContext(String name) throws PlayerDebugException
+	{
+		long id = Value.UNKNOWN_ID;
+
+		// have we already resolved our context...
+		if (m_current != null)
+		{
+			id = toValue().getId();
+		}
+
+		// nothing to go on, so we're done
+		else if (name == null)
+			;
+
+		// use the name and try and resolve where we are...
+		else
+		{
+			// Each stack frame has a root variable under (BASE_ID-depth)
+			// where depth is the depth of the stack.
+			// So we query for our current stack depth and use that 
+			// as the context for our base computation
+			long baseId = Value.BASE_ID;
+			int depth = ((Integer)m_cache.get(DebugCLI.DISPLAY_FRAME_NUMBER)).intValue();
+			baseId -= depth;
+
+			// obtain data about our current state 
+			Variable contextVar = null;
+			Value contextVal = null;
+			Value val = null;
+
+			// look for 'name' starting from local scope
+			if ( (val = locateParentForNamed(baseId, name, false)) != null)
+				;
+
+			// get the this pointer, then look for 'name' starting from that point
+			else if ( ( (contextVar = locateForNamed(baseId, "this", false)) != null ) &&  //$NON-NLS-1$
+					  ( setName("this") && (val = locateParentForNamed(contextVar.getValue().getId(), name, true)) != null ) ) //$NON-NLS-1$
+				;
+
+			// now try to see if 'name' exists off of _root
+			else if ( setName("_root") && (val = locateParentForNamed(Value.ROOT_ID, name, true)) != null ) //$NON-NLS-1$
+				;
+
+			// now try to see if 'name' exists off of _global
+			else if ( setName("_global") && (val = locateParentForNamed(Value.GLOBAL_ID, name, true)) != null ) //$NON-NLS-1$
+				;
+
+			// now try off of class level, if such a thing can be found
+			else if ( ( (contextVal = locate(Value.GLOBAL_ID, getCurrentPackageName(), false)) != null ) && 
+					  ( setName("_global."+getCurrentPackageName()) && (val = locateParentForNamed(contextVal.getId(), name, true)) != null ) ) //$NON-NLS-1$
+				;
+
+			// if we found it then stake this as our context!
+			if (val != null)
+			{
+				id = val.getId();
+				pushName(name);
+				lockName();
+			}
+		}
+		
+		return id;
+	}
+
+	/**
+	 * Performs a search for a member with the given name using the
+	 * given id as the parent variable.
+	 * 
+	 * If a match is found then, we return the parent variable of
+	 * the member that matched.  The proto chain is optionally traversed.
+	 * 
+	 * No exceptions are thrown
+	 */
+	Value locateParentForNamed(long id, String name, boolean traverseProto) throws PlayerDebugException
+	{
+		StringBuilder sb = new StringBuilder();
+
+		Variable var = null;
+		Value val = null;
+		try
+		{
+			var = memberNamed(id, name);
+
+			// see if we need to traverse the proto chain
+			while (var == null && traverseProto)
+			{
+				// first attempt to get __proto__, then resolve name
+				Variable proto = memberNamed(id, "__proto__"); //$NON-NLS-1$
+ 				sb.append("__proto__"); //$NON-NLS-1$
+				if (proto == null)
+					traverseProto = false;
+				else
+				{
+					id = proto.getValue().getId();
+					var = memberNamed(id, name);
+					if (var == null)
+						sb.append('.');
+				}
+			}
+		}
+		catch(NoSuchVariableException nsv)
+		{
+			// don't worry about this one, it means variable with id couldn't be found
+		}
+		catch(NullPointerException npe)
+		{
+			// probably no session
+		}
+
+		// what we really want is the parent not the child variable
+		if (var != null)
+		{
+			pushName(sb.toString());
+			val = getSession().getWorkerSession(m_isolateId).getValue(id);
+		}
+
+		return val;
+	}
+
+	// variant of locateParentForNamed, whereby we return the child variable
+	Variable locateForNamed(long id, String name, boolean traverseProto) throws PlayerDebugException
+	{
+		Variable var = null;
+		Value v = locateParentForNamed(id, name, traverseProto);
+		if (v != null)
+		{
+			try
+			{
+				var = memberNamed(v.getId(), name);
+			}
+			catch(NoSuchVariableException nse)
+			{
+				v = null;
+			}
+		}
+
+		return var;
+	}
+
+	/**
+	 * Locates the member via a dotted name starting at the given id.
+	 * It will traverse any and all proto chains if necc. to find the name.
+	 */
+	Value locate(long startingId, String dottedName, boolean traverseProto) throws PlayerDebugException
+	{
+		if (dottedName == null)
+			return null;
+
+		// first rip apart the dottedName
+		StringTokenizer names = new StringTokenizer(dottedName, "."); //$NON-NLS-1$
+		Value val = getSession().getWorkerSession(m_isolateId).getValue(startingId);
+
+		while(names.hasMoreTokens() && val != null)
+			val = locateForNamed(val.getId(), names.nextToken(), traverseProto).getValue();
+
+		return val;
+	}
+
+	/*
+	 * @see flash.tools.debugger.expression.Context#toValue(java.lang.Object)
+	 */
+	public Value toValue(Object o)
+	{
+		// if o is a variable or a value already, then we're done!
+		if (o instanceof Value)
+			return (Value)o;
+		else if (o instanceof Variable)
+			return ((Variable)o).getValue();
+		else if (o instanceof InternalProperty)
+			return DValue.forPrimitive(((InternalProperty)o).m_value, m_isolateId);
+		else
+			return DValue.forPrimitive(o, m_isolateId);
+	}
+
+	public Value toValue()
+	{
+		return toValue(m_current);
+	}
+
+	public Session getSession()
+	{
+		return m_cache.getSession();
+	}
+
+	@Override
+	public int getIsolateId() {
+		return m_isolateId;
+	}
+}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/07f5a7de/debugger/src/main/java/flex/tools/debugger/cli/Extensions.java
----------------------------------------------------------------------
diff --git a/debugger/src/main/java/flex/tools/debugger/cli/Extensions.java b/debugger/src/main/java/flex/tools/debugger/cli/Extensions.java
new file mode 100644
index 0000000..0222290
--- /dev/null
+++ b/debugger/src/main/java/flex/tools/debugger/cli/Extensions.java
@@ -0,0 +1,547 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package flex.tools.debugger.cli;
+
+import java.io.PrintWriter;
+import java.text.ParseException;
+import java.util.HashMap;
+import java.util.Map;
+
+import flash.localization.LocalizationManager;
+import flash.swf.tools.Disassembler;
+import flash.swf.types.ActionList;
+import flash.tools.ActionLocation;
+import flash.tools.debugger.Bootstrap;
+import flash.tools.debugger.NotConnectedException;
+import flash.tools.debugger.PlayerDebugException;
+import flash.tools.debugger.Session;
+import flash.tools.debugger.SourceFile;
+import flash.tools.debugger.SuspendReason;
+import flash.tools.debugger.SuspendedException;
+import flash.tools.debugger.SwfInfo;
+import flash.tools.debugger.Value;
+import flash.tools.debugger.concrete.DMessage;
+import flash.tools.debugger.concrete.DMessageCounter;
+import flash.tools.debugger.concrete.DModule;
+import flash.tools.debugger.concrete.DSuspendInfo;
+import flash.tools.debugger.concrete.DSwfInfo;
+import flash.tools.debugger.concrete.PlayerSession;
+import flash.tools.debugger.concrete.PlayerSessionManager;
+import flash.util.FieldFormat;
+
+/**
+ * Extensions class is a singleton that contains
+ * every cli method that does not conform to the 
+ * API.  Thus we can easily remove these features
+ * from the cli if the implementation does not
+ * support these calls.
+ */
+public class Extensions
+{
+	public final static String m_newline = System.getProperty("line.separator"); //$NON-NLS-1$
+
+	public static void doShowStats(DebugCLI cli) throws IllegalStateException
+	{
+		/* we do some magic casting */
+		Session session = cli.getSession();
+		StringBuilder sb = new StringBuilder();
+		try
+		{
+			PlayerSession p = (PlayerSession)session;
+			DMessageCounter cnt = p.getMessageCounter();
+
+			sb.append(getLocalizationManager().getLocalizedTextString("key16")); //$NON-NLS-1$
+			sb.append(m_newline);
+			for(int i=0; i<=DMessage.InSIZE; i++)
+			{
+				long amt = cnt.getInCount(i);
+				if (amt > 0)
+				{
+					sb.append('\n');
+					sb.append(DMessage.inTypeName(i));
+					sb.append(" = "); //$NON-NLS-1$
+					sb.append(amt);
+				}
+			}
+
+			sb.append("\n\n"); //$NON-NLS-1$
+			sb.append(getLocalizationManager().getLocalizedTextString("key17")); //$NON-NLS-1$
+			sb.append("\n"); //$NON-NLS-1$
+			for(int i=0; i<=DMessage.OutSIZE; i++)
+			{
+				long amt = cnt.getOutCount(i);
+				if (amt > 0)
+				{
+					sb.append('\n');
+					sb.append(DMessage.outTypeName(i));
+					sb.append(" = "); //$NON-NLS-1$
+					sb.append(amt);
+				}
+			}
+
+			sb.append('\n');
+			cli.out( sb.toString() );
+		}
+		catch(NullPointerException e)
+		{
+			throw new IllegalStateException();
+		}
+	}
+
+	public static void doShowFuncs(DebugCLI cli)
+	{
+		StringBuilder sb = new StringBuilder();
+
+		String arg = null;
+		FileInfoCache fileInfo = cli.getFileCache();
+
+		// we take an optional single arg which specifies a module
+		try
+		{
+			if (cli.hasMoreTokens())
+			{
+				arg = cli.nextToken();
+                int id = arg.equals(".") ? cli.propertyGet(DebugCLI.LIST_MODULE) : cli.parseFileArg(cli.getActiveIsolateId(), -1, arg); //$NON
+
+				DModule m = (DModule)fileInfo.getFile(id, cli.getActiveIsolateId());
+                m.lineMapping(sb);
+			}
+			else
+			{
+				SourceFile[] ar = fileInfo.getFileList();
+				if (ar == null)
+					cli.err(getLocalizationManager().getLocalizedTextString("key18")); //$NON-NLS-1$
+				else
+                {
+                    for (int i = 0; ar != null && i < ar.length; i++)
+                    {
+                        DModule m = (DModule)ar[i];
+                        m.lineMapping(sb);
+                    }
+                }
+			}
+
+			cli.out(sb.toString());
+		}
+		catch(NullPointerException npe)
+		{
+			cli.err(getLocalizationManager().getLocalizedTextString("key19")); //$NON-NLS-1$
+		}
+		catch(ParseException pe)
+		{
+			cli.err(pe.getMessage());
+		}
+		catch(AmbiguousException ae)
+		{
+			cli.err(ae.getMessage());
+		}
+		catch(NoMatchException nme)
+		{
+			cli.err(nme.getMessage());
+		}
+	}
+
+	/**
+	 * Dump the content of internal variables
+	 */
+	public static void doShowProperties(DebugCLI cli)
+	{
+		StringBuilder sb = new StringBuilder();
+
+		Session session = cli.getSession();
+		for (String key: cli.propertyKeys())
+		{
+			int value = cli.propertyGet(key);
+			sb.append(key);
+			sb.append(" = "); //$NON-NLS-1$
+			sb.append(value);
+			sb.append('\n');
+		}
+
+		// session manager
+		{
+			PlayerSessionManager mgr = (PlayerSessionManager)Bootstrap.sessionManager();
+			sb.append(getLocalizationManager().getLocalizedTextString("key21")); //$NON-NLS-1$
+			sb.append('\n');
+			for (String key: mgr.keySet())
+			{
+				Object value = mgr.getPreferenceAsObject(key);
+				sb.append(key);
+				sb.append(" = "); //$NON-NLS-1$
+				sb.append(value);
+				sb.append('\n');
+			}
+		}
+
+		if (session != null)
+		{
+			PlayerSession psession = (PlayerSession)session;
+			sb.append(getLocalizationManager().getLocalizedTextString("key22")); //$NON-NLS-1$
+			sb.append('\n');
+			for (String key: psession.keySet())
+			{
+				Object value = psession.getPreferenceAsObject(key);
+				sb.append(key);
+				sb.append(" = "); //$NON-NLS-1$
+				sb.append(value);
+				sb.append('\n');
+			}
+		}
+
+		cli.out( sb.toString() );
+	}
+
+	/**
+	 * Dump the break reason and offset
+	 */
+	public static void doShowBreak(DebugCLI cli) throws NotConnectedException
+	{
+		int isolateId = cli.getActiveIsolateId();
+		cli.waitTilHalted(isolateId);
+		try
+		{
+			Session session = cli.getSession();
+			StringBuilder sb = new StringBuilder();
+			if (session.getWorkerSession(isolateId).isSuspended())
+			{
+				sb.append(getLocalizationManager().getLocalizedTextString("stopped")); //$NON-NLS-1$
+				sb.append(' ');
+				appendBreakInfo(cli, sb, true, isolateId);
+			}
+			else
+				sb.append(getLocalizationManager().getLocalizedTextString("key24")); //$NON-NLS-1$
+
+			cli.out( sb.toString() );
+		}
+		catch(NullPointerException npe)
+		{
+			cli.err(getLocalizationManager().getLocalizedTextString("key25")); //$NON-NLS-1$
+		}
+	}
+
+	// Extended low level break information
+	public static void appendBreakInfo(DebugCLI cli, StringBuilder sb, boolean includeFault, int isolateId) throws NotConnectedException
+	{
+		Session session = cli.getSession();
+		FileInfoCache fileInfo = cli.getFileCache();
+
+		int reason = session.suspendReason();
+		int offset = ((PlayerSession)session).getSuspendOffset();
+		int index = ((PlayerSession)session).getSuspendActionIndex();
+
+		SwfInfo info = null;
+		try { info = fileInfo.getSwfs(isolateId)[index]; } catch(ArrayIndexOutOfBoundsException oobe) {}
+		if (info != null)
+		{
+			Map<String, String> args = new HashMap<String, String>();
+			args.put("swfName", FileInfoCache.nameOfSwf(info) ); //$NON-NLS-1$
+			sb.append(getLocalizationManager().getLocalizedTextString("key35", args)); //$NON-NLS-1$
+			sb.append(' ');
+		}
+
+		Map<String, String> args = new HashMap<String, String>();
+		args.put("address", "0x" + FieldFormat.formatLongToHex(new StringBuilder(), offset, 8) + " (" + offset + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+		sb.append(getLocalizationManager().getLocalizedTextString("atAddress", args)); //$NON-NLS-1$
+
+		if (includeFault)
+		{
+			args = new HashMap<String, String>();
+			StringBuilder reasonBuffer = new StringBuilder();
+			cli.appendReason(reasonBuffer, reason);
+			args.put("fault", reasonBuffer.toString() ); //$NON-NLS-1$
+			sb.append(' ');
+			sb.append(getLocalizationManager().getLocalizedTextString("haltedDueToFault", args)); //$NON-NLS-1$
+		}
+	}
+
+	// Raw direct call to Player
+	public static void doShowVariable(DebugCLI cli) throws PlayerDebugException
+	{
+		int isolateId = cli.getActiveIsolateId();
+		cli.waitTilHalted(isolateId);
+		try
+		{
+			// an integer followed by a variable name
+			Session session = cli.getSession();
+			long id = cli.nextLongToken();
+			String name = (cli.hasMoreTokens()) ? cli.nextToken() : null;
+
+			StringBuilder sb = new StringBuilder();
+			sb.append(name);
+			sb.append(" = "); //$NON-NLS-1$
+			Value v = ((PlayerSession)session).getValue(id, name, isolateId);
+			cli.m_exprCache.appendVariableValue(sb, v, isolateId);
+			cli.out( sb.toString() );
+		}
+		catch(NullPointerException npe)
+		{
+			cli.err(getLocalizationManager().getLocalizedTextString("key26")); //$NON-NLS-1$
+		}
+	}
+
+ 	public static void doDisassemble(DebugCLI cli) throws PlayerDebugException
+ 	{
+		/* currentXXX may NOT be invalid! */
+		int currentModule = cli.propertyGet(DebugCLI.LIST_MODULE);
+		int currentLine = cli.propertyGet(DebugCLI.LIST_LINE);
+		int currentIsolate = cli.propertyGet(DebugCLI.LIST_WORKER);
+ 
+		String arg1 = null;
+		int module1 = currentModule;
+		int line1 = currentLine;
+ 
+		String arg2 = null;
+		int line2 = currentLine;
+ 
+ 		boolean functionNamed = false;
+		int numLines = 0;
+ 		try
+ 		{
+			FileInfoCache fileInfo = cli.getFileCache();
+			Session session = cli.getSession();
+            int isolateId = cli.getActiveIsolateId();
+			if (cli.hasMoreTokens())
+ 			{
+				arg1 = cli.nextToken();
+				if (arg1.equals("-")) //$NON-NLS-1$
+				{
+ 					// move back one line
+					line1 = line2 = line1 - 1;
+				}
+				else
+				{
+                    int wasFunc = 0;
+
+                    FileLocation[] fileLocations = cli.parseLocationArg(currentModule, currentLine, arg1, false);
+
+                    if (fileLocations.length == 1) {
+                        module1 = fileLocations[0].getModule();
+                        line2 = line1 = fileLocations[0].getLine();
+                        functionNamed = (fileLocations[0].getWasFunc() != 0);
+                    }
+
+                    if (cli.hasMoreTokens()) {
+                        arg2 = cli.nextToken();
+                        line2 = cli.parseLineArg(module1, arg2);
+                    }
+				}
+ 			}
+ 			else
+ 			{
+ 				// since no parms test for valid location if none use players concept of where we stopped
+ 				if( fileInfo.getFile(currentModule, currentIsolate) == null)
+ 				{
+ 					//here we simply use the players concept of suspsend
+ 					DSuspendInfo info = ((PlayerSession)session).getSuspendInfoIsolate(isolateId);
+ 					int at = info.getOffset();
+ 					int which = info.getActionIndex();
+ 					int until = info.getNextOffset();
+ 					if (info.getReason() == SuspendReason.Unknown)
+ 						throw new SuspendedException();
+ 
+ 					SwfInfo swf = fileInfo.getSwfs(isolateId)[which];
+ 					outputAssembly(cli, (DSwfInfo)swf, at, until);
+ 					throw new AmbiguousException(getLocalizationManager().getLocalizedTextString("key27")); //$NON-NLS-1$
+ 				}
+ 			}			
+ 
+ 			/**
+ 			 * Check for a few error conditions, otherwise we'll write a listing!
+ 			 */
+ 			if (cli.hasMoreTokens())
+ 			{
+ 				cli.err(getLocalizationManager().getLocalizedTextString("key28")); //$NON-NLS-1$
+ 			}
+ 			else
+ 			{
+ 				SourceFile file = fileInfo.getFile(module1);
+ 				numLines = file.getLineCount();
+ 
+ 				// pressing return is ok, otherwise throw the exception
+ 				if (line1 > numLines && arg1 != null)
+ 					throw new IndexOutOfBoundsException();
+ 
+ 				/* if no arg2 then user list a single line */
+ 				if (arg2 == null)
+ 					line2 = line1;
+ 
+ 				/* adjust our range of lines to ensure we conform */
+ 				if (line1 < 1)
+ 				{
+ 					/* shrink line 1, grow line2 */
+ 					line2 += -(line1 - 1);
+ 					line1 = 1;
+ 				}
+ 
+ 				if (line2 > numLines)
+ 					line2 = numLines;
+ 
+				//			    System.out.println("1="+module1+":"+line1+",2="+module2+":"+line2+",num="+numLines+",half="+half);
+ 
+ 				/* nothing to display */
+ 				if (line1 > line2)
+ 					throw new IndexOutOfBoundsException();
+ 
+ 				/* now dump the mixed source / assembly */
+ 				// now lets find which swf this in 
+ 				DSwfInfo swf = (DSwfInfo)fileInfo.swfForFile(file, cli.getActiveIsolateId());
+ 				ActionLocation lStart = null;
+ 				ActionLocation lEnd = null;
+ 
+ 				if (swf == null)
+				{
+					Map<String, String> args = new HashMap<String, String>();
+					args.put("arg3", file.getName()); //$NON-NLS-1$
+ 					cli.err(getLocalizationManager().getLocalizedTextString("key29", args)); //$NON-NLS-1$
+				}
+ 				else if (functionNamed)
+ 				{
+ 					// if we name a function just dump the whole thing without source.
+ 					int offset = file.getOffsetForLine(line1);
+ 					lStart = swf.locate(offset);
+ 					if (lStart.function == null)
+ 						cli.err(getLocalizationManager().getLocalizedTextString("key30")); //$NON-NLS-1$
+ 					else
+ 					{
+ 						// create a psudeo action list from which to disasemble the function
+ 						ActionList al = new ActionList(true);
+ 						al.setActionOffset(0, lStart.function);
+ 						lStart.actions = al;
+ 						lStart.at = 0;
+ 						lEnd = new ActionLocation();
+ 						lEnd.actions = al;
+ 						lEnd.at = 0;
+ 						outputAssembly(cli, swf, lStart, lEnd);
+ 					}
+ 				}
+ 				else
+ 				{
+ 					ActionLocation lastEnd = null;
+ 					for(int i=line1; i<=line2; i++)
+ 					{
+ 						int offset = file.getOffsetForLine(i);
+ 
+ 						// locate the action list associated with this of the swf
+ 						if (offset != 0)
+ 						{
+ 							// get the starting point and try to locate a nice ending
+ 							lStart = swf.locate(offset);
+ 							lEnd = swf.locateSourceLineEnd(lStart);
+ 
+ 							// now see if we skipped some assembly between source lines
+ 							if (lastEnd != null)
+ 							{
+ 								lastEnd.at++;  // point our pseudo start to the next action
+ 
+ 								// new actions list so attempt to find the end of source in the old actions list
+ 								if (lastEnd.actions != lStart.actions && lastEnd.actions.size() != lastEnd.at)
+ 								{
+ 									String atString = Integer.toHexString(lastEnd.actions.getOffset(lastEnd.at));
+									Map<String, String> args = new HashMap<String, String>();
+									args.put("arg4", atString); //$NON-NLS-1$
+ 									cli.out(getLocalizationManager().getLocalizedTextString("key31", args)); //$NON-NLS-1$
+ 
+  									// we are missing some of the dissassembly, so back up a bit and dump it out
+ 									ActionLocation gapEnd = swf.locateSourceLineEnd(lastEnd);
+ 									outputAssembly(cli, swf, lastEnd, gapEnd);
+ 								}
+ 								else if (lastEnd.at < lStart.at)
+ 								{
+ 									// same action list but we skipped some instructions 
+ 									ActionLocation gapEnd = new ActionLocation(lStart);
+ 									gapEnd.at--;
+ 									outputAssembly(cli, swf, lastEnd, gapEnd);
+ 								}
+ 							}
+ 							lastEnd = lEnd;
+ 						}
+ 
+ 						// dump source
+ 						cli.outputSource(module1, i, file.getLine(i));
+ 						
+ 						// obtain the offset, locate it in the swf
+ 						if (offset != 0)
+ 							outputAssembly(cli, swf, lStart, lEnd);
+ 					}
+ 
+ 					/* save away valid context */
+ 					cli.propertyPut(DebugCLI.LIST_MODULE, module1);
+ 					cli.propertyPut(DebugCLI.LIST_LINE, line2 + 1);  // add one
+ 					cli.m_repeatLine = "disassemble";   /* allow repeated listing by typing CR */ //$NON-NLS-1$
+ 				}
+ 			}
+ 		}
+		catch(IndexOutOfBoundsException iob)
+ 		{
+ 			String name = "#"+module1; //$NON-NLS-1$
+			Map<String, String> args = new HashMap<String, String>();
+			args.put("arg5", Integer.toString(line1)); //$NON-NLS-1$
+			args.put("arg6", name); //$NON-NLS-1$
+			args.put("arg7", Integer.toString(numLines)); //$NON-NLS-1$
+ 			cli.err(getLocalizationManager().getLocalizedTextString("key32", args)); //$NON-NLS-1$
+ 		}
+ 		catch(AmbiguousException ae)
+ 		{
+ 			cli.err(ae.getMessage());
+ 		}
+ 		catch(NullPointerException npe)
+ 		{
+ 			cli.err(getLocalizationManager().getLocalizedTextString("key33")); //$NON-NLS-1$
+ 		}
+ 		catch(ParseException pe)
+ 		{
+ 			cli.err(pe.getMessage());
+ 		}
+		catch(NoMatchException nme)
+		{
+			cli.err(nme.getMessage());
+		}
+ 		catch(SuspendedException se)
+ 		{
+			cli.err(getLocalizationManager().getLocalizedTextString("key34")); //$NON-NLS-1$
+ 		}
+ 	}
+ 
+ 	private static LocalizationManager getLocalizationManager()
+	{
+ 		return DebugCLI.getLocalizationManager();
+	}
+
+	/**
+ 	 * Disassemble part of the swf to the output 
+ 	 */
+ 	public static ActionLocation outputAssembly(DebugCLI cli, DSwfInfo swf, int start, int end)
+ 	{
+ 		// first we need to locate the action list associated with this
+ 		// portion of the swf
+ 		ActionLocation lStart = swf.locate(start);
+ 		ActionLocation lEnd = (end > -1) ? swf.locate(end) : swf.locateSourceLineEnd(lStart);
+ 
+ 		return outputAssembly(cli, swf, lStart, lEnd);
+ 	}
+ 
+ 	public static ActionLocation outputAssembly(DebugCLI cli, SwfInfo info, ActionLocation lStart, ActionLocation lEnd)
+ 	{
+ 		// now make sure our actions lists are the same (i.e we haven't spanned past one tag)
+ 		if (lStart.actions != lEnd.actions)
+ 			lEnd.at = lStart.actions.size()-1;
+ 		
+ 		Disassembler.disassemble(lStart.actions, lStart.pool, lStart.at, lEnd.at, new PrintWriter(cli.getOut()));
+ 		return lEnd;
+ 	}
+}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/07f5a7de/debugger/src/main/java/flex/tools/debugger/cli/ExtensionsDisabled.java
----------------------------------------------------------------------
diff --git a/debugger/src/main/java/flex/tools/debugger/cli/ExtensionsDisabled.java b/debugger/src/main/java/flex/tools/debugger/cli/ExtensionsDisabled.java
new file mode 100644
index 0000000..caf33af
--- /dev/null
+++ b/debugger/src/main/java/flex/tools/debugger/cli/ExtensionsDisabled.java
@@ -0,0 +1,37 @@
+/*
+ * 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;
+
+/**
+ * ExtensionsDisabled class is a singleton that contains
+ * every cli method that does not conform to the 
+ * API.  There are two implementations of this singleton
+ * In Extensions the full code is provided in this class
+ * ExtensionsDisabled emtpy stubs are provided that allow
+ * for DebugCLI to be fully compliant with the API 
+ */
+public class ExtensionsDisabled
+{
+	public static void doShowStats(DebugCLI cli) { cli.out("Command not supported."); } //$NON-NLS-1$
+	public static void doShowFuncs(DebugCLI cli) { cli.out("Command not supported."); } //$NON-NLS-1$
+	public static void doShowProperties(DebugCLI cli) { cli.out("Command not supported."); } //$NON-NLS-1$
+	public static void doShowBreak(DebugCLI cli) { cli.out("Command not supported."); } //$NON-NLS-1$
+	public static void appendBreakInfo(DebugCLI cli, StringBuilder sb, boolean includeFault) { cli.out("Command not supported."); } //$NON-NLS-1$
+	public static void doShowVariable(DebugCLI cli) { cli.out("Command not supported."); } //$NON-NLS-1$
+ 	public static void doDisassemble(DebugCLI cli) { cli.out("Command not supported."); } //$NON-NLS-1$
+}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/07f5a7de/debugger/src/main/java/flex/tools/debugger/cli/FaultActions.java
----------------------------------------------------------------------
diff --git a/debugger/src/main/java/flex/tools/debugger/cli/FaultActions.java b/debugger/src/main/java/flex/tools/debugger/cli/FaultActions.java
new file mode 100644
index 0000000..73bc074
--- /dev/null
+++ b/debugger/src/main/java/flex/tools/debugger/cli/FaultActions.java
@@ -0,0 +1,228 @@
+/*
+ * 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.HashMap;
+
+import flash.localization.LocalizationManager;
+import flash.tools.debugger.events.DivideByZeroFault;
+import flash.tools.debugger.events.ExceptionFault;
+import flash.tools.debugger.events.InvalidTargetFault;
+import flash.tools.debugger.events.InvalidURLFault;
+import flash.tools.debugger.events.InvalidWithFault;
+import flash.tools.debugger.events.ProtoLimitFault;
+import flash.tools.debugger.events.RecursionLimitFault;
+import flash.tools.debugger.events.ScriptTimeoutFault;
+import flash.tools.debugger.events.StackUnderFlowFault;
+
+/**
+ * FaultActions proivdes a convenient wrapper for housing the user specified
+ * behaviour for a set of faults (aka text strings)
+ * 
+ * The underlying data structure is a HashMap that maps strings (i.e. fault
+ * names) to Integers.  The integers are used as bit fields for holding
+ * the state of setting per fault.
+ * 
+ * Add new actions by calling addAction("name") 
+ */
+public class FaultActions
+{
+	HashMap<String, Integer> m_faults = new HashMap<String, Integer>();
+	HashMap<String, String> m_description = new HashMap<String, String>();  // @todo should really use an object within the faults map for this 
+	HashMap<String, Integer> m_actions = new HashMap<String, Integer>();
+
+	int m_nextBitForAction = 0x1;  // the next bit to use for the action
+
+	private FaultActions() {}
+
+	Integer		get(String o)			{ return m_faults.get(o); }
+	Integer		getAction(String o)		{ return m_actions.get(o); }
+	void		put(String k, Integer v){ m_faults.put(k,v); }
+
+	/* getters */
+	public void			clear()					{ m_faults.clear(); }
+	public int			size()					{ return m_faults.size(); }
+	public Object[]     names()					{ return m_faults.keySet().toArray(); }
+	public Object[]     actions()				{ return m_actions.keySet().toArray(); }
+	public boolean		exists(String k)		{ return (get(k) == null) ? false : true;  }
+
+	public void			putDescription(String k, String v)	{ m_description.put(k,v);	}
+	public String		getDescription(String k)			{ return (m_description.get(k) == null) ? "" :  m_description.get(k);	} //$NON-NLS-1$
+
+	/**
+	 * Add a new fault to the table, with all actions disabled
+	 */
+	public void add(String k)				
+	{ 
+		put(k, new Integer(0)); 
+	}
+
+	/**
+	 * Add a new action type to the table 
+	 */
+	public void addAction(String k)	
+	{ 
+		Integer v = new Integer(m_nextBitForAction++);
+		m_actions.put(k,v); 
+	}
+
+	/**
+	 * Check if the given fault has the action set or not 
+	 */
+	public boolean is(String fault, String action)
+	{
+		int mask  = getAction(action).intValue();
+		int bits = get(fault).intValue();
+
+		boolean set = ( (bits & mask) == mask ) ? true : false;
+		return set;
+	}
+
+	/**
+	 * Sets the action bits as appropriate for the given fault 
+	 * and action 
+	 */
+	public int action(String fault, String action)
+	{
+		// first check if fault is legal
+		Integer current = get(fault);
+		if (current == null)
+			throw new IllegalArgumentException(fault);			
+		
+		// check for no?
+		boolean no = action.startsWith("no"); //$NON-NLS-1$
+		if (no)
+			action = action.substring(2);
+
+		// do the search for action 
+		Integer bit = getAction(action);
+		if (bit == null)
+			throw new IllegalArgumentException(action);
+
+		// now do the math
+		int old = current.intValue();
+		int mask = bit.intValue();
+
+		int n = (old & (~mask));  // turn it off
+		n = (no) ? n : (n | mask); // leave it off or turn it on
+
+		put(fault, new Integer(n));
+
+		return n;
+	}
+	
+	public static class FaultActionsBuilder {
+
+		private final LocalizationManager localizationManager;
+
+		public FaultActionsBuilder(LocalizationManager localizationManager) {
+			super();
+			this.localizationManager = localizationManager;
+		}
+
+		public FaultActions build() {
+			FaultActions faultActions = new FaultActions();
+			populateFaultTable(faultActions);
+			return faultActions;
+		}
+
+		private void populateFaultTable(FaultActions faultActions) {
+			// possible actions for our fault table
+			faultActions.addAction("stop"); //$NON-NLS-1$
+			faultActions.addAction("print"); //$NON-NLS-1$
+
+			// the faults we support
+			faultActions.add(InvalidTargetFault.name);
+			faultActions.add(RecursionLimitFault.name);
+			faultActions.add(InvalidWithFault.name);
+			faultActions.add(ProtoLimitFault.name);
+			faultActions.add(InvalidURLFault.name);
+			faultActions.add(ExceptionFault.name);
+			faultActions.add(StackUnderFlowFault.name);
+			faultActions.add(DivideByZeroFault.name);
+			faultActions.add(ScriptTimeoutFault.name);
+			// faultActions.add(ConsoleErrorFault.name);
+
+			// nice description of the faults
+			faultActions.putDescription(
+					InvalidTargetFault.name,
+					getLocalizationManager().getLocalizedTextString(
+							"invalidTargetFault")); //$NON-NLS-1$
+			faultActions.putDescription(
+					RecursionLimitFault.name,
+					getLocalizationManager().getLocalizedTextString(
+							"recursionLimitFault")); //$NON-NLS-1$
+			faultActions.putDescription(
+					InvalidWithFault.name,
+					getLocalizationManager().getLocalizedTextString(
+							"invalidWithFault")); //$NON-NLS-1$
+			faultActions.putDescription(
+					ProtoLimitFault.name,
+					getLocalizationManager().getLocalizedTextString(
+							"protoLimitFault")); //$NON-NLS-1$
+			faultActions.putDescription(
+					InvalidURLFault.name,
+					getLocalizationManager().getLocalizedTextString(
+							"invalidUrlFault")); //$NON-NLS-1$
+			faultActions.putDescription(
+					ExceptionFault.name,
+					getLocalizationManager().getLocalizedTextString(
+							"exceptionFault")); //$NON-NLS-1$
+			faultActions.putDescription(
+					StackUnderFlowFault.name,
+					getLocalizationManager().getLocalizedTextString(
+							"stackUnderflowFault")); //$NON-NLS-1$
+			faultActions.putDescription(
+					DivideByZeroFault.name,
+					getLocalizationManager().getLocalizedTextString(
+							"divideByZeroFault")); //$NON-NLS-1$
+			faultActions.putDescription(
+					ScriptTimeoutFault.name,
+					getLocalizationManager().getLocalizedTextString(
+							"scriptTimeoutFault")); //$NON-NLS-1$
+			// faultActions.putDescription(ConsoleErrorFault.name,
+			// "ActionScript recoverable error");
+
+			// default values for the faults
+			faultActions.action(InvalidTargetFault.name, "stop"); //$NON-NLS-1$
+			faultActions.action(InvalidTargetFault.name, "print"); //$NON-NLS-1$
+			faultActions.action(RecursionLimitFault.name, "stop"); //$NON-NLS-1$
+			faultActions.action(RecursionLimitFault.name, "print"); //$NON-NLS-1$
+			faultActions.action(InvalidWithFault.name, "stop"); //$NON-NLS-1$
+			faultActions.action(InvalidWithFault.name, "print"); //$NON-NLS-1$
+			faultActions.action(ProtoLimitFault.name, "stop"); //$NON-NLS-1$
+			faultActions.action(ProtoLimitFault.name, "print"); //$NON-NLS-1$
+			faultActions.action(InvalidURLFault.name, "stop"); //$NON-NLS-1$
+			faultActions.action(InvalidURLFault.name, "print"); //$NON-NLS-1$
+			faultActions.action(ExceptionFault.name, "stop"); //$NON-NLS-1$
+			faultActions.action(ExceptionFault.name, "print"); //$NON-NLS-1$
+			faultActions.action(StackUnderFlowFault.name, "stop"); //$NON-NLS-1$
+			faultActions.action(StackUnderFlowFault.name, "print"); //$NON-NLS-1$
+			faultActions.action(DivideByZeroFault.name, "stop"); //$NON-NLS-1$
+			faultActions.action(DivideByZeroFault.name, "print"); //$NON-NLS-1$
+			faultActions.action(ScriptTimeoutFault.name, "stop"); //$NON-NLS-1$
+			faultActions.action(ScriptTimeoutFault.name, "print"); //$NON-NLS-1$
+			//			faultActions.action(ConsoleErrorFault.name, "print"); //$NON-NLS-1$
+			//			faultActions.action(ConsoleErrorFault.name, "stop"); //$NON-NLS-1$
+		}
+
+		private LocalizationManager getLocalizationManager() {
+			return localizationManager;
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/07f5a7de/debugger/src/main/java/flex/tools/debugger/cli/FileInfoCache.java
----------------------------------------------------------------------
diff --git a/debugger/src/main/java/flex/tools/debugger/cli/FileInfoCache.java b/debugger/src/main/java/flex/tools/debugger/cli/FileInfoCache.java
new file mode 100644
index 0000000..e66b89a
--- /dev/null
+++ b/debugger/src/main/java/flex/tools/debugger/cli/FileInfoCache.java
@@ -0,0 +1,569 @@
+/*
+ * 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.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Iterator;
+
+import flash.tools.debugger.InProgressException;
+import flash.tools.debugger.Isolate;
+import flash.tools.debugger.NoResponseException;
+import flash.tools.debugger.Session;
+import flash.tools.debugger.SourceFile;
+import flash.tools.debugger.SwfInfo;
+import flash.util.IntMap;
+
+/**
+ * FileInfoCache manages a list of files that are unique
+ * across multiple swfs.
+ */
+public class FileInfoCache implements Comparator<SourceFile>
+{
+	Session m_session;
+
+	/**
+	 * We can get at files by module id or path
+	 */
+	IntMap				m_byInt = new IntMap();
+	HashMap<Integer, IntMap> m_isolateState = new HashMap<Integer, IntMap> ();
+	
+	private IntMap getIsolateState(int isolateId) {
+		IntMap isolateState = null;
+		if (!m_isolateState.containsKey(isolateId)) {
+			isolateState = new IntMap();
+			m_isolateState.put(isolateId, isolateState);
+		}
+		else
+			isolateState = m_isolateState.get(isolateId);
+		return isolateState;
+	}
+	
+	SourceFile[]		m_files = null;
+	SourceFile[]		m_isolateFiles = null;
+	SwfInfo				m_swfFilter = null;
+	int					m_swfsLoaded = 0;
+    boolean             m_dirty = false;
+    int lastActiveIsolate = Isolate.DEFAULT_ID;
+
+	public FileInfoCache() {
+		
+	}
+
+	public void			bind(Session s)									{ setSession(s); }
+	public void			unbind()										{ m_session = null; }
+	
+	public SourceFile getFile(int i) {
+		return getFile(i, Isolate.DEFAULT_ID);
+	}
+
+	public SourceFile getFile(int i, int isolateId) {
+		populate();
+		if (isolateId == Isolate.DEFAULT_ID)
+			return (SourceFile) m_byInt.get(i);
+		else
+			return (SourceFile)getIsolateState(isolateId).get(i);
+	}
+	
+	public SourceFile[] getFileList() {
+		populate();
+		return m_files;
+	}
+	
+	public SourceFile[] getFileList(int isolateId) {
+		populate();
+		if (isolateId == Isolate.DEFAULT_ID) {
+			final Object[] valuesToArray = m_byInt.valuesToArray(new Object[m_byInt.size()]);
+	        return Arrays.copyOf(valuesToArray, valuesToArray.length, SourceFile[].class);
+		} 
+		else if (isolateId != lastActiveIsolate) {
+			buildIsolateFiles(isolateId);
+		}
+		return m_isolateFiles;
+	}
+	
+	private void buildIsolateFiles(int isolateId) {
+		SwfInfo[] swfs = getSwfs(isolateId);
+		boolean worked = true; // check that all worked correctly
+		ArrayList<SourceFile> files = new ArrayList<SourceFile>();
+
+		for(int i=0; i<swfs.length; i++)
+		{
+			if (swfs[i] != null)
+				worked = loadSwfFiles(files, swfs[i]) ? worked : false;
+		}
+
+		// trim the file list
+		ArrayList<SourceFile> fa = trimFileList(files);
+		m_isolateFiles = fa.toArray( new SourceFile[fa.size()] );
+
+		// sort this array in place so calls to getFileList will be ordered
+		Arrays.sort(m_isolateFiles, this);
+	}
+
+	public Iterator getAllFiles(int isolateId) {
+		populate();		
+		if (isolateId == Isolate.DEFAULT_ID)
+			return m_byInt.iterator();
+		else
+			return getIsolateState(isolateId).iterator();
+	}
+	
+    public SwfInfo      getSwfFilter()                                  { return m_swfFilter; }
+    public boolean      isSwfFilterOn()                                 { return (m_swfFilter != null); }
+    public void         setDirty()                                      { m_dirty = true; }
+
+	void setSession(Session s)
+	{
+		m_session = s;
+		m_swfFilter = null;
+		clear();
+	}
+	
+	SwfInfo[] getAllSwfs() {
+		ArrayList<SwfInfo> result = new ArrayList<SwfInfo>();
+		
+		for ( Isolate isolate : m_session.getWorkers()) {
+			SwfInfo[] swfs = new SwfInfo[0];
+			try {
+				swfs = m_session.getWorkerSession(isolate.getId()).getSwfs();
+			} catch (NoResponseException e) {
+				swfs = new SwfInfo[0];
+			}
+			
+			for (SwfInfo swf : swfs)
+				result.add(swf);
+		}
+		
+		return result.toArray(new SwfInfo[0]);
+	}
+
+	void populate()
+	{
+		// do we have a new swf to load?
+		if (m_session != null && (m_dirty || getAllSwfs().length > m_swfsLoaded))
+			reloadCache();
+	}
+
+	void reloadCache()
+	{
+		clear();
+		loadCache();
+        m_dirty = false;
+	}
+
+	void clear()
+	{
+		m_byInt.clear();
+		m_isolateState.clear();
+		m_files = null;
+	}
+
+	/**
+	 * Determine if the given SourceFile is in the current fileList
+	 */
+	public boolean inFileList(SourceFile f)
+	{
+		boolean isIt = false;
+
+		SourceFile[] files = getFileList();
+		for(int i=0; i<files.length && !isIt; i++)
+		{
+			if (files[i] == f)
+				isIt = true;
+		}
+		return isIt;
+	}
+
+	/**
+	 * Go out to the session and request a list of files
+	 * But we dump ones that have a name collision.
+	 * Also if selectedSwf is set then we only add files
+	 * that are contained within the given swf.
+	 */
+	void loadCache()
+	{
+		boolean worked = true; // check that all worked correctly
+		ArrayList<SourceFile> files = new ArrayList<SourceFile>();
+		SwfInfo[] swfs = getAllSwfs();
+		for(int i=0; i<swfs.length; i++)
+		{
+			if (swfs[i] != null)
+				worked = loadSwfFiles(files, swfs[i]) ? worked : false;
+		}
+
+		// trim the file list
+		ArrayList<SourceFile> fa = trimFileList(files);
+		m_files = fa.toArray( new SourceFile[fa.size()] );
+
+		// sort this array in place so calls to getFileList will be ordered
+		Arrays.sort(m_files, this);
+
+		// mark our cache complete if all was good.
+		if (worked)
+			m_swfsLoaded = swfs.length;
+	}
+
+	boolean loadSwfFiles(ArrayList<SourceFile> ar, SwfInfo swf)
+	{
+		boolean worked = true;
+		try
+		{
+			// @todo should we include unloaded swfs?
+			SourceFile[] files = swf.getSourceList(m_session);
+			ar.ensureCapacity(ar.size()+files.length);
+
+			// add each file to our global source file IntMap and our list
+			for(int i=0; i<files.length; i++)
+			{
+				putFile(files[i], swf.getIsolateId());
+				ar.add(files[i]);
+			}
+		}
+		catch(InProgressException ipe)
+		{
+			// can't load this one, its not ready yet
+			worked = false;
+		}
+		return worked;
+	}
+
+	/**
+	 * Walk the file list looking for name collisions.
+	 * If we find one, then we remove it
+	 */
+	ArrayList<SourceFile> trimFileList(ArrayList<SourceFile> files)
+	{
+		HashMap<String, String> names = new HashMap<String, String>();
+		ArrayList<SourceFile> list = new ArrayList<SourceFile>();
+
+		int size = files.size();
+		for(int i=0; i<size; i++)
+		{
+			boolean addIt = false;
+
+			SourceFile fi = files.get(i);
+			// no filter currently in place so we add the file as long
+			// as no duplicates exist.  We use the original Swd full
+			// name for matching.
+			String fName = fi.getRawName();
+			if (m_swfFilter == null)
+			{
+				// If it exists, then we don't add it!
+				if (names.get(fName) == null)
+					addIt = true;
+			}
+			else
+			{
+				// we have a filter in place so, see
+				// if the source file is in our currently
+				// selected swf.
+				addIt = m_swfFilter.containsSource(fi);
+			}
+
+			// did we mark this one to add?
+			if (addIt)
+			{
+				names.put(fName, fName);
+				list.add(fi);
+			}
+		}
+		return list;
+	}
+	
+	/**
+	 * All files from all swfs are placed into our byInt map
+	 * since we know that ids are unique across the entire
+	 * Player session.
+	 *
+	 * This is also important in the case that the player
+	 * halts in one of these files, that the debugger
+	 * be able to locate the SourceFile so that we can
+	 * display the correct context for the user.
+	 */
+	void putFile(SourceFile s, int isolateId)
+	{
+		int i = s.getId();
+		if (isolateId == Isolate.DEFAULT_ID)
+			m_byInt.put(i, s);
+		else
+			getIsolateState(isolateId).put(i, s);
+	}
+
+	/**
+	 * Attempt to set a swf as a filter
+	 * for the file list that we create
+	 */
+	public boolean setSwfFilter(String swfName)
+	{
+		// look for a match in our list
+		boolean worked = false;
+		if (swfName == null)
+		{
+			m_swfFilter = null;
+			worked = true;
+		}
+		else
+		{
+			SwfInfo[] swfs = getAllSwfs();
+			for(int i=0; i<swfs.length; i++)
+			{
+				SwfInfo e = swfs[i];
+				if (e != null && nameOfSwf(e).equalsIgnoreCase(swfName))
+				{
+					worked = true;
+					m_swfFilter = e;
+					break;
+				}
+			}
+		}
+
+		// reload if it worked
+		if (worked)
+			reloadCache();
+
+		return worked;
+	}
+
+	// list all swfs we know about
+	public SwfInfo[] getSwfs(int isolateId)
+	{
+		return getSwfsIsolate(isolateId);
+	}
+	
+	public SwfInfo[] getSwfsIsolate(int isolateId)
+	{
+		SwfInfo[] swfs = null;
+		try
+		{
+			swfs = m_session.getWorkerSession(isolateId).getSwfs();
+		}
+		catch(NoResponseException nre)
+		{
+			swfs = new SwfInfo[] {};  // oh bery bad
+		}
+		return swfs;
+	}
+
+	/**
+	 * Given a SourceFile locate the swf which it came from
+	 */
+	public SwfInfo swfForFile(SourceFile f, int isolateId)
+	{
+		// We use the id to determine which swf this source files resides in
+		int id = f.getId();
+		SwfInfo info = null;
+		SwfInfo[] swfs = getSwfs(isolateId);//getAllSwfs();
+		for(int i=0; ( i<swfs.length && (info == null) ); i++)
+		{
+			if (swfs[i] != null && swfs[i].containsSource(f))
+				info = swfs[i];
+		}
+		return info;
+	}
+
+	// locate the name of the swf
+	public static String nameOfSwf(SwfInfo e)
+	{
+		int at = -1;
+		String name = e.getUrl();
+		if ( (at = e.getUrl().lastIndexOf('/')) > -1)
+			name = e.getUrl().substring(at+1);
+		if ( (at = e.getUrl().lastIndexOf('\\')) > -1)
+			name = e.getUrl().substring(at+1);
+		else if ( (at = e.getPath().lastIndexOf('\\')) > -1)
+			name = e.getPath().substring(at+1);
+		else if ( (at = e.getPath().lastIndexOf('/')) > -1)
+			name = e.getPath().substring(at+1);
+
+		// now rip off any trailing ? options
+		at = name.lastIndexOf('?');
+		name = (at > -1) ? name.substring(0, at) : name;
+
+		return name;
+	}
+
+	// locate the name of the swf
+	public static String shortNameOfSwf(SwfInfo e)
+	{
+		String name = nameOfSwf(e);
+
+		// now strip off any leading path
+		int at = -1;
+		if ( (at = name.lastIndexOf('/')) > -1)
+			name = name.substring(at+1);
+		else if ( (at = name.lastIndexOf('\\')) > -1)
+			name = name.substring(at+1);
+		return name;
+	}
+
+    /**
+     * Given the URL of a specfic swf determine
+     * if there is a file within it that appears
+     * to be the same as the given source file
+     * @param f
+     * @return
+     */
+    public SourceFile similarFileInSwf(SwfInfo info, SourceFile f) throws InProgressException
+    {
+        SourceFile hit = null;
+		SourceFile[] files = info.getSourceList(m_session);
+		if (!info.isProcessingComplete())
+			throw new InProgressException();
+
+		for(int i=0; i<files.length; i++)
+		{
+			if (filesMatch(f, files[i]))
+				hit = files[i];
+		}
+        return hit;
+    }
+
+	/**
+	 * Comparator interface for sorting SourceFiles
+	 */
+	public int compare(SourceFile o1, SourceFile o2)
+	{
+		String n1 = o1.getName();
+		String n2 = o2.getName();
+
+		return n1.compareTo(n2);
+	}
+
+    /**
+     * Compare two files and determine if they are the same.
+     * Our criteria included only line count package names
+     * and the name of the class itself.  If there are
+     * any other differences then we won't be able to detect
+     * them.  We should probably do something like an MD5
+     * computation on the characters in ScriptText. Then
+     * we'd really be sure of a match.
+     * @param a first file to compare
+     * @param b second file to compare
+     * @return  true if files appear to be the same
+     */
+    public boolean filesMatch(SourceFile a, SourceFile b)
+    {
+        boolean yes = true;
+
+		if (a == null || b == null)
+			yes = false;
+        else if (a.getPackageName().compareTo(b.getPackageName()) != 0)
+            yes = false;
+        else if (a.getName().compareTo(b.getName()) != 0)
+            yes = false;
+        else if (a.getLineCount() != b.getLineCount()) // warning, this is sometimes expensive, so do it last
+            yes = false;
+
+        return yes;
+    }
+    /**
+     * Return a array of SourceFiles whose names match
+     * the specified string. The array is sorted by name.
+	 * The input can be mx.controls.xxx which will
+     */
+    public SourceFile[] getFiles(String matchString)
+    {
+        return getFiles(matchString, -1);
+    }
+
+    public SourceFile[] getFiles(String matchString, int isolateId)
+    {
+        boolean doStartsWith = false;
+        boolean doIndexOf = false;
+        boolean doEndsWith = false;
+
+        boolean leadingAsterisk = matchString.startsWith("*") && matchString.length() > 1; //$NON-NLS-1$
+        boolean trailingAsterisk = matchString.endsWith("*"); //$NON-NLS-1$
+        boolean usePath = matchString.indexOf('.') > -1;
+
+        if (leadingAsterisk && trailingAsterisk)
+        {
+            matchString = matchString.substring(1, matchString.length() - 1);
+            doIndexOf = true;
+        }
+        else if (leadingAsterisk)
+        {
+            matchString = matchString.substring(1);
+            doEndsWith = true;
+        }
+        else if (trailingAsterisk)
+        {
+            matchString = matchString.substring(0, matchString.length() - 1);
+            doStartsWith = true;
+        }
+		else if (usePath)
+		{
+			doIndexOf = true;
+		}
+		else
+        {
+            doStartsWith = true;
+        }
+
+        SourceFile[] files = isolateId > -1 ? getFileList(isolateId) : getFileList();
+        ArrayList<SourceFile> fileList = new ArrayList<SourceFile>();
+        int n = files.length;
+		int exactHitAt = -1;
+		// If the matchString already starts with "." (e.g. ".as" or ".mxml"), then dotMatchString
+		// will be equal to matchString; otherwise, dotMatchString will be "." + matchString
+		String dotMatchString = (matchString.startsWith(".")) ? matchString : ("." + matchString); //$NON-NLS-1$ //$NON-NLS-2$
+        for (int i = 0; i < n; i++)
+        {
+            SourceFile sourceFile = files[i];
+			boolean pathExists = (usePath && sourceFile.getFullPath().matches(".*[/\\\\].*")); //$NON-NLS-1$
+            String name = pathExists ? sourceFile.getFullPath() : sourceFile.getName();
+
+			// if we are using the full path string, then prefix a '.' to our matching string so that abc.as and Gabc.as don't both hit
+			String match = (usePath && pathExists) ? dotMatchString : matchString;
+
+            match = match.replace('/', '.');  // get rid of path identifiers and use dots
+            match = match.replace('\\', '.');
+
+			name = name.replace('/', '.');  // get rid of path identifiers and use dots
+			name = name.replace('\\', '.'); // would be better to modify the input string, but we don't know which path char will be used.
+
+			// exact match? We are done
+			if (name.equals(match))
+			{
+				exactHitAt = i;
+				break;
+			}
+            else if (doStartsWith && name.startsWith(match))
+				fileList.add(sourceFile);
+			else if (doEndsWith && name.endsWith(match))
+                fileList.add(sourceFile);
+			else if (doIndexOf && name.contains(match))
+				fileList.add(sourceFile);
+        }
+
+		// trim all others if we have an exact file match
+		if (exactHitAt > -1)
+		{
+			fileList.clear();
+			fileList.add(files[exactHitAt]);
+		}
+
+		SourceFile[] fileArray = fileList.toArray( new SourceFile[fileList.size()] );
+		Arrays.sort(fileArray, this);
+        return fileArray;
+    }
+
+}