KickJava   Java API By Example, From Geeks To Geeks.

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


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 import java.util.ArrayList JavaDoc;
14 import java.util.Collections JavaDoc;
15 import java.util.Iterator JavaDoc;
16 import java.util.List JavaDoc;
17
18 import org.eclipse.debug.core.DebugException;
19 import org.eclipse.jdt.debug.core.IJavaFieldVariable;
20 import org.eclipse.jdt.debug.core.IJavaObject;
21 import org.eclipse.jdt.debug.core.IJavaThread;
22 import org.eclipse.jdt.debug.core.IJavaValue;
23
24 import com.ibm.icu.text.MessageFormat;
25 import com.sun.jdi.ArrayType;
26 import com.sun.jdi.ClassType;
27 import com.sun.jdi.Field;
28 import com.sun.jdi.IncompatibleThreadStateException;
29 import com.sun.jdi.Method;
30 import com.sun.jdi.ObjectReference;
31 import com.sun.jdi.ReferenceType;
32 import com.sun.jdi.ThreadReference;
33 import com.sun.jdi.VMDisconnectedException;
34 import com.sun.jdi.Value;
35
36 /**
37  * Implementation of a value referencing an object on the
38  * target VM.
39  */

40 public class JDIObjectValue extends JDIValue implements IJavaObject {
41     
42     private IJavaObject[] fCachedReferences;
43     private int fSuspendCount;
44     private long fPreviousMax;
45     
46     /**
47      * Constructs a new target object on the given target with
48      * the specified object reference.
49      */

50     public JDIObjectValue(JDIDebugTarget target, ObjectReference object) {
51         super(target, object);
52         fSuspendCount = -1;
53         fCachedReferences = null;
54     }
55
56     /**
57      * @see IJavaObject#sendMessage(String, String, IJavaValue[], IJavaThread)
58      */

59     public IJavaValue sendMessage(String JavaDoc selector, String JavaDoc signature, IJavaValue[] args, IJavaThread thread, boolean superSend) throws DebugException {
60         JDIThread javaThread = (JDIThread)thread;
61         List JavaDoc arguments = null;
62         if (args == null) {
63             arguments = Collections.EMPTY_LIST;
64         } else {
65             arguments= new ArrayList JavaDoc(args.length);
66             for (int i = 0; i < args.length; i++) {
67                 arguments.add(((JDIValue)args[i]).getUnderlyingValue());
68             }
69         }
70         ObjectReference object = getUnderlyingObject();
71         Method method = null;
72         ReferenceType refType = getUnderlyingReferenceType();
73         try {
74             if (superSend) {
75                 // begin lookup in superclass
76
refType = ((ClassType)refType).superclass();
77             }
78             method = concreteMethodByName(refType, selector, signature);
79             if (method == null) {
80                 targetRequestFailed(MessageFormat.format(JDIDebugModelMessages.JDIObjectValue_11, new String JavaDoc[] {selector, signature}), null);
81             }
82         } catch (RuntimeException JavaDoc e) {
83             targetRequestFailed(MessageFormat.format(JDIDebugModelMessages.JDIObjectValue_exception_while_performing_method_lookup_for_selector, new String JavaDoc[] {e.toString(), selector, signature}), e);
84         }
85         Value result = javaThread.invokeMethod(null, object, method, arguments, superSend);
86         return JDIValue.createValue((JDIDebugTarget)getDebugTarget(), result);
87     }
88     
89     /**
90      * @see IJavaObject#sendMessage(String, String, IJavaValue[], IJavaThread, String typeSignature)
91      */

92     public IJavaValue sendMessage(String JavaDoc selector, String JavaDoc signature, IJavaValue[] args, IJavaThread thread, String JavaDoc typeSignature) throws DebugException {
93         JDIThread javaThread = (JDIThread)thread;
94         List JavaDoc arguments = null;
95         if (args == null) {
96             arguments = Collections.EMPTY_LIST;
97         } else {
98             arguments= new ArrayList JavaDoc(args.length);
99             for (int i = 0; i < args.length; i++) {
100                 arguments.add(((JDIValue)args[i]).getUnderlyingValue());
101             }
102         }
103         ObjectReference object = getUnderlyingObject();
104         Method method = null;
105         ReferenceType refType = getUnderlyingReferenceType();
106         try {
107             while (typeSignature != null && !refType.signature().equals(typeSignature)) {
108                 // lookup correct type through the hierarchy
109
refType = ((ClassType)refType).superclass();
110                 if (refType == null) {
111                     targetRequestFailed(JDIDebugModelMessages.JDIObjectValueMethod_declaring_type_not_found_1, null);
112                 }
113             }
114             method= concreteMethodByName(refType, selector, signature);
115             if (method == null) {
116                 targetRequestFailed(MessageFormat.format(JDIDebugModelMessages.JDIObjectValue_11, new String JavaDoc[] {selector, signature}), null);
117             }
118         } catch (RuntimeException JavaDoc e) {
119             targetRequestFailed(MessageFormat.format(JDIDebugModelMessages.JDIObjectValue_exception_while_performing_method_lookup_for_selector, new String JavaDoc[] {e.toString(), selector, signature}), e);
120         }
121         Value result = javaThread.invokeMethod(null, object, method, arguments, true);
122         return JDIValue.createValue((JDIDebugTarget)getDebugTarget(), result);
123     }
124
125     private Method concreteMethodByName(ReferenceType refType, String JavaDoc selector, String JavaDoc signature) throws DebugException {
126         if (refType instanceof ClassType) {
127             return ((ClassType)refType).concreteMethodByName(selector, signature);
128         }
129         if (refType instanceof ArrayType) {
130             // the jdi spec specifies that all methods on methods return an empty list for array types.
131
// use a trick to get the right method from java.lang.Object
132
return ((ClassType)refType.classObject().referenceType()).superclass().concreteMethodByName(selector, signature);
133         }
134         targetRequestFailed(MessageFormat.format(JDIDebugModelMessages.JDIObjectValue_method_lookup_failed_for_selector____0____with_signature____1___1, new String JavaDoc[] {selector, signature}), null);
135         // it is not possible to return null
136
return null;
137     }
138     
139     /**
140      * Returns this object's the underlying object reference
141      *
142      * @return underlying object reference
143      */

144     public ObjectReference getUnderlyingObject() {
145         return (ObjectReference)getUnderlyingValue();
146     }
147
148     /**
149      * @see IJavaObject#getField(String, boolean)
150      */

151     public IJavaFieldVariable getField(String JavaDoc name, boolean superField) throws DebugException {
152         ReferenceType ref = getUnderlyingReferenceType();
153         try {
154             if (superField) {
155                 // begin lookup in superclass
156
ref = ((ClassType)ref).superclass();
157             }
158             Field field = ref.fieldByName(name);
159             if (field != null) {
160                 return new JDIFieldVariable((JDIDebugTarget)getDebugTarget(), field, getUnderlyingObject());
161             }
162             Field enclosingThis= null;
163             Iterator JavaDoc fields= ref.fields().iterator();
164             while (fields.hasNext()) {
165                 Field fieldTmp = (Field)fields.next();
166                 if (fieldTmp.name().startsWith("this$")) { //$NON-NLS-1$
167
enclosingThis= fieldTmp;
168                     break;
169                 }
170             }
171             
172             if (enclosingThis != null)
173                 return ((JDIObjectValue)(new JDIFieldVariable((JDIDebugTarget)getDebugTarget(), enclosingThis, getUnderlyingObject())).getValue()).getField(name, false);
174         } catch (RuntimeException JavaDoc e) {
175             targetRequestFailed(MessageFormat.format(JDIDebugModelMessages.JDIObjectValue_exception_retrieving_field, new String JavaDoc[]{e.toString()}), e);
176         }
177         // it is possible to return null
178
return null;
179     }
180     
181     /**
182      * @see IJavaObject#getField(String, String)
183      */

184     public IJavaFieldVariable getField(String JavaDoc name, String JavaDoc declaringTypeSignature) throws DebugException {
185         ReferenceType ref= getUnderlyingReferenceType();
186         try {
187             Field field= null;
188             Field fieldTmp= null;
189             Iterator JavaDoc fields= ref.allFields().iterator();
190             while (fields.hasNext()) {
191                 fieldTmp = (Field)fields.next();
192                 if (name.equals(fieldTmp.name()) && declaringTypeSignature.equals(fieldTmp.declaringType().signature())) {
193                     field= fieldTmp;
194                     break;
195                 }
196             }
197             if (field != null) {
198                 return new JDIFieldVariable((JDIDebugTarget)getDebugTarget(), field, getUnderlyingObject());
199             }
200         } catch (RuntimeException JavaDoc e) {
201             targetRequestFailed(MessageFormat.format(JDIDebugModelMessages.JDIObjectValue_exception_retrieving_field, new String JavaDoc[]{e.toString()}), e);
202         }
203         // it is possible to return null
204
return null;
205     }
206     
207     /**
208      * Returns a variable representing the field in this object
209      * with the given name, or <code>null</code> if there is no
210      * field with the given name, or the name is ambiguous.
211      *
212      * @param name field name
213      * @param superClassLevel the level of the desired field in the
214      * hierarchy. Level 0 returns the field from the current type, level 1 from the
215      * super type, etc.
216      * @return the variable representing the field, or <code>null</code>
217      * @exception DebugException if this method fails. Reasons include:
218      * <ul><li>Failure communicating with the VM. The DebugException's
219      * status code contains the underlying exception responsible for
220      * the failure.</li>
221      */

222     public IJavaFieldVariable getField(String JavaDoc name, int superClassLevel) throws DebugException {
223         ReferenceType ref= getUnderlyingReferenceType();
224         try {
225             for (int i= 0 ; i < superClassLevel; i++) {
226                 ref= ((ClassType)ref).superclass();
227             }
228             Field field = ref.fieldByName(name);
229             if (field != null) {
230                 return new JDIFieldVariable((JDIDebugTarget)getDebugTarget(), field, getUnderlyingObject());
231             }
232         } catch (RuntimeException JavaDoc e) {
233             targetRequestFailed(MessageFormat.format(JDIDebugModelMessages.JDIObjectValue_exception_retrieving_field, new String JavaDoc[]{e.toString()}), e);
234         }
235         // it is possible to return null
236
return null;
237     }
238     
239     /**
240      * Returns the underlying reference type for this object.
241      *
242      * @exception DebugException if this method fails. Reasons include:
243      * <ul><li>Failure communicating with the VM. The DebugException's
244      * status code contains the underlying exception responsible for
245      * the failure.</li>
246      */

247     protected ReferenceType getUnderlyingReferenceType() throws DebugException {
248         try {
249             return getUnderlyingObject().referenceType();
250         } catch (RuntimeException JavaDoc e) {
251             targetRequestFailed(MessageFormat.format(JDIDebugModelMessages.JDIObjectValue_exception_retrieving_reference_type, new String JavaDoc[]{e.toString()}), e);
252         }
253         // execution will not reach this line, as an exception will
254
// be thrown.
255
return null;
256             
257     }
258
259     /**
260      * Return the enclosing object of this object at the specified level.
261      * Level 0 returns the object, level 1 returns the enclosing object, etc.
262      */

263     public IJavaObject getEnclosingObject(int enclosingLevel) throws DebugException {
264         JDIObjectValue res= this;
265         for (int i= 0; i < enclosingLevel; i ++) {
266             ReferenceType ref= res.getUnderlyingReferenceType();
267             try {
268                 Field enclosingThis= null, fieldTmp= null;
269                 Iterator JavaDoc fields= ref.fields().iterator();
270                 while (fields.hasNext()) {
271                     fieldTmp = (Field)fields.next();
272                     if (fieldTmp.name().startsWith("this$")) { //$NON-NLS-1$
273
enclosingThis= fieldTmp;
274                     }
275                 }
276                 if (enclosingThis != null) {
277                     JDIDebugTarget debugTarget = (JDIDebugTarget)getDebugTarget();
278                     JDIFieldVariable fieldVariable = new JDIFieldVariable(debugTarget, enclosingThis, res.getUnderlyingObject());
279                     res = (JDIObjectValue)fieldVariable.getValue();
280                 } else {
281                     // it is possible to return null
282
return null;
283                 }
284             } catch (RuntimeException JavaDoc e) {
285                 targetRequestFailed(MessageFormat.format(JDIDebugModelMessages.JDIObjectValue_exception_retrieving_field, new String JavaDoc[]{e.toString()}), e);
286             }
287         }
288         return res;
289     }
290     
291     /* (non-Javadoc)
292      * @see org.eclipse.jdt.debug.core.IJavaObject#getWaitingThreads()
293      */

294     public IJavaThread[] getWaitingThreads() throws DebugException {
295         List JavaDoc waiting = new ArrayList JavaDoc();
296         try {
297             List JavaDoc threads= getUnderlyingObject().waitingThreads();
298             JDIDebugTarget debugTarget= (JDIDebugTarget)getDebugTarget();
299             for (Iterator JavaDoc iter= threads.iterator(); iter.hasNext();) {
300                 JDIThread jdiThread = debugTarget.findThread((ThreadReference) iter.next());
301                 if (jdiThread != null) {
302                     waiting.add(jdiThread);
303                 }
304             }
305         } catch (IncompatibleThreadStateException e) {
306             targetRequestFailed(JDIDebugModelMessages.JDIObjectValue_0, e);
307         } catch (VMDisconnectedException e) {
308             // Ignore
309
} catch (RuntimeException JavaDoc e) {
310             targetRequestFailed(JDIDebugModelMessages.JDIObjectValue_0, e);
311         }
312         return (IJavaThread[]) waiting.toArray(new IJavaThread[waiting.size()]);
313     }
314     
315     /* (non-Javadoc)
316      * @see org.eclipse.jdt.debug.core.IJavaObject#getOwningThread()
317      */

318     public IJavaThread getOwningThread() throws DebugException {
319         IJavaThread owningThread= null;
320         try {
321             ThreadReference thread= getUnderlyingObject().owningThread();
322             JDIDebugTarget debugTarget= (JDIDebugTarget)getDebugTarget();
323             if (thread != null) {
324                 owningThread= debugTarget.findThread(thread);
325             }
326         } catch (IncompatibleThreadStateException e) {
327             targetRequestFailed(JDIDebugModelMessages.JDIObjectValue_1, e);
328         } catch (VMDisconnectedException e) {
329             return null;
330         } catch (RuntimeException JavaDoc e) {
331             targetRequestFailed(JDIDebugModelMessages.JDIObjectValue_1, e);
332         }
333         return owningThread;
334     }
335     
336     /**
337      * @see IValue#getReferenceTypeName()
338      */

339     public String JavaDoc getReferenceTypeName() throws DebugException {
340         try {
341             return JDIReferenceType.getGenericName(getUnderlyingReferenceType());
342         } catch (RuntimeException JavaDoc e) {
343             targetRequestFailed(MessageFormat.format(JDIDebugModelMessages.JDIValue_exception_retrieving_reference_type_name, new String JavaDoc[] {e.toString()}), e);
344             // execution will not reach this line, as
345
// #targetRequestFailed will thrown an exception
346
return null;
347         }
348     }
349     
350     /**
351      * Returns the unique id for this object.
352      *
353      * @return unique id or -1 if this value is null
354      * @throws DebugException
355      *
356      * TODO: make API on IJavaObject
357      */

358     public long getUniqueId() throws DebugException {
359         try {
360             ObjectReference underlyingObject = getUnderlyingObject();
361             if (underlyingObject != null) {
362                 return underlyingObject.uniqueID();
363             } else {
364                 return -1L;
365             }
366         } catch (RuntimeException JavaDoc e) {
367             targetRequestFailed(MessageFormat.format(JDIDebugModelMessages.JDIValue_exception_retrieving_unique_id, new String JavaDoc[] {e.toString()}), e);
368             // execution will not reach this line, as
369
// #targetRequestFailed will thrown an exception
370
return 0;
371         }
372     }
373
374     /* (non-Javadoc)
375      * @see org.eclipse.jdt.debug.core.IJavaObject#getReferringObjects(long)
376      */

377     public IJavaObject[] getReferringObjects(long max) throws DebugException {
378         // The cached references should be reloaded if the suspend count has changed, or the maximum entries has changed
379
if (fCachedReferences == null || fSuspendCount < ((JDIDebugTarget)getDebugTarget()).getSuspendCount() || fPreviousMax != max){
380             reloadReferringObjects(max);
381             fPreviousMax = max;
382             fSuspendCount = ((JDIDebugTarget)getDebugTarget()).getSuspendCount();
383         }
384         return fCachedReferences;
385     }
386     
387     /**
388      * Returns true if references to this object have been calculated and cached. This
389      * method will return true even if the cached references are stale.
390      * @return true is references to this object have been calculated and cached, false otherwise
391      */

392     public boolean isReferencesLoaded(){
393         return fCachedReferences != null;
394     }
395     
396     /**
397      * Gets the list of objects that reference this object from the vm, overwriting the
398      * cached list (if one exists).
399      *
400      * @param max The maximum number of entries to return
401      * @throws DebugException if the vm cannot return a list of referring objects
402      */

403     protected void reloadReferringObjects(long max) throws DebugException{
404         try{
405             List JavaDoc list = getUnderlyingObject().referringObjects(max);
406             IJavaObject[] references = new IJavaObject[list.size()];
407             for (int i = 0; i < references.length; i++) {
408                 references[i] = (IJavaObject) JDIValue.createValue(getJavaDebugTarget(), (Value) list.get(i));
409             }
410             fCachedReferences = references;
411         } catch (RuntimeException JavaDoc e) {
412             targetRequestFailed(JDIDebugModelMessages.JDIObjectValue_12, e);
413             fCachedReferences = null;
414         }
415     }
416 }
Popular Tags