KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > debugger > jpda > models > CallStackTreeModel


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.debugger.jpda.models;
21
22 import com.sun.jdi.AbsentInformationException;
23 import com.sun.jdi.IncompatibleThreadStateException;
24 import java.beans.PropertyChangeEvent JavaDoc;
25 import java.beans.PropertyChangeListener JavaDoc;
26 import java.lang.ref.WeakReference JavaDoc;
27 import java.util.Collection JavaDoc;
28 import java.util.HashSet JavaDoc;
29
30 import org.netbeans.api.debugger.jpda.CallStackFrame;
31 import org.netbeans.api.debugger.jpda.JPDAThread;
32 import org.netbeans.spi.debugger.ContextProvider;
33 import org.netbeans.api.debugger.jpda.JPDADebugger;
34 import org.netbeans.spi.viewmodel.ModelEvent;
35 import org.netbeans.spi.viewmodel.TreeModel;
36 import org.netbeans.spi.viewmodel.ModelListener;
37 import org.netbeans.spi.viewmodel.UnknownTypeException;
38
39 import org.netbeans.modules.debugger.jpda.JPDADebuggerImpl;
40 import org.openide.util.RequestProcessor;
41 import org.openide.util.WeakListeners;
42
43
44 /**
45  * This tree model provides an array of CallStackFrame objects.
46  *
47  * @author Jan Jancura, Martin Entlicher
48  */

