KickJava   Java API By Example, From Geeks To Geeks.

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


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 com.sun.jdi.InvalidStackFrameException;
25 import com.sun.jdi.ObjectCollectedException;
26 import com.sun.jdi.ObjectReference;
27 import com.sun.jdi.StackFrame;
28 import com.sun.jdi.ThreadGroupReference;
29 import com.sun.jdi.ThreadReference;
30 import com.sun.jdi.VMDisconnectedException;
31 import java.beans.PropertyChangeListener JavaDoc;
32 import java.beans.PropertyChangeSupport JavaDoc;
33 import java.util.ArrayList JavaDoc;
34
35 import java.util.List JavaDoc;
36
37 import org.netbeans.api.debugger.jpda.CallStackFrame;
38 import org.netbeans.api.debugger.jpda.JPDAThread;
39 import org.netbeans.api.debugger.jpda.JPDAThreadGroup;
40 import org.netbeans.api.debugger.jpda.ObjectVariable;
41 import org.netbeans.modules.debugger.jpda.JPDADebuggerImpl;
42 import org.netbeans.spi.debugger.jpda.EditorContext;
43 import org.netbeans.spi.debugger.jpda.EditorContext.Operation;
44 import org.netbeans.spi.viewmodel.UnknownTypeException;
45
46
47 /**
48  * The implementation of JPDAThread.
49  */

