blob: ddb36023d2ff1eccdb920efa0861d3407b6d8dea [file] [log] [blame]
package org.eclipse.jdi.internal;
/*
* (c) Copyright IBM Corp. 2000, 2001.
* All Rights Reserved.
*/
import com.sun.jdi.*;
import com.sun.jdi.connect.*;
import com.sun.jdi.event.*;
import com.sun.jdi.request.*;
import org.eclipse.jdi.internal.connect.*;
import org.eclipse.jdi.internal.request.*;
import org.eclipse.jdi.internal.event.*;
import org.eclipse.jdi.internal.jdwp.*;
import org.eclipse.jdi.internal.spy.*;
import java.util.*;
import java.io.*;
/**
* this class implements the corresponding interfaces
* declared by the JDI specification. See the com.sun.jdi package
* for more information.
*
*/
public class ArrayReferenceImpl extends ObjectReferenceImpl implements ArrayReference {
/** JDWP Tag. */
public static final byte tag = JdwpID.ARRAY_TAG;
/**
* Creates new ArrayReferenceImpl.
*/
public ArrayReferenceImpl(VirtualMachineImpl vmImpl, JdwpObjectID objectID) {
super("ArrayReference", vmImpl, objectID);
}
/**
* @returns tag.
*/
public byte getTag() {
return tag;
}
/**
* @returns Returns an array component value.
*/
public Value getValue(int index) throws IndexOutOfBoundsException {
return (Value)getValues(index, 1).get(0);
}
/**
* @returns Returns all of the components in this array.
*/
public List getValues() {
return getValues(0, -1);
}
/**
* @return Returns a list containing each Method declared directly in this type.
*/
public List methods() {
return new Vector();
}
/**
* @returns Returns a range of array components.
*/
public List getValues(int firstIndex, int length) throws IndexOutOfBoundsException {
// Negative length indicates all elements.
if (length < 0)
length = length();
// Note that this information should not be cached.
initJdwpRequest();
try {
ByteArrayOutputStream outBytes = new ByteArrayOutputStream();
DataOutputStream outData = new DataOutputStream(outBytes);
write(this, outData); // arrayObject
writeInt(firstIndex, "firstIndex", outData);
writeInt(length, "length", outData);
JdwpReplyPacket replyPacket = requestVM(JdwpCommandPacket.AR_GET_VALUES, outBytes);
switch (replyPacket.errorCode()) {
case JdwpReplyPacket.INVALID_INDEX:
throw new IndexOutOfBoundsException("Invalid index of array reference given.");
}
defaultReplyErrorHandler(replyPacket.errorCode());
DataInputStream replyData = replyPacket.dataInStream();
/* NOTE: The JDWP documentation is not clear on this: it turns out that the following is received from the VM:
* - type tag;
* - length of array;
* - values of elements.
*/
int type = readByte("type", JdwpID.tagMap(), replyData);
int readLength = readInt("length", replyData);
// See also ValueImpl.
switch(type) {
// Multidimensional array.
case ArrayReferenceImpl.tag:
// Object references.
case ClassLoaderReferenceImpl.tag:
case ClassObjectReferenceImpl.tag:
case StringReferenceImpl.tag:
case ObjectReferenceImpl.tag:
case ThreadGroupReferenceImpl.tag:
case ThreadReferenceImpl.tag:
return readObjectSequence(readLength, replyData);
// Primitive type.
case BooleanValueImpl.tag:
case ByteValueImpl.tag:
case CharValueImpl.tag:
case DoubleValueImpl.tag:
case FloatValueImpl.tag:
case IntegerValueImpl.tag:
case LongValueImpl.tag:
case ShortValueImpl.tag:
return readPrimitiveSequence(readLength, type, replyData);
case VoidValueImpl.tag:
case 0:
default:
throw new InternalException("Invalid ArrayReference Value tag encountered: " + type);
}
} catch (IOException e) {
defaultIOExceptionHandler(e);
return null;
} finally {
handledJdwpRequest();
}
}
/**
* @returns Returns sequence of object reference values.
*/
private List readObjectSequence(int length, DataInputStream in) throws IOException {
Vector elements = new Vector();
for (int i = 0; i < length; i++) {
ValueImpl value = ObjectReferenceImpl.readObjectRefWithTag(this, in);
elements.add(value);
}
return elements;
}
/**
* @returns Returns sequence of values of primitive type.
*/
private List readPrimitiveSequence(int length, int type, DataInputStream in) throws IOException {
Vector elements = new Vector();
for (int i = 0; i < length; i++) {
ValueImpl value = ValueImpl.readWithoutTag(this, type, in);
elements.add(value);
}
return elements;
}
/**
* @returns Returns the number of components in this array.
*/
public int length() {
initJdwpRequest();
try {
JdwpReplyPacket replyPacket = requestVM(JdwpCommandPacket.AR_LENGTH, this);
defaultReplyErrorHandler(replyPacket.errorCode());
DataInputStream replyData = replyPacket.dataInStream();
return readInt("length", replyData);
} catch (IOException e) {
defaultIOExceptionHandler(e);
return 0;
} finally {
handledJdwpRequest();
}
}
/**
* Replaces an array component with another value.
*/
public void setValue(int index, Value value) throws InvalidTypeException, ClassNotLoadedException {
ArrayList list = new ArrayList(1);
list.add(value);
setValues(index, list, 0, 1);
}
/**
* Replaces all array components with other values.
*/
public void setValues(List values) throws InvalidTypeException, ClassNotLoadedException {
setValues(0, values, 0, -1);
}
/**
* Replaces a range of array components with other values.
*/
public void setValues(int index, List values, int srcIndex, int length) throws InvalidTypeException, ClassNotLoadedException {
// Negative length indicates all elements.
if (length < 0)
length = length() - index;
else if (index + length > length())
throw new IndexOutOfBoundsException("Attempted to set more values in array than length of array.");
// Check if enough values are given.
if (values.size() < srcIndex + length)
throw new IndexOutOfBoundsException("Attempted to set more values in array than given.");
// Note that this information should not be cached.
initJdwpRequest();
try {
ByteArrayOutputStream outBytes = new ByteArrayOutputStream();
DataOutputStream outData = new DataOutputStream(outBytes);
write(this, outData);
writeInt(index, "index", outData);
writeInt(length, "length", outData);
for (int i = srcIndex; i < srcIndex + length; i++) {
ValueImpl value = (ValueImpl)values.get(i);
if (value != null) {
checkVM(value);
((ValueImpl)value).write(this, outData);
} else {
ValueImpl.writeNull(this, outData);
}
}
JdwpReplyPacket replyPacket = requestVM(JdwpCommandPacket.AR_SET_VALUES, outBytes);
switch (replyPacket.errorCode()) {
case JdwpReplyPacket.TYPE_MISMATCH:
throw new InvalidTypeException();
case JdwpReplyPacket.INVALID_CLASS:
throw new ClassNotLoadedException(type().name());
}
defaultReplyErrorHandler(replyPacket.errorCode());
} catch (IOException e) {
defaultIOExceptionHandler(e);
} finally {
handledJdwpRequest();
}
}
/**
* @return Returns description of Mirror object.
*/
public String toString() {
try {
StringBuffer buf = new StringBuffer(type().name());
// Insert length of string between (last) square braces.
buf.insert(buf.length() - 1, length());
// Append space and idString.
buf.append(' ');
buf.append(idString());
return buf.toString();
} catch (ObjectCollectedException e) {
return "(Garbage Collected) ArrayReference" + "[" + length() + "] " + idString();
} catch (Exception e) {
return fDescription;
}
}
/**
* @return Reads JDWP representation and returns new instance.
*/
public static ArrayReferenceImpl read(MirrorImpl target, DataInputStream in) throws IOException {
VirtualMachineImpl vmImpl = target.virtualMachineImpl();
JdwpObjectID ID = new JdwpObjectID(vmImpl);
ID.read(in);
if (target.fVerboseWriter != null)
target.fVerboseWriter.println("arrayReference", ID.value());
if (ID.isNull())
return null;
ArrayReferenceImpl mirror = new ArrayReferenceImpl(vmImpl, ID);
return mirror;
}
}