KickJava   Java API By Example, From Geeks To Geeks.

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


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.ThreadGroupReference;
23 import com.sun.jdi.ThreadReference;
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 import java.util.List JavaDoc;
30 import java.util.Map JavaDoc;
31 import java.util.Set JavaDoc;
32 import java.util.WeakHashMap JavaDoc;
33 import org.netbeans.api.debugger.jpda.JPDAThread;
34 import org.netbeans.api.debugger.jpda.JPDAThreadGroup;
35
36 import org.netbeans.spi.debugger.ContextProvider;
37 import org.netbeans.api.debugger.jpda.JPDADebugger;
38 import org.netbeans.spi.viewmodel.ModelEvent;
39 import org.netbeans.spi.viewmodel.ModelListener;
40 import org.netbeans.spi.viewmodel.TreeModel;
41 import org.netbeans.spi.viewmodel.UnknownTypeException;
42
43 import org.netbeans.modules.debugger.jpda.JPDADebuggerImpl;
44 import org.openide.util.RequestProcessor;
45
46
47 /**
48  * This class represents JPDA Debugger Implementation.
49  *
50  * @author Jan Jancura
51  */

52 public class ThreadsTreeModel implements TreeModel {
53
54     private static boolean verbose =
55         (System.getProperty ("netbeans.debugger.viewrefresh") != null) &&
56         (System.getProperty ("netbeans.debugger.viewrefresh").indexOf ('t') >= 0);
57     
58     private JPDADebuggerImpl debugger;
59     private Map JavaDoc<Object JavaDoc, ChildrenTree> childrenCache = new WeakHashMap JavaDoc<Object JavaDoc, ChildrenTree>();
60     private Listener JavaDoc listener;
61     private Collection JavaDoc<ModelListener> listeners = new HashSet JavaDoc<ModelListener>();
62     
63     
64     public ThreadsTreeModel (ContextProvider lookupProvider) {
65         debugger = (JPDADebuggerImpl) lookupProvider.
66             lookupFirst (null, JPDADebugger.class);
67     }
68
69     public Object JavaDoc getRoot () {
70         return ROOT;
71     }
72     
73     public Object JavaDoc[] getChildren (Object JavaDoc o, int from, int to)
74     throws UnknownTypeException {
75         /*
76         if (node.equals (ROOT)) {
77             return debugger.getTopLevelThreadGroups();
78         } else if (node instanceof JPDAThreadGroup) {
79             JPDAThreadGroup tg = (JPDAThreadGroup) node;
80             JPDAThreadGroup[] tgs = tg.getThreadGroups();
81             JPDAThread[] ts = tg.getThreads();
82             int n = tgs.length + ts.length;
83             from = Math.min(n, from);
84             to = Math.min(n, to);
85             Object[] ch = new Object[to - from];
86             if (from < tgs.length) {
87                 if (to >= tgs.length) {
88                     System.arraycopy(tgs, from, ch, 0, tgs.length - from);
89                 } else {
90                     System.arraycopy(tgs, from, ch, 0, to - from);
91                 }
92             }
93             if (to > tgs.length) {
94                 to -= tgs.length;
95                 int pos = tgs.length - from;
96                 if (from >= tgs.length) {
97                     from -= tgs.length;
98                 } else {
99                     from = 0;
100                 }
101                 System.arraycopy(ts, from, ch, pos, to - from);
102             }
103             return ch;
104         } else {
105             throw new UnknownTypeException (node);
106         }
107         */

108         
109         Object JavaDoc[] ch;
110         synchronized (childrenCache) {
111             //ch = (List) childrenCache.get(o);
112
ChildrenTree cht = childrenCache.get(o);
113             if (cht != null) {
114                 ch = cht.getChildren();
115             } else {
116                 ch = null;
117             }
118         }
119         if (ch == null) {
120             ch = computeChildren(o);
121             if (ch == null) {
122                 throw new UnknownTypeException (o);
123             } else {
124                 synchronized (childrenCache) {
125                     ChildrenTree cht = new ChildrenTree(o);
126                     cht.setChildren(ch);
127                     childrenCache.put(o, cht);
128                 }
129             }
130         }
131         int l = ch.length;
132         from = Math.min(l, from);
133         to = Math.min(l, to);
134         if (from == 0 && to == l) {
135             return ch;
136         } else {
137             Object JavaDoc[] ch1 = new Object JavaDoc[to - from];
138             System.arraycopy(ch, from, ch1, 0, to - from);
139             ch = ch1;
140         }
141         return ch;
142     }
143     
144     private Object JavaDoc[] computeChildren(Object JavaDoc node) {
145         /*
146         List ch;
147         try {
148             if (node.equals (ROOT)) {
149                 VirtualMachine vm = debugger.getVirtualMachine ();
150                 if (vm != null)
151                     ch = vm.topLevelThreadGroups ();
152                 else
153                     ch = Collections.EMPTY_LIST;
154             } else
155             if (node instanceof ThreadGroupReference) {
156                 ThreadGroupReference tgr = (ThreadGroupReference) node;
157                 ch = new ArrayList (tgr.threadGroups ());
158                 ch.addAll(tgr.threads ());
159             } else
160                 ch = null;
161         } catch (VMDisconnectedException ex) {
162             ch = Collections.EMPTY_LIST;
163         }
164         return ch;
165          */

166         if (node.equals (ROOT)) {
167             
168             if (verbose) {
169                 com.sun.jdi.VirtualMachine vm = debugger.getVirtualMachine();
170                 if (vm == null) {
171                     System.err.println("\nThreadsTreeModel.computeChildren():\nVM is null!\n");
172                 } else {
173                     List JavaDoc<ThreadReference> threads = vm.allThreads();
174                     System.err.println("\nThreadsTreeModel.computeChildren() ALL Threads:");
175                     for (ThreadReference t : threads) {
176                         System.err.println(" "+t.name()+" is suspended: "+t.isSuspended()+", suspend count = "+t.suspendCount());
177                     }
178                     System.err.println("");
179                 }
180             }
181             
182             return debugger.getTopLevelThreadGroups();
183         } else if (node instanceof JPDAThreadGroup) {
184             JPDAThreadGroup tg = (JPDAThreadGroup) node;
185             JPDAThreadGroup[] tgs = tg.getThreadGroups();
186             JPDAThread[] ts = tg.getThreads();
187             int n = tgs.length + ts.length;
188             Object JavaDoc[] ch = new Object JavaDoc[n];
189             System.arraycopy(tgs, 0, ch, 0, tgs.length);
190             System.arraycopy(ts, 0, ch, tgs.length, ts.length);
191             return ch;
192         } else {
193             return new Object JavaDoc[0];
194         }
195     }
196     
197     private void recomputeChildren() {
198         synchronized (childrenCache) {
199             recomputeChildren(getRoot());
200         }
201     }
202     
203     private void recomputeChildren(Object JavaDoc node) {
204         ChildrenTree cht = childrenCache.get(node);
205         if (cht != null) {
206             Set JavaDoc keys = childrenCache.keySet();
207             Object JavaDoc[] oldCh = cht.getChildren();
208             Object JavaDoc[] newCh = computeChildren(node);
209             cht.setChildren(newCh);
210             for (int i = 0; i < newCh.length; i++) {
211                 if (keys.contains(newCh[i])) {
212                     recomputeChildren(newCh[i]);
213                 }
214             }
215         }
216         /*
217             Set nodes = childrenCache.keySet();
218             for (Iterator it = nodes.iterator(); it.hasNext(); ) {
219                 Object node = it.next();
220                 // potreba brat jako tree - vyhodit stare nody hierarchicky
221                 // takto bych se ptal i na stare out-of-date nody!
222             }
223             //List ch = (List) childrenCache.get(o);
224         */

225     }
226     
227     /**
228      * Returns number of children for given node.
229      *
230      * @param node the parent node
231      * @throws UnknownTypeException if this TreeModel implementation is not
232      * able to resolve children for given node type
233      *
234      * @return true if node is leaf
235      */

236     public int getChildrenCount (Object JavaDoc node) throws UnknownTypeException {
237         // Performance, see issue #59058.
238
return Integer.MAX_VALUE;
239         /*
240         Object[] ch;
241         synchronized (childrenCache) {
242             ChildrenTree cht = childrenCache.get(node);
243             if (cht != null) {
244                 ch = cht.getChildren();
245             } else {
246                 ch = null;
247             }
248         }
249         if (ch == null) {
250             ch = computeChildren(node);
251             if (ch == null) {
252                 throw new UnknownTypeException (node);
253             } else {
254                 synchronized (childrenCache) {
255                     ChildrenTree cht = new ChildrenTree(node);
256                     cht.setChildren(ch);
257                     childrenCache.put(node, cht);
258                 }
259             }
260         }
261         return ch.length;
262          */

263         /*
264         try {
265             List ch;
266             if (node.equals (ROOT)) {
267                 VirtualMachine vm = debugger.getVirtualMachine ();
268                 if (vm != null)
269                     ch = vm.topLevelThreadGroups ();
270                 else
271                     ch = Collections.EMPTY_LIST;
272             } else
273             if (node instanceof ThreadGroupReference) {
274                 ThreadGroupReference tgr = (ThreadGroupReference) node;
275                 ch = new ArrayList (tgr.threadGroups ());
276                 ch.addAll(tgr.threads ());
277             } else
278             throw new UnknownTypeException (node);
279             synchronized (lastCachedLock) {
280                 lastCachedChildrenNode = node;
281                 lastCachedChildren = ch;
282             }
283             return ch.size();
284         } catch (VMDisconnectedException ex) {
285             return 0;
286         }
287          */

288     }
289     
290     public boolean isLeaf (Object JavaDoc o) throws UnknownTypeException {
291         if (o instanceof JPDAThread) return true;
292         if (o instanceof JPDAThreadGroup) return false;
293         if (o == ROOT) return false;
294         throw new UnknownTypeException (o);
295     }
296
297     public void addModelListener (ModelListener l) {
298         synchronized (listeners) {
299             listeners.add (l);
300             if (listener == null) {
301                 listener = new Listener JavaDoc (this, debugger);
302             }
303         }
304     }
305
306     public void removeModelListener (ModelListener l) {
307         synchronized (listeners) {
308             listeners.remove (l);
309             if (listeners.size () == 0) {
310                 listener.destroy ();
311                 listener = null;
312             }
313         }
314     }
315     
316     public void fireTreeChanged () {
317         recomputeChildren();
318         ModelListener[] ls;
319         synchronized (listeners) {
320             ls = listeners.toArray(new ModelListener[0]);
321         }
322         ModelEvent ev = new ModelEvent.TreeChanged(this);
323         for (int i = 0; i < ls.length; i++) {
324             ls[i].modelChanged (ev);
325         }
326     }
327
328     /**
329      * Listens on JPDADebugger state property and updates all threads hierarchy.
330      */

331     private static class Listener implements PropertyChangeListener JavaDoc {
332         
333         private JPDADebugger debugger;
334         private WeakReference JavaDoc<ThreadsTreeModel> model;
335         // currently waiting / running refresh task
336
// there is at most one
337
private RequestProcessor.Task task;
338         
339         public Listener (
340             ThreadsTreeModel tm,
341             JPDADebugger debugger
342         ) {
343             this.debugger = debugger;
344             model = new WeakReference JavaDoc<ThreadsTreeModel>(tm);
345             debugger.addPropertyChangeListener (this);
346             if (debugger.getState() == debugger.STATE_RUNNING) {
347                 task = createTask();
348                 task.schedule(500);
349             }
350         }
351         
352         private ThreadsTreeModel getModel () {
353             ThreadsTreeModel tm = model.get ();
354             if (tm == null) {
355                 destroy ();
356             }
357             return tm;
358         }
359         
360         void destroy () {
361             debugger.removePropertyChangeListener (this);
362             synchronized (this) {
363                 if (task != null) {
364                     // cancel old task
365
task.cancel ();
366                     if (verbose)
367                         System.out.println("TTM cancel old task " + task);
368                     task = null;
369                 }
370             }
371         }
372         
373         private RequestProcessor.Task createTask() {
374             RequestProcessor.Task task =
375                 new RequestProcessor("Threads Refresh", 1).create(
376                                 new RefreshTree());
377             if (verbose)
378                 System.out.println("TTM create task " + task);
379             return task;
380         }
381         
382         public void propertyChange (PropertyChangeEvent JavaDoc e) {
383             if ( (e.getPropertyName () == debugger.PROP_STATE) &&
384                  (debugger.getState () == debugger.STATE_STOPPED)
385             ) {
386                 final ThreadsTreeModel tm = getModel ();
387                 if (tm == null) return;
388                 synchronized (this) {
389                     if (task == null) {
390                         task = createTask();
391                     }
392                 }
393                 task.schedule(500);
394             } else
395             if ( (e.getPropertyName () == debugger.PROP_STATE) &&
396                  (debugger.getState () == debugger.STATE_RUNNING)
397             ) {
398                 final ThreadsTreeModel tm = getModel ();
399                 if (tm == null) return;
400                 synchronized (this) {
401                     if (task == null) {
402                         task = createTask();
403                     }
404                 }
405                 task.schedule (2000);
406             }
407         }
408         
409         private class RefreshTree implements Runnable JavaDoc {
410             public RefreshTree () {}
411             
412             public void run() {
413                 ThreadsTreeModel tm = getModel ();
414                 if (tm == null) return;
415                 if (verbose)
416                     System.out.println("TTM do R task " + task);
417                 tm.fireTreeChanged ();
418                 if (debugger.getState () == debugger.STATE_RUNNING) {
419                     task.schedule (2000);
420                 }
421             }
422         }
423     }
424     
425     private static class ChildrenTree {
426         
427         private Object JavaDoc node;
428         private Object JavaDoc[] ch;
429         
430         public ChildrenTree(Object JavaDoc node) {
431             this.node = node;
432         }
433         
434         public void setChildren(Object JavaDoc[] ch) {
435             this.ch = ch;
436         }
437         
438         public Object JavaDoc[] getChildren() {
439             return ch;
440         }
441         
442     }
443     
444 }
445
446
Popular Tags