KickJava   Java API By Example, From Geeks To Geeks.

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


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.ObjectReference;
23 import com.sun.jdi.Value;
24
25 import java.beans.PropertyChangeEvent JavaDoc;
26 import java.beans.PropertyChangeListener JavaDoc;
27 import java.beans.PropertyChangeSupport JavaDoc;
28 import java.lang.ref.WeakReference JavaDoc;
29 import java.util.*;
30 import javax.security.auth.RefreshFailedException JavaDoc;
31 import javax.security.auth.Refreshable JavaDoc;
32
33 import org.netbeans.api.debugger.Watch;
34 import org.netbeans.api.debugger.DebuggerManager;
35 import org.netbeans.api.debugger.DebuggerManagerAdapter;
36 import org.netbeans.api.debugger.jpda.InvalidExpressionException;
37 import org.netbeans.api.debugger.jpda.Variable;
38 import org.netbeans.spi.debugger.ContextProvider;
39 import org.netbeans.api.debugger.jpda.JPDADebugger;
40 import org.netbeans.api.debugger.jpda.JPDAWatch;
41 import org.netbeans.spi.viewmodel.ModelEvent;
42 import org.netbeans.spi.viewmodel.TreeModel;
43 import org.netbeans.spi.viewmodel.ModelListener;
44 import org.netbeans.spi.viewmodel.UnknownTypeException;
45
46 import org.netbeans.modules.debugger.jpda.JPDADebuggerImpl;
47 import org.netbeans.modules.debugger.jpda.expr.Expression;
48 import org.netbeans.modules.debugger.jpda.expr.ParseException;
49
50 import org.openide.util.RequestProcessor;
51
52 /**
53  * @author Jan Jancura
54  */

