* Update Rhino to 1.6R3.

* Remove old Rhino 1.5 classes, make Helma debugger subclass Rhino 1.6 classes
  (not fully functional yet, needs patches to Rhino debugger).
* Make helma.doc.DocFunction compile with Rhino 1.6 by introducing intermediary
  DockenStream class that proxies TokenStream using java reflection.
This commit is contained in:
hns 2006-08-18 20:09:37 +00:00
parent fc37ba8cb3
commit e5033685db
14 changed files with 254 additions and 4963 deletions

Binary file not shown.

View file

@ -47,7 +47,7 @@ public class DocFunction extends DocResourceElement {
DocFunction func = new DocFunction(name, res, parent, ACTION); DocFunction func = new DocFunction(name, res, parent, ACTION);
String rawComment = ""; String rawComment = "";
try { try {
TokenStream ts = getTokenStream (res); DockenStream ts = getDockenStream (res);
Point p = getPoint (ts); Point p = getPoint (ts);
ts.getToken(); ts.getToken();
rawComment = Util.getStringFromFile(res, p, getPoint(ts)); rawComment = Util.getStringFromFile(res, p, getPoint(ts));
@ -90,7 +90,7 @@ public class DocFunction extends DocResourceElement {
String functionName = null; String functionName = null;
String context = null; String context = null;
TokenStream ts = getTokenStream (res); DockenStream ts = getDockenStream (res);
while (!ts.eof()) { while (!ts.eof()) {
@ -101,7 +101,7 @@ public class DocFunction extends DocResourceElement {
lastToken = token; lastToken = token;
// now get a new token // now get a new token
// regular expression syntax is troublesome for the TokenStream // regular expression syntax is troublesome for the DockenStream
// we can safely ignore syntax errors in regular expressions here // we can safely ignore syntax errors in regular expressions here
try { try {
token = ts.getToken(); token = ts.getToken();
@ -208,7 +208,7 @@ public class DocFunction extends DocResourceElement {
token = ts.getToken(); token = ts.getToken();
int level = (token == Token.LC) ? 1 : 0; int level = (token == Token.LC) ? 1 : 0;
while (!ts.eof() && level > 0) { while (!ts.eof() && level > 0) {
// regular expression syntax is troublesome for the TokenStream // regular expression syntax is troublesome for the DockenStream
// we don't need them here, so we just ignore such an error // we don't need them here, so we just ignore such an error
try { try {
token = ts.getToken(); token = ts.getToken();
@ -250,7 +250,7 @@ public class DocFunction extends DocResourceElement {
/** /**
* creates a rhino token stream for a given file * creates a rhino token stream for a given file
*/ */
protected static TokenStream getTokenStream (Resource res) throws IOException { protected static DockenStream getDockenStream (Resource res) throws IOException {
Reader reader = null; Reader reader = null;
try { try {
reader = new InputStreamReader(res.getInputStream()); reader = new InputStreamReader(res.getInputStream());
@ -258,18 +258,20 @@ public class DocFunction extends DocResourceElement {
fnfe.printStackTrace(); fnfe.printStackTrace();
throw new DocException (fnfe.toString()); throw new DocException (fnfe.toString());
} }
String name = res.getName(); // String name = res.getName();
int line = 0; Integer line = new Integer(0);
CompilerEnvirons compilerEnv = new CompilerEnvirons(); CompilerEnvirons compilerEnv = new CompilerEnvirons();
compilerEnv.initFromContext(Context.getCurrentContext()); compilerEnv.initFromContext(Context.getCurrentContext());
return new TokenStream (compilerEnv, reader, null, name, line); ErrorReporter errorReporter = Context.getCurrentContext().getErrorReporter();
Parser parser = new Parser(compilerEnv, errorReporter);
return new DockenStream (parser, reader, null, line);
} }
/** /**
* returns a pointer to the current position in the TokenStream * returns a pointer to the current position in the DockenStream
*/ */
protected static Point getPoint (TokenStream ts) { protected static Point getPoint (DockenStream ts) {
return new Point (ts.getOffset(), ts.getLineno()); return new Point (ts.getOffset(), ts.getLineno());
} }

View file

@ -0,0 +1,112 @@
/*
* Copyright 2006 Hannes Wallnoefer <hannes@helma.at>
*
* Licensed 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 helma.doc;
import java.lang.reflect.Method;
import java.lang.reflect.Constructor;
import java.io.Reader;
import org.mozilla.javascript.*;
public class DockenStream {
Object tokenStream;
static Constructor cnst;
static String[] names = new String[]
{ "getToken", "getString", "getOffset", "getLineno", "eof" };
static Method[] methods = new Method[5];
final static Class[] noclass = new Class[0];
final static Object[] noargs = new Object[0];
int peek;
boolean peeked;
static {
try {
Class clazz = Class.forName("org.mozilla.javascript.TokenStream");
cnst = clazz.getDeclaredConstructor(new Class[] {Parser.class, Reader.class, String.class, Integer.TYPE});
for (int i = 0; i < 5; i++) {
methods[i] = clazz.getDeclaredMethod(names[i], noclass);
}
cnst.setAccessible(true);
Method.setAccessible(methods, true);
} catch (Exception x) {
x.printStackTrace();
}
}
public DockenStream(Parser parser, Reader reader, String name, Integer lineno) {
try {
tokenStream = cnst.newInstance(new Object[] {parser, reader, name, lineno});
} catch (Exception x) {
throw new RuntimeException(x);
}
}
public int getToken() {
if (peeked) {
peeked = false;
return peek;
}
try {
return ((Integer) methods[0].invoke(tokenStream, noargs)).intValue();
} catch (Exception x) {
throw new RuntimeException(x);
}
}
public String getString() {
try {
return (String) methods[1].invoke(tokenStream, noargs);
} catch (Exception x) {
throw new RuntimeException(x);
}
}
public int getOffset() {
try {
return ((Integer) methods[2].invoke(tokenStream, noargs)).intValue();
} catch (Exception x) {
throw new RuntimeException(x);
}
}
public int getLineno() {
try {
return ((Integer) methods[3].invoke(tokenStream, noargs)).intValue();
} catch (Exception x) {
throw new RuntimeException(x);
}
}
public int peekToken() {
if (!peeked) {
peek = getToken();
peeked = true;
}
return peek;
}
public boolean eof() {
try {
return ((Boolean) methods[4].invoke(tokenStream, noargs)).booleanValue();
} catch (Exception x) {
throw new RuntimeException(x);
}
}
}

View file

@ -18,7 +18,6 @@ package helma.scripting.rhino;
import helma.scripting.rhino.extensions.*; import helma.scripting.rhino.extensions.*;
import helma.scripting.rhino.debug.HelmaDebugger; import helma.scripting.rhino.debug.HelmaDebugger;
import helma.scripting.rhino.debug.ScopeProvider;
import helma.framework.core.*; import helma.framework.core.*;
import helma.framework.repository.Resource; import helma.framework.repository.Resource;
import helma.objectmodel.*; import helma.objectmodel.*;
@ -29,6 +28,7 @@ import helma.util.SystemMap;
import helma.util.WrappedMap; import helma.util.WrappedMap;
import helma.util.WeakCacheMap; import helma.util.WeakCacheMap;
import org.mozilla.javascript.*; import org.mozilla.javascript.*;
import org.mozilla.javascript.tools.debugger.ScopeProvider;
import java.io.*; import java.io.*;
import java.text.*; import java.text.*;
@ -72,6 +72,11 @@ public final class RhinoCore implements ScopeProvider {
// as the app remains unchanged // as the app remains unchanged
long updateSnooze = 500; long updateSnooze = 500;
static {
ContextFactory.initGlobal(new HelmaContextFactory());
}
/** /**
* Create a Rhino evaluator for the given application and request evaluator. * Create a Rhino evaluator for the given application and request evaluator.
*/ */
@ -104,7 +109,6 @@ public final class RhinoCore implements ScopeProvider {
app.logError("Invalid rhino optlevel: " + opt); app.logError("Invalid rhino optlevel: " + opt);
} }
} }
context.setOptimizationLevel(optLevel); context.setOptimizationLevel(optLevel);
try { try {
@ -148,25 +152,24 @@ public final class RhinoCore implements ScopeProvider {
throw new RuntimeException(e.getMessage()); throw new RuntimeException(e.getMessage());
} finally { } finally {
Context.exit(); Context.exit();
if (debugger != null) {
debugger.contextExited(context);
debugger.contextReleased(context);
}
} }
} }
void initDebugger(Context context) { void initDebugger(Context context) {
try {
if (debugger == null) { if (debugger == null) {
debugger = new HelmaDebugger(app.getName()); debugger = new HelmaDebugger(app.getName());
debugger.setScopeProvider(this); debugger.setScopeProvider(this);
debugger.pack(); // debugger.setScope(global);
debugger.setLocation(60, 60); debugger.attachTo(context.getFactory());
// debugger.pack();
// debugger.getDebugFrame().setLocation(60, 60);
}
// if (!debugger.isVisible())
// debugger.setVisible(true);
} catch (Exception x) {
x.printStackTrace();
} }
if (!debugger.isVisible())
debugger.setVisible(true);
debugger.contextCreated(context);
debugger.contextEntered(context);
} }
/** /**
@ -1078,3 +1081,12 @@ public final class RhinoCore implements ScopeProvider {
} }
} }
class HelmaContextFactory extends ContextFactory {
protected boolean hasFeature(Context cx, int featureIndex) {
if (featureIndex == Context.FEATURE_DYNAMIC_SCOPE) {
return true;
}
return super.hasFeature(cx, featureIndex);
}
}

View file

@ -232,12 +232,6 @@ public class RhinoEngine implements ScriptingEngine {
// core.global.unregisterScope(); // core.global.unregisterScope();
thread = null; thread = null;
// if visual debugger is on let it know we're exiting a context
if (core.debugger != null) {
core.debugger.contextExited(context);
core.debugger.contextReleased(context);
}
// loop through previous globals and unset them, if necessary. // loop through previous globals and unset them, if necessary.
if (lastGlobals != null) { if (lastGlobals != null) {
for (Iterator i = lastGlobals.keySet().iterator(); i.hasNext();) { for (Iterator i = lastGlobals.keySet().iterator(); i.hasNext();) {

View file

@ -1,63 +0,0 @@
package helma.scripting.rhino.debug;
import java.awt.Component;
import java.awt.event.*;
import java.awt.AWTEvent;
import javax.swing.*;
import javax.swing.event.*;
import java.util.EventObject;
import java.io.Serializable;
public class AbstractCellEditor implements CellEditor {
protected EventListenerList listenerList = new EventListenerList();
public Object getCellEditorValue() { return null; }
public boolean isCellEditable(EventObject e) { return true; }
public boolean shouldSelectCell(EventObject anEvent) { return false; }
public boolean stopCellEditing() { return true; }
public void cancelCellEditing() {}
public void addCellEditorListener(CellEditorListener l) {
listenerList.add(CellEditorListener.class, l);
}
public void removeCellEditorListener(CellEditorListener l) {
listenerList.remove(CellEditorListener.class, l);
}
/*
* Notify all listeners that have registered interest for
* notification on this event type.
* @see EventListenerList
*/
protected void fireEditingStopped() {
// Guaranteed to return a non-null array
Object[] listeners = listenerList.getListenerList();
// Process the listeners last to first, notifying
// those that are interested in this event
for (int i = listeners.length-2; i>=0; i-=2) {
if (listeners[i]==CellEditorListener.class) {
((CellEditorListener)listeners[i+1]).editingStopped(new ChangeEvent(this));
}
}
}
/*
* Notify all listeners that have registered interest for
* notification on this event type.
* @see EventListenerList
*/
protected void fireEditingCanceled() {
// Guaranteed to return a non-null array
Object[] listeners = listenerList.getListenerList();
// Process the listeners last to first, notifying
// those that are interested in this event
for (int i = listeners.length-2; i>=0; i-=2) {
if (listeners[i]==CellEditorListener.class) {
((CellEditorListener)listeners[i+1]).editingCanceled(new ChangeEvent(this));
}
}
}
}

View file

@ -1,198 +0,0 @@
/*
* @(#)AbstractTreeTableModel.java 1.2 98/10/27
*
* Copyright 1997, 1998 by Sun Microsystems, Inc.,
* 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
* All rights reserved.
*
* This software is the confidential and proprietary information
* of Sun Microsystems, Inc. ("Confidential Information"). You
* shall not disclose such Confidential Information and shall use
* it only in accordance with the terms of the license agreement
* you entered into with Sun.
*/
package helma.scripting.rhino.debug;
import javax.swing.tree.*;
import javax.swing.event.*;
/**
* @version 1.2 10/27/98
* An abstract implementation of the TreeTableModel interface, handling the list
* of listeners.
* @author Philip Milne
*/
public abstract class AbstractTreeTableModel implements TreeTableModel {
protected Object root;
protected EventListenerList listenerList = new EventListenerList();
public AbstractTreeTableModel(Object root) {
this.root = root;
}
//
// Default implmentations for methods in the TreeModel interface.
//
public Object getRoot() {
return root;
}
public boolean isLeaf(Object node) {
return getChildCount(node) == 0;
}
public void valueForPathChanged(TreePath path, Object newValue) {}
// This is not called in the JTree's default mode: use a naive implementation.
public int getIndexOfChild(Object parent, Object child) {
for (int i = 0; i < getChildCount(parent); i++) {
if (getChild(parent, i).equals(child)) {
return i;
}
}
return -1;
}
public void addTreeModelListener(TreeModelListener l) {
listenerList.add(TreeModelListener.class, l);
}
public void removeTreeModelListener(TreeModelListener l) {
listenerList.remove(TreeModelListener.class, l);
}
/*
* Notify all listeners that have registered interest for
* notification on this event type. The event instance
* is lazily created using the parameters passed into
* the fire method.
* @see EventListenerList
*/
protected void fireTreeNodesChanged(Object source, Object[] path,
int[] childIndices,
Object[] children) {
// Guaranteed to return a non-null array
Object[] listeners = listenerList.getListenerList();
TreeModelEvent e = null;
// Process the listeners last to first, notifying
// those that are interested in this event
for (int i = listeners.length-2; i>=0; i-=2) {
if (listeners[i]==TreeModelListener.class) {
// Lazily create the event:
if (e == null)
e = new TreeModelEvent(source, path,
childIndices, children);
((TreeModelListener)listeners[i+1]).treeNodesChanged(e);
}
}
}
/*
* Notify all listeners that have registered interest for
* notification on this event type. The event instance
* is lazily created using the parameters passed into
* the fire method.
* @see EventListenerList
*/
protected void fireTreeNodesInserted(Object source, Object[] path,
int[] childIndices,
Object[] children) {
// Guaranteed to return a non-null array
Object[] listeners = listenerList.getListenerList();
TreeModelEvent e = null;
// Process the listeners last to first, notifying
// those that are interested in this event
for (int i = listeners.length-2; i>=0; i-=2) {
if (listeners[i]==TreeModelListener.class) {
// Lazily create the event:
if (e == null)
e = new TreeModelEvent(source, path,
childIndices, children);
((TreeModelListener)listeners[i+1]).treeNodesInserted(e);
}
}
}
/*
* Notify all listeners that have registered interest for
* notification on this event type. The event instance
* is lazily created using the parameters passed into
* the fire method.
* @see EventListenerList
*/
protected void fireTreeNodesRemoved(Object source, Object[] path,
int[] childIndices,
Object[] children) {
// Guaranteed to return a non-null array
Object[] listeners = listenerList.getListenerList();
TreeModelEvent e = null;
// Process the listeners last to first, notifying
// those that are interested in this event
for (int i = listeners.length-2; i>=0; i-=2) {
if (listeners[i]==TreeModelListener.class) {
// Lazily create the event:
if (e == null)
e = new TreeModelEvent(source, path,
childIndices, children);
((TreeModelListener)listeners[i+1]).treeNodesRemoved(e);
}
}
}
/*
* Notify all listeners that have registered interest for
* notification on this event type. The event instance
* is lazily created using the parameters passed into
* the fire method.
* @see EventListenerList
*/
protected void fireTreeStructureChanged(Object source, Object[] path,
int[] childIndices,
Object[] children) {
// Guaranteed to return a non-null array
Object[] listeners = listenerList.getListenerList();
TreeModelEvent e = null;
// Process the listeners last to first, notifying
// those that are interested in this event
for (int i = listeners.length-2; i>=0; i-=2) {
if (listeners[i]==TreeModelListener.class) {
// Lazily create the event:
if (e == null)
e = new TreeModelEvent(source, path,
childIndices, children);
((TreeModelListener)listeners[i+1]).treeStructureChanged(e);
}
}
}
//
// Default impelmentations for methods in the TreeTableModel interface.
//
public Class getColumnClass(int column) { return Object.class; }
/** By default, make the column with the Tree in it the only editable one.
* Making this column editable causes the JTable to forward mouse
* and keyboard events in the Tree column to the underlying JTree.
*/
public boolean isCellEditable(Object node, int column) {
return getColumnClass(column) == TreeTableModel.class;
}
public void setValueAt(Object aValue, Object node, int column) {}
// Left to be implemented in the subclass:
/*
* public Object getChild(Object parent, int index)
* public int getChildCount(Object parent)
* public int getColumnCount()
* public String getColumnName(Object node, int column)
* public Object getValueAt(Object node, int column)
*/
}

View file

@ -16,24 +16,30 @@
package helma.scripting.rhino.debug; package helma.scripting.rhino.debug;
import org.mozilla.javascript.tools.debugger.Main;
import org.mozilla.javascript.tools.debugger.SwingGui;
import org.mozilla.javascript.tools.debugger.Dim;
import org.mozilla.javascript.Context; import org.mozilla.javascript.Context;
import org.mozilla.javascript.debug.DebuggableScript; import org.mozilla.javascript.debug.DebuggableScript;
import javax.swing.tree.*;
import javax.swing.*; import javax.swing.*;
import javax.swing.event.TreeSelectionListener; import javax.swing.event.TreeSelectionListener;
import javax.swing.event.TreeSelectionEvent; import javax.swing.event.TreeSelectionEvent;
import javax.swing.tree.*; import java.util.Enumeration;
import java.awt.*; import java.util.HashMap;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent; import java.awt.event.MouseEvent;
import java.awt.event.MouseAdapter; import java.awt.event.MouseAdapter;
import java.awt.event.KeyAdapter; import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent; import java.awt.*;
import java.util.*;
import helma.util.StringUtils; import helma.util.StringUtils;
public class HelmaDebugger extends Main implements TreeSelectionListener {
public class HelmaDebugger extends Dim implements TreeSelectionListener {
DebugGui gui;
JTree tree; JTree tree;
JList list; JList list;
DebuggerTreeNode treeRoot; DebuggerTreeNode treeRoot;
@ -41,80 +47,22 @@ public class HelmaDebugger extends Main implements TreeSelectionListener {
HashMap treeNodes = new HashMap(); HashMap treeNodes = new HashMap();
HashMap scriptNames = new HashMap(); HashMap scriptNames = new HashMap();
public HelmaDebugger(String name) {
super(name);
Container contentPane = getContentPane();
Component main = contentPane.getComponent(1);
contentPane.remove(main);
treeRoot = new DebuggerTreeNode(name); public HelmaDebugger(String title) {
tree = new JTree(treeRoot); gui = new DebugGui(this, title);
treeModel = new DefaultTreeModel(treeRoot); gui.pack();
tree.setModel(treeModel); gui.setVisible(true);
tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
tree.addTreeSelectionListener(this);
// tree.setRootVisible(false);
// track double clicks
tree.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent evt) {
openScript(tree.getSelectionPath());
}
});
// track enter key
tree.addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent evt) {
if (evt.getKeyCode() == KeyEvent.VK_ENTER)
openScript(tree.getSelectionPath());
}
});
JScrollPane treeScroller = new JScrollPane(tree);
treeScroller.setPreferredSize(new Dimension(180, 300));
list = new JList();
// no bold font lists for me, thanks
list.setFont(list.getFont().deriveFont(Font.PLAIN));
list.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent evt) {
openFunction((String) list.getSelectedValue());
}
});
list.addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent evt) {
if (evt.getKeyCode() == KeyEvent.VK_ENTER)
openFunction((String) list.getSelectedValue());
}
});
JScrollPane listScroller = new JScrollPane(list);
listScroller.setPreferredSize(new Dimension(180, 200));
JSplitPane split1 = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
split1.setTopComponent(treeScroller);
split1.setBottomComponent(listScroller);
split1.setOneTouchExpandable(true);
Main.setResizeWeight(split1, 0.66);
JSplitPane split2 = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
split2.setLeftComponent(split1);
split2.setRightComponent(main);
split2.setOneTouchExpandable(true);
contentPane.add(split2, BorderLayout.CENTER);
}
public void setVisible(boolean b) {
super.setVisible(b);
// hide console window
console.hide();
} }
public void handleCompilationDone(Context cx, DebuggableScript fnOrScript, public void handleCompilationDone(Context cx, DebuggableScript fnOrScript,
String source) { String source) {
String sourceName = fnOrScript.getSourceName(); String sourceName = fnOrScript.getSourceName();
FileWindow w = (FileWindow) fileWindows.get(sourceName); // FileWindow w = (FileWindow) fileWindows.get(sourceName);
super.handleCompilationDone(cx, fnOrScript, source); /* super.(cx, fnOrScript, source);
if (!treeNodes.containsKey(sourceName)) { if (!treeNodes.containsKey(sourceName)) {
createTreeNode(sourceName); createTreeNode(sourceName);
} } */
if (w != null) { /* if (w != null) {
// renew existing file window // renew existing file window
int position = w.textArea.getCaretPosition(); int position = w.textArea.getCaretPosition();
// System.err.println(" VISIBLE: " + point); // System.err.println(" VISIBLE: " + point);
@ -122,10 +70,10 @@ public class HelmaDebugger extends Main implements TreeSelectionListener {
w.sourceInfo = (SourceInfo) sourceNames.get(sourceName); w.sourceInfo = (SourceInfo) sourceNames.get(sourceName);
w.updateText(); w.updateText();
w.textArea.setCaretPosition(position); w.textArea.setCaretPosition(position);
} } */
} }
void createTreeNode(String sourceName) { void createTreeNode(String sourceName, Dim.SourceInfo sourceInfo) {
String[] path = StringUtils.split(sourceName, ":/\\"); String[] path = StringUtils.split(sourceName, ":/\\");
DebuggerTreeNode node = treeRoot; DebuggerTreeNode node = treeRoot;
DebuggerTreeNode newNode = null; DebuggerTreeNode newNode = null;
@ -151,27 +99,13 @@ public class HelmaDebugger extends Main implements TreeSelectionListener {
Object node = path.getLastPathComponent(); Object node = path.getLastPathComponent();
if (node == null) if (node == null)
return; return;
String scriptName = (String) scriptNames.get(node); String sourceName = (String) scriptNames.get(node);
if (scriptName == null) if (sourceName == null)
return; return;
JInternalFrame w = (JInternalFrame) fileWindows.get(scriptName); SourceInfo sourceInfo = sourceInfo(sourceName);
if (w != null) { gui.showSourceText(sourceInfo);
try {
if (w.isIcon())
w.setMaximum(true);
w.show();
w.setSelected(true);
} catch (Exception exc) {
}
} else {
SourceInfo si = (SourceInfo) sourceNames.get(scriptName);
if (si == null) {
System.out.println("debugger error: Couldn't find source: " + scriptName);
}
swingInvoke(CreateFileWindow.action(this, si, -1));
}
// display functions for opened script file // display functions for opened script file
Vector functions = new Vector(); /*Vector functions = new Vector();
Iterator it = functionNames.entrySet().iterator(); Iterator it = functionNames.entrySet().iterator();
while (it.hasNext()) { while (it.hasNext()) {
Map.Entry entry = (Map.Entry) it.next(); Map.Entry entry = (Map.Entry) it.next();
@ -181,13 +115,13 @@ public class HelmaDebugger extends Main implements TreeSelectionListener {
} }
} }
Collections.sort(functions); Collections.sort(functions);
list.setListData(functions); list.setListData(functions); */
} }
void openFunction(String function) { void openFunction(String function) {
if (function == null) if (function == null)
return; return;
ScriptItem item = (ScriptItem) functionNames.get(function); /* ScriptItem item = (ScriptItem) functionNames.get(function);
if (item != null) { if (item != null) {
SourceInfo si = item.getSourceInfo(); SourceInfo si = item.getSourceInfo();
String url = si.getUrl(); String url = si.getUrl();
@ -212,8 +146,10 @@ public class HelmaDebugger extends Main implements TreeSelectionListener {
w.textArea.requestFocus(); w.textArea.requestFocus();
} catch (Exception exc) { } catch (Exception exc) {
} }
} */
} }
}
public void valueChanged(TreeSelectionEvent e) { public void valueChanged(TreeSelectionEvent e) {
DefaultMutableTreeNode node = (DefaultMutableTreeNode) DefaultMutableTreeNode node = (DefaultMutableTreeNode)
@ -260,5 +196,78 @@ public class HelmaDebugger extends Main implements TreeSelectionListener {
} }
} }
class DebugGui extends SwingGui {
public DebugGui(Dim dim, String title) {
super(dim, title);
Container contentPane = getContentPane();
Component main = contentPane.getComponent(1);
contentPane.remove(main);
treeRoot = new DebuggerTreeNode(title);
tree = new JTree(treeRoot);
treeModel = new DefaultTreeModel(treeRoot);
tree.setModel(treeModel);
tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
tree.addTreeSelectionListener(HelmaDebugger.this);
// tree.setRootVisible(false);
// track double clicks
tree.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent evt) {
openScript(tree.getSelectionPath());
}
});
// track enter key
tree.addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent evt) {
if (evt.getKeyCode() == KeyEvent.VK_ENTER)
openScript(tree.getSelectionPath());
}
});
JScrollPane treeScroller = new JScrollPane(tree);
treeScroller.setPreferredSize(new Dimension(180, 300));
list = new JList();
// no bold font lists for me, thanks
list.setFont(list.getFont().deriveFont(Font.PLAIN));
list.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent evt) {
openFunction((String) list.getSelectedValue());
}
});
list.addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent evt) {
if (evt.getKeyCode() == KeyEvent.VK_ENTER)
openFunction((String) list.getSelectedValue());
}
});
JScrollPane listScroller = new JScrollPane(list);
listScroller.setPreferredSize(new Dimension(180, 200));
JSplitPane split1 = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
split1.setTopComponent(treeScroller);
split1.setBottomComponent(listScroller);
split1.setOneTouchExpandable(true);
split1.setResizeWeight(0.66);
JSplitPane split2 = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
split2.setLeftComponent(split1);
split2.setRightComponent(main);
split2.setOneTouchExpandable(true);
contentPane.add(split2, BorderLayout.CENTER);
}
public void updateSourceText(Dim.SourceInfo sourceInfo) {
// super.updateSourceText(sourceInfo);
String filename = sourceInfo.url();
if (!treeNodes.containsKey(filename)) {
createTreeNode(filename, sourceInfo);
}
// System.err.println("UPDATE SOURCE TEXT CALLED: " + sourceInfo.url());
}
public void showSourceText(Dim.SourceInfo sourceInfo) {
super.updateSourceText(sourceInfo);
}
}
} }

