/* * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package com.sun.max.jdwp.data; import java.io.*; import com.sun.max.jdwp.constants.*; import com.sun.max.jdwp.data.ID.*; /** * Class representing a JDWPValue. Instances of this class can represent any possible JDWP value (see {@link com.sun.max.jdwp.constants.Tag}). * For simplicity, this class is implemented as a union. The methods starting with "as" return the specific representation of the object or null, if * the object is of a different representation. */ public class JDWPValue { private byte tag; private Object value; public JDWPValue(InputStream is) throws IOException { tag = (byte) is.read(); readValue(is); } public JDWPValue(InputStream is, int typeTag) throws IOException { tag = (byte) typeTag; readValue(is); } public JDWPValue(ID.ArrayID v) { value = v; tag = Tag.ARRAY; } public JDWPValue(Byte v) { value = v; tag = Tag.BYTE; } public JDWPValue(Character v) { value = v; tag = Tag.CHAR; } public JDWPValue(ID.ObjectID v) { value = v; tag = Tag.OBJECT; } public JDWPValue(Float v) { value = v; tag = Tag.FLOAT; } public JDWPValue(Double v) { value = v; tag = Tag.DOUBLE; } public JDWPValue(Integer v) { value = v; tag = Tag.INT; } public JDWPValue(Long v) { value = v; tag = Tag.LONG; } public JDWPValue(Short v) { value = v; tag = Tag.SHORT; } public JDWPValue() { tag = Tag.VOID; } public JDWPValue(Boolean v) { value = v; tag = Tag.BOOLEAN; } public JDWPValue(ID.StringID v) { value = v; tag = Tag.STRING; } public JDWPValue(ID.ThreadID v) { value = v; tag = Tag.THREAD; } public JDWPValue(ID.ThreadGroupID v) { value = v; tag = Tag.THREAD_GROUP; } public JDWPValue(ID.ClassLoaderID v) { value = v; tag = Tag.CLASS_LOADER; } public JDWPValue(ID.ClassObjectID v) { value = v; tag = Tag.CLASS_OBJECT; } public byte tag() { return tag; } public ID.ArrayID asArray() { return (tag == Tag.ARRAY) ? (ID.ArrayID) value : null; } public Byte asByte() { return (tag == Tag.BYTE) ? (Byte) value : null; } public Character asCharacter() { return (tag == Tag.CHAR) ? (Character) value : null; } public ID.ObjectID asObject() { return (tag == Tag.OBJECT) ? (ID.ObjectID) value : null; } public Float asFloat() { return (tag == Tag.FLOAT) ? (Float) value : null; } public Double asDouble() { return (tag == Tag.DOUBLE) ? (Double) value : null; } public Integer asInteger() { return (tag == Tag.INT) ? (Integer) value : null; } public Long asLong() { return (tag == Tag.LONG) ? (Long) value : null; } public Short asShort() { return (tag == Tag.SHORT) ? (Short) value : null; } public boolean isVoid() { return tag == Tag.VOID; } public Boolean asBoolean() { return (tag == Tag.BOOLEAN) ? (Boolean) value : null; } public ID.StringID asString() { return (tag == Tag.STRING) ? (ID.StringID) value : null; } public ID.ThreadID asThread() { return (tag == Tag.THREAD) ? (ID.ThreadID) value : null; } public ID.ThreadGroupID asThreadGroup() { return (tag == Tag.THREAD_GROUP) ? (ID.ThreadGroupID) value : null; } public ID.ClassLoaderID asClassLoader() { return (tag == Tag.CLASS_LOADER) ? (ID.ClassLoaderID) value : null; } public ID.ClassObjectID asClassObject() { return (tag == Tag.CLASS_OBJECT) ? (ID.ClassObjectID) value : null; } /** * Writes this value untagged onto an output stream. * @param outputStream the stream to write the data on * @throws IOException this exception is thrown, when a problem occurred while writing the raw bytes */ public void writeUntagged(OutputStream outputStream) throws IOException { final DataOutputStream dos = new DataOutputStream(outputStream); switch (tag) { case Tag.ARRAY: asArray().write(dos); break; case Tag.BYTE: dos.writeByte(asByte().byteValue()); break; case Tag.CHAR: dos.writeChar(asCharacter().charValue()); break; case Tag.OBJECT: asObject().write(dos); break; case Tag.FLOAT: dos.writeFloat(asFloat().floatValue()); break; case Tag.DOUBLE: dos.writeDouble(asDouble().doubleValue()); break; case Tag.INT: dos.writeInt(asInteger().intValue()); break; case Tag.LONG: dos.writeLong(asLong().longValue()); break; case Tag.SHORT: dos.writeShort(asShort().shortValue()); break; case Tag.VOID: break; case Tag.BOOLEAN: dos.writeBoolean(asBoolean().booleanValue()); break; case Tag.STRING: asString().write(dos); break; case Tag.THREAD: asThread().write(dos); break; case Tag.THREAD_GROUP: asThreadGroup().write(dos); break; case Tag.CLASS_LOADER: asClassLoader().write(dos); break; case Tag.CLASS_OBJECT: asClassObject().write(dos); break; default: assert false : "Unhandled Tag constant!"; } } /** * Writes this value as a tagged value to the output stream. * @param outputStream stream to write the value on * @throws IOException this exception is thrown, when there is a problem writing the raw bytes */ public void write(OutputStream outputStream) throws IOException { final DataOutputStream dos = new DataOutputStream(outputStream); dos.writeByte(tag()); writeUntagged(outputStream); } private void readValue(InputStream is) throws IOException { switch (tag) { case Tag.ARRAY: value = ID.read(is, ID.ArrayID.class); break; case Tag.BYTE: value = new Byte(new DataInputStream(is).readByte()); break; case Tag.CHAR: value = new Character(new DataInputStream(is).readChar()); break; case Tag.OBJECT: value = ID.read(is, ID.ObjectID.class); break; case Tag.FLOAT: value = new Float(new DataInputStream(is).readFloat()); break; case Tag.DOUBLE: value = new Double(new DataInputStream(is).readDouble()); break; case Tag.INT: value = new Integer(new DataInputStream(is).readInt()); break; case Tag.LONG: value = new Long(new DataInputStream(is).readLong()); break; case Tag.SHORT: value = new Short(new DataInputStream(is).readShort()); break; case Tag.VOID: break; case Tag.BOOLEAN: value = new Boolean(new DataInputStream(is).readBoolean()); break; case Tag.STRING: value = ID.read(is, ID.StringID.class); break; case Tag.THREAD: value = ID.read(is, ID.ThreadID.class); break; case Tag.THREAD_GROUP: value = ID.read(is, ID.ThreadGroupID.class); break; case Tag.CLASS_LOADER: value = ID.read(is, ID.ClassLoaderID.class); break; case Tag.CLASS_OBJECT: value = ID.read(is, ID.ClassObjectID.class); break; default: assert false : "Unhandled Tag constant " + tag + "!"; } } /** * Returns an object identifier, if this value represents any subclass of {@link ID.ObjectID}. * @return the object identifier or null, if the value cannot be converted to it */ public ID.ObjectID asGeneralObjectID() { return (value instanceof ObjectID) ? (ID.ObjectID) value : null; } @Override public String toString() { return "JDWPValue(" + tag + ")[" + value + "]"; } }