001: /*******************************************************************************
002: * Copyright (c) 2000, 2005 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.spy;
011:
012: import java.io.DataInputStream;
013: import java.io.DataOutputStream;
014: import java.io.IOException;
015: import java.lang.reflect.Field;
016: import java.lang.reflect.Modifier;
017: import java.util.HashMap;
018: import java.util.Map;
019:
020: /**
021: * This class implements the corresponding Java Debug Wire Protocol (JDWP) packet
022: * declared by the JDWP specification.
023: *
024: */
025: public class JdwpCommandPacket extends JdwpPacket {
026: /** Command Sets. */
027: public static final int CSET_VIRTUAL_MACHINE = 1;
028: public static final int CSET_REFERENCE_TYPE = 2;
029: public static final int CSET_CLASS_TYPE = 3;
030: public static final int CSET_ARRAY_TYPE = 4;
031: public static final int CSET_INTERFACE_TYPE = 5;
032: public static final int CSET_METHOD = 6;
033: public static final int CSET_FIELD = 8;
034: public static final int CSET_OBJECT_REFERENCE = 9;
035: public static final int CSET_STRING_REFERENCE = 10;
036: public static final int CSET_THREAD_REFERENCE = 11;
037: public static final int CSET_THREAD_GROUP_REFERENCE = 12;
038: public static final int CSET_ARRAY_REFERENCE = 13;
039: public static final int CSET_CLASS_LOADER_REFERENCE = 14;
040: public static final int CSET_EVENT_REQUEST = 15;
041: public static final int CSET_STACK_FRAME = 16;
042: public static final int CSET_CLASS_OBJECT_REFERENCE = 17;
043: public static final int CSET_EVENT = 64;
044: public static final int CSET_HOT_CODE_REPLACEMENT = 128;
045:
046: /** Commands VirtualMachine. */
047: public static final int VM_VERSION = 1 + (CSET_VIRTUAL_MACHINE << 8);
048: public static final int VM_CLASSES_BY_SIGNATURE = 2 + (CSET_VIRTUAL_MACHINE << 8);
049: public static final int VM_ALL_CLASSES = 3 + (CSET_VIRTUAL_MACHINE << 8);
050: public static final int VM_ALL_THREADS = 4 + (CSET_VIRTUAL_MACHINE << 8);
051: public static final int VM_TOP_LEVEL_THREAD_GROUPS = 5 + (CSET_VIRTUAL_MACHINE << 8);
052: public static final int VM_DISPOSE = 6 + (CSET_VIRTUAL_MACHINE << 8);
053: public static final int VM_ID_SIZES = 7 + (CSET_VIRTUAL_MACHINE << 8);
054: public static final int VM_SUSPEND = 8 + (CSET_VIRTUAL_MACHINE << 8);
055: public static final int VM_RESUME = 9 + (CSET_VIRTUAL_MACHINE << 8);
056: public static final int VM_EXIT = 10 + (CSET_VIRTUAL_MACHINE << 8);
057: public static final int VM_CREATE_STRING = 11 + (CSET_VIRTUAL_MACHINE << 8);
058: public static final int VM_CAPABILITIES = 12 + (CSET_VIRTUAL_MACHINE << 8);
059: public static final int VM_CLASS_PATHS = 13 + (CSET_VIRTUAL_MACHINE << 8);
060: public static final int VM_DISPOSE_OBJECTS = 14 + (CSET_VIRTUAL_MACHINE << 8);
061: public static final int VM_HOLD_EVENTS = 15 + (CSET_VIRTUAL_MACHINE << 8);
062: public static final int VM_RELEASE_EVENTS = 16 + (CSET_VIRTUAL_MACHINE << 8);
063: public static final int VM_CAPABILITIES_NEW = 17 + (CSET_VIRTUAL_MACHINE << 8);
064: public static final int VM_REDEFINE_CLASSES = 18 + (CSET_VIRTUAL_MACHINE << 8);
065: public static final int VM_SET_DEFAULT_STRATUM = 19 + (CSET_VIRTUAL_MACHINE << 8);
066: public static final int VM_ALL_CLASSES_WITH_GENERIC = 20 + (CSET_VIRTUAL_MACHINE << 8);
067:
068: /** Commands ReferenceType. */
069: public static final int RT_SIGNATURE = 1 + (CSET_REFERENCE_TYPE << 8);
070: public static final int RT_CLASS_LOADER = 2 + (CSET_REFERENCE_TYPE << 8);
071: public static final int RT_MODIFIERS = 3 + (CSET_REFERENCE_TYPE << 8);
072: public static final int RT_FIELDS = 4 + (CSET_REFERENCE_TYPE << 8);
073: public static final int RT_METHODS = 5 + (CSET_REFERENCE_TYPE << 8);
074: public static final int RT_GET_VALUES = 6 + (CSET_REFERENCE_TYPE << 8);
075: public static final int RT_SOURCE_FILE = 7 + (CSET_REFERENCE_TYPE << 8);
076: public static final int RT_NESTED_TYPES = 8 + (CSET_REFERENCE_TYPE << 8);
077: public static final int RT_STATUS = 9 + (CSET_REFERENCE_TYPE << 8);
078: public static final int RT_INTERFACES = 10 + (CSET_REFERENCE_TYPE << 8);
079: public static final int RT_CLASS_OBJECT = 11 + (CSET_REFERENCE_TYPE << 8);
080: public static final int RT_SOURCE_DEBUG_EXTENSION = 12 + (CSET_REFERENCE_TYPE << 8);
081: public static final int RT_SIGNATURE_WITH_GENERIC = 13 + (CSET_REFERENCE_TYPE << 8);
082: public static final int RT_FIELDS_WITH_GENERIC = 14 + (CSET_REFERENCE_TYPE << 8);
083: public static final int RT_METHODS_WITH_GENERIC = 15 + (CSET_REFERENCE_TYPE << 8);
084:
085: /** Commands ClassType. */
086: public static final int CT_SUPERCLASS = 1 + (CSET_CLASS_TYPE << 8);
087: public static final int CT_SET_VALUES = 2 + (CSET_CLASS_TYPE << 8);
088: public static final int CT_INVOKE_METHOD = 3 + (CSET_CLASS_TYPE << 8);
089: public static final int CT_NEW_INSTANCE = 4 + (CSET_CLASS_TYPE << 8);
090:
091: /** Commands ArrayType. */
092: public static final int AT_NEW_INSTANCE = 1 + (CSET_ARRAY_TYPE << 8);
093:
094: /** Commands Method. */
095: public static final int M_LINE_TABLE = 1 + (CSET_METHOD << 8);
096: public static final int M_VARIABLE_TABLE = 2 + (CSET_METHOD << 8);
097: public static final int M_BYTECODES = 3 + (CSET_METHOD << 8);
098: public static final int M_IS_OBSOLETE = 4 + (CSET_METHOD << 8);
099: public static final int M_VARIABLE_TABLE_WITH_GENERIC = 5 + (CSET_METHOD << 8);
100:
101: /** Commands ObjectReference. */
102: public static final int OR_REFERENCE_TYPE = 1 + (CSET_OBJECT_REFERENCE << 8);
103: public static final int OR_GET_VALUES = 2 + (CSET_OBJECT_REFERENCE << 8);
104: public static final int OR_SET_VALUES = 3 + (CSET_OBJECT_REFERENCE << 8);
105: public static final int OR_MONITOR_INFO = 5 + (CSET_OBJECT_REFERENCE << 8);
106: public static final int OR_INVOKE_METHOD = 6 + (CSET_OBJECT_REFERENCE << 8);
107: public static final int OR_DISABLE_COLLECTION = 7 + (CSET_OBJECT_REFERENCE << 8);
108: public static final int OR_ENABLE_COLLECTION = 8 + (CSET_OBJECT_REFERENCE << 8);
109: public static final int OR_IS_COLLECTED = 9 + (CSET_OBJECT_REFERENCE << 8);
110:
111: /** Commands StringReference. */
112: public static final int SR_VALUE = 1 + (CSET_STRING_REFERENCE << 8);
113:
114: /** Commands ThreadReference. */
115: public static final int TR_NAME = 1 + (CSET_THREAD_REFERENCE << 8);
116: public static final int TR_SUSPEND = 2 + (CSET_THREAD_REFERENCE << 8);
117: public static final int TR_RESUME = 3 + (CSET_THREAD_REFERENCE << 8);
118: public static final int TR_STATUS = 4 + (CSET_THREAD_REFERENCE << 8);
119: public static final int TR_THREAD_GROUP = 5 + (CSET_THREAD_REFERENCE << 8);
120: public static final int TR_FRAMES = 6 + (CSET_THREAD_REFERENCE << 8);
121: public static final int TR_FRAME_COUNT = 7 + (CSET_THREAD_REFERENCE << 8);
122: public static final int TR_OWNED_MONITORS = 8 + (CSET_THREAD_REFERENCE << 8);
123: public static final int TR_CURRENT_CONTENDED_MONITOR = 9 + (CSET_THREAD_REFERENCE << 8);
124: public static final int TR_STOP = 10 + (CSET_THREAD_REFERENCE << 8);
125: public static final int TR_INTERRUPT = 11 + (CSET_THREAD_REFERENCE << 8);
126: public static final int TR_SUSPEND_COUNT = 12 + (CSET_THREAD_REFERENCE << 8);
127: public static final int TR_POP_TOP_FRAME = 13 + (CSET_THREAD_REFERENCE << 8);
128:
129: /** Commands ThreadGroupReference. */
130: public static final int TGR_NAME = 1 + (CSET_THREAD_GROUP_REFERENCE << 8);
131: public static final int TGR_PARENT = 2 + (CSET_THREAD_GROUP_REFERENCE << 8);
132: public static final int TGR_CHILDREN = 3 + (CSET_THREAD_GROUP_REFERENCE << 8);
133:
134: /** Commands ArrayReference. */
135: public static final int AR_LENGTH = 1 + (CSET_ARRAY_REFERENCE << 8);
136: public static final int AR_GET_VALUES = 2 + (CSET_ARRAY_REFERENCE << 8);
137: public static final int AR_SET_VALUES = 3 + (CSET_ARRAY_REFERENCE << 8);
138:
139: /** Commands ClassLoaderReference. */
140: public static final int CLR_VISIBLE_CLASSES = 1 + (CSET_CLASS_LOADER_REFERENCE << 8);
141:
142: /** Commands EventRequest. */
143: public static final int ER_SET = 1 + (CSET_EVENT_REQUEST << 8);
144: public static final int ER_CLEAR = 2 + (CSET_EVENT_REQUEST << 8);
145: public static final int ER_CLEAR_ALL_BREAKPOINTS = 3 + (CSET_EVENT_REQUEST << 8);
146:
147: /** Commands StackFrame. */
148: public static final int SF_GET_VALUES = 1 + (CSET_STACK_FRAME << 8);
149: public static final int SF_SET_VALUES = 2 + (CSET_STACK_FRAME << 8);
150: public static final int SF_THIS_OBJECT = 3 + (CSET_STACK_FRAME << 8);
151: public static final int SF_POP_FRAME = 4 + (CSET_STACK_FRAME << 8);
152:
153: /** Commands ClassObjectReference. */
154: public static final int COR_REFLECTED_TYPE = 1 + (CSET_CLASS_OBJECT_REFERENCE << 8);
155:
156: /** Commands Event. */
157: public static final int E_COMPOSITE = 100 + (CSET_EVENT << 8);
158:
159: /** Commands Hot Code Replacement (OTI specific). */
160: public static final int HCR_CLASSES_HAVE_CHANGED = 1 + (CSET_HOT_CODE_REPLACEMENT << 8);
161: public static final int HCR_GET_CLASS_VERSION = 2 + (CSET_HOT_CODE_REPLACEMENT << 8);
162: public static final int HCR_DO_RETURN = 3 + (CSET_HOT_CODE_REPLACEMENT << 8);
163: public static final int HCR_REENTER_ON_EXIT = 4 + (CSET_HOT_CODE_REPLACEMENT << 8);
164: public static final int HCR_CAPABILITIES = 5 + (CSET_HOT_CODE_REPLACEMENT << 8);
165:
166: /** Mapping of command codes to strings. */
167: private static Map fgCommandMap = null;
168:
169: /** Next id to be assigned. */
170: private static int fgNextId = 1;
171: /** Command, note that this field is 256 * JDWP CommandSet (unsigned) + JDWP Command. */
172: private int fCommand;
173:
174: /**
175: * Creates new JdwpCommandPacket.
176: */
177: protected JdwpCommandPacket() {
178: }
179:
180: /**
181: * Creates new JdwpCommandPacket.
182: */
183: public JdwpCommandPacket(int command) {
184: setCommand(command);
185: setId(getNewId());
186: }
187:
188: /**
189: * @return Returns unique id for command packet.
190: */
191: public static synchronized int getNewId() {
192: return fgNextId++;
193: }
194:
195: /**
196: * @return Returns JDWP command set of packet.
197: */
198: public byte getCommandSet() {
199: return (byte) (fCommand >>> 8);
200: }
201:
202: /**
203: * @return Returns 256 * JDWP CommandSet (unsigned) + JDWP Command.
204: */
205: public int getCommand() {
206: return fCommand;
207: }
208:
209: /**
210: * Assigns command (256 * JDWP CommandSet (unsigned) + JDWP Command)
211: */
212: public void setCommand(int command) {
213: fCommand = command;
214: }
215:
216: /**
217: * Reads header fields that are specific for this type of packet.
218: */
219: protected void readSpecificHeaderFields(DataInputStream dataInStream)
220: throws IOException {
221: byte commandSet = dataInStream.readByte();
222: fCommand = dataInStream.readByte() + (commandSet << 8);
223: }
224:
225: /**
226: * Writes header fields that are specific for this type of packet.
227: */
228: protected void writeSpecificHeaderFields(
229: DataOutputStream dataOutStream) throws IOException {
230: dataOutStream.writeByte(getCommandSet());
231: dataOutStream.writeByte((byte) fCommand);
232: }
233:
234: /**
235: * Retrieves constant mappings.
236: */
237: public static void getConstantMaps() {
238: if (fgCommandMap != null) {
239: return;
240: }
241:
242: Field[] fields = JdwpCommandPacket.class.getDeclaredFields();
243:
244: // First get the set names.
245: Map setNames = new HashMap(fields.length);
246: for (int i = 0; i < fields.length; i++) {
247: Field field = fields[i];
248: if ((field.getModifiers() & Modifier.PUBLIC) == 0
249: || (field.getModifiers() & Modifier.STATIC) == 0
250: || (field.getModifiers() & Modifier.FINAL) == 0)
251: continue;
252:
253: try {
254: String name = field.getName();
255: // If it is not a set, continue.
256: if (!name.startsWith("CSET_")) {//$NON-NLS-1$
257: continue;
258: }
259: int value = field.getInt(null);
260: setNames.put(new Integer(value), removePrefix(name));
261: } catch (IllegalAccessException e) {
262: // Will not occur for own class.
263: } catch (IllegalArgumentException e) {
264: // Should not occur.
265: // We should take care that all public static final constants
266: // in this class are numbers that are convertible to int.
267: }
268: }
269:
270: // Get the commands.
271: fgCommandMap = new HashMap();
272: for (int i = 0; i < fields.length; i++) {
273: Field field = fields[i];
274: if ((field.getModifiers() & Modifier.PUBLIC) == 0
275: || (field.getModifiers() & Modifier.STATIC) == 0
276: || (field.getModifiers() & Modifier.FINAL) == 0) {
277: continue;
278: }
279:
280: try {
281: String name = field.getName();
282:
283: // If it is a set, continue.
284: if (name.startsWith("CSET_")) { //$NON-NLS-1$
285: continue;
286: }
287: Integer val = (Integer) field.get(null);
288: int value = val.intValue();
289: int set = value >>> 8;
290: String setName = (String) setNames
291: .get(new Integer(set));
292: String entryName = setName + " - " + removePrefix(name); //$NON-NLS-1$
293:
294: fgCommandMap.put(val, entryName);
295:
296: } catch (IllegalAccessException e) {
297: // Will not occur for own class.
298: }
299: }
300: }
301:
302: /**
303: * @return Returns a map with string representations of error codes.
304: */
305: public static Map commandMap() {
306: getConstantMaps();
307: return fgCommandMap;
308: }
309:
310: /**
311: * @return Returns string without XXX_ prefix.
312: */
313: public static String removePrefix(String str) {
314: int i = str.indexOf('_');
315: if (i < 0) {
316: return str;
317: }
318: return str.substring(i + 1);
319: }
320: }
|