KickJava   Java API By Example, From Geeks To Geeks.

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


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.ArrayType;
23 import com.sun.jdi.ClassLoaderReference;
24 import com.sun.jdi.ObjectCollectedException;
25 import com.sun.jdi.ReferenceType;
26 import com.sun.jdi.VMDisconnectedException;
27 import com.sun.jdi.VirtualMachine;
28
29 import java.beans.PropertyChangeEvent JavaDoc;
30 import java.beans.PropertyChangeListener JavaDoc;
31 import java.lang.ref.WeakReference JavaDoc;
32 import java.util.ArrayList JavaDoc;
33 import java.util.Comparator JavaDoc;
34 import java.util.HashMap JavaDoc;
35 import java.util.List JavaDoc;
36 import java.util.Set JavaDoc;
37 import java.util.TreeSet JavaDoc;
38 import java.util.Vector JavaDoc;
39 import org.netbeans.api.debugger.Properties;
40
41 import org.netbeans.spi.debugger.ContextProvider;
42 import org.netbeans.api.debugger.jpda.JPDADebugger;
43 import org.netbeans.spi.viewmodel.TreeModel;
44 import org.netbeans.spi.viewmodel.ModelListener;
45 import org.netbeans.spi.viewmodel.UnknownTypeException;
46
47 import org.netbeans.modules.debugger.jpda.JPDADebuggerImpl;
48
49 import org.openide.util.RequestProcessor;
50
51
52 /**
53  * @author Jan Jancura
54  */

