001: /*******************************************************************************
002: * Copyright (c) 2000, 2007 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.jdi.internal;
011:
012: import java.io.DataInputStream;
013: import java.io.DataOutputStream;
014: import java.io.IOException;
015: import java.util.ArrayList;
016: import java.util.Iterator;
017: import java.util.List;
018:
019: import org.eclipse.jdi.internal.jdwp.JdwpID;
020: import org.eclipse.jdi.internal.jdwp.JdwpObjectID;
021:
022: import com.ibm.icu.text.MessageFormat;
023: import com.sun.jdi.ArrayType;
024: import com.sun.jdi.ClassNotLoadedException;
025: import com.sun.jdi.ClassType;
026: import com.sun.jdi.InterfaceType;
027: import com.sun.jdi.InternalException;
028: import com.sun.jdi.InvalidTypeException;
029: import com.sun.jdi.PrimitiveType;
030: import com.sun.jdi.ReferenceType;
031: import com.sun.jdi.Type;
032: import com.sun.jdi.Value;
033: import com.sun.jdi.VoidType;
034:
035: /**
036: * this class implements the corresponding interfaces
037: * declared by the JDI specification. See the com.sun.jdi package
038: * for more information.
039: *
040: */
041: public abstract class ValueImpl extends MirrorImpl implements Value {
042: /**
043: * Creates new ValueImpl.
044: */
045: protected ValueImpl(String description, VirtualMachineImpl vmImpl) {
046: super (description, vmImpl);
047: }
048:
049: /**
050: * @returns type of value.
051: */
052: public abstract Type type();
053:
054: /**
055: * @returns type of value.
056: */
057: public abstract byte getTag();
058:
059: /**
060: * @return Reads JDWP representation and returns new instance.
061: */
062: public static ValueImpl readWithTag(MirrorImpl target,
063: DataInputStream in) throws IOException {
064: byte tag = target.readByte("object tag", JdwpID.tagMap(), in); //$NON-NLS-1$
065: return readWithoutTag(target, tag, in);
066: }
067:
068: /**
069: * @return Reads JDWP representation and returns new instance.
070: */
071: public static ValueImpl readWithoutTag(MirrorImpl target, int type,
072: DataInputStream in) throws IOException {
073: VirtualMachineImpl vmImpl = target.virtualMachineImpl();
074: // See also ArrayReference Impl.
075: switch (type) {
076: case ArrayReferenceImpl.tag:
077: return ArrayReferenceImpl.read(target, in);
078: case ClassLoaderReferenceImpl.tag:
079: return ClassLoaderReferenceImpl.read(target, in);
080: case ClassObjectReferenceImpl.tag:
081: return ClassObjectReferenceImpl.read(target, in);
082: case StringReferenceImpl.tag:
083: return StringReferenceImpl.read(target, in);
084: case ObjectReferenceImpl.tag:
085: return ObjectReferenceImpl.readObjectRefWithoutTag(target,
086: in);
087: case ThreadGroupReferenceImpl.tag:
088: return ThreadGroupReferenceImpl.read(target, in);
089: case ThreadReferenceImpl.tag:
090: return ThreadReferenceImpl.read(target, in);
091: case BooleanValueImpl.tag:
092: return BooleanValueImpl.read(target, in);
093: case ByteValueImpl.tag:
094: return ByteValueImpl.read(target, in);
095: case CharValueImpl.tag:
096: return CharValueImpl.read(target, in);
097: case DoubleValueImpl.tag:
098: return DoubleValueImpl.read(target, in);
099: case FloatValueImpl.tag:
100: return FloatValueImpl.read(target, in);
101: case IntegerValueImpl.tag:
102: return IntegerValueImpl.read(target, in);
103: case LongValueImpl.tag:
104: return LongValueImpl.read(target, in);
105: case ShortValueImpl.tag:
106: return ShortValueImpl.read(target, in);
107: case VoidValueImpl.tag:
108: return new VoidValueImpl(vmImpl);
109: case 0:
110: return null;
111: default:
112: throw new InternalException(
113: JDIMessages.ValueImpl_Invalid_Value_tag_encountered___1
114: + type);
115: }
116: }
117:
118: /**
119: * Writes value with value tag.
120: */
121: public void writeWithTag(MirrorImpl target, DataOutputStream out)
122: throws IOException {
123: target.writeByte(getTag(), "tag", JdwpID.tagMap(), out); //$NON-NLS-1$
124: write(target, out);
125: }
126:
127: /**
128: * Writes value without value tag.
129: */
130: public abstract void write(MirrorImpl target, DataOutputStream out)
131: throws IOException;
132:
133: /**
134: * Writes null value without value tag.
135: */
136: public static void writeNull(MirrorImpl target, DataOutputStream out)
137: throws IOException {
138: JdwpObjectID nullID = new JdwpObjectID(target
139: .virtualMachineImpl());
140: nullID.write(out);
141: if (target.fVerboseWriter != null)
142: target.fVerboseWriter.println(
143: "objectReference", nullID.value()); //$NON-NLS-1$
144: }
145:
146: /**
147: * Writes null value with value tag.
148: */
149: public static void writeNullWithTag(MirrorImpl target,
150: DataOutputStream out) throws IOException {
151: target.writeByte(ObjectReferenceImpl.tag,
152: "tag", JdwpID.tagMap(), out); //$NON-NLS-1$
153: writeNull(target, out);
154: }
155:
156: /**
157: * Check the type and the vm of each values, according to the associated type.
158: * For primitive values, convert the value for match the given type if needed.
159: * The two list must have the same size.
160: * @return the (converted) values.
161: * @see checkValue(Value, Type, VirtualMachineImpl)
162: */
163: protected static List checkValues(List values, List types,
164: VirtualMachineImpl vm) throws InvalidTypeException {
165: List result = new ArrayList(values.size());
166: Iterator iterValues = values.iterator();
167: Iterator iterTypes = types.iterator();
168: while (iterValues.hasNext()) {
169: Value value = (Value) iterValues.next();
170: Type type = (Type) iterTypes.next();
171: result.add(checkValue(value, type, vm));
172: }
173: return result;
174: }
175:
176: /**
177: * Check the type and the vm of the given value.
178: * In case of primitive value, the value is converted if needed.
179: * @return the (converted) value.
180: * @throws InvalidTypeException if the given value is no assignment
181: * compatible with the given type.
182: * @see checkPrimitiveValue(PrimitiveValueImpl, PrimitiveTypeImpl, PrimitiveTypeImpl)
183: */
184: public static ValueImpl checkValue(Value value, Type type,
185: VirtualMachineImpl vm) throws InvalidTypeException {
186: if (value == null) {
187: if (!(type instanceof PrimitiveType)) {
188: return null;
189: }
190: } else {
191: vm.checkVM(value);
192: TypeImpl valueType = (TypeImpl) value.type();
193: if (valueType instanceof PrimitiveType
194: && type instanceof PrimitiveType) {
195: return checkPrimitiveValue((PrimitiveValueImpl) value,
196: (PrimitiveTypeImpl) valueType,
197: (PrimitiveTypeImpl) type);
198: }
199: if (valueType instanceof ReferenceType
200: && type instanceof ReferenceType) {
201: checkReferenceType((ReferenceType) valueType,
202: (ReferenceType) type);
203: return (ValueImpl) value;
204: }
205: if (valueType instanceof VoidType
206: && type instanceof VoidType) {
207: return (VoidValueImpl) value;
208: }
209: }
210: throw new InvalidTypeException(
211: MessageFormat
212: .format(
213: JDIMessages.ValueImpl_Type_of_the_value_not_compatible_with_the_expected_type__1,
214: new String[] { value.type().name(),
215: type.name() }));
216: }
217:
218: /**
219: */
220: private static void checkReferenceType(ReferenceType valueType,
221: ReferenceType type) throws InvalidTypeException {
222: if (valueType instanceof ArrayType) {
223: if (type instanceof ArrayType) {
224: try {
225: Type valueComponentType = ((ArrayType) valueType)
226: .componentType();
227: Type componentType = ((ArrayType) type)
228: .componentType();
229: if (valueComponentType instanceof PrimitiveType) {
230: if (valueComponentType.equals(componentType)) {
231: return;
232: }
233: } else if (valueComponentType instanceof ReferenceType
234: && componentType instanceof ReferenceType) {
235: checkReferenceType(
236: (ReferenceType) valueComponentType,
237: (ReferenceType) componentType);
238: return;
239: }
240: } catch (ClassNotLoadedException e) {
241: // should not append
242: }
243: } else {
244: // an array can be assigned to an object
245: if (type.signature().equals("Ljava/lang/Object;")) { //$NON-NLS-1$
246: return;
247: }
248: }
249: } else {
250: if (type instanceof ClassType) {
251: if (valueType instanceof ClassType) {
252: ClassType super Class = (ClassType) valueType;
253: while (super Class != null) {
254: if (super Class.equals(type)) {
255: return;
256: }
257: super Class = super Class.super class();
258: }
259: } else if (valueType instanceof InterfaceType) {
260: // an interface can be assigned to an object
261: if (type.signature().equals("Ljava/lang/Object;")) { //$NON-NLS-1$
262: return;
263: }
264: }
265: } else if (type instanceof InterfaceType) {
266: if (valueType instanceof InterfaceType) {
267: if (checkInterfaceType((InterfaceType) valueType,
268: (InterfaceType) type)) {
269: return;
270: }
271: } else {
272: List interfaces = ((ClassType) valueType)
273: .allInterfaces();
274: for (Iterator iter = interfaces.iterator(); iter
275: .hasNext();) {
276: if (checkInterfaceType((InterfaceType) iter
277: .next(), (InterfaceType) type)) {
278: return;
279: }
280: }
281: }
282: }
283: }
284:
285: throw new InvalidTypeException(
286: MessageFormat
287: .format(
288: JDIMessages.ValueImpl_Type_of_the_value_not_compatible_with_the_expected_type__1,
289: new String[] { valueType.name(),
290: type.name() }));
291: }
292:
293: private static boolean checkInterfaceType(InterfaceType valueType,
294: InterfaceType type) {
295: if (valueType.equals(type)) {
296: return true;
297: }
298: List super Interfaces = valueType.super interfaces();
299: for (Iterator iter = super Interfaces.iterator(); iter.hasNext();) {
300: if (checkInterfaceType((InterfaceType) iter.next(), type)) {
301: return true;
302: }
303: }
304: return false;
305: }
306:
307: /**
308: * Check the type of the given value, and convert the value to the given
309: * type if needed (see Java Language Spec, section 5.2).
310: * @return the (converted) value.
311: * @throws InvalidTypeException if the given value is no assignment
312: * compatible with the given type.
313: */
314: protected static ValueImpl checkPrimitiveValue(
315: PrimitiveValueImpl value, PrimitiveTypeImpl valueType,
316: PrimitiveTypeImpl type) throws InvalidTypeException {
317: char valueTypeSignature = valueType.signature().charAt(0);
318: char typeSignature = type.signature().charAt(0);
319: if (valueTypeSignature == typeSignature) {
320: return value;
321: }
322: VirtualMachineImpl vm = value.virtualMachineImpl();
323: switch (typeSignature) {
324: case 'D':
325: if (valueTypeSignature != 'Z') {
326: return new DoubleValueImpl(vm, new Double(value
327: .doubleValue()));
328: }
329: break;
330: case 'F':
331: if (valueTypeSignature != 'Z' && valueTypeSignature != 'D') {
332: return new FloatValueImpl(vm, new Float(value
333: .floatValue()));
334: }
335: break;
336: case 'J':
337: if (valueTypeSignature != 'Z' && valueTypeSignature != 'D'
338: && valueTypeSignature != 'F') {
339: return new LongValueImpl(vm,
340: new Long(value.longValue()));
341: }
342: break;
343: case 'I':
344: if (valueTypeSignature == 'B' || valueTypeSignature == 'C'
345: || valueTypeSignature == 'S') {
346: return new IntegerValueImpl(vm, new Integer(value
347: .intValue()));
348: }
349: break;
350: case 'S':
351: if (valueTypeSignature == 'B') {
352: return new ShortValueImpl(vm, new Short(value
353: .shortValue()));
354: }
355: break;
356: }
357: throw new InvalidTypeException(
358: MessageFormat
359: .format(
360: JDIMessages.ValueImpl_Type_of_the_value_not_compatible_with_the_expected_type__1,
361: new String[] { valueType.name(),
362: type.name() }));
363: }
364: }
|