KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > aspectj > debugger > gui > AJStackFrameNode


1 /* -*- Mode: JDE; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2  *
3  * This file is part of the debugger and core tools for the AspectJ(tm)
4  * programming language; see http://aspectj.org
5  *
6  * The contents of this file are subject to the Mozilla Public License
7  * Version 1.1 (the "License"); you may not use this file except in
8  * compliance with the License. You may obtain a copy of the License at
9  * either http://www.mozilla.org/MPL/ or http://aspectj.org/MPL/.
10  *
11  * Software distributed under the License is distributed on an "AS IS" basis,
12  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13  * for the specific language governing rights and limitations under the
14  * License.
15  *
16  * The Original Code is AspectJ.
17  *
18  * The Initial Developer of the Original Code is Xerox Corporation. Portions
19  * created by Xerox Corporation are Copyright (C) 1999-2002 Xerox Corporation.
20  * All Rights Reserved.
21  */

22
23 package org.aspectj.debugger.gui;
24
25 import org.aspectj.debugger.base.*;
26 import org.aspectj.debugger.request.*;
27
28 import java.awt.*;
29 import java.awt.event.*;
30 import javax.swing.*;
31 import javax.swing.event.*;
32 import javax.swing.tree.*;
33 import java.util.List JavaDoc;
34 import java.util.Map JavaDoc;
35 import java.util.Iterator JavaDoc;
36 import com.sun.jdi.*;
37
38 public class AJStackFrameNode extends AJTreeNode {
39
40     /**
41      * The underlying StackFrame user object.
42      */

43     protected StackFrame frame = null;
44
45     /**
46      * The original location of this frame.
47      */

48     protected Location originalLocation = null;
49
50     /**
51      * The representation of the method and source.
52      */

53     protected AJStackFrameFormatter.MethodAndSource ms = null;
54
55     private String JavaDoc str = "<unititialized frame>";
56
57     /**
58      * Constructs a new node with underlying user object <code>frame<\code>.
59      * NEW VERSION: We don't need the index.
60      * @param frame the underlying user object.
61      */

62     public AJStackFrameNode(StackFrame frame) {
63         super(AJIcons.STACKFRAME_ICON);
64         setUserObject(frame);
65         //setFrame(frame); //XXX Must come before setting original location
66
this.frame = frame;
67         originalLocation = frame.location(); //TODO: Check for the exception
68
ms = AJStackFrameFormatter.format(getStackFrame());
69         str = ms + "";
70         thread = frame.thread();
71     }
72
73     //XXX
74
ThreadReference thread = null;
75
76     // TODO: Deal with exception
77
public int index() {
78         int index = -1;
79         try {
80             index =
81                 ComponentRepository.getAJDebugger().
82                 frames(frame.thread()).indexOf(frame);
83             //index = frame.thread().frames().indexOf(frame);
84
} catch (Exception JavaDoc e) {}
85         return index;
86     }
87
88     public void rightMouseButton(MouseEvent e) {
89         JPopupMenu menu = null;
90         if (ms.isValid()) {
91             menu = new ShowMenu();
92         } else {
93             menu = new NoShowMenu();
94         }
95         menu.show(ComponentRepository.
96                   getThreadGroupTreePane().getTree(),
97                   e.getX(),
98                   e.getY());
99     }
100
101     class ShowMenu extends JPopupMenu {
102         ShowMenu() {
103             //String s = AJStackFrameNode.this.ms.sourceName + ":" +
104
String JavaDoc s = AJStackFrameNode.this.ms.getFullPath() + ":" +
105                        AJStackFrameNode.this.ms.lineNumber;
106             JMenuItem item;
107             item = new JMenuItem("goto " + s);
108             item.addActionListener(new ActionListener() {
109                     public void actionPerformed(ActionEvent e) {
110                         ComponentRepository.getSourcePane().
111                             showSourceForFileAndLine
112                             (AJStackFrameNode.this.ms.getFullPath(),
113                              AJStackFrameNode.this.ms.lineNumber);
114                     }
115                 });
116             add(item);
117             Iterator JavaDoc iter =
118                 ComponentRepository.getAJDebugger().
119                 getBreakpointRequests().iterator();
120             String JavaDoc cmd = " " + AJStackFrameNode.this.ms.getProto();
121             boolean found = false;
122             while (iter.hasNext()) {
123                 BreakpointRequestAction req =
124                     (BreakpointRequestAction)iter.next();
125                 if (req.equals(AJStackFrameNode.this.ms)) {
126                     found = true;
127                     break;
128                 }
129             }
130             final String JavaDoc msg = (found ? "clear" : "stop on") + cmd;
131             item = new JMenuItem(msg);
132             item.addActionListener(new ActionListener() {
133                     public void actionPerformed(ActionEvent e) {
134                         ComponentRepository.execute(msg);
135                     }
136                 });
137             add(item);
138         }
139     }
140
141     static class NoShowMenu extends JPopupMenu {
142         NoShowMenu() {
143             add(new JMenuItem("Source is unavailable"));
144         }
145     }
146
147
148     // ------------------------------------------------------------------------
149
// Access to the user object.
150
//
151
// ASPECT: Do null-checking on these methods and other checking.
152
// ------------------------------------------------------------------------
153

154     /**
155      * Gets the Value of a LocalVariable in this frame. The variable must be
156      * valid for this frame's method and visible according to the rules
157      * described in visibleVariables().
158      *
159      * @param variable the LocalVariable to be accessed
160      * @return the Value of the instance field.
161      */

162     public Value getValue(LocalVariable variable) {
163         return frame.getValue(variable);
164     }
165
166     /**
167      * Returns the values of multiple local variables in this frame. Each
168      * variable must be valid for this frame's method and visible according to
169      * the rules described in visibleVariables().
170      *
171      * @param variables a list of LocalVariable objects to be accessed
172      * @return a map associating each LocalVariable with its Value
173      */

174     public Map JavaDoc getValues(java.util.List JavaDoc variables) {
175         return frame.getValues(variables);
176     }
177
178     /**
179      * Returns the Location of the current instruction in the frame. The method
180      * for which this frame was created can also be accessed through the
181      * returned location. For the top frame in the stack, this location
182      * identifies the next instruction to be executed. For all other frames,
183      * this location identifies the instruction that caused the next frame's
184      * method to be invoked. If the frame represents a native method invocation,
185      * the returned location indicates the class and method, but the code index
186      * will not be valid.
187      *
188      * @return the Location of the current instruction.
189      */

190     public Location location() {
191         return frame.location();
192     }
193
194     /**
195      * Returns the value of 'this' for the current frame. The ObjectReference
196      * for 'this' is only available for non-native instance methods.
197      *
198      * @return an ObjectReference, or null if the frame represents a native or
199      * static method.
200      */

201     public ObjectReference thisObject() {
202         return frame.thisObject();
203     }
204
205     /**
206      * Returns the thread under which this frame's method is running.
207      *
208      * @return a ThreadReference which mirrors the frame's thread.
209      */

210     public ThreadReference thread() {
211         return frame.thread();
212     }
213
214     /**
215      * Finds a LocalVariable that matches the given name and is visible at the
216      * current frame location. See visibleVariables() for more information on
217      * visibility.
218      *
219      * @param name the variable name to find.
220      * @return the matching LocalVariable, or null if there is no visible
221      * variable with the given name.
222      * @throws AbsentInformationException if there is no line number
223      * information for this method.
224      */

225     public LocalVariable visibleVariableByName(String JavaDoc name)
226             throws AbsentInformationException {
227         return frame.visibleVariableByName(name);
228     }
229
230     /**
231      * Returns a list containing each LocalVariable that can be accessed from
232      * this frame's location.
233      * <br>
234      * Visibility is based on the code index of the current instruction of this
235      * StackFrame. Each variable has a range of byte code indices in which it
236      * is accessible. If this stack frame's method matches this variable's
237      * method and if the code index of this StackFrame is within the variable's
238      * byte code range, the variable is visible.
239      * <br>
240      * A variable's byte code range is at least as large as the scope of that
241      * variable, but can continue beyond the end of the scope under certain
242      * circumstances:
243      * - the compiler/VM does not immediately reuse the variable's slot.
244      * - the compiler/VM is implemented to report the extended range that would
245      * result from the item above.
246      * The advantage of an extended range is that variables from recently
247      * exited scopes may remain available for examination (this is especially
248      * useful for loop indices). If, as a result of the extensions above, the
249      * current frame location is contained within the range of multiple local
250      * variables of the same name, the variable with the highest-starting range
251      * is chosen for the returned list.
252      *
253      * @return the list of LocalVariable objects currently visible.
254      * @throws AbsentInformationException if there is no line number
255      * information for this method.
256      */

257     public List JavaDoc visibleVariables()
258             throws AbsentInformationException {
259         return frame.visibleVariables();
260     }
261
262     // ------------------------------------------------------------------------
263
// Other misc. methods
264
// ------------------------------------------------------------------------
265

266     /**
267      * Access to the user object StackFrame.
268      *
269      * @return the StackFrame <code>frame<\code>.
270      */

271     public StackFrame getStackFrame() {
272         return frame;
273     }
274
275     /**
276      * Returns the line number of the location of this frame.
277      *
278      * @return the line number of the location of this frame.
279      */

280     public int lineNumber() {
281         return this.location().lineNumber();
282     }
283
284     /**
285      * Returns the source file name for this frame.
286      *
287      * @return the source file name for this frame.
288      * @throws AbsentInformationException if there is no line number
289      * information for this method.
290      */

291     public String JavaDoc sourceName()
292             throws AbsentInformationException {
293         return this.location().sourceName();
294     }
295
296     /**
297      * Gets the method, if any, containing this Location.
298      *
299      * @return the Method if this location is in a method, otherwise null.
300      */

301     public Method method() {
302         return this.location().method();
303     }
304
305     /**
306      * Returns true because this <b>is<\b> a stack frame.
307      *
308      * @return true.
309      */

310     public boolean isStackFrame() {
311         return true;
312     }
313
314     /**
315      * Checks to be sure that this frame is still valid.
316      */

317     public boolean isValid() {
318         try {
319             frame.location();
320         } catch (InvalidStackFrameException ie) {
321             return false;
322         }
323         return true;
324     }
325
326     public void showKids() {
327         //if (getChildCount() > 0) return;
328
try {
329             removeAllChildren();
330             showThisObject();
331             showLocalVariables();
332         } catch (InvalidStackFrameException isfe) {
333         }
334     }
335
336     public void hideKids() {
337         this.removeAllChildren();
338     }
339
340     /**
341      * Shows the local variables in this frame.
342      */

343     private void showLocalVariables() {
344         try {
345             Iterator JavaDoc iter = visibleVariables().iterator();
346             while (iter.hasNext()) {
347                 LocalVariable local = (LocalVariable) iter.next();
348                 StackFrame frame = getStackFrame();
349                 AJValueNode valueNode = AJValueNodeFactory.make(local, frame);
350                 //System.out.println(" * " + valueNode);
351
this.add(valueNode);
352             }
353         } catch (AbsentInformationException aie) {
354         } catch (NativeMethodException nme) {
355         }
356     }
357
358     /**
359      * Shows the ObjectReference <code>this<\code> in this frame.
360      */

361     private void showThisObject() {
362         ObjectReference object = frame.thisObject();
363
364         // The object will be null if the frame is static
365
if (object == null) {
366             return;
367         }
368         AJValueNode valueNode = AJValueNodeFactory.make(object, "this");
369         this.add(valueNode);
370     }
371
372     /**
373      * Overrides AJDBTreeNode.toString to return the <TODO>.
374      */

375     boolean sdb = false;
376     public String JavaDoc toString() {
377         String JavaDoc t = "thread=";
378         try {
379             t += System.identityHashCode(frame.thread()) + "";
380         } catch (Exception JavaDoc e) {
381             t += "***" + System.identityHashCode(thread);
382         }
383         t += ": ";
384
385         return (sdb ? dd() + t : "") +
386             str;
387     }
388
389     /**
390      * First checks to see if this node it valid, if it is sets the icon to
391      * the INVALID icon.
392      */

393     public int getType() {
394         if (isValid()) {
395             return super.getType();
396         }
397
398         // Tell the parent that this and all frames are crap
399
DefaultMutableTreeNode parent = (DefaultMutableTreeNode)getParent();
400         if (parent != null) {
401             parent.removeAllChildren();
402         }
403         return AJIcons.INVALID_ICON;
404     }
405
406     /**
407      * Returns the original location of this frame.
408      */

409     public Location getOriginalLocation() {
410         return this.originalLocation;
411     }
412
413     /**
414      * Allows someone to reset the frame node, this should be done <b>only</b>
415      * if the original location is the same as the frames location.
416      * TODO: Either debug here or in the caller <i>or both</i>.
417      * TODO: Exceptions.
418      */

419     public void setFrame(StackFrame frame) {
420         //TODO: Testing to see that this frame is compatible with the
421
// original location
422
this.frame = frame;
423         setUserObject(frame);
424         originalLocation = frame.location(); //TODO: Check for the exception
425
ms = AJStackFrameFormatter.format(getStackFrame());
426         str = ms + "";
427         thread = frame.thread();
428         //
429
// Possibly adding kids as soon as we get a frame will work
430
//
431
showKids();
432     }
433 }
434
Popular Tags