KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > debug > core > model > JDIStackFrame


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jdt.internal.debug.core.model;
12
13  
14 import java.util.ArrayList JavaDoc;
15 import java.util.Collections JavaDoc;
16 import java.util.Comparator JavaDoc;
17 import java.util.Iterator JavaDoc;
18 import java.util.List JavaDoc;
19
20 import org.eclipse.core.runtime.IStatus;
21 import org.eclipse.core.runtime.Status;
22 import org.eclipse.debug.core.DebugEvent;
23 import org.eclipse.debug.core.DebugException;
24 import org.eclipse.debug.core.model.IRegisterGroup;
25 import org.eclipse.debug.core.model.IStackFrame;
26 import org.eclipse.debug.core.model.IThread;
27 import org.eclipse.debug.core.model.IVariable;
28 import org.eclipse.jdi.internal.ValueImpl;
29 import org.eclipse.jdi.internal.VirtualMachineImpl;
30 import org.eclipse.jdt.core.Signature;
31 import org.eclipse.jdt.debug.core.IJavaClassType;
32 import org.eclipse.jdt.debug.core.IJavaModifiers;
33 import org.eclipse.jdt.debug.core.IJavaObject;
34 import org.eclipse.jdt.debug.core.IJavaReferenceType;
35 import org.eclipse.jdt.debug.core.IJavaStackFrame;
36 import org.eclipse.jdt.debug.core.IJavaThread;
37 import org.eclipse.jdt.debug.core.IJavaValue;
38 import org.eclipse.jdt.debug.core.IJavaVariable;
39 import org.eclipse.jdt.internal.debug.core.JDIDebugPlugin;
40
41 import com.ibm.icu.text.MessageFormat;
42 import com.sun.jdi.AbsentInformationException;
43 import com.sun.jdi.ClassNotLoadedException;
44 import com.sun.jdi.ClassType;
45 import com.sun.jdi.Field;
46 import com.sun.jdi.IncompatibleThreadStateException;
47 import com.sun.jdi.InvalidTypeException;
48 import com.sun.jdi.LocalVariable;
49 import com.sun.jdi.Location;
50 import com.sun.jdi.Method;
51 import com.sun.jdi.NativeMethodException;
52 import com.sun.jdi.ObjectReference;
53 import com.sun.jdi.ReferenceType;
54 import com.sun.jdi.StackFrame;
55 import com.sun.jdi.Type;
56 import com.sun.jdi.VirtualMachine;
57
58 /**
59  * Proxy to a stack frame on the target.
60  */

