blob: f9e2ef4e033015c3aea08f8c56c95b727bf1d28f [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2015 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.jdt.internal.debug.core.model;
import org.eclipse.core.runtime.PlatformObject;
import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.model.IValue;
import org.eclipse.debug.core.model.IValueModification;
import org.eclipse.debug.core.model.IVariable;
import org.eclipse.jdt.debug.core.IJavaModifiers;
import org.eclipse.jdt.debug.core.IJavaType;
import org.eclipse.jdt.debug.core.IJavaVariable;
import com.ibm.icu.text.MessageFormat;
import com.sun.jdi.Type;
import com.sun.jdi.Value;
public abstract class JDIVariable extends JDIDebugElement implements
IJavaVariable {
/**
* Cache of current value - see #getValue().
*/
private JDIValue fValue;
/**
* Counter corresponding to this variable's debug target suspend count
* indicating the last time this value changed. This variable's value has
* changed on the last suspend event if this counter is equal to the debug
* target's suspend count.
*/
private int fLastChangeIndex = -1;
protected final static String jdiStringSignature = "Ljava/lang/String;"; //$NON-NLS-1$
public JDIVariable(JDIDebugTarget target) {
super(target);
}
/**
* @see PlatformObject#getAdapter(Class)
*/
@SuppressWarnings("unchecked")
@Override
public <T> T getAdapter(Class<T> adapter) {
if (adapter == IJavaVariable.class || adapter == IJavaModifiers.class) {
return (T) this;
}
return super.getAdapter(adapter);
}
/**
* Returns this variable's current underlying jdi value. Subclasses must
* implement #retrieveValue() and do not need to guard against JDI
* exceptions, as this method handles them.
*
* @exception DebugException
* if unable to access the value
*/
protected final Value getCurrentValue() throws DebugException {
try {
return retrieveValue();
} catch (RuntimeException e) {
targetRequestFailed(MessageFormat.format(
JDIDebugModelMessages.JDIVariable_exception_retrieving,
new Object[] { e.toString() }), e);
// execution will not reach this line, as
// #targetRequestFailed will throw an exception
return null;
}
}
/**
* Returns this variable's underlying jdi value
*/
protected abstract Value retrieveValue() throws DebugException;
/**
* Returns the current value of this variable. The value is cached, but on
* each access we see if the value has changed and update if required.
*
* @see IVariable#getValue()
*/
@Override
public IValue getValue() throws DebugException {
Value currentValue = getCurrentValue();
if (fValue == null) {
fValue = JDIValue.createValue((JDIDebugTarget) getDebugTarget(),
currentValue);
} else {
Value previousValue = fValue.getUnderlyingValue();
if (currentValue == previousValue) {
return fValue;
}
if (previousValue == null || currentValue == null) {
fValue = JDIValue.createValue(
(JDIDebugTarget) getDebugTarget(), currentValue);
setChangeCount(getJavaDebugTarget().getSuspendCount());
} else if (!previousValue.equals(currentValue)) {
fValue = JDIValue.createValue(
(JDIDebugTarget) getDebugTarget(), currentValue);
setChangeCount(getJavaDebugTarget().getSuspendCount());
}
}
return fValue;
}
/**
* @see IValueModification#supportsValueModification()
*/
@Override
public boolean supportsValueModification() {
return false;
}
/**
* @see IValueModification#setValue(String)
*/
@Override
public void setValue(String expression) throws DebugException {
notSupported(JDIDebugModelMessages.JDIVariable_does_not_support_value_modification);
}
/**
* @see IValueModification#setValue(IValue)
*/
@Override
public void setValue(IValue value) throws DebugException {
notSupported(JDIDebugModelMessages.JDIVariable_does_not_support_value_modification);
}
/**
* @see IValueModification#verifyValue(String)
*/
@Override
public boolean verifyValue(String expression) throws DebugException {
return false;
}
/**
* @see IValueModification#verifyValue(IValue)
*/
@Override
public boolean verifyValue(IValue value) throws DebugException {
return false;
}
/**
* @see IJavaModifiers#isSynthetic()
*/
@Override
public boolean isSynthetic() {
return false;
}
/**
* @see IJavaModifiers#isPublic()
*/
@Override
public boolean isPublic() throws DebugException {
return false;
}
/**
* @see IJavaModifiers#isPrivate()
*/
@Override
public boolean isPrivate() throws DebugException {
return false;
}
/**
* @see IJavaModifiers#isProtected()
*/
@Override
public boolean isProtected() throws DebugException {
return false;
}
/**
* @see IJavaModifiers#isPackagePrivate()
*/
@Override
public boolean isPackagePrivate() {
return false;
}
/**
* @see IJavaModifiers#isStatic()
*/
@Override
public boolean isStatic() {
return false;
}
/**
* @see IJavaModifiers#isFinal()
*/
@Override
public boolean isFinal() {
return false;
}
/**
* @see org.eclipse.jdt.debug.core.IJavaVariable#isLocal()
*/
@Override
public boolean isLocal() {
return false;
}
/**
* @see IJavaVariable#getJavaType()
*/
@Override
public IJavaType getJavaType() throws DebugException {
return JDIType.createType((JDIDebugTarget) getDebugTarget(),
getUnderlyingType());
}
/**
* Returns the underlying type of this variable
*
* @return the underlying type of this variable
*
* @exception DebugException
* if this method fails. Reasons include:
* <ul>
* <li>Failure communicating with the VM. The
* DebugException's status code contains the underlying
* exception responsible for the failure.</li>
* <li>The type associated with this variable is not yet
* loaded</li>
* </ul>
*/
protected abstract Type getUnderlyingType() throws DebugException;
/**
* Returns the last known value for this variable
*/
protected Value getLastKnownValue() {
if (fValue == null) {
return null;
}
return fValue.getUnderlyingValue();
}
/**
* Sets this variable's change counter to the specified value
*
* @param count
* new value
*/
protected void setChangeCount(int count) {
fLastChangeIndex = count;
}
/**
* Returns this variable's change counter. This corresponds to the last time
* this variable changed.
*
* @return this variable's change counter
*/
protected int getChangeCount() {
return fLastChangeIndex;
}
/**
* @see IVariable#hasValueChanged()
*/
@Override
public boolean hasValueChanged() {
return getChangeCount() == getJavaDebugTarget().getSuspendCount();
}
}