1. Reorganize debugger to move all code that interacts with the engine into Main.java while all GUI logic now presents in DebugGui

2. Move downloaded files for swing tree table into downloaded directory and adjust build files accordingly.
This commit is contained in:
igor%mir2.org 2004-05-23 16:15:09 +00:00
parent cfe01facb2
commit 1e8e9be624
6 changed files with 419 additions and 553 deletions

View File

@ -10,59 +10,12 @@ Requires Ant version 1.2
<property name="nest" value=".."/>
<property name="build.dir" value="./build"/>
<property name="classes" value="${build.dir}/classes"/>
<property name="src.debugger"
value="org/mozilla/javascript/tools/debugger"/>
<available file="${src.debugger}/AbstractCellEditor.java"
property="swing-ex-available"/>
<property name="debugger"
value="org/mozilla/javascript/tools/debugger"/>
</target>
<target name="get-swing-ex" unless="swing-ex-available">
<!-- Download source from Sun's site, unzip it, remove
the files we don't need, and change the package
-->
<get src="http://java.sun.com/products/jfc/tsc/articles/treetable2/downloads/src.zip" dest="${nest}/${build.dir}/swingExSrc.zip"/>
<unzip src="${nest}/${build.dir}/swingExSrc.zip" dest="${src.debugger}"/>
<delete file="${src.debugger}/FileSystemModel2.java" />
<delete file="${src.debugger}/MergeSort.java" />
<delete file="${src.debugger}/TreeTableExample2.java" />
<replace file="${src.debugger}/AbstractCellEditor.java">
<replacetoken>import java.awt.Component;</replacetoken>
<replacevalue>
package org.mozilla.javascript.tools.debugger;
import java.awt.Component;
</replacevalue>
</replace>
<replace file="${src.debugger}/AbstractTreeTableModel.java">
<replacetoken>import javax.swing.tree.*;</replacetoken>
<replacevalue>
package org.mozilla.javascript.tools.debugger;
import javax.swing.tree.*;
</replacevalue>
</replace>
<replace file="${src.debugger}/JTreeTable.java">
<replacetoken>import javax.swing.*;</replacetoken>
<replacevalue>
package org.mozilla.javascript.tools.debugger;
import javax.swing.*;
</replacevalue>
</replace>
<replace file="${src.debugger}/TreeTableModel.java">
<replacetoken>import javax.swing.tree.TreeModel;</replacetoken>
<replacevalue>
package org.mozilla.javascript.tools.debugger;
import javax.swing.tree.TreeModel;
</replacevalue>
</replace>
<replace file="${src.debugger}/TreeTableModelAdapter.java">
<replacetoken>import javax.swing.JTree;</replacetoken>
<replacevalue>
package org.mozilla.javascript.tools.debugger;
import javax.swing.JTree;
</replacevalue>
</replace>
</target>
<target name="compile" depends="properties,get-swing-ex">
<target name="compile" depends="properties">
<ant dir="${debugger}" target="download"/>
<javac srcdir="."
destdir="${nest}/${classes}"
includes="org/**/*.java"
@ -78,7 +31,7 @@ Requires Ant version 1.2
<copy todir="${nest}/${dist.toolsrc}">
<fileset dir="."
includes="org/**/*.java,org/**/*.properties,build.xml"
excludes="**/AbstractCellEditor.java,**/TreeTableModel.java,**/AbstractTreeTableModel.java,**/TreeTableModelAdapter.java,**/JTreeTable.java" />
excludes="${debugger}/downloaded/**" />
</copy>
</target>

View File

@ -1,6 +1 @@
#These are generated by the build system
AbstractCellEditor.java
AbstractTreeTableModel.java
JTreeTable.java
TreeTableModel.java
TreeTableModelAdapter.java
downloaded

View File