55 public class ClassesTreeModel implements TreeModel {
56
57     
58     private static boolean verbose =
59         (System.getProperty ("netbeans.debugger.viewrefresh") != null) &&
60         (System.getProperty ("netbeans.debugger.viewrefresh").indexOf ('s') >= 0);
61     
62     private Properties classesProperties = Properties.getDefault().
63             getProperties("debugger").getProperties("classesView"); // NOI18N
64

65     
66     private JPDADebuggerImpl debugger;
67     private Listener JavaDoc listener;
68     private Vector JavaDoc<ModelListener> listeners = new Vector JavaDoc<ModelListener>();
69     
70     
71     public ClassesTreeModel(ContextProvider lookupProvider) {
72         debugger = (JPDADebuggerImpl) lookupProvider.
73             lookupFirst (null, JPDADebugger.class);
74     }
75     
76     public Object JavaDoc getRoot () {
77         return ROOT;
78     }
79     
80     public Object JavaDoc[] getChildren (Object JavaDoc o, int from, int to)
81     throws UnknownTypeException {
82         try {
83             Object JavaDoc[] r = null;
84             if (o.equals (ROOT)) {
85                 r = getLoaders ();
86             } else
87             if (o instanceof Object JavaDoc[]) {
88                 r = getChildren ((Object JavaDoc[]) o);
89             } else
90             if (o instanceof ClassLoaderReference) {
91                 r = getPackages ((ClassLoaderReference) o);
92             } else
93             if (o == NULL_CLASS_LOADER) {
94                 r = getPackages (null);
95             } else
96             if (o instanceof ReferenceType) {
97                 r = ((ReferenceType) o).nestedTypes ().toArray ();
98             } else
99             throw new UnknownTypeException (o);
100             to = Math.min(r.length, to);
101             from = Math.min(r.length, from);
102             Object JavaDoc[] rr = new Object JavaDoc [to - from];
103             System.arraycopy (r, from, rr, 0, to - from);
104             return rr;
105         } catch (VMDisconnectedException ex) {
106             return new Object JavaDoc [0];
107         }
108     }
109     
110     /**
111      * Returns number of children for given node.
112      *
113      * @param node the parent node
114      * @throws UnknownTypeException if this TreeModel implementation is not
115      * able to resolve children for given node type
116      *
117      * @return true if node is leaf
118      */

119     public int getChildrenCount (Object JavaDoc node) throws UnknownTypeException {
120         try {
121             if (node.equals (ROOT))
122                 // Performance, see issue #59058.
123
return Integer.MAX_VALUE;
124                 //return getLoaders ().length;
125
if (node instanceof Object JavaDoc[])
126                 // Performance, see issue #59058.
127
return Integer.MAX_VALUE;
128                 //return getChildren ((Object[]) node).length;
129
if (node instanceof ClassLoaderReference)
130                 // Performance, see issue #59058.
131
return Integer.MAX_VALUE;
132                 //return getPackages ((ClassLoaderReference) node).length;
133
if (node == NULL_CLASS_LOADER)
134                 // Performance, see issue #59058.
135
return Integer.MAX_VALUE;
136                 //return getPackages (null).length;
137
if (node instanceof ReferenceType) {
138                 // Performance, see issue #59058.
139
return Integer.MAX_VALUE;
140                 //return ((ReferenceType) node).nestedTypes ().size ();
141
}
142             throw new UnknownTypeException (node);
143         } catch (VMDisconnectedException ex) {
144             return 0;
145         }
146     }
147     
148     public boolean isLeaf (Object JavaDoc o) throws UnknownTypeException {
149         if (o.equals (ROOT)) return false;
150         if (o instanceof Object JavaDoc[]) return false;
151         if (o instanceof ReferenceType) return false;
152         if (o instanceof ClassLoaderReference) return false;
153         if (o == NULL_CLASS_LOADER) return false;
154         throw new UnknownTypeException (o);
155     }
156
157     public void addModelListener (ModelListener l) {
158         listeners.add (l);
159         if (listener == null)
160             listener = new Listener JavaDoc (this, debugger);
161     }
162
163     public void removeModelListener (ModelListener l) {
164         listeners.remove (l);
165         if (listeners.size () == 0) {
166             listener.destroy ();
167             listener = null;
168         }
169     }
170     
171     public void fireTreeChanged () {
172         classes = null;
173         names = null;
174         cache = new HashMap JavaDoc ();
175         Vector JavaDoc v = (Vector JavaDoc) listeners.clone ();
176         int i, k = v.size ();
177         for (i = 0; i < k; i++)
178             ((ModelListener) v.get (i)).modelChanged (null);
179     }
180
181     
182     // private methods .........................................................
183

184     private List JavaDoc<ReferenceType> classes = null; // name of class -> ReferenceType
185
private List JavaDoc<String JavaDoc> names = null; // list on names of all clases
186
private HashMap JavaDoc cache = new HashMap JavaDoc ();
187         // null => list of class loaders
188
// ClassLoaderReference -> list of packages & ReferenceTypes
189
// package name -> list of packages & ReferenceTypes
190
private Comparator JavaDoc comparator = new PackageComparator ();
191     private Comparator JavaDoc comparator1 = new ClassLoaderComparator ();
192     static final Integer JavaDoc NULL_CLASS_LOADER = new Integer JavaDoc (11);
193     
194     
195     private List JavaDoc<String JavaDoc> getNames () {
196         if (classes == null) {
197         VirtualMachine vm = debugger.getVirtualMachine ();
198             List JavaDoc referenceTypes = new ArrayList JavaDoc ();
199             if (vm != null)
200                 referenceTypes = vm.allClasses ();
201             int i, k = referenceTypes.size ();
202             names = new ArrayList JavaDoc<String JavaDoc>();
203             classes = new ArrayList JavaDoc<ReferenceType>();
204             for (i = 0; i < k; i++) {
205                 ReferenceType rt = (ReferenceType) referenceTypes.get (i);
206                 if (rt instanceof ArrayType) continue;
207                 names.add (rt.name ());
208                 classes.add (rt);
209             }
210         }
211         return names;
212     }
213     
214     private Object JavaDoc[] getLoaders () {
215         Object JavaDoc[] ch = (Object JavaDoc[]) cache.get (null);
216         if (ch != null) return ch;
217         List JavaDoc<String JavaDoc> names = getNames ();
218         Set JavaDoc loaders = new TreeSet JavaDoc (comparator1);
219         int i, k = names.size ();
220         for (i = 0; i < k; i++) {
221             try {
222             String JavaDoc name = names.get (i);
223             ReferenceType rt = classes.get (i);
224             ClassLoaderReference clr = rt.classLoader ();
225             if (clr == null)
226                 loaders.add (NULL_CLASS_LOADER);
227             else
228             if (clr.referenceType ().name ().equals ("sun.reflect.DelegatingClassLoader"))
229                 continue;
230             else
231                 loaders.add (clr);
232             } catch (ObjectCollectedException ex) {
233             }
234         }
235         ch = loaders.toArray ();
236         cache.put (null, ch);
237         return ch;
238     }
239     
240     private Object JavaDoc[] getPackages (ClassLoaderReference clr) {
241         Object JavaDoc[] ch = clr == null ?
242             (Object JavaDoc[]) cache.get (NULL_CLASS_LOADER) :
243             (Object JavaDoc[]) cache.get (clr);
244         if (ch != null) return ch;
245         boolean flat = classesProperties.getBoolean("flat", true);
246         List JavaDoc<String JavaDoc> names = getNames ();
247         Set JavaDoc objects = new TreeSet JavaDoc (comparator);
248         int i, k = names.size ();
249         for (i = 0; i < k; i++) {
250             String JavaDoc name = names.get (i);
251             ReferenceType rt = classes.get (i);
252             if (rt.classLoader () != clr) continue;
253             int end;
254             if (flat) {
255                 end = name.lastIndexOf ('.');
256             } else {
257                 end = name.indexOf ('.');
258             }
259             if (end < 0) {
260                 // ReferenceType found
261
if (name.indexOf ('$') < 0) {
262                     ReferenceType tr = classes.get (i);
263                     objects.add (tr);
264                 }
265             } else
266                 objects.add (new Object JavaDoc[] {name.substring (0, end), clr});
267         }
268         ch = objects.toArray ();
269         if (clr == null)
270             cache.put (NULL_CLASS_LOADER, ch);
271         else
272             cache.put (clr, ch);
273         return ch;
274     }
275     
276     private Object JavaDoc[] getChildren (Object JavaDoc[] parent) {
277         Object JavaDoc[] ch = (Object JavaDoc[]) cache.get (parent);
278         if (ch != null) return ch;
279         List JavaDoc<String JavaDoc> names = getNames ();
280         Set JavaDoc objects = new TreeSet JavaDoc (comparator);
281         int i, k = names.size ();
282         boolean flat = classesProperties.getBoolean("flat", true);
283         for (i = 0; i < k; i++) {
284             String JavaDoc name = names.get (i);
285             ReferenceType rt = classes.get (i);
286             if (rt.classLoader () != parent [1]) continue;
287             String JavaDoc parentN = ((String JavaDoc) parent [0]) + '.';
288             if (!name.startsWith (parentN)) continue;
289             int start = (parentN).length ();
290             int end = name.indexOf ('.', start);
291             if (end < 0) {
292                 // ReferenceType found
293
if (name.indexOf ('$', start) < 0) {
294                     objects.add (rt);
295                 }
296             } else if (!flat) {
297                 objects.add (new Object JavaDoc[] {name.substring (0, end), rt.classLoader ()});
298             }
299         }
300         ch = objects.toArray ();
301         cache.put (parent, ch);
302         return ch;
303     }
304     
305     JPDADebuggerImpl getDebugger () {
306         return debugger;
307     }
308     
309     private static String JavaDoc shortName (String JavaDoc name) {
310         int i = name.lastIndexOf ('.');
311         if (i < 0) return name;
312         return name.substring (i + 1);
313     }
314     
315     
316     // innerclasses ............................................................
317

318     private static class Listener implements PropertyChangeListener JavaDoc {
319         
320         private JPDADebugger debugger;
321         private WeakReference JavaDoc<ClassesTreeModel> model;
322         
323         public Listener (
324             ClassesTreeModel tm,
325             JPDADebugger debugger
326         ) {
327             this.debugger = debugger;
328             model = new WeakReference JavaDoc<ClassesTreeModel>(tm);
329             debugger.addPropertyChangeListener (this);
330         }
331         
332         void destroy () {
333             debugger.removePropertyChangeListener (this);
334             if (task != null) {
335                 // cancel old task
336
task.cancel ();
337                 if (verbose)
338                     System.out.println ("ClTM cancel old task " + task);
339                 task = null;
340             }
341         }
342         
343         private ClassesTreeModel getModel () {
344             ClassesTreeModel tm = model.get ();
345             if (tm == null) {
346                 destroy ();
347             }
348             return tm;
349         }
350         
351         // currently waiting / running refresh task
352
// there is at most one
353
private RequestProcessor.Task task;
354         
355         public void propertyChange (PropertyChangeEvent JavaDoc e) {
356             if ( ( (e.getPropertyName () ==
357                      debugger.PROP_CURRENT_CALL_STACK_FRAME) ||
358                    //(e.getPropertyName () == debugger.PROP_CURRENT_THREAD) ||
359
(e.getPropertyName () == debugger.PROP_STATE)
360                  ) && (debugger.getState () == debugger.STATE_STOPPED)
361             ) {
362                 // IF state has been changed to STOPPED or
363
// IF current call stack frame has been changed & state is stoped
364
final ClassesTreeModel ltm = getModel ();
365                 if (ltm == null) return;
366                 if (task != null) {
367                     // cancel old task
368
task.cancel ();
369                     if (verbose)
370                         System.out.println ("ClTM cancel old task " + task);
371                     task = null;
372                 }
373                 task = RequestProcessor.getDefault ().post (new Runnable JavaDoc () {
374                     public void run () {
375                         if (debugger.getState () != debugger.STATE_STOPPED) {
376                             if (verbose)
377                                 System.out.println ("ClTM cancel started task " + task);
378                             return;
379                         }
380                         if (verbose)
381                             System.out.println ("ClTM do task " + task);
382                         ltm.fireTreeChanged ();
383                     }
384                 }, 500);
385                 if (verbose)
386                     System.out.println ("ClTM create task " + task);
387             } else
388             if ( (e.getPropertyName () == debugger.PROP_STATE) &&
389                  (debugger.getState () != debugger.STATE_STOPPED) &&
390                  (task != null)
391             ) {
392                 // debugger has been resumed
393
// =>> cancel task
394
task.cancel ();
395                 if (verbose)
396                     System.out.println ("ClTM cancel task " + task);
397                 task = null;
398             }
399         }
400     }
401     
402     private static class PackageComparator implements Comparator JavaDoc {
403         public PackageComparator () {}
404         
405         public int compare (Object JavaDoc o1, Object JavaDoc o2) {
406             if (o1 instanceof Object JavaDoc[]) {
407                 if (o2 instanceof Object JavaDoc[])
408                     return ((String JavaDoc) ((Object JavaDoc[]) o1) [0]).compareTo ((String JavaDoc) ((Object JavaDoc[]) o2) [0]);
409                 return -1;
410             }
411             if (o2 instanceof Object JavaDoc[])
412                 return 1;
413             return shortName (((ReferenceType) o1).name ()).compareTo (
414                 shortName (((ReferenceType) o2).name ())
415             );
416         }
417     }
418     
419     private static class ClassLoaderComparator implements Comparator JavaDoc {
420         public ClassLoaderComparator () {}
421         
422         public int compare (Object JavaDoc o1, Object JavaDoc o2) {
423             if (o1 == NULL_CLASS_LOADER) {
424                 if (o2 == NULL_CLASS_LOADER)
425                     return 0;
426                 return -1;
427             }
428             if (o2 == NULL_CLASS_LOADER)
429                 return 1;
430             return ((ClassLoaderReference) o1).toString ().compareTo (
431                 ((ClassLoaderReference) o2).toString ()
432             );
433         }
434     }
435 }
436
Popular Tags