50 public final class JPDAThreadImpl implements JPDAThread {
51     
52     /**
53      * Suspended property of the thread. Fired when isSuspended() changes.
54      */

55     public static final String JavaDoc PROP_SUSPENDED = "suspended";
56     
57     private ThreadReference threadReference;
58     private JPDADebuggerImpl debugger;
59     private boolean suspended;
60     private int suspendCount;
61     private Operation currentOperation;
62     private List JavaDoc<Operation> lastOperations;
63     private boolean doKeepLastOperations;
64     private ReturnVariableImpl returnVariable;
65     private PropertyChangeSupport JavaDoc pch = new PropertyChangeSupport JavaDoc(this);
66     private CallStackFrame[] cachedFrames;
67     private int cachedFramesFrom = -1;
68     private int cachedFramesTo = -1;
69     private Object JavaDoc cachedFramesLock = new Object JavaDoc();
70
71     public JPDAThreadImpl (
72         ThreadReference threadReference,
73         JPDADebuggerImpl debugger
74     ) {
75         this.threadReference = threadReference;
76         this.debugger = debugger;
77         suspended = threadReference.isSuspended();
78         suspendCount = threadReference.suspendCount();
79     }
80
81     /**
82      * Getter for the name of thread property.
83      *
84      * @return name of thread.
85      */

86     public String JavaDoc getName () {
87         try {
88             return threadReference.name ();
89         } catch (ObjectCollectedException ex) {
90             return "";
91         } catch (VMDisconnectedException ex) {
92             return "";
93         }
94     }
95     
96     /**
97     * Returns parent thread group.
98     *
99     * @return parent thread group.
100     */

101     public JPDAThreadGroup getParentThreadGroup () {
102         try {
103             ThreadGroupReference tgr = threadReference.threadGroup ();
104             if (tgr == null) return null;
105             return debugger.getThreadGroup(tgr);
106         } catch (ObjectCollectedException ex) {
107             return null;
108         } catch (VMDisconnectedException ex) {
109             return null;
110         }
111     }
112
113     /**
114      * Returns line number of the location this thread stopped at.
115      * The thread should be suspended at the moment this method is called.
116      *
117      * @return line number of the current location if the thread is suspended,
118      * contains at least one frame and the topmost frame does not
119      * represent a native method invocation; <CODE>-1</CODE> otherwise
120      * @see CallStackFrame
121     */

122     public int getLineNumber (String JavaDoc stratum) {
123         try {
124             if (threadReference.frameCount () < 1) return -1;
125             return threadReference.frame (0).location ().lineNumber (stratum);
126         } catch (ObjectCollectedException ex) {
127         } catch (InvalidStackFrameException ex) {
128         } catch (IncompatibleThreadStateException ex) {
129         } catch (VMDisconnectedException ex) {
130         }
131         return -1;
132     }
133     
134     public synchronized Operation getCurrentOperation() {
135         return currentOperation;
136     }
137     
138     public synchronized void setCurrentOperation(Operation operation) { // Set the current operation for the default stratum.
139
this.currentOperation = operation;
140     }
141
142     public synchronized List JavaDoc<Operation> getLastOperations() {
143         return lastOperations;
144     }
145     
146     public synchronized void addLastOperation(Operation operation) {
147         if (lastOperations == null) {
148             lastOperations = new ArrayList JavaDoc<Operation>();
149         }
150         lastOperations.add(operation);
151     }
152     
153     public synchronized void clearLastOperations() {
154         lastOperations = null;
155     }
156     
157     public synchronized void keepLastOperationsUponResume() {
158         doKeepLastOperations = true;
159     }
160
161
162     /**
163      * Returns current state of this thread.
164      *
165      * @return current state of this thread
166      */

167     public int getState () {
168         try {
169             return threadReference.status ();
170         } catch (ObjectCollectedException ex) {
171         } catch (VMDisconnectedException ex) {
172         }
173         return STATE_UNKNOWN;
174     }
175     
176     /**
177      * Returns true if this thread is suspended by debugger.
178      *
179      * @return true if this thread is suspended by debugger
180      */

181     public synchronized boolean isSuspended () {
182         return suspended;
183     }
184     
185     /**
186      * Returns true if this thread is suspended by debugger.
187      *
188      * @return true if this thread is suspended by debugger
189      */

190     public boolean isThreadSuspended () {
191         try {
192             return threadReference.isSuspended ();
193         } catch (ObjectCollectedException ex) {
194         } catch (VMDisconnectedException ex) {
195         }
196         return false;
197     }
198
199     /**
200     * If this thread is suspended returns class name where this thread is stopped.
201     *
202     * @return class name where this thread is stopped.
203     */

204     public String JavaDoc getClassName () {
205         try {
206             if (threadReference.frameCount () < 1) return "";
207             return threadReference.frame (0).location ().declaringType ().name ();
208         } catch (ObjectCollectedException ex) {
209         } catch (InvalidStackFrameException ex) {
210         } catch (IncompatibleThreadStateException ex) {
211         } catch (VMDisconnectedException ex) {
212         }
213         return "";
214     }
215
216     /**
217     * If this thread is suspended returns method name where this thread is stopped.
218     *
219     * @return method name where this thread is stopped.
220     */

221     public String JavaDoc getMethodName () {
222         try {
223             if (threadReference.frameCount () < 1) return "";
224             return threadReference.frame (0).location ().method ().name ();
225         } catch (ObjectCollectedException ex) {
226         } catch (InvalidStackFrameException ex) {
227         } catch (IncompatibleThreadStateException ex) {
228         } catch (VMDisconnectedException ex) {
229         }
230         return "";
231     }
232     
233     /**
234     * Returns name of file of this frame or null if thread has no frame.
235     *
236     * @return Returns name of file of this frame.
237     */

238     public String JavaDoc getSourceName (String JavaDoc stratum) throws AbsentInformationException {
239         try {
240             if (threadReference.frameCount () < 1) return "";
241             return threadReference.frame (0).location ().sourceName (stratum);
242         } catch (ObjectCollectedException ex) {
243         } catch (InvalidStackFrameException ex) {
244         } catch (IncompatibleThreadStateException ex) {
245         } catch (VMDisconnectedException ex) {
246         }
247         return "";
248     }
249     
250     /**
251     * Returns name of file of this frame or null if thread has no frame.
252     *
253     * @return Returns name of file of this frame.
254     */

255     public String JavaDoc getSourcePath (String JavaDoc stratum)
256     throws AbsentInformationException {
257         try {
258             if (threadReference.frameCount () < 1) return "";
259             return threadReference.frame (0).location ().sourcePath (stratum);
260         } catch (ObjectCollectedException ex) {
261         } catch (InvalidStackFrameException ex) {
262         } catch (IncompatibleThreadStateException ex) {
263         } catch (VMDisconnectedException ex) {
264         }
265         return "";
266     }
267     
268     /**
269      * Returns call stack for this thread.
270      *
271      * @throws AbsentInformationException if the thread is running or not able
272      * to return callstack. If the thread is in an incompatible state
273      * (e.g. running), the AbsentInformationException has
274      * IncompatibleThreadStateException as a cause.
275      * If the thread is collected, the AbsentInformationException has
276      * ObjectCollectedException as a cause.
277      * @return call stack
278      */

279     public CallStackFrame[] getCallStack () throws AbsentInformationException {
280         return getCallStack (0, getStackDepth ());
281     }
282     
283     private Object JavaDoc lastBottomSF;
284     
285     /**
286      * Returns call stack for this thread on the given indexes.
287      *
288      * @param from a from index, inclusive
289      * @param to a to index, exclusive
290      * @throws AbsentInformationException if the thread is running or not able
291      * to return callstack. If the thread is in an incompatible state
292      * (e.g. running), the AbsentInformationException has
293      * IncompatibleThreadStateException as a cause.
294      * If the thread is collected, the AbsentInformationException has
295      * ObjectCollectedException as a cause.
296      * @return call stack
297      */

298     public CallStackFrame[] getCallStack (int from, int to)
299     throws AbsentInformationException {
300         try {
301             int max = threadReference.frameCount();
302             from = Math.min(from, max);
303             to = Math.min(to, max);
304             if (to - from > 1) {
305                 synchronized (cachedFramesLock) {
306                     if (from == cachedFramesFrom && to == cachedFramesTo) {
307                         return cachedFrames;
308                     }
309                 }
310             }
311             List JavaDoc l = threadReference.frames (from, to - from);
312             int n = l.size();
313             CallStackFrame[] frames = new CallStackFrame[n];
314             for (int i = 0; i < n; i++) {
315                 frames[i] = new CallStackFrameImpl((StackFrame) l.get(i), from + i, debugger);
316                 if (from == 0 && i == 0 && currentOperation != null) {
317                     ((CallStackFrameImpl) frames[i]).setCurrentOperation(currentOperation);
318                 }
319             }
320             if (to - from > 1) {
321                 synchronized (cachedFramesLock) {
322                     cachedFrames = frames;
323                     cachedFramesFrom = from;
324                     cachedFramesTo = to;
325                 }
326             }
327             return frames;
328         } catch (IncompatibleThreadStateException ex) {
329             AbsentInformationException aiex = new AbsentInformationException(ex.getLocalizedMessage());
330             aiex.initCause(ex);
331             throw aiex;
332         } catch (ObjectCollectedException ocex) {
333             AbsentInformationException aiex = new AbsentInformationException(ocex.getLocalizedMessage());
334             aiex.initCause(ocex);
335             throw aiex;
336         } catch (VMDisconnectedException ex) {
337             return new CallStackFrame [0];
338         }
339     }
340     
341     private void cleanCachedFrames() {
342         synchronized (cachedFramesLock) {
343             cachedFrames = null;
344             cachedFramesFrom = -1;
345             cachedFramesTo = -1;
346         }
347     }
348     
349     /**
350      * Returns length of current call stack.
351      *
352      * @return length of current call stack
353      */

354     public int getStackDepth () {
355         try {
356             return threadReference.frameCount ();
357         } catch (ObjectCollectedException ex) {
358         } catch (IncompatibleThreadStateException e) {
359         }
360         return 0;
361     }
362     
363     public void popFrames(StackFrame sf) throws IncompatibleThreadStateException {
364         threadReference.popFrames(sf);
365         cleanCachedFrames();
366         setReturnVariable(null); // Clear the return var
367
}
368     
369     /**
370      * Suspends thread.
371      */

372     public void suspend () {
373         Boolean JavaDoc suspendedToFire = null;
374         synchronized (this) {
375             try {
376                 if (!isSuspended ()) {
377                     threadReference.suspend ();
378                     suspendedToFire = Boolean.TRUE;
379                     suspendCount++;
380                 }
381                 suspended = true;
382             } catch (ObjectCollectedException ex) {
383             } catch (VMDisconnectedException ex) {
384             }
385         }
386         if (suspendedToFire != null) {
387             pch.firePropertyChange(PROP_SUSPENDED,
388                     Boolean.valueOf(!suspendedToFire.booleanValue()),
389                     suspendedToFire);
390         }
391     }
392     
393     /**
394      * Unsuspends thread.
395      */

396     public void resume () {
397         if (this == debugger.getCurrentThread()) {
398             boolean can = debugger.currentThreadToBeResumed();
399             if (!can) return ;
400         }
401         Boolean JavaDoc suspendedToFire = null;
402         synchronized (this) {
403             setReturnVariable(null); // Clear the return var on resume
404
setCurrentOperation(null);
405             if (doKeepLastOperations) {
406                 doKeepLastOperations = false;
407             } else {
408                 clearLastOperations();
409             }
410             try {
411                 if (isSuspended ()) {
412                     int count = threadReference.suspendCount ();
413                     while (count > 0) {
414                         threadReference.resume (); count--;
415                     }
416                     suspendedToFire = Boolean.FALSE;
417                 }
418                 suspendCount = 0;
419                 suspended = false;
420             } catch (ObjectCollectedException ex) {
421             } catch (VMDisconnectedException ex) {
422             }
423         }
424         cleanCachedFrames();
425         if (suspendedToFire != null) {
426             pch.firePropertyChange(PROP_SUSPENDED,
427                     Boolean.valueOf(!suspendedToFire.booleanValue()),
428                     suspendedToFire);
429         }
430     }
431     
432     public void notifyToBeResumed() {
433         notifyToBeRunning(true, true);
434     }
435     
436     private void notifyToBeRunning(boolean clearVars, boolean resumed) {
437         Boolean JavaDoc suspendedToFire = null;
438         synchronized (this) {
439             if (resumed && (--suspendCount > 0)) return ;
440             suspendCount = 0;
441             if (clearVars) {
442                 setCurrentOperation(null);
443                 setReturnVariable(null); // Clear the return var on resume
444
if (doKeepLastOperations) {
445                     doKeepLastOperations = false;
446                 } else {
447                     clearLastOperations();
448                 }
449             }
450             if (suspended) {
451                 suspended = false;
452                 suspendedToFire = Boolean.FALSE;
453             }
454         }
455         cleanCachedFrames();
456         if (suspendedToFire != null) {
457             pch.firePropertyChange(PROP_SUSPENDED,
458                     Boolean.valueOf(!suspendedToFire.booleanValue()),
459                     suspendedToFire);
460         }
461     }
462     
463     public void notifySuspended() {
464         Boolean JavaDoc suspendedToFire = null;
465         synchronized (this) {
466             suspendCount = threadReference.suspendCount();
467             if (!suspended && isThreadSuspended()) {
468                 suspended = true;
469                 suspendedToFire = Boolean.TRUE;
470             }
471         }
472         if (suspendedToFire != null) {
473             pch.firePropertyChange(PROP_SUSPENDED,
474                     Boolean.valueOf(!suspendedToFire.booleanValue()),
475                     suspendedToFire);
476         }
477     }
478     
479     public void notifyMethodInvoking() {
480         notifyToBeRunning(false, false);
481     }
482     
483     public void notifyMethodInvokeDone() {
484         notifySuspended();
485     }
486     
487     public void interrupt() {
488         try {
489             if (isSuspended ()) return;
490             threadReference.interrupt();
491         } catch (ObjectCollectedException ex) {
492         } catch (VMDisconnectedException ex) {
493         }
494     }
495     
496     /**
497      * Sets this thread current.
498      *
499      * @see JPDADebugger#getCurrentThread
500      */

501     public void makeCurrent () {
502         debugger.setCurrentThread (this);
503     }
504     
505     /**
506      * Returns monitor this thread is waiting on.
507      *
508      * @return monitor this thread is waiting on
509      */

510     public ObjectVariable getContendedMonitor () {
511         try {
512             ObjectReference or;
513             synchronized (this) {
514                 if (!isSuspended()) return null;
515                 if ("DestroyJavaVM".equals(threadReference.name())) {
516                     // See defect #6474293
517
return null;
518                 }
519                 or = threadReference.currentContendedMonitor ();
520             }
521             if (or == null) return null;
522             return new ThisVariable (debugger, or, "");
523         } catch (ObjectCollectedException ex) {
524         } catch (IncompatibleThreadStateException e) {
525         } catch (UnsupportedOperationException JavaDoc e) {
526             // if JVM deos not support this feature - not a problem
527
}
528         return null;
529     }
530     
531     /**
532      * Returns monitors owned by this thread.
533      *
534      * @return monitors owned by this thread
535      */

536     public ObjectVariable[] getOwnedMonitors () {
537         try {
538             List JavaDoc l;
539             synchronized (this) {
540                 if (!isSuspended()) return new ObjectVariable [0];
541                 if ("DestroyJavaVM".equals(threadReference.name())) {
542                     // See defect #6474293
543
return new ObjectVariable[0];
544                 }
545                 l = threadReference.ownedMonitors ();
546             }
547             int i, k = l.size ();
548             ObjectVariable[] vs = new ObjectVariable [k];
549             for (i = 0; i < k; i++) {
550                 vs [i] = new ThisVariable (debugger, (ObjectReference) l.get (i), "");
551             }
552             return vs;
553         } catch (ObjectCollectedException ex) {
554         } catch (IncompatibleThreadStateException e) {
555         } catch (UnsupportedOperationException JavaDoc e) {
556         }
557         return new ObjectVariable [0];
558     }
559     
560     public ThreadReference getThreadReference () {
561         return threadReference;
562     }
563     
564     public synchronized ReturnVariableImpl getReturnVariable() {
565         return returnVariable;
566     }
567     
568     public synchronized void setReturnVariable(ReturnVariableImpl returnVariable) {
569         this.returnVariable = returnVariable;
570     }
571     
572     public void addPropertyChangeListener(PropertyChangeListener JavaDoc l) {
573         pch.addPropertyChangeListener(l);
574     }
575     
576     public void removePropertyChangeListener(PropertyChangeListener JavaDoc l) {
577         pch.removePropertyChangeListener(l);
578     }
579     
580     private void fireSuspended(boolean suspended) {
581         pch.firePropertyChange(PROP_SUSPENDED,
582                 Boolean.valueOf(!suspended), Boolean.valueOf(suspended));
583     }
584
585 }
586
Popular Tags