@ -49,6 +49,7 @@ import java.util.*;
import java.io.*;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.TreePath;
import java.lang.reflect.Method;
import org.mozilla.javascript.Scriptable;
@ -57,6 +58,9 @@ import org.mozilla.javascript.Kit;
import org.mozilla.javascript.tools.shell.ConsoleTextArea;
import org.mozilla.javascript.tools.debugger.downloaded.JTreeTable;
import org.mozilla.javascript.tools.debugger.downloaded.TreeTableModel;
import org.mozilla.javascript.tools.debugger.downloaded.TreeTableModelAdapter;
class MessageDialogWrapper {
@ -1100,9 +1104,204 @@ class Evaluator extends JTable {
}
}
class VariableModel implements TreeTableModel {
static class VariableNode {
Object object;
Object id;
VariableNode[] children;
VariableNode(Object object, Object id) {
this.object = object;
this.id = id;
}
public String toString()
{
return (id instanceof String)
? (String)id : "[" + ((Integer)id).intValue() + "]";
}
}
// Names of the columns.
private static final String[] cNames = { " Name", " Value"};
// Types of the columns.
private static final Class[] cTypes = {TreeTableModel.class, String.class};
private static final VariableNode[] CHILDLESS = new VariableNode[0];
private Main debugger;
private VariableNode root;
VariableModel()
{
}
VariableModel(Main debugger, Object scope)
{
this.debugger = debugger;
this.root = new VariableNode(scope, "this");
}
//
// The TreeModel interface
//
public Object getRoot()
{
if (debugger == null) { return null; }
return root;
}
public int getChildCount(Object nodeObj)
{
if (debugger == null) { return 0; }
VariableNode node = (VariableNode)nodeObj;
return children(node).length;
}
public Object getChild(Object nodeObj, int i)
{
if (debugger == null) { return null; }
VariableNode node = (VariableNode)nodeObj;
return children(node)[i];
}
public boolean isLeaf(Object nodeObj)
{
if (debugger == null) { return true; }
VariableNode node = (VariableNode)nodeObj;
return children(node).length == 0;
}
public int getIndexOfChild(Object parentObj, Object childObj)
{
if (debugger == null) { return -1; }
VariableNode parent = (VariableNode)parentObj;
VariableNode child = (VariableNode)childObj;
VariableNode[] children = children(parent);
for (int i = 0; i != children.length; ++i) {
if (children[i] == child) {
return i;
}
}
return -1;
}
public boolean isCellEditable(Object node, int column)
{
return column == 0;
}
public void setValueAt(Object value, Object node, int column) { }
public void addTreeModelListener(TreeModelListener l) { }
public void removeTreeModelListener(TreeModelListener l) { }
public void valueForPathChanged(TreePath path, Object newValue) { }
//
// The TreeTableNode interface.
//
public int getColumnCount() {
return cNames.length;
}
public String getColumnName(int column) {
return cNames[column];
}
public Class getColumnClass(int column) {
return cTypes[column];
}
public Object getValueAt(Object nodeObj, int column) {
if (debugger == null) { return null; }
VariableNode node = (VariableNode)nodeObj;
switch (column) {
case 0: // Name
return node.toString();
case 1: // Value
String result;
try {
result = debugger.objectToString(getValue(node));
} catch (RuntimeException exc) {
result = exc.getMessage();
}
StringBuffer buf = new StringBuffer();
int len = result.length();
for (int i = 0; i < len; i++) {
char ch = result.charAt(i);
if (Character.isISOControl(ch)) {
ch = ' ';
}
buf.append(ch);
}
return buf.toString();
}
return null;
}
private VariableNode[] children(VariableNode node)
{
if (node.children != null) {
return node.children;
}
VariableNode[] children;
Object value = getValue(node);
Object[] ids = debugger.getObjectIds(value);
if (ids.length == 0) {
children = CHILDLESS;
} else {
java.util.Arrays.sort(ids, new java.util.Comparator() {
public int compare(Object l, Object r)
{
if (l instanceof String) {
if (r instanceof Integer) {
return -1;
}
return ((String)l).compareToIgnoreCase((String)r);
} else {
if (r instanceof String) {
return 1;
}
int lint = ((Integer)l).intValue();
int rint = ((Integer)r).intValue();
return lint - rint;
}
}
});
children = new VariableNode[ids.length];
for (int i = 0; i != ids.length; ++i) {
children[i] = new VariableNode(value, ids[i]);
}
}
node.children = children;
return children;
}
Object getValue(VariableNode node) {
try {
return debugger.getObjectProperty(node.object, node.id);
} catch (Exception exc) {
return "undefined";
}
}
}
class MyTreeTable extends JTreeTable {
public MyTreeTable(TreeTableModel model) {
public MyTreeTable(VariableModel model) {
super(model);
}
@ -1240,58 +1439,11 @@ class ContextWindow extends JPanel implements ActionListener
left.add(context);
tabs = new JTabbedPane(SwingConstants.BOTTOM);
tabs.setPreferredSize(new Dimension(500,300));
thisTable = new MyTreeTable(new AbstractTreeTableModel(new DefaultMutableTreeNode()) {
public Object getChild(Object parent, int index) {
return null;
}
public int getChildCount(Object parent) {
return 0;
}
public int getColumnCount() {
//return 3;
return 2;
}
public String getColumnName(int column) {
switch (column) {
case 0:
return " Name";
case 1:
//return "Type";
//case 2:
return " Value";
}
return null;
}
public Object getValueAt(Object node, int column) {
return null;
}
});
thisTable = new MyTreeTable(new VariableModel());
JScrollPane jsp = new JScrollPane(thisTable);
jsp.getViewport().setViewSize(new Dimension(5,2));
tabs.add("this", jsp);
localsTable = new MyTreeTable(new AbstractTreeTableModel(new DefaultMutableTreeNode()) {
public Object getChild(Object parent, int index) {
return null;
}
public int getChildCount(Object parent) {
return 0;
}
public int getColumnCount() {
return 2;
}
public String getColumnName(int column) {
switch (column) {
case 0:
return " Name";
case 1:
return " Value";
}
return null;
}
public Object getValueAt(Object node, int column) {
return null;
}
});
localsTable = new MyTreeTable(new VariableModel());
localsTable.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
localsTable.setPreferredSize(null);
jsp = new JScrollPane(localsTable);
@ -1482,40 +1634,18 @@ class ContextWindow extends JPanel implements ActionListener
return;
}
Main.StackFrame frame = contextData.getFrame(frameIndex);
Scriptable scope = frame.scope();
Scriptable thisObj = frame.thisObj();
thisTable.resetTree(new VariableModel(thisObj));
AbstractTreeTableModel scopeModel;
Object scope = frame.scope();
Object thisObj = frame.thisObj();
thisTable.resetTree(new VariableModel(debugGui.main, thisObj));
VariableModel scopeModel;
if (scope != thisObj) {
scopeModel = new VariableModel(scope);
scopeModel = new VariableModel(debugGui.main, scope);
} else {
scopeModel = new AbstractTreeTableModel(new DefaultMutableTreeNode()) {
public Object getChild(Object parent, int index) {
return null;
}
public int getChildCount(Object parent) {
return 0;
}
public int getColumnCount() {
return 2;
}
public String getColumnName(int column) {
switch (column) {
case 0:
return " Name";
case 1:
return " Value";
}
return null;
}
public Object getValueAt(Object node, int column) {
return null;
}
};
scopeModel = new VariableModel();
}
localsTable.resetTree(scopeModel);
debugGui.main.contextSwitch(frameIndex);
debugGui.showStackFrame(frame);
debugGui.showStopLine(frame);
tableModel.updateModel();
}
}
@ -2029,7 +2159,7 @@ class DebugGui extends JFrame
windowMenu.revalidate();
}
void showStackFrame(Main.StackFrame frame)
void showStopLine(Main.StackFrame frame)
{
String sourceName = frame.getUrl();
if (sourceName == null || sourceName.equals("<stdin>")) {
@ -2139,7 +2269,7 @@ class DebugGui extends JFrame
{
statusBar.setText("Thread: " + threadTitle);
showStackFrame(lastFrame);
showStopLine(lastFrame);
if (alertMessage != null) {
MessageDialogWrapper.showMessageDialog(this,

View File

@ -97,16 +97,13 @@ public class Main {
static class StackFrame implements DebugFrame {
StackFrame(Context cx, Main db, DebuggableScript fnOrScript)
StackFrame(Context cx, Main db, FunctionSource fsource)
{
this.db = db;
this.contextData = ContextData.get(cx);
this.fnOrScript = fnOrScript;
FunctionSource item = db.getFunctionSource(fnOrScript);
if (item != null) {
this.sourceInfo = item.sourceInfo();
this.lineNumber = item.firstLine();
}
this.fsource = fsource;
this.breakpoints = fsource.sourceInfo().breakpoints;
this.lineNumber = fsource.firstLine();
contextData.pushFrame(this);
}
@ -120,33 +117,30 @@ public class Main {
}
}
public void onLineChange(Context cx, int lineno) {
public void onLineChange(Context cx, int lineno)
{
this.lineNumber = lineno;
checks:
if (sourceInfo == null || !sourceInfo.checkBreakpointFast(lineno)) {
if (db.breakFlag) {
break checks;
}
if (!contextData.breakNextLine) {
if (!breakpoints[lineno] && !db.breakFlag) {
if (!contextData.breakNextLine
|| contextData.frameCount() > contextData.stopAtFrameDepth)
{
return;
}
if (contextData.stopAtFrameDepth > 0) {
if (contextData.frameCount() > contextData.stopAtFrameDepth) {
return;
}
contextData.stopAtFrameDepth = -1;
}
contextData.stopAtFrameDepth = -1;
contextData.breakNextLine = false;
}
db.handleBreakpointHit(this, cx);
}
public void onExceptionThrown(Context cx, Throwable exception) {
public void onExceptionThrown(Context cx, Throwable exception)
{
db.handleExceptionThrown(cx, exception, this);
}
public void onExit(Context cx, boolean byThrow, Object resultOrException) {
public void onExit(Context cx, boolean byThrow, Object resultOrException)
{
if (db.breakOnReturn && !byThrow) {
db.handleBreakpointHit(this, cx);
}
@ -154,7 +148,7 @@ public class Main {
}
SourceInfo sourceInfo() {
return sourceInfo;
return fsource.sourceInfo();
}
ContextData contextData()
@ -162,37 +156,31 @@ public class Main {
return contextData;
}
Scriptable scope()
Object scope()
{
return scope;
}
Scriptable thisObj()
Object thisObj()
{
return thisObj;
}
String getUrl() {
if (sourceInfo != null) {
return sourceInfo.url();
}
return db.getNormilizedUrl(fnOrScript);
String getUrl()
{
return fsource.sourceInfo().url();
}
int getLineNumber() {
return lineNumber;
}
DebuggableScript getScript() {
return fnOrScript;
}
private Main db;
private ContextData contextData;
private Scriptable scope;
private Scriptable thisObj;
private DebuggableScript fnOrScript;
private SourceInfo sourceInfo;
private FunctionSource fsource;
private boolean[] breakpoints;
private int lineNumber;
}
@ -233,7 +221,7 @@ public class Main {
private int minLine;
private boolean[] breakableLines;
private boolean[] breakpoints;
boolean[] breakpoints;
private static final boolean[] EMPTY_BOOLEAN_ARRAY = new boolean[0];
@ -365,11 +353,6 @@ public class Main {
return line < this.breakpoints.length && this.breakpoints[line];
}
final boolean checkBreakpointFast(int line)
{
return this.breakpoints[line];
}
boolean breakpoint(int line, boolean value)
{
if (!breakableLine(line)) {
@ -468,7 +451,12 @@ public class Main {
DebugFrame mirrorStackFrame(Context cx, DebuggableScript fnOrScript)
{
return new StackFrame(cx, this, fnOrScript);
FunctionSource item = getFunctionSource(fnOrScript);
if (item == null) {
// Can not debug if source is not available
return null;
}
return new StackFrame(cx, this, item);
}
void onCompilationDone(Context cx, DebuggableScript fnOrScript,
@ -704,41 +692,11 @@ public class Main {
}
}
public void doBreak() {
breakFlag = true;
}
void handleBreakpointHit(StackFrame frame, Context cx) {
breakFlag = false;
interrupted(cx, frame, null);
}
private static String exceptionString(StackFrame frame, Throwable ex)
{
String details;
if (ex instanceof JavaScriptException) {
JavaScriptException jse = (JavaScriptException)ex;
details = ScriptRuntime.toString(jse.getValue());
} else if (ex instanceof EcmaError) {
details = ex.toString();
} else {
if (ex instanceof WrappedException) {
Throwable wrapped
= ((WrappedException)ex).getWrappedException();
if (wrapped != null) {
ex = wrapped;
}
}
details = ex.toString();
if (details == null || details.length() == 0) {
details = ex.getClass().toString();
}
}
String url = frame.getUrl();
int lineNumber = frame.getLineNumber();
return details+" (" + url + ", line " + lineNumber + ")";
}
void handleExceptionThrown(Context cx, Throwable ex, StackFrame frame) {
if (breakOnExceptions) {
ContextData cd = frame.contextData();
@ -844,7 +802,7 @@ public class Main {
if (scriptException == null) {
alertMessage = null;
} else {
alertMessage = exceptionString(frame, scriptException);
alertMessage = scriptException.toString();
}
Runnable enterAction = new Runnable() {
@ -946,6 +904,94 @@ public class Main {
return result;
}
String objectToString(Object object)
{
if (object == Undefined.instance) {
return "undefined";
}
if (object == null) {
return "null";
}
if (object instanceof NativeCall) {
return "[object Call]";
}
Context cx = Context.enter();
try {
return Context.toString(object);
} finally {
Context.exit();
}
}
Object getObjectProperty(Object object, Object id)
{
Scriptable scriptable = (Scriptable)object;
Object result;
if (id instanceof String) {
String name = (String)id;
if (name.equals("this")) {
result = scriptable;
} else if (name.equals("__proto__")) {
result = scriptable.getPrototype();
} else if (name.equals("__parent__")) {
result = scriptable.getParentScope();
} else {
result = ScriptableObject.getProperty(scriptable, name);
if (result == ScriptableObject.NOT_FOUND) {
result = Undefined.instance;
}
}
} else {
int index = ((Integer)id).intValue();
result = ScriptableObject.getProperty(scriptable, index);
if (result == ScriptableObject.NOT_FOUND) {
result = Undefined.instance;
}
}
return result;
}
Object[] getObjectIds(Object object)
{
if (!(object instanceof Scriptable) || object == Undefined.instance) {
return Context.emptyArgs;
}
Scriptable scriptable = (Scriptable)object;
Object[] ids;
Context cx = Context.enter();
try {
if (scriptable instanceof DebuggableObject) {
ids = ((DebuggableObject)scriptable).getAllIds();
} else {
ids = scriptable.getIds();
}
} finally {
Context.exit();
}
Scriptable proto = scriptable.getPrototype();
Scriptable parent = scriptable.getParentScope();
int extra = 0;
if (proto != null) {
++extra;
}
if (parent != null) {
++extra;
}
if (extra != 0) {
Object[] tmp = new Object[extra + ids.length];
System.arraycopy(ids, 0, tmp, extra, ids.length);
ids = tmp;
extra = 0;
if (proto != null) {
ids[extra++] = "__proto__";
}
if (parent != null) {
ids[extra++] = "__parent__";
}
}
return ids;
}
String eval(String expr)
{
String result = "undefined";
@ -993,7 +1039,7 @@ public class Main {
cx.setGeneratingDebug(false);
try {
Callable script = (Callable)cx.compileString(expr, "", 0, null);
Object result = script.call(cx, frame.scope(), frame.thisObj(),
Object result = script.call(cx, frame.scope, frame.thisObj,
ScriptRuntime.emptyArgs);
if (result == Undefined.instance) {
resultString = "";
@ -1055,6 +1101,10 @@ public class Main {
debugGui = new DebugGui(this, title);
}
public void doBreak() {
breakFlag = true;
}
/**
* Toggle Break-on-Exception behavior
*/

View File

@ -1,339 +0,0 @@
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (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.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Rhino JavaScript Debugger code, released
* November 21, 2000.
*
* The Initial Developer of the Original Code is SeeBeyond Corporation.
* Portions created by SeeBeyond are
* Copyright (C) 2000 SeeBeyond Technology Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Christopher Oliver
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU Public License (the "GPL"), in which case the
* provisions of the GPL are applicable instead of those above.
* If you wish to allow use of your version of this file only
* under the terms of the GPL and not to allow others to use your
* version of this file under the NPL, indicate your decision by
* deleting the provisions above and replace them with the notice
* and other provisions required by the GPL. If you do not delete
* the provisions above, a recipient may use your version of this
* file under either the NPL or the GPL.
*/
package org.mozilla.javascript.tools.debugger;
import org.mozilla.javascript.*;
import javax.swing.event.TableModelEvent;
import java.util.Hashtable;
import java.util.Enumeration;
public class VariableModel extends AbstractTreeTableModel
implements TreeTableModel {
// Names of the columns.
static protected String[] cNames = { " Name", " Value"};
// Types of the columns.
static protected Class[] cTypes = {TreeTableModel.class, String.class};
public VariableModel(Scriptable scope) {
super(scope == null ? null : new VariableNode(scope, "this"));
}
//
// Some convenience methods.
//
protected Object getObject(Object node) {
VariableNode varNode = ((VariableNode)node);
if (varNode == null) return null;
return varNode.getObject();
}
protected Object[] getChildren(Object node) {
VariableNode varNode = ((VariableNode)node);
return varNode.getChildren();
}
//
// The TreeModel interface
//
public int getChildCount(Object node) {
Object[] children = getChildren(node);
return (children == null) ? 0 : children.length;
}
public Object getChild(Object node, int i) {
return getChildren(node)[i];
}
// The superclass's implementation would work, but this is more efficient.
public boolean isLeaf(Object node) {
if (node == null) return true;
VariableNode varNode = (VariableNode)node;
Object[] children = varNode.getChildren();
if (children != null && children.length > 0) {
return false;
}
return true;
}
public boolean isCellEditable(Object node, int column) {
return column == 0;
}
//
// The TreeTableNode interface.
//
public int getColumnCount() {
return cNames.length;
}
public String getColumnName(int column) {
return cNames[column];
}
public Class getColumnClass(int column) {
return cTypes[column];
}
public Object getValueAt(Object node, int column) {
Context cx = Context.enter();
try {
Object value = getObject(node);
switch (column) {
case 0: // Name
VariableNode varNode = (VariableNode)node;
String name = "";
if (varNode.name != null) {
return name + varNode.name;
}
return name + "[" + varNode.index + "]";
case 1: // Value
if (value == Undefined.instance ||
value == ScriptableObject.NOT_FOUND) {
return "undefined";
}
if (value == null) {
return "null";
}
if (value instanceof NativeCall) {
return "[object Call]";
}
String result;
try {
result = Context.toString(value);
} catch (RuntimeException exc) {
result = exc.getMessage();
}
StringBuffer buf = new StringBuffer();
int len = result.length();
for (int i = 0; i < len; i++) {
char ch = result.charAt(i);
if (Character.isISOControl(ch)) {
ch = ' ';
}
buf.append(ch);
}
return buf.toString();
}
} catch (Exception exc) {
//exc.printStackTrace();
} finally {
cx.exit();
}
return null;
}
public void setScope(Scriptable scope) {
VariableNode rootVar = (VariableNode)root;
rootVar.scope = scope;
fireTreeNodesChanged(this,
new Object[]{root},
null, new Object[]{root});
}
}
class VariableNode {
Scriptable scope;
String name;
int index;
public VariableNode(Scriptable scope, String name) {
this.scope = scope;
this.name = name;
}
public VariableNode(Scriptable scope, int index) {
this.scope = scope;
this.name = null;
this.index = index;
}
/**
* Returns the the string to be used to display this leaf in the JTree.
*/
public String toString() {
return (name != null ? name : "[" + index + "]");
}
public Object getObject() {
try {
if (scope == null) return null;
if (name != null) {
if (name.equals("this")) {
return scope;
}
Object result = ScriptableObject.NOT_FOUND;
if (name.equals("__proto__")) {
result = scope.getPrototype();
} else if (name.equals("__parent__")) {
result = scope.getParentScope();
} else {
try {
result = ScriptableObject.getProperty(scope, name);
} catch (RuntimeException e) {
result = e.getMessage();
}
}
if (result == ScriptableObject.NOT_FOUND) {
result = Undefined.instance;
}
return result;
}
Object result = ScriptableObject.getProperty(scope, index);
if (result == ScriptableObject.NOT_FOUND) {
result = Undefined.instance;
}
return result;
} catch (Exception exc) {
return "undefined";
}
}
Object[] children;
static final Object[] empty = new Object[0];
protected Object[] getChildren() {
if (children != null) return children;
Context cx = Context.enter();
try {
Object value = getObject();
if (value == null) return children = empty;
if (value == ScriptableObject.NOT_FOUND ||
value == Undefined.instance) {
return children = empty;
}
if (value instanceof Scriptable) {
Scriptable scrip = (Scriptable)value;
Scriptable proto = scrip.getPrototype();
Scriptable parent = scrip.getParentScope();
if (scrip.has(0, scrip)) {
int len = 0;
try {
Scriptable start = scrip;
Scriptable obj = start;
Object result = Undefined.instance;
do {
if (obj.has("length", start)) {
result = obj.get("length", start);
if (result != Scriptable.NOT_FOUND)
break;
}
obj = obj.getPrototype();
} while (obj != null);
if (result instanceof Number) {
len = ((Number)result).intValue();
}
} catch (Exception exc) {
}
if (parent != null) {
len++;
}
if (proto != null) {
len++;
}
children = new VariableNode[len];
int i = 0;
int j = 0;
if (parent != null) {
children[i++] = new VariableNode(scrip, "__parent__");
j++;
}
if (proto != null) {
children[i++] = new VariableNode(scrip, "__proto__");
j++;
}
for (; i < len; i++) {
children[i] = new VariableNode(scrip, i-j);
}
} else {
int len = 0;
Hashtable t = new Hashtable();
Object[] ids;
if (scrip instanceof ScriptableObject) {
ids = ((ScriptableObject)scrip).getAllIds();
} else {
ids = scrip.getIds();
}
if (ids == null) ids = empty;
if (proto != null) t.put("__proto__", "__proto__");
if (parent != null) t.put("__parent__", "__parent__");
if (ids.length > 0) {
for (int j = 0; j < ids.length; j++) {
t.put(ids[j], ids[j]);
}
}
ids = new Object[t.size()];
Enumeration e = t.keys();
int j = 0;
while (e.hasMoreElements()) {
ids[j++] = e.nextElement().toString();
}
if (ids != null && ids.length > 0) {
java.util.Arrays.sort(ids, new java.util.Comparator() {
public int compare(Object l, Object r) {
return l.toString().compareToIgnoreCase(r.toString());
}
});
len = ids.length;
}
children = new VariableNode[len];
for (int i = 0; i < len; i++) {
Object id = ids[i];
children[i] = new
VariableNode(scrip, id.toString());
}
}
}
} catch (Exception exc) {
exc.printStackTrace();
} finally {
cx.exit();
}
return children;
}
}

View File

@ -0,0 +1,77 @@
<?xml version="1.0" encoding="utf-8"?>
<project name="toolsrc" default="help" basedir=".">
<target name="properties">
<property name="swing-ex-url" value="http://java.sun.com/products/jfc/tsc/articles/treetable2/downloads/src.zip"/>
<available file="downloaded/AbstractCellEditor.java"
property="swing-ex-available"/>
</target>
<target name="get-swing-ex" unless="swing-ex-available">
<!-- Download source from Sun's site, unzip it, remove
the files we don't need, and change the package
-->
<mkdir dir="downloaded"/>
<get src="${swing-ex-url}" dest="downloaded/swingExSrc.zip"/>
<unzip src="downloaded/swingExSrc.zip" dest="downloaded/">
<patternset>
<include name="AbstractCellEditor.java"/>
<include name="JTreeTable.java"/>
<include name="TreeTableModel.java"/>
<include name="TreeTableModelAdapter.java"/>
</patternset>
</unzip>
<replace file="downloaded/AbstractCellEditor.java">
<replacetoken>import java.awt.Component;</replacetoken>
<replacevalue>
package org.mozilla.javascript.tools.debugger.downloaded;
import java.awt.Component;
</replacevalue>
</replace>
<replace file="downloaded/JTreeTable.java">
<replacetoken>import javax.swing.*;</replacetoken>
<replacevalue>
package org.mozilla.javascript.tools.debugger.downloaded;
import javax.swing.*;
</replacevalue>
</replace>
<replace file="downloaded/JTreeTable.java">
<replacetoken>class ListToTreeSelectionModelWrapper</replacetoken>
<replacevalue>public class ListToTreeSelectionModelWrapper</replacevalue>
</replace>
<replace file="downloaded/JTreeTable.java">
<replacetoken>ListSelectionModel getListSelectionModel</replacetoken>
<replacevalue>public ListSelectionModel getListSelectionModel</replacevalue>
</replace>
<replace file="downloaded/TreeTableModel.java">
<replacetoken>import javax.swing.tree.TreeModel;</replacetoken>
<replacevalue>
package org.mozilla.javascript.tools.debugger.downloaded;
import javax.swing.tree.TreeModel;
</replacevalue>
</replace>
<replace file="downloaded/TreeTableModelAdapter.java">
<replacetoken>import javax.swing.JTree;</replacetoken>
<replacevalue>
package org.mozilla.javascript.tools.debugger.downloaded;
import javax.swing.JTree;
</replacevalue>
</replace>
<delete file="downloaded/swingExSrc.zip"/>
</target>
<target name="download" depends="properties,get-swing-ex"/>
<target name="help" depends="properties">
<echo>The following targets are available with this build file:
download Download ${swing-ex-url}
and extract the necessary files from it.
help Print this help.
</echo>
</target>
</project>