View file

@ -1,356 +0,0 @@
/*
* @(#)JTreeTable.java 1.2 98/10/27
*
* Copyright 1997, 1998 by Sun Microsystems, Inc.,
* 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
* All rights reserved.
*
* This software is the confidential and proprietary information
* of Sun Microsystems, Inc. ("Confidential Information"). You
* shall not disclose such Confidential Information and shall use
* it only in accordance with the terms of the license agreement
* you entered into with Sun.
*/
package helma.scripting.rhino.debug;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.tree.*;
import javax.swing.table.*;
import java.awt.Dimension;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.util.EventObject;
/**
* This example shows how to create a simple JTreeTable component,
* by using a JTree as a renderer (and editor) for the cells in a
* particular column in the JTable.
*
* @version 1.2 10/27/98
*
* @author Philip Milne
* @author Scott Violet
*/
public class JTreeTable extends JTable {
/** A subclass of JTree. */
protected TreeTableCellRenderer tree;
public JTreeTable(TreeTableModel treeTableModel) {
super();
// Create the tree. It will be used as a renderer and editor.
tree = new TreeTableCellRenderer(treeTableModel);
// Install a tableModel representing the visible rows in the tree.
super.setModel(new TreeTableModelAdapter(treeTableModel, tree));
// Force the JTable and JTree to share their row selection models.
ListToTreeSelectionModelWrapper selectionWrapper = new
ListToTreeSelectionModelWrapper();
tree.setSelectionModel(selectionWrapper);
setSelectionModel(selectionWrapper.getListSelectionModel());
// Install the tree editor renderer and editor.
setDefaultRenderer(TreeTableModel.class, tree);
setDefaultEditor(TreeTableModel.class, new TreeTableCellEditor());
// No grid.
setShowGrid(false);
// No intercell spacing
setIntercellSpacing(new Dimension(0, 0));
// And update the height of the trees row to match that of
// the table.
if (tree.getRowHeight() < 1) {
// Metal looks better like this.
setRowHeight(18);
}
}
/**
* Overridden to message super and forward the method to the tree.
* Since the tree is not actually in the component hieachy it will
* never receive this unless we forward it in this manner.
*/
public void updateUI() {
super.updateUI();
if(tree != null) {
tree.updateUI();
}
// Use the tree's default foreground and background colors in the
// table.
LookAndFeel.installColorsAndFont(this, "Tree.background",
"Tree.foreground", "Tree.font");
}
/* Workaround for BasicTableUI anomaly. Make sure the UI never tries to
* paint the editor. The UI currently uses different techniques to
* paint the renderers and editors and overriding setBounds() below
* is not the right thing to do for an editor. Returning -1 for the
* editing row in this case, ensures the editor is never painted.
*/
public int getEditingRow() {
return (getColumnClass(editingColumn) == TreeTableModel.class) ? -1 :
editingRow;
}
/**
* Overridden to pass the new rowHeight to the tree.
*/
public void setRowHeight(int rowHeight) {
super.setRowHeight(rowHeight);
if (tree != null && tree.getRowHeight() != rowHeight) {
tree.setRowHeight(getRowHeight());
}
}
/**
* Returns the tree that is being shared between the model.
*/
public JTree getTree() {
return tree;
}
/**
* A TreeCellRenderer that displays a JTree.
*/
public class TreeTableCellRenderer extends JTree implements
TableCellRenderer {
/** Last table/tree row asked to renderer. */
protected int visibleRow;
public TreeTableCellRenderer(TreeModel model) {
super(model);
}
/**
* updateUI is overridden to set the colors of the Tree's renderer
* to match that of the table.
*/
public void updateUI() {
super.updateUI();
// Make the tree's cell renderer use the table's cell selection
// colors.
TreeCellRenderer tcr = getCellRenderer();
if (tcr instanceof DefaultTreeCellRenderer) {
DefaultTreeCellRenderer dtcr = ((DefaultTreeCellRenderer)tcr);
// For 1.1 uncomment this, 1.2 has a bug that will cause an
// exception to be thrown if the border selection color is
// null.
// dtcr.setBorderSelectionColor(null);
dtcr.setTextSelectionColor(UIManager.getColor
("Table.selectionForeground"));
dtcr.setBackgroundSelectionColor(UIManager.getColor
("Table.selectionBackground"));
}
}
/**
* Sets the row height of the tree, and forwards the row height to
* the table.
*/
public void setRowHeight(int rowHeight) {
if (rowHeight > 0) {
super.setRowHeight(rowHeight);
if (JTreeTable.this != null &&
JTreeTable.this.getRowHeight() != rowHeight) {
JTreeTable.this.setRowHeight(getRowHeight());
}
}
}
/**
* This is overridden to set the height to match that of the JTable.
*/
public void setBounds(int x, int y, int w, int h) {
super.setBounds(x, 0, w, JTreeTable.this.getHeight());
}
/**
* Sublcassed to translate the graphics such that the last visible
* row will be drawn at 0,0.
*/
public void paint(Graphics g) {
g.translate(0, -visibleRow * getRowHeight());
super.paint(g);
}
/**
* TreeCellRenderer method. Overridden to update the visible row.
*/
public Component getTableCellRendererComponent(JTable table,
Object value,
boolean isSelected,
boolean hasFocus,
int row, int column) {
if(isSelected)
setBackground(table.getSelectionBackground());
else
setBackground(table.getBackground());
visibleRow = row;
return this;
}
}
/**
* TreeTableCellEditor implementation. Component returned is the
* JTree.
*/
public class TreeTableCellEditor extends AbstractCellEditor implements
TableCellEditor {
public Component getTableCellEditorComponent(JTable table,
Object value,
boolean isSelected,
int r, int c) {
return tree;
}
/**
* Overridden to return false, and if the event is a mouse event
* it is forwarded to the tree.<p>
* The behavior for this is debatable, and should really be offered
* as a property. By returning false, all keyboard actions are
* implemented in terms of the table. By returning true, the
* tree would get a chance to do something with the keyboard
* events. For the most part this is ok. But for certain keys,
* such as left/right, the tree will expand/collapse where as
* the table focus should really move to a different column. Page
* up/down should also be implemented in terms of the table.
* By returning false this also has the added benefit that clicking
* outside of the bounds of the tree node, but still in the tree
* column will select the row, whereas if this returned true
* that wouldn't be the case.
* <p>By returning false we are also enforcing the policy that
* the tree will never be editable (at least by a key sequence).
*/
public boolean isCellEditable(EventObject e) {
if (e instanceof MouseEvent) {
for (int counter = getColumnCount() - 1; counter >= 0;
counter--) {
if (getColumnClass(counter) == TreeTableModel.class) {
MouseEvent me = (MouseEvent)e;
MouseEvent newME = new MouseEvent(tree, me.getID(),
me.getWhen(), me.getModifiers(),
me.getX() - getCellRect(0, counter, true).x,
me.getY(), me.getClickCount(),
me.isPopupTrigger());
tree.dispatchEvent(newME);
break;
}
}
}
return false;
}
}
/**
* ListToTreeSelectionModelWrapper extends DefaultTreeSelectionModel
* to listen for changes in the ListSelectionModel it maintains. Once
* a change in the ListSelectionModel happens, the paths are updated
* in the DefaultTreeSelectionModel.
*/
class ListToTreeSelectionModelWrapper extends DefaultTreeSelectionModel {
/** Set to true when we are updating the ListSelectionModel. */
protected boolean updatingListSelectionModel;
public ListToTreeSelectionModelWrapper() {
super();
getListSelectionModel().addListSelectionListener
(createListSelectionListener());
}
/**
* Returns the list selection model. ListToTreeSelectionModelWrapper
* listens for changes to this model and updates the selected paths
* accordingly.
*/
ListSelectionModel getListSelectionModel() {
return listSelectionModel;
}
/**
* This is overridden to set <code>updatingListSelectionModel</code>
* and message super. This is the only place DefaultTreeSelectionModel
* alters the ListSelectionModel.
*/
public void resetRowSelection() {
if(!updatingListSelectionModel) {
updatingListSelectionModel = true;
try {
super.resetRowSelection();
}
finally {
updatingListSelectionModel = false;
}
}
// Notice how we don't message super if
// updatingListSelectionModel is true. If
// updatingListSelectionModel is true, it implies the
// ListSelectionModel has already been updated and the
// paths are the only thing that needs to be updated.
}
/**
* Creates and returns an instance of ListSelectionHandler.
*/
protected ListSelectionListener createListSelectionListener() {
return new ListSelectionHandler();
}
/**
* If <code>updatingListSelectionModel</code> is false, this will
* reset the selected paths from the selected rows in the list
* selection model.
*/
protected void updateSelectedPathsFromSelectedRows() {
if(!updatingListSelectionModel) {
updatingListSelectionModel = true;
try {
// This is way expensive, ListSelectionModel needs an
// enumerator for iterating.
int min = listSelectionModel.getMinSelectionIndex();
int max = listSelectionModel.getMaxSelectionIndex();
clearSelection();
if(min != -1 && max != -1) {
for(int counter = min; counter <= max; counter++) {
if(listSelectionModel.isSelectedIndex(counter)) {
TreePath selPath = tree.getPathForRow
(counter);
if(selPath != null) {
addSelectionPath(selPath);
}
}
}
}
}
finally {
updatingListSelectionModel = false;
}
}
}
/**
* Class responsible for calling updateSelectedPathsFromSelectedRows
* when the selection of the list changse.
*/
class ListSelectionHandler implements ListSelectionListener {
public void valueChanged(ListSelectionEvent e) {
updateSelectedPathsFromSelectedRows();
}
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,43 +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 See Beyond Corporation.
* Portions created by See Beyond are
* Copyright (C) 2000 See Beyond Communications 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 helma.scripting.rhino.debug;
import org.mozilla.javascript.Scriptable;
public interface ScopeProvider {
public Scriptable getScope();
};

View file

@ -1,71 +0,0 @@
/*
* TreeTableModel.java
*
* Copyright (c) 1998 Sun Microsystems, Inc. All Rights Reserved.
*
* This software is the confidential and proprietary information of Sun
* Microsystems, Inc. ("Confidential Information"). You shall not
* disclose such Confidential Information and shall use it only in
* accordance with the terms of the license agreement you entered into
* with Sun.
*
* SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
* SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
* IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
* PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
* SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
* THIS SOFTWARE OR ITS DERIVATIVES.
*
*/
package helma.scripting.rhino.debug;
import javax.swing.tree.TreeModel;
/**
* TreeTableModel is the model used by a JTreeTable. It extends TreeModel
* to add methods for getting inforamtion about the set of columns each
* node in the TreeTableModel may have. Each column, like a column in
* a TableModel, has a name and a type associated with it. Each node in
* the TreeTableModel can return a value for each of the columns and
* set that value if isCellEditable() returns true.
*
* @author Philip Milne
* @author Scott Violet
*/
public interface TreeTableModel extends TreeModel
{
/**
* Returns the number ofs availible column.
*/
public int getColumnCount();
/**
* Returns the name for column number <code>column</code>.
*/
public String getColumnName(int column);
/**
* Returns the type for column number <code>column</code>.
*/
public Class getColumnClass(int column);
/**
* Returns the value to be displayed for node <code>node</code>,
* at column number <code>column</code>.
*/
public Object getValueAt(Object node, int column);
/**
* Indicates whether the the value for node <code>node</code>,
* at column number <code>column</code> is editable.
*/
public boolean isCellEditable(Object node, int column);
/**
* Sets the value for node <code>node</code>,
* at column number <code>column</code>.
*/
public void setValueAt(Object aValue, Object node, int column);
}

View file

@ -1,128 +0,0 @@
/*
* @(#)TreeTableModelAdapter.java 1.2 98/10/27
*
* Copyright 1997, 1998 by Sun Microsystems, Inc.,
* 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
* All rights reserved.
*
* This software is the confidential and proprietary information
* of Sun Microsystems, Inc. ("Confidential Information"). You
* shall not disclose such Confidential Information and shall use
* it only in accordance with the terms of the license agreement
* you entered into with Sun.
*/
package helma.scripting.rhino.debug;
import javax.swing.JTree;
import javax.swing.SwingUtilities;
import javax.swing.table.AbstractTableModel;
import javax.swing.tree.TreePath;
import javax.swing.event.TreeExpansionEvent;
import javax.swing.event.TreeExpansionListener;
import javax.swing.event.TreeModelEvent;
import javax.swing.event.TreeModelListener;
/**
* This is a wrapper class takes a TreeTableModel and implements
* the table model interface. The implementation is trivial, with
* all of the event dispatching support provided by the superclass:
* the AbstractTableModel.
*
* @version 1.2 10/27/98
*
* @author Philip Milne
* @author Scott Violet
*/
public class TreeTableModelAdapter extends AbstractTableModel
{
JTree tree;
TreeTableModel treeTableModel;
public TreeTableModelAdapter(TreeTableModel treeTableModel, JTree tree) {
this.tree = tree;
this.treeTableModel = treeTableModel;
tree.addTreeExpansionListener(new TreeExpansionListener() {
// Don't use fireTableRowsInserted() here; the selection model
// would get updated twice.
public void treeExpanded(TreeExpansionEvent event) {
fireTableDataChanged();
}
public void treeCollapsed(TreeExpansionEvent event) {
fireTableDataChanged();
}
});
// Install a TreeModelListener that can update the table when
// tree changes. We use delayedFireTableDataChanged as we can
// not be guaranteed the tree will have finished processing
// the event before us.
treeTableModel.addTreeModelListener(new TreeModelListener() {
public void treeNodesChanged(TreeModelEvent e) {
delayedFireTableDataChanged();
}
public void treeNodesInserted(TreeModelEvent e) {
delayedFireTableDataChanged();
}
public void treeNodesRemoved(TreeModelEvent e) {
delayedFireTableDataChanged();
}
public void treeStructureChanged(TreeModelEvent e) {
delayedFireTableDataChanged();
}
});
}
// Wrappers, implementing TableModel interface.
public int getColumnCount() {
return treeTableModel.getColumnCount();
}
public String getColumnName(int column) {
return treeTableModel.getColumnName(column);
}
public Class getColumnClass(int column) {
return treeTableModel.getColumnClass(column);
}
public int getRowCount() {
return tree.getRowCount();
}
protected Object nodeForRow(int row) {
TreePath treePath = tree.getPathForRow(row);
return treePath.getLastPathComponent();
}
public Object getValueAt(int row, int column) {
return treeTableModel.getValueAt(nodeForRow(row), column);
}
public boolean isCellEditable(int row, int column) {
return treeTableModel.isCellEditable(nodeForRow(row), column);
}
public void setValueAt(Object value, int row, int column) {
treeTableModel.setValueAt(value, nodeForRow(row), column);
}
/**
* Invokes fireTableDataChanged after all the pending events have been
* processed. SwingUtilities.invokeLater is used to handle this.
*/
protected void delayedFireTableDataChanged() {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
fireTableDataChanged();
}
});
}
}

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 helma.scripting.rhino.debug;
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;
}
}