61
62 public class JDIStackFrame extends JDIDebugElement implements IJavaStackFrame {
63
64     /**
65      * This frame's depth in the call stack (0 == bottom of stack).
66      * A new frame is indicated by -2.
67      * An invalid frame is indicated by -1.
68      */

69     private int fDepth = -2;
70     
71     /**
72      * Underlying JDI stack frame.
73      */

74     private StackFrame fStackFrame;
75
76     /**
77      * Containing thread.
78      */

79     private JDIThread fThread;
80     /**
81      * Visible variables.
82      */

83     private List JavaDoc fVariables;
84
85     /**
86      * The underlying Object associated with this stack frame.
87      * Cached lazily on first access.
88      */

89     private ObjectReference fThisObject;
90
91     /**
92      * The name of the type of the object that received the method call associated
93      * with this stack frame. Cached lazily on first access.
94      */

95     private String JavaDoc fReceivingTypeName;
96     /**
97      * Whether the variables need refreshing
98      */

99     private boolean fRefreshVariables= true;
100     /**
101      * Whether this stack frame has been marked as out of synch. If set
102      * to <code>true</code> this stack frame will stop dynamically
103      * calculating its out of synch state.
104      */

105     private boolean fIsOutOfSynch= false;
106     
107     /**
108      * Whether local variable information was available
109      */

110     private boolean fLocalsAvailable = true;
111     
112     /**
113      * Location of this stack frame
114      */

115     private Location fLocation;
116
117     /**
118      * Creates a new stack frame in the given thread.
119      *
120      * @param thread The parent JDI thread
121      * @param frame underlying frame
122      * @param depth depth on the stack (0 is bottom)
123      */

124     public JDIStackFrame(JDIThread thread, StackFrame frame, int depth) {
125         super((JDIDebugTarget)thread.getDebugTarget());
126         setThread(thread);
127         bind(frame, depth);
128     }
129     
130     /**
131      * Binds this frame to the given underlying frame
132      * on the target VM or returns a new frame representing the
133      * given frame. A frame can only be re-bound to an underlying frame
134      * if it refers to the same depth on the stack in the same method.
135      *
136      * @param frame underlying frame, or <code>null</code>
137      * @param depth depth in the call stack, or -1 to indicate the
138      * frame should become invalid
139      * @param return a frame to refer to the given frame or <code>null</code>
140      */

141     protected JDIStackFrame bind(StackFrame frame, int depth) {
142         synchronized (fThread) {
143             if (fDepth == -2) {
144                 // first initialization
145
fStackFrame = frame;
146                 fDepth = depth;
147                 fLocation = frame.location();
148                 return this;
149             } else if (depth == -1) {
150                 // mark as invalid
151
fDepth = -1;
152                 fStackFrame = null;
153                 return null;
154             } else if (fDepth == depth) {
155                 Location location = frame.location();
156                 Method method = location.method();
157                 if (method.equals(fLocation.method())) {
158                     try {
159                         if (method.declaringType().defaultStratum().equals("Java") || //$NON-NLS-1$
160
equals(getSourceName(location), getSourceName(fLocation))) {
161                             // TODO: what about receiving type being the same?
162
fStackFrame = frame;
163                             fLocation = location;
164                             clearCachedData();
165                             return this;
166                         }
167                     } catch (DebugException e) {
168                     }
169                 }
170             }
171             // invalidate this frame
172
bind(null, -1);
173             // return a new frame
174
return new JDIStackFrame(fThread, frame, depth);
175         }
176
177     }
178     
179     /**
180      * @see IStackFrame#getThread()
181      */

182     public IThread getThread() {
183         return fThread;
184     }
185
186     /**
187      * @see ISuspendResume#canResume()
188      */

189     public boolean canResume() {
190         return getThread().canResume();
191     }
192
193     /**
194      * @see ISuspendResume#canSuspend()
195      */

196     public boolean canSuspend() {
197         return getThread().canSuspend();
198     }
199
200     /**
201      * @see IStep#canStepInto()
202      */

203     public boolean canStepInto() {
204         try {
205             return exists() && isTopStackFrame() && !isObsolete() && getThread().canStepInto();
206         } catch (DebugException e) {
207             logError(e);
208             return false;
209         }
210     }
211
212     /**
213      * @see IStep#canStepOver()
214      */

215     public boolean canStepOver() {
216         return exists() && !isObsolete() && getThread().canStepOver();
217     }
218
219     /**
220      * @see IStep#canStepReturn()
221      */

222     public boolean canStepReturn() {
223         try {
224             if (!exists() || isObsolete() || !getThread().canStepReturn()) {
225                 return false;
226             }
227             List JavaDoc frames = ((JDIThread)getThread()).computeStackFrames();
228             if (frames != null && !frames.isEmpty()) {
229                 boolean bottomFrame = this.equals(frames.get(frames.size() - 1));
230                 boolean aboveObsoleteFrame= false;
231                 if (!bottomFrame) {
232                     int index= frames.indexOf(this);
233                     if (index < frames.size() -1 && ((JDIStackFrame)frames.get(index + 1)).isObsolete()) {
234                         aboveObsoleteFrame= true;
235                     }
236                 }
237                 return !bottomFrame && !aboveObsoleteFrame;
238             }
239         } catch (DebugException e) {
240             logError(e);
241         }
242         return false;
243     }
244
245     /**
246      * Returns the underlying method associated with this stack frame,
247      * retrieving the method is necessary.
248      */

249     public Method getUnderlyingMethod() {
250         synchronized (fThread) {
251             return fLocation.method();
252         }
253     }
254
255     /**
256      * @see IStackFrame#getVariables()
257      */

258     public IVariable[] getVariables() throws DebugException {
259         List JavaDoc list = getVariables0();
260         return (IVariable[])list.toArray(new IVariable[list.size()]);
261     }
262     
263     protected List JavaDoc getVariables0() throws DebugException {
264         synchronized (fThread) {
265             if (fVariables == null) {
266                 
267                 // throw exception if native method, so variable view will update
268
// with information message
269
if (isNative()) {
270                     requestFailed(JDIDebugModelMessages.JDIStackFrame_Variable_information_unavailable_for_native_methods, null);
271                 }
272                 
273                 Method method= getUnderlyingMethod();
274                 fVariables= new ArrayList JavaDoc();
275                 // #isStatic() does not claim to throw any exceptions - so it is not try/catch coded
276
if (method.isStatic()) {
277                     // add statics
278
List JavaDoc allFields= null;
279                     ReferenceType declaringType = method.declaringType();
280                     try {
281                         allFields= declaringType.allFields();
282                     } catch (RuntimeException JavaDoc e) {
283                         targetRequestFailed(MessageFormat.format(JDIDebugModelMessages.JDIStackFrame_exception_retrieving_fields,new String JavaDoc[] {e.toString()}), e);
284                         // execution will not reach this line, as
285
// #targetRequestFailed will throw an exception
286
return Collections.EMPTY_LIST;
287                     }
288                     if (allFields != null) {
289                         Iterator JavaDoc fields= allFields.iterator();
290                         while (fields.hasNext()) {
291                             Field field= (Field) fields.next();
292                             if (field.isStatic()) {
293                                 fVariables.add(new JDIFieldVariable((JDIDebugTarget)getDebugTarget(), field, declaringType));
294                             }
295                         }
296                         Collections.sort(fVariables, new Comparator JavaDoc() {
297                             public int compare(Object JavaDoc a, Object JavaDoc b) {
298                                 JDIFieldVariable v1= (JDIFieldVariable)a;
299                                 JDIFieldVariable v2= (JDIFieldVariable)b;
300                                 try {
301                                     return v1.getName().compareToIgnoreCase(v2.getName());
302                                 } catch (DebugException de) {
303                                     logError(de);
304                                     return -1;
305                                 }
306                             }
307                         });
308                     }
309                 } else {
310                     // add "this"
311
ObjectReference t= getUnderlyingThisObject();
312                     if (t != null) {
313                         fVariables.add(new JDIThisVariable((JDIDebugTarget)getDebugTarget(), t));
314                     }
315                 }
316                 // add locals
317
Iterator JavaDoc variables= getUnderlyingVisibleVariables().iterator();
318                 while (variables.hasNext()) {
319                     LocalVariable var= (LocalVariable) variables.next();
320                     fVariables.add(new JDILocalVariable(this, var));
321                 }
322             } else if (fRefreshVariables) {
323                 updateVariables();
324             }
325             fRefreshVariables = false;
326             return fVariables;
327         }
328     }
329
330     /**
331      * @see IStackFrame#getName()
332      */

333     public String JavaDoc getName() throws DebugException {
334         return getMethodName();
335     }
336     
337     /**
338      * @see IJavaStackFrame#getArgumentTypeNames()
339      */

340     public List JavaDoc getArgumentTypeNames() throws DebugException {
341         try {
342             Method underlyingMethod= getUnderlyingMethod();
343             String JavaDoc genericSignature= underlyingMethod.genericSignature();
344             if (genericSignature == null) {
345                 // no generic signature
346
return underlyingMethod.argumentTypeNames();
347             }
348             // generic signature
349
String JavaDoc[] parameterTypes= Signature.getParameterTypes(genericSignature);
350             List JavaDoc argumentTypeNames= new ArrayList JavaDoc();
351             for (int i= 0; i < parameterTypes.length; i++) {
352                 argumentTypeNames.add(Signature.toString(parameterTypes[i]).replace('/', '.'));
353             }
354             return argumentTypeNames;
355         } catch (RuntimeException JavaDoc e) {
356             targetRequestFailed(MessageFormat.format(JDIDebugModelMessages.JDIStackFrame_exception_retrieving_argument_type_names, new String JavaDoc[] {e.toString()}), e);
357             // execution will never reach this line, as
358
// #targetRequestFailed will throw an exception
359
return null;
360         }
361     }
362
363     /**
364      * @see IStackFrame#getLineNumber()
365      */

366     public int getLineNumber() throws DebugException {
367         synchronized (fThread) {
368             try {
369                 return fLocation.lineNumber();
370             } catch (RuntimeException JavaDoc e) {
371                 if (getThread().isSuspended()) {
372                     targetRequestFailed(MessageFormat.format(JDIDebugModelMessages.JDIStackFrame_exception_retrieving_line_number, new String JavaDoc[] {e.toString()}), e);
373                 }
374             }
375         }
376         return -1;
377     }
378
379     /**
380      * @see IStep#isStepping()
381      */

382     public boolean isStepping() {
383         return getThread().isStepping();
384     }
385
386     /**
387      * @see ISuspendResume#isSuspended()
388      */

389     public boolean isSuspended() {
390         return getThread().isSuspended();
391     }
392
393     /**
394      * @see ISuspendResume#resume()
395      */

396     public void resume() throws DebugException {
397         getThread().resume();
398     }
399
400     /**
401      * @see IStep#stepInto()
402      */

403     public void stepInto() throws DebugException {
404         if (!canStepInto()) {
405             return;
406         }
407         getThread().stepInto();
408     }
409
410     /**
411      * @see IStep#stepOver()
412      */

413     public void stepOver() throws DebugException {
414         if (!canStepOver()) {
415             return;
416         }
417         if (isTopStackFrame()) {
418             getThread().stepOver();
419         } else {
420             ((JDIThread)getThread()).stepToFrame(this);
421         }
422     }
423
424     /**
425      * @see IStep#stepReturn()
426      */

427     public void stepReturn() throws DebugException {
428         if (!canStepReturn()) {
429             return;
430         }
431         if (isTopStackFrame()) {
432             getThread().stepReturn();
433         } else {
434             List JavaDoc frames = ((JDIThread)getThread()).computeStackFrames();
435             int index = frames.indexOf(this);
436             if (index >= 0 && index < frames.size() - 1) {
437                 IStackFrame nextFrame = (IStackFrame)frames.get(index + 1);
438                 ((JDIThread)getThread()).stepToFrame(nextFrame);
439             }
440         }
441     }
442
443     /**
444      * @see ISuspendResume#suspend()
445      */

446     public void suspend() throws DebugException {
447         getThread().suspend();
448     }
449
450     /**
451      * Incrementally updates this stack frames variables.
452      *
453      * @see JDIDebugElement#targetRequestFailed(String, RuntimeException)
454      */

455     protected void updateVariables() throws DebugException {
456         if (fVariables == null) {
457             return;
458         }
459
460         Method method= getUnderlyingMethod();
461         int index= 0;
462         if (!method.isStatic()) {
463             // update "this"
464
ObjectReference thisObject;
465             try {
466                 thisObject= getUnderlyingThisObject();
467             } catch (DebugException exception) {
468                 if (!getThread().isSuspended()) {
469                     thisObject= null;
470                 } else {
471                     throw exception;
472                 }
473             }
474             JDIThisVariable oldThisObject= null;
475             if (!fVariables.isEmpty() && fVariables.get(0) instanceof JDIThisVariable) {
476                 oldThisObject= (JDIThisVariable) fVariables.get(0);
477             }
478             if (thisObject == null && oldThisObject != null) {
479                 // removal of 'this'
480
fVariables.remove(0);
481                 index= 0;
482             } else {
483                 if (oldThisObject == null && thisObject != null) {
484                     // creation of 'this'
485
oldThisObject= new JDIThisVariable((JDIDebugTarget)getDebugTarget(),thisObject);
486                     fVariables.add(0, oldThisObject);
487                     index= 1;
488                 } else {
489                     if (oldThisObject != null) {
490                         // 'this' still exists, replace with new 'this' if a different receiver
491
if (!oldThisObject.retrieveValue().equals(thisObject)) {
492                             fVariables.remove(0);
493                             fVariables.add(0, new JDIThisVariable((JDIDebugTarget)getDebugTarget(),thisObject));
494                         }
495                         index= 1;
496                     }
497                 }
498             }
499         }
500
501         List JavaDoc locals= null;
502         try {
503             locals= getUnderlyingStackFrame().visibleVariables();
504         } catch (AbsentInformationException e) {
505             locals= Collections.EMPTY_LIST;
506         } catch (NativeMethodException e) {
507             locals= Collections.EMPTY_LIST;
508         } catch (RuntimeException JavaDoc e) {
509             targetRequestFailed(MessageFormat.format(JDIDebugModelMessages.JDIStackFrame_exception_retrieving_visible_variables,new String JavaDoc[] {e.toString()}), e);
510             // execution will not reach this line, as
511
// #targetRequestFailed will throw an exception
512
return;
513         }
514         int localIndex= -1;
515         while (index < fVariables.size()) {
516             Object JavaDoc var= fVariables.get(index);
517             if (var instanceof JDILocalVariable) {
518                 JDILocalVariable local= (JDILocalVariable) fVariables.get(index);
519                 localIndex= locals.indexOf(local.getLocal());
520                 if (localIndex >= 0) {
521                     // update variable with new underling JDI LocalVariable
522
local.setLocal((LocalVariable) locals.get(localIndex));
523                     locals.remove(localIndex);
524                     index++;
525                 } else {
526                     // remove variable
527
fVariables.remove(index);
528                 }
529             } else {
530                 //field variable of a static frame
531
index++;
532             }
533         }
534
535         // add any new locals
536
Iterator JavaDoc newOnes= locals.iterator();
537         while (newOnes.hasNext()) {
538             JDILocalVariable local= new JDILocalVariable(this, (LocalVariable) newOnes.next());
539             fVariables.add(local);
540         }
541     }
542     
543     /**
544      * @see org.eclipse.debug.core.model.IDropToFrame#canDropToFrame()
545      */

546     public boolean canDropToFrame() {
547         return supportsDropToFrame();
548     }
549
550     /**
551      * @see IJavaStackFrame#supportsDropToFrame()
552      */

553     public boolean supportsDropToFrame() {
554         JDIThread thread= (JDIThread) getThread();
555         JDIDebugTarget target= (JDIDebugTarget)thread.getDebugTarget();
556         try {
557             if (!target.isAvailable() || !thread.isSuspended() || thread.isTerminated() ||
558                     thread.isInvokingMethod()) {
559                 return false;
560             }
561             boolean j9Support= false;
562             boolean jdkSupport= target.canPopFrames();
563             VirtualMachine vm = getVM();
564             if (vm == null) {
565                 return false;
566             }
567             try {
568                 j9Support= (thread.getUnderlyingThread() instanceof org.eclipse.jdi.hcr.ThreadReference) &&
569                         ((org.eclipse.jdi.hcr.VirtualMachine)vm).canDoReturn();
570             } catch (UnsupportedOperationException JavaDoc uoe) {
571                 j9Support= false;
572             }
573             
574             if (jdkSupport || j9Support) {
575                 // Also ensure that this frame and no frames above this
576
// frame are native. Unable to pop native stack frames.
577
List JavaDoc frames= thread.computeStackFrames();
578                 if (jdkSupport) {
579                     // JDK 1.4 VMs are currently unable to pop the bottom
580
// stack frame.
581
if ((frames.size() > 0) && frames.get(frames.size() - 1) == this) {
582                         return false;
583                     }
584                 }
585                 int index = 0;
586                 JDIStackFrame frame= null;
587                 while (index < frames.size()) {
588                     frame= (JDIStackFrame) frames.get(index);
589                     index++;
590                     if (frame.isNative()) {
591                         return false;
592                     }
593                     if (frame.equals(this)) {
594                         if (jdkSupport) {
595                             // JDK 1.4 VMs are currently unable to pop the
596
// frame directly above a native frame
597
if (index < frames.size() && ((JDIStackFrame)frames.get(index)).isNative()) {
598                                 return false;
599                             }
600                         }
601                         return true;
602                     }
603                 }
604             }
605             return false;
606         } catch (DebugException e) {
607             if (e.getStatus().getException() instanceof IncompatibleThreadStateException || e.getStatus().getCode() == IJavaThread.ERR_THREAD_NOT_SUSPENDED) {
608                 // if the thread has since resumed, drop is not supported
609
return false;
610             }
611             logError(e);
612         } catch (UnsupportedOperationException JavaDoc e) {
613             // drop to frame not supported - this is an expected
614
// exception for VMs that do not support drop to frame
615
return false;
616         } catch (RuntimeException JavaDoc e) {
617             internalError(e);
618         }
619         return false;
620     }
621
622     /**
623      * @see IJavaStackFrame#dropToFrame()
624      */

625     public void dropToFrame() throws DebugException {
626         if (supportsDropToFrame()) {
627             ((JDIThread) getThread()).dropToFrame(this);
628         } else {
629             notSupported(JDIDebugModelMessages.JDIStackFrame_Drop_to_frame_not_supported);
630         }
631     }
632
633     public void popFrame() throws DebugException {
634         if (supportsDropToFrame()) {
635             ((JDIThread) getThread()).popFrame(this);
636         } else {
637             notSupported(JDIDebugModelMessages.JDIStackFrame_pop_frame_not_supported);
638         }
639     }
640
641     /**
642      * @see IJavaStackFrame#findVariable(String)
643      */

644     public IJavaVariable findVariable(String JavaDoc varName) throws DebugException {
645         if (isNative()) {
646             return null;
647         }
648         IVariable[] variables = getVariables();
649         IJavaVariable thisVariable= null;
650         for (int i = 0; i < variables.length; i++) {
651             IJavaVariable var = (IJavaVariable) variables[i];
652             if (var.getName().equals(varName)) {
653                 return var;
654             }
655             if (var instanceof JDIThisVariable) {
656                 // save for later - check for instance and static variables
657
thisVariable= var;
658             }
659         }
660
661         if (thisVariable != null) {
662             IVariable[] thisChildren = thisVariable.getValue().getVariables();
663             for (int i = 0; i < thisChildren.length; i++) {
664                 IJavaVariable var= (IJavaVariable) thisChildren[i];
665                 if (var.getName().equals(varName)) {
666                     return var;
667                 }
668             }
669         }
670
671         return null;
672
673     }
674
675     /**
676      * Retrieves visible variables in this stack frame
677      * handling any exceptions. Returns an empty list if there are no
678      * variables.
679      *
680      * @see JDIDebugElement#targetRequestFailed(String, RuntimeException)
681      */

682     protected List JavaDoc getUnderlyingVisibleVariables() throws DebugException {
683         synchronized (fThread) {
684             List JavaDoc variables= Collections.EMPTY_LIST;
685             try {
686                 variables= getUnderlyingStackFrame().visibleVariables();
687             } catch (AbsentInformationException e) {
688                 setLocalsAvailable(false);
689             } catch (NativeMethodException e) {
690                 setLocalsAvailable(false);
691             } catch (RuntimeException JavaDoc e) {
692                 targetRequestFailed(MessageFormat.format(JDIDebugModelMessages.JDIStackFrame_exception_retrieving_visible_variables_2,new String JavaDoc[] {e.toString()}), e);
693             }
694             return variables;
695         }
696     }
697
698     /**
699      * Retrieves 'this' from the underlying stack frame.
700      * Returns <code>null</code> for static stack frames.
701      *
702      * @see JDIDebugElement#targetRequestFailed(String, RuntimeException)
703      */

704     protected ObjectReference getUnderlyingThisObject() throws DebugException {
705         synchronized (fThread) {
706             if ((fStackFrame == null || fThisObject == null) && !isStatic()) {
707                 try {
708                     fThisObject = getUnderlyingStackFrame().thisObject();
709                 } catch (RuntimeException JavaDoc e) {
710                     targetRequestFailed(MessageFormat.format(JDIDebugModelMessages.JDIStackFrame_exception_retrieving_this,new String JavaDoc[] {e.toString()}), e);
711                     // execution will not reach this line, as
712
// #targetRequestFailed will throw an exception
713
return null;
714                 }
715             }
716             return fThisObject;
717         }
718     }
719     
720     /**
721      * @see IAdaptable#getAdapter(Class)
722      */

723     public Object JavaDoc getAdapter(Class JavaDoc adapter) {
724         if (adapter == IJavaStackFrame.class || adapter == IJavaModifiers.class) {
725             return this;
726         }
727         return super.getAdapter(adapter);
728     }
729     
730     /**
731      * @see IJavaStackFrame#getSignature()
732      */

733     public String JavaDoc getSignature() throws DebugException {
734         try {
735             return getUnderlyingMethod().signature();
736         } catch (RuntimeException JavaDoc e) {
737             targetRequestFailed(MessageFormat.format(JDIDebugModelMessages.JDIStackFrame_exception_retrieving_method_signature, new String JavaDoc[] {e.toString()}), e);
738             // execution will not reach this line, as
739
// #targetRequestFailed will throw an exception
740
return null;
741         }
742     }
743     
744     /**
745      * @see IJavaStackFrame#getDeclaringTypeName()
746      */

747     public String JavaDoc getDeclaringTypeName() throws DebugException {
748         synchronized (fThread) {
749             try {
750                 if (isObsolete()) {
751                     return JDIDebugModelMessages.JDIStackFrame__unknown_declaring_type__1;
752                 }
753                 return JDIReferenceType.getGenericName(getUnderlyingMethod().declaringType());
754             } catch (RuntimeException JavaDoc e) {
755                 if (getThread().isSuspended()) {
756                     targetRequestFailed(MessageFormat.format(JDIDebugModelMessages.JDIStackFrame_exception_retrieving_declaring_type, new String JavaDoc[] {e.toString()}), e);
757                 }
758                 return JDIDebugModelMessages.JDIStackFrame__unknown_declaring_type__1;
759             }
760         }
761     }
762     
763     /**
764      * @see IJavaStackFrame#getReceivingTypeName()
765      */

766     public String JavaDoc getReceivingTypeName() throws DebugException {
767         if (fStackFrame == null || fReceivingTypeName == null) {
768             try {
769                 if (isObsolete()) {
770                     fReceivingTypeName=JDIDebugModelMessages.JDIStackFrame__unknown_receiving_type__2;
771                 } else {
772                     ObjectReference thisObject = getUnderlyingThisObject();
773                     if (thisObject == null) {
774                         fReceivingTypeName = getDeclaringTypeName();
775                     } else {
776                         fReceivingTypeName = JDIReferenceType.getGenericName(thisObject.referenceType());
777                     }
778                 }
779             } catch (RuntimeException JavaDoc e) {
780                 if (getThread().isSuspended()) {
781                     targetRequestFailed(MessageFormat.format(JDIDebugModelMessages.JDIStackFrame_exception_retrieving_receiving_type, new String JavaDoc[] {e.toString()}), e);
782                 }
783                 return JDIDebugModelMessages.JDIStackFrame__unknown_receiving_type__2;
784             }
785         }
786         return fReceivingTypeName;
787     }
788     
789     /**
790      * @see IJavaStackFrame#getMethodName()
791      */

792     public String JavaDoc getMethodName() throws DebugException {
793         try {
794             return getUnderlyingMethod().name();
795         } catch (RuntimeException JavaDoc e) {
796             if (getThread().isSuspended()) {
797                 targetRequestFailed(MessageFormat.format(JDIDebugModelMessages.JDIStackFrame_exception_retrieving_method_name, new String JavaDoc[] {e.toString()}), e);
798             }
799             return JDIDebugModelMessages.JDIStackFrame__unknown_method__1;
800         }
801     }
802     
803     /**
804      * @see IJavaStackFrame#isNative()
805      */

806     public boolean isNative() throws DebugException {
807         return getUnderlyingMethod().isNative();
808     }
809     
810     /**
811      * @see IJavaStackFrame#isConstructor()
812      */

813     public boolean isConstructor() throws DebugException {
814         return getUnderlyingMethod().isConstructor();
815     }
816     
817     /**
818      * @see IJavaStackFrame#isStaticInitializer()
819      */

820     public boolean isStaticInitializer() throws DebugException {
821         return getUnderlyingMethod().isStaticInitializer();
822     }
823     
824     /**
825      * @see IJavaModifiers#isFinal()
826      */

827     public boolean isFinal() throws DebugException {
828         return getUnderlyingMethod().isFinal();
829     }
830     
831     /**
832      * @see IJavaStackFrame#isSynchronized()
833      */

834     public boolean isSynchronized() throws DebugException {
835         return getUnderlyingMethod().isSynchronized();
836     }
837     
838     /**
839      * @see IJavaModifiers#isSynthetic()
840      */

841     public boolean isSynthetic() throws DebugException {
842         return getUnderlyingMethod().isSynthetic();
843     }
844     
845     /**
846      * @see IJavaModifiers#isPublic()
847      */

848     public boolean isPublic() throws DebugException {
849         return getUnderlyingMethod().isPublic();
850     }
851     
852     /**
853      * @see IJavaModifiers#isPrivate()
854      */

855     public boolean isPrivate() throws DebugException {
856         return getUnderlyingMethod().isPrivate();
857     }
858     
859     /**
860      * @see IJavaModifiers#isProtected()
861      */

862     public boolean isProtected() throws DebugException {
863         return getUnderlyingMethod().isProtected();
864     }
865     
866     /**
867      * @see IJavaModifiers#isPackagePrivate()
868      */

869     public boolean isPackagePrivate() throws DebugException {
870         return getUnderlyingMethod().isPackagePrivate();
871     }
872     
873     /**
874      * @see IJavaModifiers#isStatic()
875      */

876     public boolean isStatic() throws DebugException {
877         return getUnderlyingMethod().isStatic();
878     }
879         
880     /**
881      * @see IJavaStackFrame#getSourceName()
882      */

883     public String JavaDoc getSourceName() throws DebugException {
884         synchronized (fThread) {
885             return getSourceName(fLocation);
886         }
887     }
888     
889     /**
890      * Returns the source from the default stratum of the given location
891      * or <code>null</code> if not available (missing attribute).
892      */

893     private String JavaDoc getSourceName(Location location) throws DebugException {
894         try {
895             return location.sourceName();
896         } catch (AbsentInformationException e) {
897             return null;
898         } catch (NativeMethodException e) {
899             return null;
900         } catch (RuntimeException JavaDoc e) {
901             targetRequestFailed(MessageFormat.format(JDIDebugModelMessages.JDIStackFrame_exception_retrieving_source_name, new String JavaDoc[] {e.toString()}), e);
902         }
903         return null;
904     }
905     
906     private boolean equals(Object JavaDoc o1, Object JavaDoc o2) {
907         if (o1 == null) {
908             return o2 == null;
909         } else {
910             return o1.equals(o2);
911         }
912     }
913     
914     protected boolean isTopStackFrame() throws DebugException {
915         IStackFrame tos = getThread().getTopStackFrame();
916         return tos != null && tos.equals(this);
917     }
918     
919     /**
920      * Sets this stack frame to be out of synch.
921      * Note that passing <code>true</code> to this method
922      * marks this stack frame as out of synch permanently (statically).
923      */

924     public void setOutOfSynch(boolean outOfSynch) {
925         fIsOutOfSynch= outOfSynch;
926     }
927     
928     /**
929      * @see IJavaStackFrame#isOutOfSynch()
930      */

931     public boolean isOutOfSynch() throws DebugException {
932         if (fIsOutOfSynch) {
933             return true;
934         }
935         // if this frame's thread is not suspended, the out-of-synch info cannot
936
// change until it suspends again
937
if (getThread().isSuspended()) {
938             JDIDebugTarget target= (JDIDebugTarget)getDebugTarget();
939             if (target.hasHCROccurred() && target.isOutOfSynch(getUnderlyingMethod().declaringType().name())) {
940                 return true;
941             }
942         }
943         return false;
944     }
945     
946     /**
947      * @see IJavaStackFrame#isObsolete()
948      */

949     public boolean isObsolete() {
950         if (!JDIDebugPlugin.isJdiVersionGreaterThanOrEqual(new int[] {1,4}) || !((JDIDebugTarget)getDebugTarget()).hasHCROccurred()) {
951             // If no hot code replace has occurred, this frame
952
// cannot be obsolete.
953
return false;
954         }
955         // if this frame's thread is not suspended, the obsolete status cannot
956
// change until it suspends again
957
synchronized (fThread) {
958             if (getThread().isSuspended()) {
959                 return getUnderlyingMethod().isObsolete();
960             }
961             return false;
962         }
963     }
964     
965     protected boolean exists() {
966         synchronized (fThread) {
967             return fDepth != -1;
968         }
969     }
970     
971     /**
972      * @see ITerminate#canTerminate()
973      */

974     public boolean canTerminate() {
975         return exists() && getThread().canTerminate() || getDebugTarget().canTerminate();
976     }
977
978     /**
979      * @see ITerminate#isTerminated()
980      */

981     public boolean isTerminated() {
982         return getThread().isTerminated();
983     }
984
985     /**
986      * @see ITerminate#terminate()
987      */

988     public void terminate() throws DebugException {
989         if (getThread().canTerminate()) {
990             getThread().terminate();
991         } else {
992             getDebugTarget().terminate();
993         }
994     }
995     
996     /**
997      * Returns this stack frame's underlying JDI frame.
998      *
999      * @exception DebugException if this stack frame does
1000     * not currently have an underlying frame (is in an
1001     * interim state where this frame's thread has been
1002     * resumed, and is not yet suspended).
1003     */

1004    protected StackFrame getUnderlyingStackFrame() throws DebugException {
1005        synchronized (fThread) {
1006            if (fStackFrame == null) {
1007                if (fDepth == -1) {
1008                    throw new DebugException(new Status(IStatus.ERROR, JDIDebugPlugin.getUniqueIdentifier(), IJavaStackFrame.ERR_INVALID_STACK_FRAME, JDIDebugModelMessages.JDIStackFrame_25, null));
1009                }
1010                if (fThread.isSuspended()) {
1011                    // re-index stack frames - See Bug 47198
1012
fThread.computeStackFrames();
1013                    if (fDepth == -1) {
1014                        // If depth is -1, then this is an invalid frame
1015
throw new DebugException(new Status(IStatus.ERROR, JDIDebugPlugin.getUniqueIdentifier(), IJavaStackFrame.ERR_INVALID_STACK_FRAME, JDIDebugModelMessages.JDIStackFrame_25, null));
1016                    }
1017                } else {
1018                    throw new DebugException(new Status(IStatus.ERROR, JDIDebugPlugin.getUniqueIdentifier(), IJavaThread.ERR_THREAD_NOT_SUSPENDED, JDIDebugModelMessages.JDIStackFrame_25, null));
1019                }
1020            }
1021            return fStackFrame;
1022        }
1023    }
1024    
1025    /**
1026     * Sets the underlying JDI StackFrame. Called by a thread
1027     * when incrementally updating after a step has completed.
1028     *
1029     * @param frame The underlying stack frame
1030     */

1031    protected void setUnderlyingStackFrame(StackFrame frame) {
1032        synchronized (fThread) {
1033            fStackFrame = frame;
1034            if (frame == null) {
1035                fRefreshVariables = true;
1036            }
1037        }
1038    }
1039    
1040    protected void setThread(JDIThread thread) {
1041        fThread = thread;
1042    }
1043
1044    protected void setVariables(List JavaDoc variables) {
1045        fVariables = variables;
1046    }
1047    
1048    /**
1049     * @see IJavaStackFrame#getLocalVariables()
1050     */

1051    public IJavaVariable[] getLocalVariables() throws DebugException {
1052        List JavaDoc list = getUnderlyingVisibleVariables();
1053        IJavaVariable[] locals = new IJavaVariable[list.size()];
1054        for (int i = 0; i < list.size(); i++) {
1055            locals[i] = new JDILocalVariable(this, (LocalVariable)list.get(i));
1056        }
1057        return locals;
1058    }
1059
1060    /**
1061     * @see IJavaStackFrame#getThis()
1062     */

1063    public IJavaObject getThis() throws DebugException {
1064        IJavaObject receiver = null;
1065        if (!isStatic()) {
1066            ObjectReference thisObject = getUnderlyingThisObject();
1067            if (thisObject != null) {
1068                receiver = (IJavaObject)JDIValue.createValue((JDIDebugTarget)getDebugTarget(), thisObject);
1069            }
1070        }
1071        return receiver;
1072    }
1073
1074    /**
1075     * Java stack frames do not support registers
1076     *
1077     * @see IStackFrame#getRegisterGroups()
1078     */

1079    public IRegisterGroup[] getRegisterGroups() {
1080        return new IRegisterGroup[0];
1081    }
1082
1083    /**
1084     * @see IJavaStackFrame#getDeclaringType()
1085     */

1086    public IJavaClassType getDeclaringType() throws DebugException {
1087        Method method = getUnderlyingMethod();
1088        try {
1089            Type type = method.declaringType();
1090            if (type instanceof ClassType) {
1091                return (IJavaClassType)JDIType.createType((JDIDebugTarget)getDebugTarget(), type);
1092            }
1093            targetRequestFailed(JDIDebugModelMessages.JDIStackFrame_0, null);
1094        } catch (RuntimeException JavaDoc e) {
1095            targetRequestFailed(MessageFormat.format(JDIDebugModelMessages.JDIStackFrame_exception_retreiving_declaring_type, new String JavaDoc[] {e.toString()}), e);
1096        }
1097        return null;
1098    }
1099    
1100    /* (non-Javadoc)
1101     * @see org.eclipse.jdt.debug.core.IJavaStackFrame#getReferenceType()
1102     */

1103    public IJavaReferenceType getReferenceType() throws DebugException {
1104        Method method = getUnderlyingMethod();
1105        try {
1106            Type type = method.declaringType();
1107            return (IJavaReferenceType)JDIType.createType((JDIDebugTarget)getDebugTarget(), type);
1108        } catch (RuntimeException JavaDoc e) {
1109            targetRequestFailed(MessageFormat.format(JDIDebugModelMessages.JDIStackFrame_exception_retreiving_declaring_type, new String JavaDoc[] {e.toString()}), e);
1110        }
1111        return null;
1112    }
1113
1114    /**
1115     * Expression level stepping not supported.
1116     *
1117     * @see IStackFrame#getCharEnd()
1118     */

1119    public int getCharEnd() {
1120        return -1;
1121    }
1122
1123    /**
1124     * Expression level stepping not supported.
1125     *
1126     * @see IStackFrame#getCharStart()
1127     */

1128    public int getCharStart() {
1129        return -1;
1130    }
1131
1132    /**
1133     * Clears the cached data of this stack frame.
1134     * The underlying stack frame has changed in such a way
1135     * that the cached data may not be valid.
1136     */

1137    private void clearCachedData() {
1138        fThisObject= null;
1139        fReceivingTypeName= null;
1140    }
1141    
1142    /**
1143     * @see IJavaStackFrame#wereLocalsAvailable()
1144     */

1145    public boolean wereLocalsAvailable() {
1146        return fLocalsAvailable;
1147    }
1148    
1149    /**
1150     * Sets whether locals were available. If the setting is
1151     * not the same as the current value, a change event is
1152     * fired such that a UI client can update.
1153     *
1154     * @param available whether local variable information is
1155     * available for this stack frame.
1156     */

1157    private void setLocalsAvailable(boolean available) {
1158        if (available != fLocalsAvailable) {
1159            fLocalsAvailable = available;
1160            fireChangeEvent(DebugEvent.STATE);
1161        }
1162    }
1163    /**
1164     * @see IStackFrame#hasRegisterGroups()
1165     */

1166    public boolean hasRegisterGroups() {
1167        return false;
1168    }
1169
1170    /**
1171     * @see IStackFrame#hasVariables()
1172     */

1173    public boolean hasVariables() throws DebugException {
1174        return getVariables0().size() > 0;
1175    }
1176
1177    /**
1178     * @see org.eclipse.debug.core.model.IFilteredStep#canStepWithFilters()
1179     */

1180    public boolean canStepWithFilters() {
1181        if (canStepInto()) {
1182            String JavaDoc[] filters = getJavaDebugTarget().getStepFilters();
1183            return filters != null && filters.length > 0;
1184        }
1185        return false;
1186    }
1187
1188    /**
1189     * @see org.eclipse.debug.core.model.IFilteredStep#stepWithFilters()
1190     */

1191    public void stepWithFilters() throws DebugException {
1192        ((IJavaThread)getThread()).stepWithFilters();
1193    }
1194
1195    /**
1196     * @see org.eclipse.jdt.debug.core.IJavaStackFrame#getSourcePath(java.lang.String)
1197     */

1198    public String JavaDoc getSourcePath(String JavaDoc stratum) throws DebugException {
1199        synchronized (fThread) {
1200            try {
1201                return fLocation.sourcePath(stratum);
1202            } catch (AbsentInformationException e) {
1203            } catch (RuntimeException JavaDoc e) {
1204                targetRequestFailed(MessageFormat.format(JDIDebugModelMessages.JDIStackFrame_exception_retrieving_source_path, new String JavaDoc[] {e.toString()}), e);
1205            }
1206        }
1207        return null;
1208    }
1209    
1210    /**
1211     * @see org.eclipse.jdt.debug.core.IJavaStackFrame#getSourcePath()
1212     */

1213    public String JavaDoc getSourcePath() throws DebugException {
1214        synchronized (fThread) {
1215            try {
1216                return fLocation.sourcePath();
1217            } catch (AbsentInformationException e) {
1218            } catch (RuntimeException JavaDoc e) {
1219                targetRequestFailed(MessageFormat.format(JDIDebugModelMessages.JDIStackFrame_exception_retrieving_source_path, new String JavaDoc[] {e.toString()}), e);
1220            }
1221        }
1222        return null;
1223    }
1224
1225    /*
1226     * @see org.eclipse.jdt.debug.core.IJavaStackFrame#getLineNumber(java.lang.String)
1227     */

1228    public int getLineNumber(String JavaDoc stratum) throws DebugException {
1229        synchronized (fThread) {
1230            try {
1231                return fLocation.lineNumber(stratum);
1232            } catch (RuntimeException JavaDoc e) {
1233                if (getThread().isSuspended()) {
1234                    targetRequestFailed(MessageFormat.format(JDIDebugModelMessages.JDIStackFrame_exception_retrieving_line_number, new String JavaDoc[] {e.toString()}), e);
1235                }
1236            }
1237        }
1238        return -1;
1239    }
1240
1241    /*
1242     * @see org.eclipse.jdt.debug.core.IJavaStackFrame#getSourceName(java.lang.String)
1243     */

1244    public String JavaDoc getSourceName(String JavaDoc stratum) throws DebugException {
1245        synchronized (fThread) {
1246            try {
1247                return fLocation.sourceName(stratum);
1248            } catch (AbsentInformationException e) {
1249            } catch (NativeMethodException e) {
1250            } catch (RuntimeException JavaDoc e) {
1251                targetRequestFailed(MessageFormat.format(JDIDebugModelMessages.JDIStackFrame_exception_retrieving_source_name, new String JavaDoc[] {e.toString()}), e);
1252            }
1253        }
1254        return null;
1255    }
1256
1257    /* (non-Javadoc)
1258     * @see org.eclipse.jdt.debug.core.IJavaStackFrame#isVarargs()
1259     */

1260    public boolean isVarArgs() throws DebugException {
1261        return getUnderlyingMethod().isVarArgs();
1262    }
1263
1264    /* (non-Javadoc)
1265     * @see org.eclipse.jdt.debug.core.IJavaStackFrame#canForceReturn()
1266     */

1267    public boolean canForceReturn() {
1268        if (getJavaDebugTarget().supportsForceReturn() && isSuspended()) {
1269            try {
1270                if (!isNative()) {
1271                    if (isTopStackFrame()) {
1272                        return true;
1273                    } else {
1274                        List JavaDoc frames= fThread.computeStackFrames();
1275                        int index = frames.indexOf(this);
1276                        if (index > 0) {
1277                            JDIStackFrame prev = (JDIStackFrame) frames.get(index - 1);
1278                            return prev.canDropToFrame();
1279                        }
1280                    }
1281                }
1282            } catch (DebugException e) {
1283            }
1284        }
1285        return false;
1286    }
1287
1288    /* (non-Javadoc)
1289     * @see org.eclipse.jdt.debug.core.IJavaStackFrame#forceReturn(org.eclipse.jdt.debug.core.IJavaValue)
1290     */

1291    public void forceReturn(IJavaValue value) throws DebugException {
1292        if (isTopStackFrame()) {
1293            fThread.forceReturn(value);
1294        } else {
1295            // first check assignment compatible
1296
Method method = getUnderlyingMethod();
1297            try {
1298                ValueImpl.checkValue(((JDIValue)value).getUnderlyingValue(), method.returnType(), (VirtualMachineImpl) method.virtualMachine());
1299            } catch (InvalidTypeException e) {
1300                targetRequestFailed(JDIDebugModelMessages.JDIStackFrame_26, e);
1301            } catch (ClassNotLoadedException e) {
1302                targetRequestFailed(JDIDebugModelMessages.JDIThread_48, e);
1303            }
1304            List JavaDoc frames= fThread.computeStackFrames();
1305            int index = frames.indexOf(this);
1306            if (index > 0) {
1307                JDIStackFrame prev = (JDIStackFrame) frames.get(index - 1);
1308                fThread.popFrame(prev);
1309                fThread.forceReturn(value);
1310            }
1311        }
1312    }
1313
1314}
1315
Popular Tags