55 public class WatchesModel implements TreeModel {
56
57     
58     private static boolean verbose =
59         (System.getProperty ("netbeans.debugger.viewrefresh") != null) &&
60         (System.getProperty ("netbeans.debugger.viewrefresh").indexOf ('w') >= 0);
61
62     private JPDADebuggerImpl debugger;
63     private Listener JavaDoc listener;
64     private Vector<ModelListener> listeners = new Vector<ModelListener>();
65     private ContextProvider lookupProvider;
66     // Watch to Expression or Exception
67
private Map<Watch, JPDAWatchEvaluating> watchToValue = new WeakHashMap<Watch, JPDAWatchEvaluating>(); // <node (expression), JPDAWatch>
68

69     
70     public WatchesModel (ContextProvider lookupProvider) {
71         debugger = (JPDADebuggerImpl) lookupProvider.
72             lookupFirst (null, JPDADebugger.class);
73         this.lookupProvider = lookupProvider;
74     }
75     
76     /**
77      *
78      * @return threads contained in this group of threads
79      */

80     public Object JavaDoc getRoot () {
81         return ROOT;
82     }
83
84     /**
85      *
86      * @return watches contained in this group of watches
87      */

88     public Object JavaDoc[] getChildren (Object JavaDoc parent, int from, int to)
89     throws UnknownTypeException {
90         if (parent == ROOT) {
91             
92             // 1) ger Watches
93
Watch[] ws = DebuggerManager.getDebuggerManager ().
94                 getWatches ();
95             to = Math.min(ws.length, to);
96             from = Math.min(ws.length, from);
97             Watch[] fws = new Watch [to - from];
98             System.arraycopy (ws, from, fws, 0, to - from);
99             
100             // 2) create JPDAWatches for Watches
101
int i, k = fws.length;
102             JPDAWatch[] jws = new JPDAWatch [k];
103             for (i = 0; i < k; i++) {
104                 
105                 
106                 JPDAWatchEvaluating jw = watchToValue.get(fws[i]);
107                 if (jw == null) {
108                     jw = new JPDAWatchEvaluating(this, fws[i], debugger);
109                     watchToValue.put(fws[i], jw);
110                 }
111                 jws[i] = jw;
112                 
113                 // The actual expressions are computed on demand in JPDAWatchEvaluating
114
}
115             
116             if (listener == null)
117                 listener = new Listener JavaDoc (this, debugger);
118             return jws;
119         }
120         if (parent instanceof JPDAWatchImpl) {
121             return getLocalsTreeModel ().getChildren (parent, from, to);
122         }
123         return getLocalsTreeModel ().getChildren (parent, from, to);
124     }
125     
126     /**
127      * Returns number of children for given node.
128      *
129      * @param node the parent node
130      * @throws UnknownTypeException if this TreeModel implementation is not
131      * able to resolve children for given node type
132      *
133      * @return true if node is leaf
134      */

135     public int getChildrenCount (Object JavaDoc node) throws UnknownTypeException {
136         if (node == ROOT) {
137             if (listener == null)
138                 listener = new Listener JavaDoc (this, debugger);
139             // Performance, see issue #59058.
140
return Integer.MAX_VALUE;
141             //return DebuggerManager.getDebuggerManager ().getWatches ().length;
142
}
143         if (node instanceof JPDAWatchImpl) {
144             return getLocalsTreeModel ().getChildrenCount (node);
145         }
146         return getLocalsTreeModel ().getChildrenCount (node);
147     }
148     
149     public boolean isLeaf (Object JavaDoc node) throws UnknownTypeException {
150         if (node == ROOT) return false;
151         if (node instanceof JPDAWatchEvaluating) {
152             JPDAWatchEvaluating jwe = (JPDAWatchEvaluating) node;
153             JPDAWatch jw = jwe.getEvaluatedWatch();
154             if (jw instanceof JPDAWatchImpl) {
155                 return ((JPDAWatchImpl) jw).isPrimitive ();
156             }
157         }
158         return getLocalsTreeModel ().isLeaf (node);
159     }
160
161     public void addModelListener (ModelListener l) {
162         listeners.add (l);
163     }
164
165     public void removeModelListener (ModelListener l) {
166         listeners.remove (l);
167     }
168     
169     private void fireTreeChanged () {
170         synchronized (watchToValue) {
171             for (Iterator<JPDAWatchEvaluating> it = watchToValue.values().iterator(); it.hasNext(); ) {
172                 it.next().setEvaluated(null);
173             }
174         }
175         Vector v = (Vector) listeners.clone ();
176         int i, k = v.size ();
177         ModelEvent event = new ModelEvent.TreeChanged(this);
178         for (i = 0; i < k; i++)
179             ((ModelListener) v.get (i)).modelChanged (event);
180     }
181     
182     private void fireWatchesChanged () {
183         Vector v = (Vector) listeners.clone ();
184         int i, k = v.size ();
185         ModelEvent event = new ModelEvent.NodeChanged(this, ROOT, ModelEvent.NodeChanged.CHILDREN_MASK);
186         for (i = 0; i < k; i++)
187             ((ModelListener) v.get (i)).modelChanged (event);
188     }
189     
190     void fireTableValueChangedChanged (Object JavaDoc node, String JavaDoc propertyName) {
191         ((JPDAWatchEvaluating) node).setEvaluated(null);
192         fireTableValueChangedComputed(node, propertyName);
193     }
194         
195     void fireTableValueChangedComputed (Object JavaDoc node, String JavaDoc propertyName) {
196         Vector v = (Vector) listeners.clone ();
197         int i, k = v.size ();
198         for (i = 0; i < k; i++)
199             ((ModelListener) v.get (i)).modelChanged (
200                 new ModelEvent.TableValueChanged (this, node, propertyName)
201             );
202     }
203     
204     
205     // other methods ...........................................................
206

207     JPDADebuggerImpl getDebugger () {
208         return debugger;
209     }
210     
211     private LocalsTreeModel localsTreeModel;
212
213     LocalsTreeModel getLocalsTreeModel () {
214         if (localsTreeModel == null)
215             localsTreeModel = (LocalsTreeModel) lookupProvider.
216                 lookupFirst ("LocalsView", TreeModel.class);
217         return localsTreeModel;
218     }
219
220
221     // innerclasses ............................................................
222

223     private static class JPDAWatchEvaluating extends AbstractVariable
224                                              implements JPDAWatch, Variable,
225                                                         Refreshable JavaDoc, //.Lazy {
226
PropertyChangeListener JavaDoc {
227         
228         private WatchesModel model;
229         private Watch w;
230         private JPDADebuggerImpl debugger;
231         private JPDAWatch evaluatedWatch;
232         private Expression expression;
233         private ParseException parseException;
234         private boolean[] evaluating = new boolean[] { false };
235         private PropertyChangeSupport JavaDoc propSupp = new PropertyChangeSupport JavaDoc(this);
236         
237         public JPDAWatchEvaluating(WatchesModel model, Watch w, JPDADebuggerImpl debugger) {
238             super(debugger, null, "" + w);
239             this.model = model;
240             this.w = w;
241             this.debugger = debugger;
242             parseExpression(w.getExpression());
243         }
244         
245         private void parseExpression(String JavaDoc exprStr) {
246             try {
247                 expression = Expression.parse (
248                     exprStr,
249                     Expression.LANGUAGE_JAVA_1_5
250                 );
251                 parseException = null;
252             } catch (ParseException e) {
253                 setEvaluated(new JPDAWatchImpl(debugger, w, e, this));
254                 parseException = e;
255             }
256         }
257         
258         Expression getParsedExpression() throws ParseException {
259             if (parseException != null) {
260                 throw parseException;
261             }
262             return expression;
263         }
264
265         
266         public void setEvaluated(JPDAWatch evaluatedWatch) {
267             synchronized (this) {
268                 this.evaluatedWatch = evaluatedWatch;
269             }
270             if (evaluatedWatch != null) {
271                 if (evaluatedWatch instanceof JPDAWatchImpl) {
272                     setInnerValue(((JPDAWatchImpl) evaluatedWatch).getInnerValue());
273                 } else if (evaluatedWatch instanceof JPDAObjectWatchImpl) {
274                     setInnerValue(((JPDAObjectWatchImpl) evaluatedWatch).getInnerValue());
275                 }
276                 //propSupp.firePropertyChange(PROP_INITIALIZED, null, Boolean.TRUE);
277
} else {
278                 setInnerValue(null);
279             }
280             //model.fireTableValueChangedComputed(this, null);
281
}
282         
283         synchronized JPDAWatch getEvaluatedWatch() {
284             return evaluatedWatch;
285         }
286         
287         public void expressionChanged() {
288             setEvaluated(null);
289             parseExpression(w.getExpression());
290         }
291         
292         public synchronized String JavaDoc getExceptionDescription() {
293             if (evaluatedWatch != null) {
294                 return evaluatedWatch.getExceptionDescription();
295             } else {
296                 return null;
297             }
298         }
299
300         public synchronized String JavaDoc getExpression() {
301             if (evaluatedWatch != null) {
302                 return evaluatedWatch.getExpression();
303             } else {
304                 return w.getExpression();
305             }
306         }
307
308         public String JavaDoc getToStringValue() throws InvalidExpressionException {
309             synchronized (this) {
310                 JPDAWatch evaluatedWatch = this.evaluatedWatch;
311             }
312             if (evaluatedWatch == null) {
313                 getValue();
314             }
315             return evaluatedWatch.getToStringValue();
316         }
317
318         public String JavaDoc getType() {
319             synchronized (this) {
320                 JPDAWatch evaluatedWatch = this.evaluatedWatch;
321             }
322             if (evaluatedWatch == null) {
323                 getValue(); // To init the evaluatedWatch
324
}
325             return evaluatedWatch.getType();
326         }
327
328         public String JavaDoc getValue() {
329             synchronized (evaluating) {
330                 if (evaluating[0]) {
331                     try {
332                         evaluating.wait();
333                     } catch (InterruptedException JavaDoc iex) {
334                         return null;
335                     }
336                 }
337                 synchronized (this) {
338                     if (evaluatedWatch != null) {
339                         return evaluatedWatch.getValue();
340                     }
341                 }
342                 evaluating[0] = true;
343             }
344             
345             JPDAWatch jw = null;
346             try {
347                 Expression expr = getParsedExpression();
348                 Value v = debugger.evaluateIn (expr);
349                 //if (v instanceof ObjectReference)
350
// jw = new JPDAObjectWatchImpl (debugger, w, (ObjectReference) v);
351
JPDAWatchImpl jwi = new JPDAWatchImpl (debugger, w, v, this);
352                 jwi.addPropertyChangeListener(this);
353                 jw = jwi;
354             } catch (InvalidExpressionException e) {
355                 JPDAWatchImpl jwi = new JPDAWatchImpl (debugger, w, e, this);
356                 jwi.addPropertyChangeListener(this);
357                 jw = jwi;
358             } catch (ParseException e) {
359                 JPDAWatchImpl jwi = new JPDAWatchImpl (debugger, w, e, this);
360                 jwi.addPropertyChangeListener(this);
361                 jw = jwi;
362             } finally {
363                 setEvaluated(jw);
364                 synchronized (evaluating) {
365                     evaluating[0] = false;
366                     evaluating.notifyAll();
367                 }
368             }
369             //System.out.println(" value = "+jw.getValue());
370
return jw.getValue();
371         }
372
373         public synchronized void remove() {
374             if (evaluatedWatch != null) {
375                 evaluatedWatch.remove();
376             } else {
377                 w.remove ();
378             }
379         }
380
381         public void setExpression(String JavaDoc expression) {
382             w.setExpression (expression);
383             expressionChanged();
384         }
385
386         public synchronized void setValue(String JavaDoc value) throws InvalidExpressionException {
387             if (evaluatedWatch != null) {
388                 evaluatedWatch.setValue(value);
389             } else {
390                 throw new InvalidExpressionException("Can not set value while evaluating.");
391             }
392         }
393         
394         public void addPropertyChangeListener(PropertyChangeListener JavaDoc l) {
395             propSupp.addPropertyChangeListener(l);
396         }
397         
398         public void removePropertyChangeListener(PropertyChangeListener JavaDoc l) {
399             propSupp.removePropertyChangeListener(l);
400         }
401         
402         public void propertyChange(PropertyChangeEvent JavaDoc evt) {
403             model.fireTableValueChangedChanged (this, null);
404         }
405         
406         /** Does wait for the value to be evaluated. */
407         public void refresh() throws RefreshFailedException JavaDoc {
408             synchronized (evaluating) {
409                 if (evaluating[0]) {
410                     try {
411                         evaluating.wait();
412                     } catch (InterruptedException JavaDoc iex) {
413                         throw new RefreshFailedException JavaDoc(iex.getLocalizedMessage());
414                     }
415                 }
416             }
417         }
418         
419         /** Tells whether the variable is fully initialized and getValue()
420          * returns the value immediately. */

421         public synchronized boolean isCurrent() {
422             return evaluatedWatch != null;
423         }
424
425         public JPDAWatchEvaluating clone() {
426             return new JPDAWatchEvaluating(model, w, debugger);
427         }
428         
429     }
430     
431     private static class Listener extends DebuggerManagerAdapter implements
432     PropertyChangeListener JavaDoc {
433         
434         private WeakReference JavaDoc<WatchesModel> model;
435         private WeakReference JavaDoc<JPDADebuggerImpl> debugger;
436         
437         private Listener (
438             WatchesModel tm,
439             JPDADebuggerImpl debugger
440         ) {
441             model = new WeakReference JavaDoc<WatchesModel>(tm);
442             this.debugger = new WeakReference JavaDoc<JPDADebuggerImpl>(debugger);
443             DebuggerManager.getDebuggerManager ().addDebuggerListener (
444                 DebuggerManager.PROP_WATCHES,
445                 this
446             );
447             debugger.addPropertyChangeListener (this);
448             Watch[] ws = DebuggerManager.getDebuggerManager ().
449                 getWatches ();
450             int i, k = ws.length;
451             for (i = 0; i < k; i++)
452                 ws [i].addPropertyChangeListener (this);
453         }
454         
455         private WatchesModel getModel () {
456             WatchesModel m = model.get ();
457             if (m == null) destroy ();
458             return m;
459         }
460         
461         public void watchAdded (Watch watch) {
462             WatchesModel m = getModel ();
463             if (m == null) return;
464             watch.addPropertyChangeListener (this);
465             m.fireWatchesChanged ();
466         }
467         
468         public void watchRemoved (Watch watch) {
469             WatchesModel m = getModel ();
470             if (m == null) return;
471             watch.removePropertyChangeListener (this);
472             m.fireWatchesChanged ();
473         }
474         
475         // currently waiting / running refresh task
476
// there is at most one
477
private RequestProcessor.Task task;
478         
479         public void propertyChange (PropertyChangeEvent JavaDoc evt) {
480             String JavaDoc propName = evt.getPropertyName();
481             // We already have watchAdded & watchRemoved. Ignore PROP_WATCHES:
482
if (DebuggerManager.PROP_WATCHES.equals(propName)) return ;
483             final WatchesModel m = getModel ();
484             if (m == null) return;
485             if (m.debugger.getState () == JPDADebugger.STATE_DISCONNECTED) {
486                 destroy ();
487                 return;
488             }
489             if (m.debugger.getState () == JPDADebugger.STATE_RUNNING) {
490                 return ;
491             }
492             
493             if (evt.getSource () instanceof Watch) {
494                 Object JavaDoc node;
495                 synchronized (m.watchToValue) {
496                     node = m.watchToValue.get(evt.getSource());
497                 }
498                 if (node != null) {
499                     m.fireTableValueChangedChanged(node, null);
500                     return ;
501                 }
502             }
503             
504             if (task == null) {
505                 task = RequestProcessor.getDefault ().create (new Runnable JavaDoc () {
506                     public void run () {
507                         if (verbose)
508                             System.out.println("WM do task " + task);
509                         m.fireTreeChanged ();
510                     }
511                 });
512                 if (verbose)
513                     System.out.println("WM create task " + task);
514             }
515             task.schedule(100);
516         }
517         
518         private void destroy () {
519             DebuggerManager.getDebuggerManager ().removeDebuggerListener (
520                 DebuggerManager.PROP_WATCHES,
521                 this
522             );
523             JPDADebugger d = debugger.get ();
524             if (d != null)
525                 d.removePropertyChangeListener (this);
526
527             Watch[] ws = DebuggerManager.getDebuggerManager ().
528                 getWatches ();
529             int i, k = ws.length;
530             for (i = 0; i < k; i++)
531                 ws [i].removePropertyChangeListener (this);
532
533             if (task != null) {
534                 // cancel old task
535
task.cancel ();
536                 if (verbose)
537                     System.out.println("WM cancel old task " + task);
538                 task = null;
539             }
540         }
541     }
542 }
543
Popular Tags