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;
+    }
+
+}

Reply via email to