49 public class CallStackTreeModel implements TreeModel {
50
51     private static boolean verbose =
52         (System.getProperty ("netbeans.debugger.viewrefresh") != null) &&
53         (System.getProperty ("netbeans.debugger.viewrefresh").indexOf ('c') >= 0);
54     
55     private JPDADebuggerImpl debugger;
56     private Collection JavaDoc<ModelListener> listeners = new HashSet JavaDoc<ModelListener>();
57     private Listener JavaDoc listener;
58     
59    
60     public CallStackTreeModel (ContextProvider lookupProvider) {
61         debugger = (JPDADebuggerImpl) lookupProvider.
62             lookupFirst (null, JPDADebugger.class);
63     }
64     
65     /**
66      *
67      * @return threads contained in this group of threads
68      */

69     public Object JavaDoc[] getChildren (Object JavaDoc parent, int from, int to)
70     throws UnknownTypeException {
71         if ( parent.equals (ROOT) ||
72              (parent instanceof JPDAThread)
73         ) {
74             // 1) get Thread
75
JPDAThread thread;
76             if (parent.equals (ROOT)) {
77                 thread = debugger.getCurrentThread ();
78             } else {
79                 thread = (JPDAThread) parent;
80             }
81             if (thread == null) {
82                 return new String JavaDoc[] {"No current thread"}; // TODO make localizable!!!
83
}
84             
85             // 2) get StackFrames for this Thread
86
try {
87                 CallStackFrame[] sfs = thread.getCallStack(from, to);
88                 return sfs;
89             } catch (AbsentInformationException aiex) {
90                 if (aiex.getCause() instanceof IncompatibleThreadStateException) {
91                     return new String JavaDoc[] {"Thread is running"}; // TODO make localizable!!!
92
} else {
93                     return new String JavaDoc[] {"No call stack information available."}; // TODO make localizable!!!
94
}
95             }
96         } else
97         throw new UnknownTypeException (parent);
98     }
99     
100     /**
101      * Returns number of children for given node.
102      *
103      * @param node the parent node
104      * @throws UnknownTypeException if this TreeModel implementation is not
105      * able to resolve children for given node type
106      *
107      * @return true if node is leaf
108      */

109     public int getChildrenCount (Object JavaDoc parent) throws UnknownTypeException {
110         if ( parent.equals (ROOT) ||
111              (parent instanceof JPDAThread)
112         ) {
113             // Performance, see issue #59058.
114
return Integer.MAX_VALUE;
115             /*
116             // 1) get Thread
117             JPDAThread thread;
118             if (parent.equals (ROOT)) {
119                 thread = debugger.getCurrentThread ();
120             } else {
121                 thread = (JPDAThread) parent;
122             }
123             if (thread == null) {
124                 return 1; //new String [] {"No current thread"};
125             }
126             
127             return thread.getStackDepth();
128              */

129         } else
130         throw new UnknownTypeException (parent);
131     }
132     
133     /**
134      *
135      * @return threads contained in this group of threads
136      */

137     public Object JavaDoc getRoot () {
138         return ROOT;
139     }
140     
141     public boolean isLeaf (Object JavaDoc node) throws UnknownTypeException {
142         if (node.equals (ROOT)) return false;
143         if (node instanceof CallStackFrame) return true;
144         throw new UnknownTypeException (node);
145     }
146
147     /**
148      *
149      * @param l the listener to add
150      */

151     public void addModelListener (ModelListener l) {
152         synchronized (listeners) {
153             listeners.add (l);
154             if (listener == null) {
155                 listener = new Listener JavaDoc (this, debugger);
156             }
157         }
158     }
159
160     /**
161      *
162      * @param l the listener to remove
163      */

164     public void removeModelListener (ModelListener l) {
165         synchronized (listeners) {
166             listeners.remove (l);
167             if (listeners.size () == 0) {
168                 listener.destroy ();
169                 listener = null;
170             }
171         }
172     }
173     
174     public void fireTreeChanged () {
175         ModelListener[] ls;
176         synchronized (listeners) {
177             ls = listeners.toArray(new ModelListener[0]);
178         }
179         ModelEvent ev = new ModelEvent.TreeChanged(this);
180         for (int i = 0; i < ls.length; i++) {
181             ls[i].modelChanged (ev);
182         }
183     }
184     
185     
186     /**
187      * Listens on JPDADebugger on PROP_STATE
188      */

189     private static class Listener implements PropertyChangeListener JavaDoc {
190         
191         private JPDADebugger debugger;
192         private WeakReference JavaDoc<CallStackTreeModel> model;
193         
194         public Listener (
195             CallStackTreeModel tm,
196             JPDADebugger debugger
197         ) {
198             this.debugger = debugger;
199             model = new WeakReference JavaDoc<CallStackTreeModel>(tm);
200             debugger.addPropertyChangeListener (this);
201             JPDAThreadImpl lastCurrentThread = (JPDAThreadImpl) debugger.getCurrentThread();
202             if (lastCurrentThread != null) {
203                 lastCurrentThread.addPropertyChangeListener(
204                         WeakListeners.propertyChange(this, lastCurrentThread));
205             }
206         }
207         
208         private CallStackTreeModel getModel () {
209             CallStackTreeModel tm = model.get ();
210             if (tm == null) {
211                 destroy ();
212             }
213             return tm;
214         }
215         
216         void destroy () {
217             debugger.removePropertyChangeListener (this);
218             if (task != null) {
219                 // cancel old task
220
task.cancel ();
221                 if (verbose)
222                     System.out.println("CSTM cancel old task " + task);
223                 task = null;
224             }
225         }
226         
227         // currently waiting / running refresh task
228
// there is at most one
229
private RequestProcessor.Task task;
230         
231         // check also whether the current thread was resumed/suspended
232
// the call stack needs to be refreshed after invokeMethod() which resumes the thread
233
public synchronized void propertyChange (PropertyChangeEvent JavaDoc e) {
234             boolean refresh = false;
235             String JavaDoc propertyName = e.getPropertyName();
236             if (propertyName == debugger.PROP_CURRENT_THREAD) {
237                 JPDAThreadImpl lastCurrentThread = (JPDAThreadImpl) debugger.getCurrentThread();
238                 if (lastCurrentThread != null) {
239                     lastCurrentThread.addPropertyChangeListener(
240                             WeakListeners.propertyChange(this, lastCurrentThread));
241                     refresh = true;
242                 }
243             }
244             if (propertyName == JPDAThreadImpl.PROP_SUSPENDED
245                     && Boolean.TRUE.equals(e.getNewValue())) {
246                 if (e.getSource() == debugger.getCurrentThread()) {
247                     refresh = true;
248                 }
249             }
250             if ((propertyName == debugger.PROP_STATE)
251                  && (debugger.getState() == debugger.STATE_STOPPED)
252             ) {
253                 refresh = true;
254             }
255             if (refresh) {
256                 synchronized (this) {
257                     if (task == null) {
258                         task = RequestProcessor.getDefault().create(new Refresher());
259                     }
260                     task.schedule(200);
261                 }
262             }
263         }
264         
265         private class Refresher extends Object JavaDoc implements Runnable JavaDoc {
266             public void run() {
267                 if (debugger.getState () == debugger.STATE_STOPPED) {
268                     CallStackTreeModel tm = getModel ();
269                     if (tm != null) {
270                         tm.fireTreeChanged();
271                     }
272                 }
273             }
274         }
275     }
276 }
277
278
Popular Tags