| /******************************************************************************* |
| * Copyright (c) 2000, 2011 IBM Corporation and others. |
| * |
| * This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.jdt.internal.debug.core.model; |
| |
| import org.eclipse.debug.core.DebugEvent; |
| import org.eclipse.debug.core.DebugException; |
| import org.eclipse.debug.core.model.IVariable; |
| import org.eclipse.jdt.debug.core.IJavaFieldVariable; |
| import org.eclipse.jdt.debug.core.IJavaModifiers; |
| import org.eclipse.jdt.debug.core.IJavaObject; |
| import org.eclipse.jdt.debug.core.IJavaReferenceType; |
| import org.eclipse.jdt.debug.core.IJavaType; |
| import org.eclipse.jdt.debug.core.IJavaValue; |
| import org.eclipse.jdt.debug.core.IJavaVariable; |
| |
| import com.ibm.icu.text.MessageFormat; |
| import com.sun.jdi.ClassNotLoadedException; |
| import com.sun.jdi.ClassType; |
| import com.sun.jdi.Field; |
| import com.sun.jdi.InterfaceType; |
| import com.sun.jdi.InvalidTypeException; |
| import com.sun.jdi.ObjectReference; |
| import com.sun.jdi.ReferenceType; |
| import com.sun.jdi.Type; |
| import com.sun.jdi.Value; |
| |
| /** |
| * A field member. |
| */ |
| public class JDIFieldVariable extends JDIModificationVariable implements |
| IJavaFieldVariable { |
| /** |
| * The underlying field |
| */ |
| private Field fField; |
| /** |
| * The object containing the field, or <code>null</code> for a static field. |
| */ |
| private ObjectReference fObject; |
| /** |
| * The type containing the field. |
| */ |
| private ReferenceType fType; |
| |
| /** |
| * When created for a logical structure we hold onto the original |
| * non-logical value for purposes of equality. This way a logical |
| * structure's children remain more stable in the variables view. |
| * |
| * This is <code>null</code> when not created for a logical structure. |
| */ |
| private IJavaValue fLogicalParent; |
| |
| /** |
| * Constructs a field for the given field. |
| */ |
| public JDIFieldVariable(JDIDebugTarget target, Field field, |
| ObjectReference objectRef, IJavaValue logicalParent) { |
| super(target); |
| fField = field; |
| if (!field.isStatic()) { |
| fObject = objectRef; |
| } |
| fType = (ReferenceType) objectRef.type(); |
| fLogicalParent = logicalParent; |
| } |
| |
| /** |
| * Constructs a field to wrap the given field. |
| */ |
| public JDIFieldVariable(JDIDebugTarget target, Field field, |
| ReferenceType refType) { |
| super(target); |
| fField = field; |
| fType = refType; |
| } |
| |
| /** |
| * Returns this variable's current <code>Value</code>. |
| */ |
| @Override |
| protected Value retrieveValue() { |
| if (getField().isStatic()) { |
| return (getField().declaringType().getValue(getField())); |
| } |
| return getObjectReference().getValue(getField()); |
| } |
| |
| /** |
| * @see IJavaFieldVariable#getDeclaringType() |
| */ |
| @Override |
| public IJavaType getDeclaringType() { |
| return JDIType.createType((JDIDebugTarget) getDebugTarget(), |
| fField.declaringType()); |
| } |
| |
| /** |
| * @see IVariable#getName() |
| */ |
| @Override |
| public String getName() throws DebugException { |
| try { |
| return getField().name(); |
| } catch (RuntimeException e) { |
| targetRequestFailed( |
| MessageFormat.format( |
| JDIDebugModelMessages.JDIFieldVariable_exception_retrieving_field_name, |
| e.toString()), e); |
| // execution will not reach this line, as |
| // #targetRequestFailed will thrown an exception |
| return null; |
| } |
| } |
| |
| @Override |
| protected void setJDIValue(Value value) throws DebugException { |
| try { |
| if (isStatic()) { |
| ReferenceType declaringType = getField().declaringType(); |
| if (declaringType instanceof InterfaceType) { |
| requestFailed(JDIDebugModelMessages.JDIFieldVariable_0, |
| null); |
| } |
| ((ClassType) declaringType).setValue(getField(), value); |
| } else { |
| getObjectReference().setValue(getField(), value); |
| } |
| fireChangeEvent(DebugEvent.CONTENT); |
| } catch (ClassNotLoadedException e) { |
| targetRequestFailed( |
| MessageFormat.format( |
| JDIDebugModelMessages.JDIFieldVariable_exception_modifying_value, |
| e.toString()), e); |
| } catch (InvalidTypeException e) { |
| targetRequestFailed( |
| MessageFormat.format( |
| JDIDebugModelMessages.JDIFieldVariable_exception_modifying_value, |
| e.toString()), e); |
| } catch (RuntimeException e) { |
| targetRequestFailed( |
| MessageFormat.format( |
| JDIDebugModelMessages.JDIFieldVariable_exception_modifying_value, |
| e.toString()), e); |
| } |
| |
| } |
| |
| /** |
| * @see IJavaVariable#isVolatile() |
| */ |
| @Override |
| public boolean isVolatile() { |
| return getField().isVolatile(); |
| } |
| |
| /** |
| * @see IJavaVariable#isTransient() |
| */ |
| @Override |
| public boolean isTransient() { |
| return getField().isTransient(); |
| } |
| |
| /** |
| * @see IJavaModifiers#isSynthetic() |
| */ |
| @Override |
| public boolean isSynthetic() { |
| return getField().isSynthetic(); |
| } |
| |
| /** |
| * @see IJavaModifiers#isPublic() |
| */ |
| @Override |
| public boolean isPublic() { |
| return getField().isPublic(); |
| } |
| |
| /** |
| * @see IJavaModifiers#isPrivate() |
| */ |
| @Override |
| public boolean isPrivate() { |
| return getField().isPrivate(); |
| } |
| |
| /** |
| * @see IJavaModifiers#isProtected() |
| */ |
| @Override |
| public boolean isProtected() { |
| return getField().isProtected(); |
| } |
| |
| /** |
| * @see IJavaModifiers#isPackagePrivate() |
| */ |
| @Override |
| public boolean isPackagePrivate() { |
| return getField().isPackagePrivate(); |
| } |
| |
| /** |
| * @see IJavaModifiers#isStatic() |
| */ |
| @Override |
| public boolean isStatic() { |
| return getField().isStatic(); |
| } |
| |
| /** |
| * @see IJavaModifiers#isFinal() |
| */ |
| @Override |
| public boolean isFinal() { |
| return getField().isFinal(); |
| } |
| |
| /** |
| * @see IVariable#getReferenceTypeName() |
| */ |
| @Override |
| public String getReferenceTypeName() throws DebugException { |
| String genericSignature = getField().genericSignature(); |
| if (genericSignature != null) { |
| return JDIReferenceType.getTypeName(genericSignature); |
| } |
| Type underlyingType = getUnderlyingType(); |
| if (underlyingType instanceof ReferenceType) { |
| return JDIReferenceType |
| .getGenericName((ReferenceType) underlyingType); |
| } |
| return getField().typeName(); |
| } |
| |
| /** |
| * @see IJavaVariable#getSignature() |
| */ |
| @Override |
| public String getSignature() throws DebugException { |
| try { |
| return getField().signature(); |
| } catch (RuntimeException e) { |
| targetRequestFailed( |
| MessageFormat.format( |
| JDIDebugModelMessages.JDIFieldVariable_exception_retrieving_field_signature, |
| e.toString()), e); |
| // execution will not reach this line, as |
| // #targetRequestFailed will thrown an exception |
| return null; |
| } |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.jdt.debug.core.IJavaVariable#getGenericSignature() |
| */ |
| @Override |
| public String getGenericSignature() throws DebugException { |
| try { |
| String genericSignature = fField.genericSignature(); |
| if (genericSignature != null) { |
| return genericSignature; |
| } |
| return fField.signature(); |
| } catch (RuntimeException e) { |
| targetRequestFailed( |
| MessageFormat.format( |
| JDIDebugModelMessages.JDIFieldVariable_exception_retrieving_field_signature, |
| e.toString()), e); |
| // execution will not reach this line, as |
| // #targetRequestFailed will thrown an exception |
| return null; |
| } |
| } |
| |
| public Field getField() { |
| return fField; |
| } |
| |
| public ObjectReference getObjectReference() { |
| return fObject; |
| } |
| |
| public ReferenceType getReferenceType() { |
| return fType; |
| } |
| |
| @Override |
| public boolean supportsValueModification() { |
| if (getField().declaringType() instanceof InterfaceType) { |
| return false; |
| } |
| return super.supportsValueModification(); |
| } |
| |
| /** |
| * @see java.lang.Object#toString() |
| */ |
| @Override |
| public String toString() { |
| return getField().toString(); |
| } |
| |
| /** |
| * @see JDIVariable#getUnderlyingType() |
| */ |
| @Override |
| protected Type getUnderlyingType() throws DebugException { |
| try { |
| return getField().type(); |
| } catch (ClassNotLoadedException e) { |
| targetRequestFailed( |
| MessageFormat.format( |
| JDIDebugModelMessages.JDIFieldVariable_exception_while_retrieving_type_of_field, |
| e.toString()), e); |
| } catch (RuntimeException e) { |
| targetRequestFailed( |
| MessageFormat.format( |
| JDIDebugModelMessages.JDIFieldVariable_exception_while_retrieving_type_of_field, |
| e.toString()), e); |
| } |
| // this line will not be executed as an exception |
| // will be throw in type retrieval fails |
| return null; |
| } |
| |
| /** |
| * @see java.lang.Object#equals(Object) |
| */ |
| @Override |
| public boolean equals(Object o) { |
| if (o instanceof JDIFieldVariable) { |
| JDIFieldVariable f = (JDIFieldVariable) o; |
| if (fLogicalParent != null) { |
| return fLogicalParent.equals(f.fLogicalParent) |
| && f.fField.equals(fField); |
| } |
| if (fObject != null) { |
| return fObject.equals(f.fObject) && f.fField.equals(fField); |
| } |
| return f.fField.equals(fField); |
| } |
| return false; |
| } |
| |
| /** |
| * @see java.lang.Object#hashCode() |
| */ |
| @Override |
| public int hashCode() { |
| if (fLogicalParent != null) { |
| return fLogicalParent.hashCode() + fField.hashCode(); |
| } |
| if (fObject != null) { |
| return fField.hashCode() + fObject.hashCode(); |
| } |
| return fField.hashCode(); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.jdt.debug.core.IJavaFieldVariable#getObject() |
| */ |
| @Override |
| public IJavaObject getReceiver() { |
| ObjectReference objectReference = getObjectReference(); |
| if (objectReference == null) { |
| return null; |
| } |
| return (IJavaObject) JDIValue.createValue(getJavaDebugTarget(), |
| objectReference); |
| } |
| |
| @Override |
| public IJavaReferenceType getReceivingType() { |
| return (IJavaReferenceType) JDIType.createType(getJavaDebugTarget(), |
| getReferenceType()); |
| } |
| |
| } |