blob: 0c9d3012c5a0ca10d7a6921e377f978ba4a48cc7 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2012 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 java.text.MessageFormat;
import org.eclipse.core.runtime.CoreException;
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.IJavaValue;
import org.eclipse.jdt.debug.core.IJavaVariable;
import com.sun.jdi.ArrayReference;
import com.sun.jdi.ArrayType;
import com.sun.jdi.ClassNotLoadedException;
import com.sun.jdi.InvalidTypeException;
import com.sun.jdi.ReferenceType;
import com.sun.jdi.Type;
import com.sun.jdi.Value;
/**
* An entry in an array.
*/
public class JDIArrayEntryVariable extends JDIModificationVariable {
/**
* The index of the variable entry
*/
private int fIndex;
/**
* The array object
*/
private ArrayReference fArray;
/**
* The reference type name of this variable. Cached lazily.
*/
private String fReferenceTypeName = null;
/**
* When created for a logical structure we hold onto the original
* non-logical object 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 an array entry at the given index in an array.
*
* @param target
* debug target containing the array entry
* @param array
* array containing the entry
* @param index
* index into the array
* @param logicalParent
* original logical parent value, or <code>null</code> if not a
* child of a logical structure
*/
public JDIArrayEntryVariable(JDIDebugTarget target, ArrayReference array,
int index, IJavaValue logicalParent) {
super(target);
fArray = array;
fIndex = index;
fLogicalParent = logicalParent;
}
/**
* Returns this variable's current underlying value.
*/
@Override
protected Value retrieveValue() {
ArrayReference ar = getArrayReference();
if (ar != null) {
return ar.getValue(getIndex());
}
return null;
}
/**
* @see IVariable#getName()
*/
@Override
public String getName() {
return "[" + getIndex() + "]"; //$NON-NLS-2$ //$NON-NLS-1$
}
@Override
protected void setJDIValue(Value value) throws DebugException {
ArrayReference ar = getArrayReference();
if (ar == null) {
requestFailed(
JDIDebugModelMessages.JDIArrayEntryVariable_value_modification_failed,
null);
}
try {
ar.setValue(getIndex(), value);
fireChangeEvent(DebugEvent.CONTENT);
} catch (ClassNotLoadedException e) {
targetRequestFailed(
MessageFormat.format(
JDIDebugModelMessages.JDIArrayEntryVariable_exception_modifying_variable_value,
e.toString()), e);
} catch (InvalidTypeException e) {
targetRequestFailed(
MessageFormat.format(
JDIDebugModelMessages.JDIArrayEntryVariable_exception_modifying_variable_value,
e.toString()), e);
} catch (RuntimeException e) {
targetRequestFailed(
MessageFormat.format(
JDIDebugModelMessages.JDIArrayEntryVariable_exception_modifying_variable_value,
e.toString()), e);
}
}
protected ArrayReference getArrayReference() {
return fArray;
}
protected int getIndex() {
return fIndex;
}
/**
* @see IVariable#getReferenceTypeName()
*/
@Override
public String getReferenceTypeName() throws DebugException {
try {
if (fReferenceTypeName == null) {
fReferenceTypeName = stripBrackets(JDIReferenceType
.getGenericName(getArrayReference().referenceType()));
}
} catch (RuntimeException e) {
targetRequestFailed(
MessageFormat.format(
JDIDebugModelMessages.JDIArrayEntryVariable_exception_retrieving_reference_type,
e.toString()), e);
// execution will not reach this line, as
// #targetRequestFailed will thrown an exception
return null;
}
return fReferenceTypeName;
}
/**
* Given a type name, strip out one set of array brackets and return the
* result. Example: "int[][][]" becomes "int[][]".
*/
protected String stripBrackets(String typeName) {
int lastLeft = typeName.lastIndexOf("[]"); //$NON-NLS-1$
if (lastLeft < 0) {
return typeName;
}
StringBuilder buffer = new StringBuilder(typeName);
buffer.replace(lastLeft, lastLeft + 2, ""); //$NON-NLS-1$
return buffer.toString();
}
/**
* @see IJavaVariable#getSignature()
*/
@Override
public String getSignature() throws DebugException {
try {
return ((ArrayType) getArrayReference().type())
.componentSignature();
} catch (RuntimeException e) {
targetRequestFailed(
MessageFormat.format(
JDIDebugModelMessages.JDIArrayEntryVariable_exception_retrieving_type_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 {
ReferenceType referenceType = getArrayReference().referenceType();
String genericSignature = referenceType.genericSignature();
if (genericSignature != null) {
return genericSignature;
}
return referenceType.signature();
} catch (RuntimeException e) {
targetRequestFailed(
MessageFormat.format(
JDIDebugModelMessages.JDIArrayEntryVariable_exception_retrieving_type_signature,
e.toString()), e);
// execution will not reach this line, as
// #targetRequestFailed will thrown an exception
return null;
}
}
/**
* @see JDIVariable#getUnderlyingType()
*/
@Override
protected Type getUnderlyingType() throws DebugException {
try {
return ((ArrayType) getArrayReference().type()).componentType();
} catch (ClassNotLoadedException e) {
targetRequestFailed(
MessageFormat.format(
JDIDebugModelMessages.JDIArrayEntryVariable_exception_while_retrieving_type_of_array_entry,
e.toString()), e);
} catch (RuntimeException e) {
targetRequestFailed(
MessageFormat.format(
JDIDebugModelMessages.JDIArrayEntryVariable_exception_while_retrieving_type_of_array_entry,
e.toString()), e);
}
// this line will not be executed as an exception
// will be throw in type retrieval fails
return null;
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (obj instanceof JDIArrayEntryVariable) {
JDIArrayEntryVariable entry = (JDIArrayEntryVariable) obj;
if (fLogicalParent != null) {
try {
return fLogicalParent.equals(entry.fLogicalParent)
&& getValue().equals(entry.getValue());
} catch (CoreException e) {
}
}
return entry.getArrayReference().equals(getArrayReference())
&& entry.getIndex() == getIndex();
}
return false;
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
if (fLogicalParent != null) {
return fLogicalParent.hashCode() + getIndex();
}
return getArrayReference().hashCode() + getIndex();
}
}