1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements.  See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License.  You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *
15  *  See the License for the specific language governing permissions and
16  *  limitations under the License.
17  */
18 
19 /**
20  * @author Vitaly A. Provodin
21  */
22 
23 package org.apache.harmony.jpda.tests.framework.jdwp;
24 
25 import java.io.IOException;
26 import java.util.ArrayList;
27 import java.util.Iterator;
28 import java.util.List;
29 
30 import org.apache.harmony.jpda.tests.framework.Breakpoint;
31 import org.apache.harmony.jpda.tests.framework.LogWriter;
32 import org.apache.harmony.jpda.tests.framework.TestErrorException;
33 import org.apache.harmony.jpda.tests.framework.TestOptions;
34 import org.apache.harmony.jpda.tests.framework.jdwp.Capabilities;
35 import org.apache.harmony.jpda.tests.framework.jdwp.CommandPacket;
36 import org.apache.harmony.jpda.tests.framework.jdwp.Event;
37 import org.apache.harmony.jpda.tests.framework.jdwp.EventMod;
38 import org.apache.harmony.jpda.tests.framework.jdwp.JDWPConstants;
39 import org.apache.harmony.jpda.tests.framework.jdwp.Location;
40 import org.apache.harmony.jpda.tests.framework.jdwp.ReplyPacket;
41 import org.apache.harmony.jpda.tests.framework.jdwp.TransportWrapper;
42 import org.apache.harmony.jpda.tests.framework.jdwp.TypesLengths;
43 import org.apache.harmony.jpda.tests.framework.jdwp.Frame.Variable;
44 import org.apache.harmony.jpda.tests.framework.jdwp.exceptions.ReplyErrorCodeException;
45 import org.apache.harmony.jpda.tests.framework.jdwp.exceptions.TimeoutException;
46 
47 /**
48  * This class provides convenient way for communicating with debuggee VM using
49  * JDWP packets.
50  * <p>
51  * Most methods can throw ReplyErrorCodeException if error occurred in execution
52  * of corresponding JDWP command or TestErrorException if any other error
53  * occurred.
54  */
55 public class VmMirror {
56 
57     /** Target VM Capabilities. */
58     public Capabilities targetVMCapabilities;
59 
60     /** Transport used to sent and receive packets. */
61     private TransportWrapper connection;
62 
63     /** PacketDispatcher thread used for asynchronous reading packets. */
64     private PacketDispatcher packetDispatcher;
65 
66     /** Test run options. */
67     protected TestOptions config;
68 
69     /** Log to write messages. */
70     protected LogWriter logWriter;
71 
72     /**
73      * Creates new VmMirror instance for given test run options.
74      *
75      * @param config
76      *            test run options
77      * @param logWriter
78      *            log writer
79      */
VmMirror(TestOptions config, LogWriter logWriter)80     public VmMirror(TestOptions config, LogWriter logWriter) {
81         connection = null;
82         this.config = config;
83         this.logWriter = logWriter;
84     }
85 
86     /**
87      * Checks error code of given reply packet and throws
88      * ReplyErrorCodeException if any error detected.
89      *
90      * @param reply
91      *            reply packet to check
92      * @return ReplyPacket unchanged reply packet
93      */
checkReply(ReplyPacket reply)94     public ReplyPacket checkReply(ReplyPacket reply) {
95         if (reply.getErrorCode() != JDWPConstants.Error.NONE)
96             throw new ReplyErrorCodeException(reply.getErrorCode());
97         return reply;
98     }
99 
100     /**
101      * Sets breakpoint to given location.
102      *
103      * @param typeTag
104      * @param breakpoint
105      * @return ReplyPacket for corresponding command
106      */
setBreakpoint(byte typeTag, Breakpoint breakpoint)107     public ReplyPacket setBreakpoint(byte typeTag, Breakpoint breakpoint) {
108 
109         return setBreakpoint(typeTag, breakpoint,
110                 JDWPConstants.SuspendPolicy.ALL);
111     }
112 
113     /**
114      * Sets breakpoint to given location.
115      *
116      * @param typeTag
117      * @param breakpoint
118      * @param suspendPolicy
119      *            Suspend policy for a breakpoint being created
120      * @return ReplyPacket for corresponding command
121      */
setBreakpoint(byte typeTag, Breakpoint breakpoint, byte suspendPolicy)122     public ReplyPacket setBreakpoint(byte typeTag, Breakpoint breakpoint,
123             byte suspendPolicy) {
124         // Get Class reference ID
125         long typeID = getTypeID(breakpoint.className, typeTag);
126 
127         // Get Method reference ID
128         long methodID = getMethodID(typeID, breakpoint.methodName);
129 
130         // Fill location
131         Location location = new Location(typeTag, typeID, methodID,
132                 breakpoint.index);
133 
134         // Set breakpoint
135         return setBreakpoint(location, suspendPolicy);
136     }
137 
138     /**
139      * Sets breakpoint to given location.
140      *
141      * @param location
142      *            Location of breakpoint
143      * @return ReplyPacket for corresponding command
144      */
setBreakpoint(Location location)145     public ReplyPacket setBreakpoint(Location location) {
146 
147         return setBreakpoint(location, JDWPConstants.SuspendPolicy.ALL);
148     }
149 
150     /**
151      * Sets breakpoint to given location
152      *
153      * @param location
154      *            Location of breakpoint
155      * @param suspendPolicy
156      *            Suspend policy for a breakpoint being created
157      * @return ReplyPacket for corresponding command
158      */
setBreakpoint(Location location, byte suspendPolicy)159     public ReplyPacket setBreakpoint(Location location, byte suspendPolicy) {
160         // Prepare corresponding event
161         byte eventKind = JDWPConstants.EventKind.BREAKPOINT;
162 
163         // EventMod[] mods = new EventMod[1];
164         EventMod[] mods = new EventMod[] { new EventMod() };
165 
166         mods[0].loc = location;
167         mods[0].modKind = EventMod.ModKind.LocationOnly;
168         Event event = new Event(eventKind, suspendPolicy, mods);
169 
170         // Set breakpoint
171         return setEvent(event);
172     }
173 
174     /**
175      * Sets breakpoint that triggers only on a certain occurrence to a given
176      * location
177      *
178      * @param typeTag
179      * @param breakpoint
180      * @param suspendPolicy
181      *            Suspend policy for a breakpoint being created
182      * @param count
183      *            Limit the requested event to be reported at most once after a
184      *            given number of occurrences
185      * @return ReplyPacket for corresponding command
186      */
setCountableBreakpoint(byte typeTag, Breakpoint breakpoint, byte suspendPolicy, int count)187     public ReplyPacket setCountableBreakpoint(byte typeTag,
188             Breakpoint breakpoint, byte suspendPolicy, int count) {
189         long typeID = getTypeID(breakpoint.className, typeTag);
190 
191         // Get Method reference ID
192         long methodID = getMethodID(typeID, breakpoint.methodName);
193 
194         byte eventKind = JDWPConstants.EventKind.BREAKPOINT;
195 
196         EventMod mod1 = new EventMod();
197         mod1.modKind = EventMod.ModKind.LocationOnly;
198         mod1.loc = new Location(typeTag, typeID, methodID, breakpoint.index);
199 
200         EventMod mod2 = new EventMod();
201         mod2.modKind = EventMod.ModKind.Count;
202         mod2.count = count;
203 
204         EventMod[] mods = new EventMod[] { mod1, mod2 };
205         Event event = new Event(eventKind, suspendPolicy, mods);
206 
207         // Set breakpoint
208         return setEvent(event);
209     }
210 
211     /**
212      * Sets breakpoint at the beginning of method with name <i>methodName</i>.
213      *
214      * @param classID
215      *            id of class with required method
216      * @param methodName
217      *            name of required method
218      * @return requestID id of request
219      */
setBreakpointAtMethodBegin(long classID, String methodName)220     public int setBreakpointAtMethodBegin(long classID, String methodName) {
221         return setBreakpointAtMethodBegin(classID, methodName, JDWPConstants.SuspendPolicy.ALL);
222     }
223 
224     /**
225      * Sets breakpoint at the beginning of method with name <i>methodName</i>.
226      *
227      * @param classID
228      *            id of class with required method
229      * @param methodName
230      *            name of required method
231      * @return requestID id of request
232      */
setBreakpointAtMethodBegin(long classID, String methodName, byte suspendPolicy)233     public int setBreakpointAtMethodBegin(long classID, String methodName, byte suspendPolicy) {
234         long methodID = getMethodID(classID, methodName);
235 
236         ReplyPacket lineTableReply = getLineTable(classID, methodID);
237         if (lineTableReply.getErrorCode() != JDWPConstants.Error.NONE) {
238             throw new TestErrorException(
239                     "Command getLineTable returned error code: "
240                             + lineTableReply.getErrorCode()
241                             + " - "
242                             + JDWPConstants.Error.getName(lineTableReply
243                                     .getErrorCode()));
244         }
245 
246         lineTableReply.getNextValueAsLong();
247         // Lowest valid code index for the method
248 
249         lineTableReply.getNextValueAsLong();
250         // Highest valid code index for the method
251 
252         // int numberOfLines =
253         lineTableReply.getNextValueAsInt();
254 
255         long lineCodeIndex = lineTableReply.getNextValueAsLong();
256 
257         // set breakpoint inside checked method
258         Location breakpointLocation = new Location(JDWPConstants.TypeTag.CLASS,
259                 classID, methodID, lineCodeIndex);
260 
261         ReplyPacket reply = setBreakpoint(breakpointLocation, suspendPolicy);
262         checkReply(reply);
263 
264         return reply.getNextValueAsInt();
265     }
266 
267     /**
268      * Waits for stop on breakpoint and gets id of thread where it stopped.
269      *
270      * @param requestID
271      *            id of request for breakpoint
272      * @return threadID id of thread, where we stop on breakpoint
273      */
waitForBreakpoint(int requestID)274     public long waitForBreakpoint(int requestID) {
275         // receive event
276         CommandPacket event = null;
277         event = receiveEvent();
278 
279         event.getNextValueAsByte();
280         // suspendPolicy - is not used here
281 
282         // int numberOfEvents =
283         event.getNextValueAsInt();
284 
285         long breakpointThreadID = 0;
286         ParsedEvent[] eventParsed = ParsedEvent.parseEventPacket(event);
287 
288         if (eventParsed.length != 1) {
289             throw new TestErrorException("Received " + eventParsed.length
290                     + " events instead of 1 BREAKPOINT_EVENT");
291         }
292 
293         // check if received event is for breakpoint
294         if (eventParsed[0].getEventKind() == JDWPConstants.EventKind.BREAKPOINT) {
295             breakpointThreadID = ((ParsedEvent.Event_BREAKPOINT) eventParsed[0])
296                     .getThreadID();
297 
298         } else {
299             throw new TestErrorException(
300                     "Kind of received event is not BREAKPOINT_EVENT: "
301                             + eventParsed[0].getEventKind());
302 
303         }
304 
305         if (eventParsed[0].getRequestID() != requestID) {
306             throw new TestErrorException(
307                     "Received BREAKPOINT_EVENT with another requestID: "
308                             + eventParsed[0].getRequestID());
309         }
310 
311         return breakpointThreadID;
312     }
313 
314     /**
315      * Removes breakpoint according to specified requestID.
316      *
317      * @param requestID
318      *            for given breakpoint
319      * @return ReplyPacket for corresponding command
320      */
clearBreakpoint(int requestID)321     public ReplyPacket clearBreakpoint(int requestID) {
322 
323         // Create new command packet
324         CommandPacket commandPacket = new CommandPacket();
325 
326         // Set command. "2" - is ID of Clear command in EventRequest Command Set
327         commandPacket
328                 .setCommand(JDWPCommands.EventRequestCommandSet.ClearCommand);
329 
330         // Set command set. "15" - is ID of EventRequest Command Set
331         commandPacket
332                 .setCommandSet(JDWPCommands.EventRequestCommandSet.CommandSetID);
333 
334         // Set outgoing data
335         // Set eventKind
336         commandPacket.setNextValueAsByte(JDWPConstants.EventKind.BREAKPOINT);
337 
338         // Set suspendPolicy
339         commandPacket.setNextValueAsInt(requestID);
340 
341         // Send packet
342         return checkReply(performCommand(commandPacket));
343     }
344 
345     /**
346      * Removes all breakpoints.
347      *
348      * @return ReplyPacket for corresponding command
349      */
ClearAllBreakpoints()350     public ReplyPacket ClearAllBreakpoints() {
351 
352         // Create new command packet
353         CommandPacket commandPacket = new CommandPacket();
354 
355         // Set command. "3" - is ID of ClearAllBreakpoints command in
356         // EventRequest Command Set
357         commandPacket
358                 .setCommand(JDWPCommands.EventRequestCommandSet.ClearAllBreakpointsCommand);
359 
360         // Set command set. "15" - is ID of EventRequest Command Set
361         commandPacket
362                 .setCommandSet(JDWPCommands.EventRequestCommandSet.CommandSetID);
363 
364         // Send packet
365         return checkReply(performCommand(commandPacket));
366     }
367 
368     /**
369      * Requests debuggee VM capabilities. Function parses reply packet of
370      * VirtualMachine::CapabilitiesNew command, creates and fills class
371      * Capabilities with returned info.
372      *
373      * @return ReplyPacket useless, already parsed reply packet.
374      */
capabilities()375     public ReplyPacket capabilities() {
376 
377         // Create new command packet
378         CommandPacket commandPacket = new CommandPacket();
379 
380         // Set command. "17" - is ID of CapabilitiesNew command in
381         // VirtualMachine Command Set
382         commandPacket
383                 .setCommand(JDWPCommands.VirtualMachineCommandSet.CapabilitiesNewCommand);
384 
385         // Set command set. "1" - is ID of VirtualMachine Command Set
386         commandPacket
387                 .setCommandSet(JDWPCommands.VirtualMachineCommandSet.CommandSetID);
388 
389         // Send packet
390         ReplyPacket replyPacket = checkReply(performCommand(commandPacket));
391 
392         targetVMCapabilities = new Capabilities();
393 
394         // Set capabilities
395         targetVMCapabilities.canWatchFieldModification = replyPacket
396                 .getNextValueAsBoolean();
397         targetVMCapabilities.canWatchFieldAccess = replyPacket
398                 .getNextValueAsBoolean();
399         targetVMCapabilities.canGetBytecodes = replyPacket
400                 .getNextValueAsBoolean();
401         targetVMCapabilities.canGetSyntheticAttribute = replyPacket
402                 .getNextValueAsBoolean();
403         targetVMCapabilities.canGetOwnedMonitorInfo = replyPacket
404                 .getNextValueAsBoolean();
405         targetVMCapabilities.canGetCurrentContendedMonitor = replyPacket
406                 .getNextValueAsBoolean();
407         targetVMCapabilities.canGetMonitorInfo = replyPacket
408                 .getNextValueAsBoolean();
409         targetVMCapabilities.canRedefineClasses = replyPacket
410                 .getNextValueAsBoolean();
411         targetVMCapabilities.canAddMethod = replyPacket.getNextValueAsBoolean();
412         targetVMCapabilities.canUnrestrictedlyRedefineClasses = replyPacket
413                 .getNextValueAsBoolean();
414         targetVMCapabilities.canPopFrames = replyPacket.getNextValueAsBoolean();
415         targetVMCapabilities.canUseInstanceFilters = replyPacket
416                 .getNextValueAsBoolean();
417         targetVMCapabilities.canGetSourceDebugExtension = replyPacket
418                 .getNextValueAsBoolean();
419         targetVMCapabilities.canRequestVMDeathEvent = replyPacket
420                 .getNextValueAsBoolean();
421         targetVMCapabilities.canSetDefaultStratum = replyPacket
422                 .getNextValueAsBoolean();
423         targetVMCapabilities.canGetInstanceInfo = replyPacket
424                 .getNextValueAsBoolean();
425         targetVMCapabilities.reserved17 = replyPacket.getNextValueAsBoolean();
426         targetVMCapabilities.canGetMonitorFrameInfo = replyPacket
427                 .getNextValueAsBoolean();
428         targetVMCapabilities.canUseSourceNameFilters = replyPacket.getNextValueAsBoolean();
429         targetVMCapabilities.canGetConstantPool = replyPacket
430                 .getNextValueAsBoolean();
431         targetVMCapabilities.canForceEarlyReturn = replyPacket
432                 .getNextValueAsBoolean();
433         targetVMCapabilities.reserved22 = replyPacket.getNextValueAsBoolean();
434         targetVMCapabilities.reserved23 = replyPacket.getNextValueAsBoolean();
435         targetVMCapabilities.reserved24 = replyPacket.getNextValueAsBoolean();
436         targetVMCapabilities.reserved25 = replyPacket.getNextValueAsBoolean();
437         targetVMCapabilities.reserved26 = replyPacket.getNextValueAsBoolean();
438         targetVMCapabilities.reserved27 = replyPacket.getNextValueAsBoolean();
439         targetVMCapabilities.reserved28 = replyPacket.getNextValueAsBoolean();
440         targetVMCapabilities.reserved29 = replyPacket.getNextValueAsBoolean();
441         targetVMCapabilities.reserved30 = replyPacket.getNextValueAsBoolean();
442         targetVMCapabilities.reserved31 = replyPacket.getNextValueAsBoolean();
443         targetVMCapabilities.reserved32 = replyPacket.getNextValueAsBoolean();
444 
445         return replyPacket;
446     }
447 
canWatchFieldModification()448     public boolean canWatchFieldModification() {
449         capabilities();
450         return targetVMCapabilities.canWatchFieldModification;
451     }
452 
canWatchFieldAccess()453     public boolean canWatchFieldAccess() {
454         capabilities();
455         return targetVMCapabilities.canWatchFieldAccess;
456     }
457 
canUseInstanceFilters()458     public boolean canUseInstanceFilters() {
459         capabilities();
460         return targetVMCapabilities.canUseInstanceFilters;
461     }
462 
463     /**
464      * Resumes debuggee VM.
465      *
466      * @return ReplyPacket for corresponding command
467      */
resume()468     public ReplyPacket resume() {
469         CommandPacket commandPacket = new CommandPacket(
470                 JDWPCommands.VirtualMachineCommandSet.CommandSetID,
471                 JDWPCommands.VirtualMachineCommandSet.ResumeCommand);
472 
473         return checkReply(performCommand(commandPacket));
474     }
475 
476     /**
477      * Resumes specified thread on target Virtual Machine
478      *
479      * @return ReplyPacket for corresponding command
480      */
resumeThread(long threadID)481     public ReplyPacket resumeThread(long threadID) {
482         CommandPacket commandPacket = new CommandPacket(
483                 JDWPCommands.ThreadReferenceCommandSet.CommandSetID,
484                 JDWPCommands.ThreadReferenceCommandSet.ResumeCommand);
485 
486         commandPacket.setNextValueAsThreadID(threadID);
487         return checkReply(performCommand(commandPacket));
488     }
489 
490     /**
491      * Suspends debuggee VM.
492      *
493      * @return ReplyPacket for corresponding command
494      */
suspend()495     public ReplyPacket suspend() {
496         CommandPacket commandPacket = new CommandPacket(
497                 JDWPCommands.VirtualMachineCommandSet.CommandSetID,
498                 JDWPCommands.VirtualMachineCommandSet.SuspendCommand);
499 
500         return checkReply(performCommand(commandPacket));
501     }
502 
503     /**
504      * Suspends specified thread in debuggee VM.
505      *
506      * @return ReplyPacket for corresponding command
507      */
suspendThread(long threadID)508     public ReplyPacket suspendThread(long threadID) {
509         CommandPacket commandPacket = new CommandPacket(
510                 JDWPCommands.ThreadReferenceCommandSet.CommandSetID,
511                 JDWPCommands.ThreadReferenceCommandSet.SuspendCommand);
512 
513         commandPacket.setNextValueAsThreadID(threadID);
514         return checkReply(performCommand(commandPacket));
515     }
516 
517     /**
518      * Disposes connection to debuggee VM.
519      *
520      * @return ReplyPacket for corresponding command
521      */
dispose()522     public ReplyPacket dispose() {
523         // Create new command packet
524         CommandPacket commandPacket = new CommandPacket();
525         commandPacket
526                 .setCommand(JDWPCommands.VirtualMachineCommandSet.DisposeCommand);
527         commandPacket
528                 .setCommandSet(JDWPCommands.VirtualMachineCommandSet.CommandSetID);
529 
530         // Send packet
531         return checkReply(performCommand(commandPacket));
532     }
533 
534     /**
535      * Exits debuggee VM process.
536      *
537      * @return ReplyPacket for corresponding command
538      */
exit(int exitCode)539     public ReplyPacket exit(int exitCode) {
540         // Create new command packet
541         CommandPacket commandPacket = new CommandPacket();
542         commandPacket
543                 .setCommand(JDWPCommands.VirtualMachineCommandSet.ExitCommand);
544         commandPacket
545                 .setCommandSet(JDWPCommands.VirtualMachineCommandSet.CommandSetID);
546         commandPacket.setNextValueAsInt(exitCode);
547 
548         // Send packet
549         return checkReply(performCommand(commandPacket));
550     }
551 
552     /**
553      * Adjusts lengths for all VM-specific types.
554      *
555      * @return ReplyPacket for corresponding command
556      */
adjustTypeLength()557     public ReplyPacket adjustTypeLength() {
558         // Create new command packet
559         CommandPacket commandPacket = new CommandPacket();
560         commandPacket
561                 .setCommand(JDWPCommands.VirtualMachineCommandSet.IDSizesCommand);
562         commandPacket
563                 .setCommandSet(JDWPCommands.VirtualMachineCommandSet.CommandSetID);
564 
565         // Send packet
566         ReplyPacket replyPacket = checkReply(performCommand(commandPacket));
567 
568         // Get FieldIDSize from ReplyPacket
569         TypesLengths.setTypeLength(TypesLengths.FIELD_ID, replyPacket
570                 .getNextValueAsInt());
571 
572         // Get MethodIDSize from ReplyPacket
573         TypesLengths.setTypeLength(TypesLengths.METHOD_ID, replyPacket
574                 .getNextValueAsInt());
575 
576         // Get ObjectIDSize from ReplyPacket
577         TypesLengths.setTypeLength(TypesLengths.OBJECT_ID, replyPacket
578                 .getNextValueAsInt());
579 
580         // Get ReferenceTypeIDSize from ReplyPacket
581         TypesLengths.setTypeLength(TypesLengths.REFERENCE_TYPE_ID, replyPacket
582                 .getNextValueAsInt());
583 
584         // Get FrameIDSize from ReplyPacket
585         TypesLengths.setTypeLength(TypesLengths.FRAME_ID, replyPacket
586                 .getNextValueAsInt());
587 
588         // Adjust all other types lengths
589         TypesLengths.setTypeLength(TypesLengths.ARRAY_ID, TypesLengths
590                 .getTypeLength(TypesLengths.OBJECT_ID));
591         TypesLengths.setTypeLength(TypesLengths.STRING_ID, TypesLengths
592                 .getTypeLength(TypesLengths.OBJECT_ID));
593         TypesLengths.setTypeLength(TypesLengths.THREAD_ID, TypesLengths
594                 .getTypeLength(TypesLengths.OBJECT_ID));
595         TypesLengths.setTypeLength(TypesLengths.THREADGROUP_ID, TypesLengths
596                 .getTypeLength(TypesLengths.OBJECT_ID));
597         TypesLengths.setTypeLength(TypesLengths.LOCATION_ID, TypesLengths
598                 .getTypeLength(TypesLengths.OBJECT_ID));
599         TypesLengths.setTypeLength(TypesLengths.CLASS_ID, TypesLengths
600                 .getTypeLength(TypesLengths.OBJECT_ID));
601         TypesLengths.setTypeLength(TypesLengths.CLASSLOADER_ID, TypesLengths
602                 .getTypeLength(TypesLengths.OBJECT_ID));
603         TypesLengths.setTypeLength(TypesLengths.CLASSOBJECT_ID, TypesLengths
604                 .getTypeLength(TypesLengths.OBJECT_ID));
605         return replyPacket;
606     }
607 
608     /**
609      * Gets TypeID for specified type signature and type tag.
610      *
611      * @param typeSignature
612      *            type signature
613      * @param classTypeTag
614      *            type tag
615      * @return received TypeID
616      */
getTypeID(String typeSignature, byte classTypeTag)617     public long getTypeID(String typeSignature, byte classTypeTag) {
618         int classes = 0;
619         byte refTypeTag = 0;
620         long typeID = -1;
621 
622         // Request referenceTypeID for exception
623         ReplyPacket classReference = getClassBySignature(typeSignature);
624 
625         // Get referenceTypeID from received packet
626         classes = classReference.getNextValueAsInt();
627         for (int i = 0; i < classes; i++) {
628             refTypeTag = classReference.getNextValueAsByte();
629             if (refTypeTag == classTypeTag) {
630                 typeID = classReference.getNextValueAsReferenceTypeID();
631                 classReference.getNextValueAsInt();
632                 break;
633             } else {
634                 classReference.getNextValueAsReferenceTypeID();
635                 classReference.getNextValueAsInt();
636                 refTypeTag = 0;
637             }
638         }
639         return typeID;
640     }
641 
642     /**
643      * Gets ClassID for specified class signature.
644      *
645      * @param classSignature
646      *            class signature
647      * @return received ClassID
648      */
getClassID(String classSignature)649     public long getClassID(String classSignature) {
650         return getTypeID(classSignature, JDWPConstants.TypeTag.CLASS);
651     }
652 
653     /**
654      * Gets ThreadID for specified thread name.
655      *
656      * @param threadName
657      *            thread name
658      * @return received ThreadID
659      */
getThreadID(String threadName)660     public long getThreadID(String threadName) {
661         ReplyPacket request = null;
662         long threadID = -1;
663         long thread = -1;
664         String name = null;
665         int threads = -1;
666 
667         // Get All Threads IDs
668         request = getAllThreadID();
669 
670         // Get thread ID for threadName
671         threads = request.getNextValueAsInt();
672         for (int i = 0; i < threads; i++) {
673             thread = request.getNextValueAsThreadID();
674             name = getThreadName(thread);
675             if (threadName.equals(name)) {
676                 threadID = thread;
677                 break;
678             }
679         }
680 
681         return threadID;
682     }
683 
684     /**
685      * Returns all running thread IDs.
686      *
687      * @return received reply packet
688      */
getAllThreadID()689     public ReplyPacket getAllThreadID() {
690         // Create new command packet
691         CommandPacket commandPacket = new CommandPacket(
692                 JDWPCommands.VirtualMachineCommandSet.CommandSetID,
693                 JDWPCommands.VirtualMachineCommandSet.AllThreadsCommand);
694 
695         return checkReply(performCommand(commandPacket));
696     }
697 
698     /**
699      * Gets class signature for specified class ID.
700      *
701      * @param classID
702      *            class ID
703      * @return received class signature
704      */
getClassSignature(long classID)705     public String getClassSignature(long classID) {
706         // Create new command packet
707         CommandPacket commandPacket = new CommandPacket(
708                 JDWPCommands.ReferenceTypeCommandSet.CommandSetID,
709                 JDWPCommands.ReferenceTypeCommandSet.SignatureCommand);
710         commandPacket.setNextValueAsReferenceTypeID(classID);
711         ReplyPacket replyPacket = checkReply(performCommand(commandPacket));
712         return replyPacket.getNextValueAsString();
713     }
714 
715     /**
716      * Returns thread name for specified <code>threadID</code>.
717      *
718      * @param threadID
719      *            thread ID
720      * @return thread name
721      */
getThreadName(long threadID)722     public String getThreadName(long threadID) {
723         // Create new command packet
724         CommandPacket commandPacket = new CommandPacket(
725                 JDWPCommands.ThreadReferenceCommandSet.CommandSetID,
726                 JDWPCommands.ThreadReferenceCommandSet.NameCommand);
727         commandPacket.setNextValueAsThreadID(threadID);
728         ReplyPacket replyPacket = checkReply(performCommand(commandPacket));
729         return replyPacket.getNextValueAsString();
730     }
731 
732     /**
733      * Returns thread status for specified <code>threadID</code>.
734      *
735      * @param threadID
736      *            thread ID
737      * @return thread status
738      */
getThreadStatus(long threadID)739     public int getThreadStatus(long threadID) {
740         CommandPacket commandPacket = new CommandPacket(
741                 JDWPCommands.ThreadReferenceCommandSet.CommandSetID,
742                 JDWPCommands.ThreadReferenceCommandSet.StatusCommand);
743         commandPacket.setNextValueAsThreadID(threadID);
744         ReplyPacket replyPacket = checkReply(performCommand(commandPacket));
745         return replyPacket.getNextValueAsInt();
746     }
747 
748     /**
749      * Returns suspend count for specified <code>threadID</code>.
750      *
751      * @param threadID
752      *            thread ID
753      * @return thread's suspend count
754      */
getThreadSuspendCount(long threadID)755     public int getThreadSuspendCount(long threadID) {
756         CommandPacket commandPacket = new CommandPacket(
757                 JDWPCommands.ThreadReferenceCommandSet.CommandSetID,
758                 JDWPCommands.ThreadReferenceCommandSet.SuspendCountCommand);
759         commandPacket.setNextValueAsThreadID(threadID);
760         ReplyPacket replyPacket = checkReply(performCommand(commandPacket));
761         return replyPacket.getNextValueAsInt();
762     }
763 
764     /**
765      * Returns name of thread group for specified <code>groupID</code>
766      *
767      * @param groupID
768      *            thread group ID
769      *
770      * @return name of thread group
771      */
getThreadGroupName(long groupID)772     public String getThreadGroupName(long groupID) {
773         // Create new command packet
774         CommandPacket commandPacket = new CommandPacket(
775                 JDWPCommands.ThreadGroupReferenceCommandSet.CommandSetID,
776                 JDWPCommands.ThreadGroupReferenceCommandSet.NameCommand);
777         commandPacket.setNextValueAsReferenceTypeID(groupID);
778         ReplyPacket replyPacket = checkReply(performCommand(commandPacket));
779         return replyPacket.getNextValueAsString();
780     }
781 
782     /**
783      * Gets InterfaceID for specified interface signature.
784      *
785      * @param interfaceSignature
786      *            interface signature
787      * @return received ClassID
788      */
getInterfaceID(String interfaceSignature)789     public long getInterfaceID(String interfaceSignature) {
790         return getTypeID(interfaceSignature, JDWPConstants.TypeTag.INTERFACE);
791     }
792 
793     /**
794      * Gets ArrayID for specified array signature.
795      *
796      * @param arraySignature
797      *            array signature
798      * @return received ArrayID
799      */
getArrayID(String arraySignature)800     public long getArrayID(String arraySignature) {
801         return getTypeID(arraySignature, JDWPConstants.TypeTag.INTERFACE);
802     }
803 
804     /**
805      * Gets RequestID from specified ReplyPacket.
806      *
807      * @param request
808      *            ReplyPacket with RequestID
809      * @return received RequestID
810      */
getRequestID(ReplyPacket request)811     public int getRequestID(ReplyPacket request) {
812         return request.getNextValueAsInt();
813     }
814 
815     /**
816      * Returns FieldID for specified class and field name.
817      *
818      * @param classID
819      *            ClassID to find field
820      * @param fieldName
821      *            field name
822      * @return received FieldID
823      */
getFieldID(long classID, String fieldName)824     public long getFieldID(long classID, String fieldName) {
825         ReplyPacket reply = getFieldsInClass(classID);
826         return getFieldID(reply, fieldName);
827     }
828 
829     /**
830      * Gets FieldID from ReplyPacket.
831      *
832      * @param request
833      *            ReplyPacket for request
834      * @param field
835      *            field name to get ID for
836      * @return received FieldID
837      */
getFieldID(ReplyPacket request, String field)838     public long getFieldID(ReplyPacket request, String field) {
839         long fieldID = -1;
840         String fieldName;
841         // Get fieldID from received packet
842         int count = request.getNextValueAsInt();
843         for (int i = 0; i < count; i++) {
844             fieldID = request.getNextValueAsFieldID();
845             fieldName = request.getNextValueAsString();
846             if (field.equals(fieldName)) {
847                 request.getNextValueAsString();
848                 request.getNextValueAsInt();
849                 break;
850             } else {
851                 request.getNextValueAsString();
852                 request.getNextValueAsInt();
853                 fieldID = 0;
854                 fieldName = null;
855             }
856         }
857         return fieldID;
858     }
859 
860     /**
861      * Gets Method ID for specified class and method name.
862      *
863      * @param classID
864      *            class to find method
865      * @param methodName
866      *            method name
867      * @return received MethodID
868      */
getMethodID(long classID, String methodName)869     public long getMethodID(long classID, String methodName) {
870         ReplyPacket reply;
871         int declared = 0;
872         String method = null;
873         long methodID = -1;
874 
875         // Get Method reference ID
876         reply = getMethods(classID);
877 
878         // Get methodID from received packet
879         declared = reply.getNextValueAsInt();
880         for (int i = 0; i < declared; i++) {
881             methodID = reply.getNextValueAsMethodID();
882             method = reply.getNextValueAsString();
883             if (methodName.equals(method)) {
884                 // If this method name is the same as requested
885                 reply.getNextValueAsString();
886                 reply.getNextValueAsInt();
887                 break;
888             } else {
889                 // If this method name is not the requested one
890                 reply.getNextValueAsString();
891                 reply.getNextValueAsInt();
892                 methodID = -1;
893                 method = null;
894             }
895         }
896         return methodID;
897     }
898 
899     /**
900      * Returns method name for specified pair of classID and methodID.
901      *
902      * @param classID
903      * @param methodID
904      * @return method name
905      */
getMethodName(long classID, long methodID)906     public String getMethodName(long classID, long methodID) {
907         CommandPacket packet = new CommandPacket(
908                 JDWPCommands.ReferenceTypeCommandSet.CommandSetID,
909                 JDWPCommands.ReferenceTypeCommandSet.MethodsCommand);
910         packet.setNextValueAsReferenceTypeID(classID);
911         ReplyPacket reply = performCommand(packet);
912 
913         int declared = reply.getNextValueAsInt();
914         long mID;
915         String value = null;
916         String methodName = "";
917         for (int i = 0; i < declared; i++) {
918             mID = reply.getNextValueAsMethodID();
919             methodName = reply.getNextValueAsString();
920             reply.getNextValueAsString();
921             reply.getNextValueAsInt();
922             if (mID == methodID) {
923                 value = methodName;
924                 break;
925             }
926         }
927         return value;
928     }
929 
930     /**
931      * Sets ClassPrepare event request for given class name pattern.
932      *
933      * @param classRegexp
934      *            Required class pattern. Matches are limited to exact matches
935      *            of the given class pattern and matches of patterns that begin
936      *            or end with '*'; for example, "*.Foo" or "java.*".
937      * @return ReplyPacket for setting request.
938      */
setClassPrepared(String classRegexp)939     public ReplyPacket setClassPrepared(String classRegexp) {
940         // Prepare corresponding event
941         byte eventKind = JDWPConstants.EventKind.CLASS_PREPARE;
942         byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL;
943         // EventMod[] mods = new EventMod[1];
944         EventMod[] mods = new EventMod[] { new EventMod() };
945         mods[0].classPattern = classRegexp;
946         mods[0].modKind = EventMod.ModKind.ClassMatch;
947         Event event = new Event(eventKind, suspendPolicy, mods);
948 
949         // Set event
950         return setEvent(event);
951     }
952 
953     /**
954      * Set ClassPrepare event request for given class ID.
955      *
956      * @param referenceTypeID
957      *            class referenceTypeID
958      * @return ReplyPacket for setting request
959      */
setClassPrepared(long referenceTypeID)960     public ReplyPacket setClassPrepared(long referenceTypeID) {
961         // Prepare corresponding event
962         byte eventKind = JDWPConstants.EventKind.CLASS_PREPARE;
963         byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL;
964         // EventMod[] mods = new EventMod[1];
965         EventMod[] mods = new EventMod[] { new EventMod() };
966         mods[0].clazz = referenceTypeID;
967         mods[0].modKind = EventMod.ModKind.ClassOnly;
968         Event event = new Event(eventKind, suspendPolicy, mods);
969 
970         // Set event
971         return setEvent(event);
972     }
973 
974     /**
975      * Sets ClassPrepare event request for given source name pattern.
976      *
977      * @param sourceNamePattern
978      *            Required source name pattern. Matches are limited to exact matches
979      *            of the given source name pattern and matches of patterns that begin
980      *            or end with '*'; for example, "*.Foo" or "java.*".
981      * @return ReplyPacket for setting request.
982      */
setClassPreparedForSourceNameMatch(String sourceNamePattern)983     public ReplyPacket setClassPreparedForSourceNameMatch(String sourceNamePattern) {
984         // Prepare corresponding event
985         byte eventKind = JDWPConstants.EventKind.CLASS_PREPARE;
986         byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL;
987         EventMod[] mods = new EventMod[] { new EventMod() };
988         mods[0].sourceNamePattern = sourceNamePattern;
989         mods[0].modKind = EventMod.ModKind.SourceNameMatch;
990         Event event = new Event(eventKind, suspendPolicy, mods);
991 
992         // Set event
993         return setEvent(event);
994     }
995 
996     /**
997      * Sets ClassUnload event request for given class name pattern.
998      *
999      * @param classSignature
1000      *            class signature
1001      * @return ReplyPacket for setting request
1002      */
setClassUnload(String classRegexp)1003     public ReplyPacket setClassUnload(String classRegexp) {
1004         // Prepare corresponding event
1005         byte eventKind = JDWPConstants.EventKind.CLASS_UNLOAD;
1006         byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL;
1007         // EventMod[] mods = new EventMod[1];
1008         EventMod[] mods = new EventMod[] { new EventMod() };
1009         mods[0].classPattern = classRegexp;
1010         mods[0].modKind = EventMod.ModKind.ClassMatch;
1011         Event event = new Event(eventKind, suspendPolicy, mods);
1012 
1013         // Set event
1014         return setEvent(event);
1015     }
1016 
1017     /**
1018      * Set ClassUnload event request for given class ID.
1019      *
1020      * @param referenceTypeID
1021      *            class referenceTypeID
1022      * @return ReplyPacket for setting request
1023      */
setClassUnload(long referenceTypeID)1024     public ReplyPacket setClassUnload(long referenceTypeID) {
1025         // Prepare corresponding event
1026         byte eventKind = JDWPConstants.EventKind.CLASS_UNLOAD;
1027         byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL;
1028         // EventMod[] mods = new EventMod[1];
1029         EventMod[] mods = new EventMod[] { new EventMod() };
1030         mods[0].clazz = referenceTypeID;
1031         mods[0].modKind = EventMod.ModKind.ClassOnly;
1032         Event event = new Event(eventKind, suspendPolicy, mods);
1033 
1034         // Set event
1035         return setEvent(event);
1036     }
1037 
1038     /**
1039      * Sets ClassLoad event request for given class signature.
1040      *
1041      * @param classSignature
1042      *            class signature
1043      * @return ReplyPacket for setting request
1044      */
setClassLoad(String classSignature)1045     public ReplyPacket setClassLoad(String classSignature) {
1046         long typeID;
1047 
1048         // Request referenceTypeID for class
1049         typeID = getClassID(classSignature);
1050 
1051         // Set corresponding event
1052         return setClassLoad(typeID);
1053     }
1054 
1055     /**
1056      * Set ClassLoad event request for given class ID.
1057      *
1058      * @param referenceTypeID
1059      *            class referenceTypeID
1060      * @return ReplyPacket for setting request
1061      */
setClassLoad(long referenceTypeID)1062     public ReplyPacket setClassLoad(long referenceTypeID) {
1063         // Prepare corresponding event
1064         byte eventKind = JDWPConstants.EventKind.CLASS_LOAD;
1065         byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL;
1066         EventMod[] mods = new EventMod[] { new EventMod() };
1067         mods[0].clazz = referenceTypeID;
1068         mods[0].modKind = EventMod.ModKind.ClassOnly;
1069         Event event = new Event(eventKind, suspendPolicy, mods);
1070 
1071         // Set event
1072         return setEvent(event);
1073     }
1074 
1075     /**
1076      * Set MonitorContendedEnter event request for given class's reference type
1077      *
1078      * @param referenceTypeID
1079      *            class referenceTypeID
1080      * @return ReplyPacket for setting request
1081      */
setMonitorContendedEnterForClassOnly(long referenceTypeID)1082     public ReplyPacket setMonitorContendedEnterForClassOnly(long referenceTypeID) {
1083         // Prepare corresponding event
1084         byte eventKind = JDWPConstants.EventKind.MONITOR_CONTENDED_ENTER;
1085         byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL;
1086         EventMod[] mods = new EventMod[] { new EventMod() };
1087         mods[0].clazz = referenceTypeID;
1088         mods[0].modKind = EventMod.ModKind.ClassOnly;
1089         Event event = new Event(eventKind, suspendPolicy, mods);
1090 
1091         // Set event
1092         return setEvent(event);
1093     }
1094 
setMonitorContendedEnterForClassMatch(String classRegexp)1095     public ReplyPacket setMonitorContendedEnterForClassMatch(String classRegexp) {
1096         // Prepare corresponding event
1097         byte eventKind = JDWPConstants.EventKind.MONITOR_CONTENDED_ENTER;
1098         byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL;
1099         EventMod[] mods = new EventMod[] { new EventMod() };
1100         mods[0].classPattern = classRegexp;
1101         mods[0].modKind = EventMod.ModKind.ClassMatch;
1102         Event event = new Event(eventKind, suspendPolicy, mods);
1103 
1104         // Set event
1105         return setEvent(event);
1106     }
1107 
1108     /**
1109      * Set MonitorContendedEntered event request for given class's reference type
1110      *
1111      * @param referenceTypeID
1112      *            class referenceTypeID
1113      * @return ReplyPacket for setting request
1114      */
setMonitorContendedEnteredForClassOnly(long referenceTypeID)1115     public ReplyPacket setMonitorContendedEnteredForClassOnly(long referenceTypeID) {
1116         // Prepare corresponding event
1117         byte eventKind = JDWPConstants.EventKind.MONITOR_CONTENDED_ENTERED;
1118         byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL;
1119         EventMod[] mods = new EventMod[] { new EventMod() };
1120         mods[0].clazz = referenceTypeID;
1121         mods[0].modKind = EventMod.ModKind.ClassOnly;
1122         Event event = new Event(eventKind, suspendPolicy, mods);
1123 
1124         // Set event
1125         return setEvent(event);
1126     }
1127 
setMonitorContendedEnteredForClassMatch(String classRegexp)1128     public ReplyPacket setMonitorContendedEnteredForClassMatch(String classRegexp) {
1129         // Prepare corresponding event
1130         byte eventKind = JDWPConstants.EventKind.MONITOR_CONTENDED_ENTERED;
1131         byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL;
1132         EventMod[] mods = new EventMod[] { new EventMod() };
1133         mods[0].classPattern = classRegexp;
1134         mods[0].modKind = EventMod.ModKind.ClassMatch;
1135         Event event = new Event(eventKind, suspendPolicy, mods);
1136 
1137         // Set event
1138         return setEvent(event);
1139     }
1140 
1141     /**
1142      * Set MonitorWait event request for given class's reference type
1143      *
1144      * @param referenceTypeID
1145      *            class referenceTypeID
1146      * @return ReplyPacket for setting request
1147      */
setMonitorWaitForClassOnly(long referenceTypeID)1148     public ReplyPacket setMonitorWaitForClassOnly(long referenceTypeID) {
1149         // Prepare corresponding event
1150         byte eventKind = JDWPConstants.EventKind.MONITOR_WAIT;
1151         byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL;
1152         EventMod[] mods = new EventMod[] { new EventMod() };
1153         mods[0].clazz = referenceTypeID;
1154         mods[0].modKind = EventMod.ModKind.ClassOnly;
1155         Event event = new Event(eventKind, suspendPolicy, mods);
1156 
1157         // Set event
1158         return setEvent(event);
1159     }
1160 
1161     /**
1162      * Set MonitorWait event request for given given class name pattern.
1163      *
1164      * @param classRegexp
1165      *            Required class pattern. Matches are limited to exact matches
1166      *            of the given class pattern and matches of patterns that begin
1167      *            or end with '*'; for example, "*.Foo" or "java.*".
1168      * @return ReplyPacket for setting request.
1169      */
setMonitorWaitForClassMatch(String classRegexp)1170     public ReplyPacket setMonitorWaitForClassMatch(String classRegexp) {
1171         // Prepare corresponding event
1172         byte eventKind = JDWPConstants.EventKind.MONITOR_WAIT;
1173         byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL;
1174         EventMod[] mods = new EventMod[] { new EventMod() };
1175         mods[0].classPattern = classRegexp;
1176         mods[0].modKind = EventMod.ModKind.ClassMatch;
1177         Event event = new Event(eventKind, suspendPolicy, mods);
1178 
1179         // Set event
1180         return setEvent(event);
1181     }
1182 
1183     /**
1184      * Set MonitorWait event request for classes
1185      * whose name does not match the given restricted regular expression.
1186      *
1187      * @param classRegexp
1188      *            Exclude class pattern. Matches are limited to exact matches
1189      *            of the given class pattern and matches of patterns that begin
1190      *            or end with '*'; for example, "*.Foo" or "java.*".
1191      * @return ReplyPacket for setting request.
1192      */
setMonitorWaitForClassExclude(String classRegexp)1193     public ReplyPacket setMonitorWaitForClassExclude (String classRegexp) {
1194         // Prepare corresponding event
1195         byte eventKind = JDWPConstants.EventKind.MONITOR_WAIT;
1196         byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL;
1197         EventMod[] mods = new EventMod[] { new EventMod() };
1198         mods[0].classPattern = classRegexp;
1199         mods[0].modKind = EventMod.ModKind.ClassExclude;
1200         Event event = new Event(eventKind, suspendPolicy, mods);
1201 
1202         // Set event
1203         return setEvent(event);
1204     }
1205 
1206     /**
1207      * Set MonitorWaited event request for given class's reference type
1208      *
1209      * @param referenceTypeID
1210      *            class referenceTypeID
1211      * @return ReplyPacket for setting request
1212      */
setMonitorWaitedForClassOnly(long referenceTypeID)1213     public ReplyPacket setMonitorWaitedForClassOnly(long referenceTypeID) {
1214         // Prepare corresponding event
1215         byte eventKind = JDWPConstants.EventKind.MONITOR_WAITED;
1216         byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL;
1217         EventMod[] mods = new EventMod[] { new EventMod() };
1218         mods[0].clazz = referenceTypeID;
1219         mods[0].modKind = EventMod.ModKind.ClassOnly;
1220         Event event = new Event(eventKind, suspendPolicy, mods);
1221 
1222         // Set event
1223         return setEvent(event);
1224     }
1225 
1226     /**
1227      * Set MonitorWaited event request for given given source name pattern.
1228      *
1229      * @param classRegexp
1230      *            Required class pattern. Matches are limited to exact matches
1231      *            of the given class pattern and matches of patterns that begin
1232      *            or end with '*'; for example, "*.Foo" or "java.*".
1233      * @return ReplyPacket for setting request.
1234      */
setMonitorWaitedForClassMatch(String classRegexp)1235     public ReplyPacket setMonitorWaitedForClassMatch(String classRegexp) {
1236         // Prepare corresponding event
1237         byte eventKind = JDWPConstants.EventKind.MONITOR_WAITED;
1238         byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL;
1239         EventMod[] mods = new EventMod[] { new EventMod() };
1240         mods[0].classPattern = classRegexp;
1241         mods[0].modKind = EventMod.ModKind.ClassMatch;
1242         Event event = new Event(eventKind, suspendPolicy, mods);
1243 
1244         // Set event
1245         return setEvent(event);
1246     }
1247 
1248     /**
1249      * Set MonitorWaited event request for classes
1250      * whose name does not match the given restricted regular expression.
1251      *
1252      * @param classRegexp
1253      *            Required class pattern. Matches are limited to exact matches
1254      *            of the given class pattern and matches of patterns that begin
1255      *            or end with '*'; for example, "*.Foo" or "java.*".
1256      * @return ReplyPacket for setting request.
1257      */
setMonitorWaitedForClassExclude(String classRegexp)1258     public ReplyPacket setMonitorWaitedForClassExclude (String classRegexp) {
1259         // Prepare corresponding event
1260         byte eventKind = JDWPConstants.EventKind.MONITOR_WAITED;
1261         byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL;
1262         EventMod[] mods = new EventMod[] { new EventMod() };
1263         mods[0].classPattern = classRegexp;
1264         mods[0].modKind = EventMod.ModKind.ClassExclude;
1265         Event event = new Event(eventKind, suspendPolicy, mods);
1266 
1267         // Set event
1268         return setEvent(event);
1269     }
1270 
1271     /**
1272      * Set event request for given event.
1273      *
1274      * @param event
1275      *            event to set request for
1276      * @return ReplyPacket for setting request
1277      */
setEvent(Event event)1278     public ReplyPacket setEvent(Event event) {
1279         // Create new command packet
1280         CommandPacket commandPacket = new CommandPacket(
1281                 JDWPCommands.EventRequestCommandSet.CommandSetID,
1282                 JDWPCommands.EventRequestCommandSet.SetCommand);
1283 
1284         // Set eventKind
1285         commandPacket.setNextValueAsByte(event.eventKind);
1286         // Set suspendPolicy
1287         commandPacket.setNextValueAsByte(event.suspendPolicy);
1288 
1289         // Set modifiers
1290         commandPacket.setNextValueAsInt(event.modifiers);
1291 
1292         for (int i = 0; i < event.modifiers; i++) {
1293 
1294             commandPacket.setNextValueAsByte(event.mods[i].modKind);
1295 
1296             switch (event.mods[i].modKind) {
1297             case EventMod.ModKind.Count: {
1298                 // Case Count
1299                 commandPacket.setNextValueAsInt(event.mods[i].count);
1300                 break;
1301             }
1302             case EventMod.ModKind.Conditional: {
1303                 // Case Conditional
1304                 commandPacket.setNextValueAsInt(event.mods[i].exprID);
1305                 break;
1306             }
1307             case EventMod.ModKind.ThreadOnly: {
1308                 // Case ThreadOnly
1309                 commandPacket.setNextValueAsThreadID(event.mods[i].thread);
1310                 break;
1311             }
1312             case EventMod.ModKind.ClassOnly: {
1313                 // Case ClassOnly
1314                 commandPacket
1315                         .setNextValueAsReferenceTypeID(event.mods[i].clazz);
1316                 break;
1317             }
1318             case EventMod.ModKind.ClassMatch: {
1319                 // Case ClassMatch
1320                 commandPacket.setNextValueAsString(event.mods[i].classPattern);
1321                 break;
1322             }
1323             case EventMod.ModKind.ClassExclude: {
1324                 // Case ClassExclude
1325                 commandPacket.setNextValueAsString(event.mods[i].classPattern);
1326                 break;
1327             }
1328             case EventMod.ModKind.LocationOnly: {
1329                 // Case LocationOnly
1330                 commandPacket.setNextValueAsLocation(event.mods[i].loc);
1331                 break;
1332             }
1333             case EventMod.ModKind.ExceptionOnly:
1334                 // Case ExceptionOnly
1335                 commandPacket
1336                         .setNextValueAsReferenceTypeID(event.mods[i].exceptionOrNull);
1337                 commandPacket.setNextValueAsBoolean(event.mods[i].caught);
1338                 commandPacket.setNextValueAsBoolean(event.mods[i].uncaught);
1339                 break;
1340             case EventMod.ModKind.FieldOnly: {
1341                 // Case FieldOnly
1342                 commandPacket
1343                         .setNextValueAsReferenceTypeID(event.mods[i].declaring);
1344                 commandPacket.setNextValueAsFieldID(event.mods[i].fieldID);
1345                 break;
1346             }
1347             case EventMod.ModKind.Step: {
1348                 // Case Step
1349                 commandPacket.setNextValueAsThreadID(event.mods[i].thread);
1350                 commandPacket.setNextValueAsInt(event.mods[i].size);
1351                 commandPacket.setNextValueAsInt(event.mods[i].depth);
1352                 break;
1353             }
1354             case EventMod.ModKind.InstanceOnly: {
1355                 // Case InstanceOnly
1356                 commandPacket.setNextValueAsObjectID(event.mods[i].instance);
1357                 break;
1358             }
1359             case EventMod.ModKind.SourceNameMatch: {
1360                 // Case SourceNameMatch
1361                 commandPacket.setNextValueAsString(event.mods[i].sourceNamePattern);
1362             }
1363             }
1364         }
1365 
1366         // Send packet
1367         return checkReply(performCommand(commandPacket));
1368     }
1369 
1370     /**
1371      * Gets method reference by signature.
1372      *
1373      * @param classReferenceTypeID
1374      *            class referenceTypeID.
1375      * @return ReplyPacket for corresponding command
1376      */
getMethods(long classReferenceTypeID)1377     public ReplyPacket getMethods(long classReferenceTypeID) {
1378         // Create new command packet
1379         CommandPacket commandPacket = new CommandPacket();
1380 
1381         // Set command. "5" - is ID of Methods command in ReferenceType Command
1382         // Set
1383         commandPacket
1384                 .setCommand(JDWPCommands.ReferenceTypeCommandSet.MethodsCommand);
1385 
1386         // Set command set. "2" - is ID of ReferenceType Command Set
1387         commandPacket
1388                 .setCommandSet(JDWPCommands.ReferenceTypeCommandSet.CommandSetID);
1389 
1390         // Set outgoing data
1391         // Set referenceTypeID
1392         commandPacket.setNextValueAsObjectID(classReferenceTypeID);
1393 
1394         // Send packet
1395         return checkReply(performCommand(commandPacket));
1396     }
1397 
1398     /**
1399      * Gets class reference by signature.
1400      *
1401      * @param classSignature
1402      *            class signature.
1403      * @return ReplyPacket for corresponding command
1404      */
getClassBySignature(String classSignature)1405     public ReplyPacket getClassBySignature(String classSignature) {
1406         CommandPacket commandPacket = new CommandPacket(
1407                 JDWPCommands.VirtualMachineCommandSet.CommandSetID,
1408                 JDWPCommands.VirtualMachineCommandSet.ClassesBySignatureCommand);
1409         commandPacket.setNextValueAsString(classSignature);
1410         return checkReply(performCommand(commandPacket));
1411     }
1412 
1413     /**
1414      * Gets class fields by class referenceTypeID.
1415      *
1416      * @param referenceTypeID
1417      *            class referenceTypeID.
1418      * @return ReplyPacket for corresponding command
1419      */
getFieldsInClass(long referenceTypeID)1420     public ReplyPacket getFieldsInClass(long referenceTypeID) {
1421         CommandPacket commandPacket = new CommandPacket(
1422                 JDWPCommands.ReferenceTypeCommandSet.CommandSetID,
1423                 JDWPCommands.ReferenceTypeCommandSet.FieldsCommand);
1424         commandPacket.setNextValueAsReferenceTypeID(referenceTypeID);
1425         return checkReply(performCommand(commandPacket));
1426     }
1427 
1428     /**
1429      * Sets exception event request for given exception class signature.
1430      *
1431      * @param exceptionSignature
1432      *            exception signature.
1433      * @param caught
1434      *            is exception caught
1435      * @param uncaught
1436      *            is exception uncaught
1437      * @return ReplyPacket for corresponding command
1438      */
setException(String exceptionSignature, boolean caught, boolean uncaught)1439     public ReplyPacket setException(String exceptionSignature, boolean caught,
1440             boolean uncaught) {
1441         // Request referenceTypeID for exception
1442         long typeID = getClassID(exceptionSignature);
1443         return setException(typeID, caught, uncaught);
1444     }
1445 
1446     /**
1447      * Sets exception event request for given exception class ID.
1448      *
1449      * @param exceptionID
1450      *            exception referenceTypeID.
1451      * @param caught
1452      *            is exception caught
1453      * @param uncaught
1454      *            is exception uncaught
1455      * @return ReplyPacket for corresponding command
1456      */
setException(long exceptionID, boolean caught, boolean uncaught)1457     public ReplyPacket setException(long exceptionID, boolean caught,
1458             boolean uncaught) {
1459         // Prepare corresponding event
1460         byte eventKind = JDWPConstants.EventKind.EXCEPTION;
1461         byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL;
1462         EventMod[] mods = new EventMod[1];
1463         mods[0] = new EventMod();
1464         mods[0].modKind = EventMod.ModKind.ExceptionOnly;
1465         mods[0].caught = caught;
1466         mods[0].uncaught = uncaught;
1467         mods[0].exceptionOrNull = exceptionID;
1468         Event event = new Event(eventKind, suspendPolicy, mods);
1469 
1470         return setEvent(event);
1471     }
1472 
1473     /**
1474      * Sets exception event request for given exception class signature.
1475      *
1476      * @param exceptionSignature
1477      *            exception signature.
1478      * @param caught
1479      *            is exception caught
1480      * @param uncaught
1481      *            is exception uncaught
1482      * @param count
1483      *            Limit the requested event to be reported at most once after a
1484      *            given number of occurrences
1485      * @return ReplyPacket for corresponding command
1486      */
setCountableException(String exceptionSignature, boolean caught, boolean uncaught, int count)1487     public ReplyPacket setCountableException(String exceptionSignature,
1488             boolean caught, boolean uncaught, int count) {
1489         // Request referenceTypeID for exception
1490         long exceptionID = getClassID(exceptionSignature);
1491         byte eventKind = JDWPConstants.EventKind.EXCEPTION;
1492         byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL;
1493         EventMod[] mods = new EventMod[2];
1494         mods[0] = new EventMod();
1495         mods[0].modKind = EventMod.ModKind.ExceptionOnly;
1496         mods[0].caught = caught;
1497         mods[0].uncaught = uncaught;
1498         mods[0].exceptionOrNull = exceptionID;
1499 
1500         mods[1] = new EventMod();
1501         mods[1].modKind = EventMod.ModKind.Count;
1502         mods[1].count = count;
1503         Event event = new Event(eventKind, suspendPolicy, mods);
1504 
1505         return setEvent(event);
1506     }
1507 
1508     /**
1509      * Sets METHOD_ENTRY event request for specified class name pattern.
1510      *
1511      * @param classRegexp
1512      *            class name pattern or null for no pattern
1513      *
1514      * @return ReplyPacket for corresponding command
1515      */
setMethodEntry(String classRegexp)1516     public ReplyPacket setMethodEntry(String classRegexp) {
1517         // Prepare corresponding event
1518         byte eventKind = JDWPConstants.EventKind.METHOD_ENTRY;
1519         byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL;
1520         EventMod[] mods = null;
1521         if (classRegexp == null) {
1522             mods = new EventMod[0];
1523         } else {
1524             mods = new EventMod[1];
1525             mods[0] = new EventMod();
1526             mods[0].modKind = EventMod.ModKind.ClassMatch;
1527             mods[0].classPattern = classRegexp;
1528         }
1529         Event event = new Event(eventKind, suspendPolicy, mods);
1530 
1531         return setEvent(event);
1532     }
1533 
1534     /**
1535      * Sets METHOD_ENTRY event request for specified class name pattern.
1536      *
1537      * @param classRegexp
1538      *            class name pattern or null for no pattern
1539      * @param count
1540      *            Limit the requested event to be reported at most once after a
1541      *            given number of occurrences
1542      * @return ReplyPacket for corresponding command
1543      */
setCountableMethodEntry(String classRegexp, int count)1544     public ReplyPacket setCountableMethodEntry(String classRegexp, int count) {
1545         byte eventKind = JDWPConstants.EventKind.METHOD_ENTRY;
1546         byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL;
1547         EventMod[] mods = null;
1548         if (classRegexp == null) {
1549             mods = new EventMod[] { new EventMod() };
1550             mods[0].modKind = EventMod.ModKind.Count;
1551             mods[0].count = count;
1552         } else {
1553             mods = new EventMod[2];
1554             mods[0] = new EventMod();
1555             mods[0].modKind = EventMod.ModKind.ClassMatch;
1556             mods[0].classPattern = classRegexp;
1557 
1558             mods[1] = new EventMod();
1559             mods[1].modKind = EventMod.ModKind.Count;
1560             mods[1].count = count;
1561         }
1562         Event event = new Event(eventKind, suspendPolicy, mods);
1563 
1564         return setEvent(event);
1565     }
1566 
1567     /**
1568      * Sets METHOD_EXIT event request for specified class name pattern.
1569      *
1570      * @param classRegexp
1571      *            class name pattern or null for no pattern
1572      *
1573      * @return ReplyPacket for corresponding command
1574      */
setMethodExit(String classRegexp)1575     public ReplyPacket setMethodExit(String classRegexp) {
1576         // Prepare corresponding event
1577         byte eventKind = JDWPConstants.EventKind.METHOD_EXIT;
1578         byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL;
1579         EventMod[] mods = null;
1580         if (classRegexp == null) {
1581             mods = new EventMod[0];
1582         } else {
1583             mods = new EventMod[1];
1584             mods[0] = new EventMod();
1585             mods[0].modKind = EventMod.ModKind.ClassMatch;
1586             mods[0].classPattern = classRegexp;
1587         }
1588         Event event = new Event(eventKind, suspendPolicy, mods);
1589 
1590         return setEvent(event);
1591     }
1592 
1593     /**
1594      * Sets METHOD_EXIT_WITH_RETURN_VALUE event request for specified class name pattern.
1595      *
1596      * @param classRegexp
1597      *            class name pattern or null for no pattern
1598      *
1599      * @return ReplyPacket for corresponding command
1600      */
setMethodExitWithReturnValue(String classRegexp)1601     public ReplyPacket setMethodExitWithReturnValue(String classRegexp) {
1602         // Prepare corresponding event
1603         byte eventKind = JDWPConstants.EventKind.METHOD_EXIT_WITH_RETURN_VALUE;
1604         byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL;
1605         EventMod[] mods = null;
1606         if (classRegexp == null) {
1607             mods = new EventMod[0];
1608         } else {
1609             mods = new EventMod[1];
1610             mods[0] = new EventMod();
1611             mods[0].modKind = EventMod.ModKind.ClassMatch;
1612             mods[0].classPattern = classRegexp;
1613         }
1614         Event event = new Event(eventKind, suspendPolicy, mods);
1615 
1616         return setEvent(event);
1617     }
1618 
1619     /**
1620      * Sets METHOD_EXIT event request for specified class name pattern.
1621      *
1622      * @param classRegexp
1623      *            classRegexp class name pattern or null for no pattern
1624      * @param count
1625      *            Limit the requested event to be reported at most once after a
1626      *            given number of occurrences
1627      * @return ReplyPacket for corresponding command
1628      */
setCountableMethodExit(String classRegexp, int count)1629     public ReplyPacket setCountableMethodExit(String classRegexp, int count) {
1630         byte eventKind = JDWPConstants.EventKind.METHOD_EXIT;
1631         byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL;
1632         EventMod[] mods = null;
1633         if (classRegexp == null) {
1634             mods = new EventMod[] { new EventMod() };
1635             mods[0].modKind = EventMod.ModKind.Count;
1636             mods[0].count = count;
1637         } else {
1638             mods = new EventMod[2];
1639             mods[0] = new EventMod();
1640             mods[0].modKind = EventMod.ModKind.ClassMatch;
1641             mods[0].classPattern = classRegexp;
1642 
1643             mods[1] = new EventMod();
1644             mods[1].modKind = EventMod.ModKind.Count;
1645             mods[1].count = count;
1646         }
1647         Event event = new Event(eventKind, suspendPolicy, mods);
1648 
1649         return setEvent(event);
1650 
1651     }
1652 
1653     /**
1654      * Sets field access event request for specified class signature and field
1655      * name.
1656      *
1657      * @param classTypeTag
1658      *            class Type Tag (class/interface/array)
1659      * @param classSignature
1660      *            class signature
1661      * @param fieldName
1662      *            field name
1663      * @return ReplyPacket if breakpoint is set
1664      * @throws ReplyErrorCodeException
1665      */
setFieldAccess(String classSignature, byte classTypeTag, String fieldName)1666     public ReplyPacket setFieldAccess(String classSignature, byte classTypeTag,
1667             String fieldName) throws ReplyErrorCodeException {
1668         ReplyPacket request = null;
1669         long typeID = -1;
1670         long fieldID = -1;
1671 
1672         // Request referenceTypeID for class
1673         typeID = getClassID(classSignature);
1674 
1675         // Request fields in class
1676         request = getFieldsInClass(typeID);
1677 
1678         // Get fieldID from received packet
1679         fieldID = getFieldID(request, fieldName);
1680 
1681         // Prepare corresponding event
1682         byte eventKind = JDWPConstants.EventKind.FIELD_ACCESS;
1683         byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL;
1684         // EventMod[] mods = new EventMod[1];
1685         EventMod[] mods = new EventMod[] { new EventMod() };
1686         mods[0].fieldID = fieldID;
1687         mods[0].declaring = typeID;
1688         mods[0].modKind = EventMod.ModKind.FieldOnly;
1689         Event event = new Event(eventKind, suspendPolicy, mods);
1690 
1691         // Set exception
1692         return setEvent(event);
1693     }
1694 
1695     /**
1696      * Sets field modification event request for specified class signature and
1697      * field name.
1698      *
1699      * @param classTypeTag
1700      *            class Type Tag (class/interface/array)
1701      * @param classSignature
1702      *            class signature
1703      * @param fieldName
1704      *            field name
1705      * @return ReplyPacket for corresponding command
1706      * @throws ReplyErrorCodeException
1707      */
setFieldModification(String classSignature, byte classTypeTag, String fieldName)1708     public ReplyPacket setFieldModification(String classSignature,
1709             byte classTypeTag, String fieldName) throws ReplyErrorCodeException {
1710         ReplyPacket request = null;
1711         long typeID = -1;
1712         long fieldID = -1;
1713 
1714         // Request referenceTypeID for class
1715         typeID = getClassID(classSignature);
1716 
1717         // Request fields in class
1718         request = getFieldsInClass(typeID);
1719 
1720         // Get fieldID from received packet
1721         fieldID = getFieldID(request, fieldName);
1722 
1723         // Prepare corresponding event
1724         byte eventKind = JDWPConstants.EventKind.FIELD_MODIFICATION;
1725         byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL;
1726         // EventMod[] mods = new EventMod[1];
1727         EventMod[] mods = new EventMod[] { new EventMod() };
1728         mods[0].fieldID = fieldID;
1729         mods[0].declaring = typeID;
1730         mods[0].modKind = EventMod.ModKind.FieldOnly;
1731         Event event = new Event(eventKind, suspendPolicy, mods);
1732 
1733         // Set event
1734         return setEvent(event);
1735     }
1736 
1737     /**
1738      * Sets step event request for given thread name.
1739      *
1740      * @param threadName
1741      *            thread name
1742      * @param stepSize
1743      * @param stepDepth
1744      * @return ReplyPacket for corresponding command
1745      */
setStep(String threadName, int stepSize, int stepDepth)1746     public ReplyPacket setStep(String threadName, int stepSize, int stepDepth) {
1747         long typeID = -1;
1748 
1749         // Request referenceTypeID for class
1750         typeID = getThreadID(threadName);
1751 
1752         // Prepare corresponding event
1753         byte eventKind = JDWPConstants.EventKind.SINGLE_STEP;
1754         byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL;
1755         // EventMod[] mods = new EventMod[1];
1756         EventMod[] mods = new EventMod[] { new EventMod() };
1757         mods[0].thread = typeID;
1758         mods[0].modKind = EventMod.ModKind.Step;
1759         mods[0].size = stepSize;
1760         mods[0].depth = stepDepth;
1761         Event event = new Event(eventKind, suspendPolicy, mods);
1762 
1763         // Set event
1764         return setEvent(event);
1765     }
1766 
1767     /**
1768      * Sets SINGLE_STEP event request for classes whose name does not match the
1769      * given restricted regular expression
1770      *
1771      * @param classRegexp
1772      *            Disallowed class patterns. Matches are limited to exact
1773      *            matches of the given class pattern and matches of patterns
1774      *            that begin or end with '*'; for example, "*.Foo" or "java.*".
1775      * @param stepSize
1776      * @param stepDepth
1777      * @return ReplyPacket for setting request.
1778      */
setStep(String[] classRegexp, long threadID, int stepSize, int stepDepth)1779     public ReplyPacket setStep(String[] classRegexp, long threadID,
1780             int stepSize, int stepDepth) {
1781         // Prepare corresponding event
1782         byte eventKind = JDWPConstants.EventKind.SINGLE_STEP;
1783         byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL;
1784         int modsSize = classRegexp.length + 1;
1785         EventMod[] mods = new EventMod[modsSize];
1786         for (int i = 0; i < classRegexp.length; i++) {
1787             mods[i] = new EventMod();
1788             mods[i].classPattern = classRegexp[i];
1789             mods[i].modKind = EventMod.ModKind.ClassExclude;
1790         }
1791 
1792         int index = modsSize - 1;
1793         mods[index] = new EventMod();
1794         mods[index].modKind = EventMod.ModKind.Step;
1795         mods[index].thread = threadID;
1796         mods[index].size = stepSize;
1797         mods[index].depth = stepDepth;
1798 
1799         Event event = new Event(eventKind, suspendPolicy, mods);
1800 
1801         // Set event
1802         return setEvent(event);
1803     }
1804 
1805     /**
1806      * Sets THREAD_START event request.
1807      *
1808      * @return ReplyPacket for corresponding command
1809      */
setThreadStart()1810     public ReplyPacket setThreadStart() {
1811         // Prepare corresponding event
1812         byte eventKind = JDWPConstants.EventKind.THREAD_START;
1813         byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL;
1814         EventMod[] mods = new EventMod[0];
1815         Event event = new Event(eventKind, suspendPolicy, mods);
1816 
1817         return setEvent(event);
1818     }
1819 
1820     /**
1821      * Sets THREAD_END event request.
1822      *
1823      * @return ReplyPacket for corresponding command
1824      */
setThreadEnd()1825     public ReplyPacket setThreadEnd() {
1826         // Prepare corresponding event
1827         byte eventKind = JDWPConstants.EventKind.THREAD_END;
1828         byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL;
1829         EventMod[] mods = new EventMod[0];
1830         Event event = new Event(eventKind, suspendPolicy, mods);
1831 
1832         return setEvent(event);
1833     }
1834 
1835     /**
1836      * Clear an event request for specified request ID.
1837      *
1838      * @param eventKind
1839      *            event type to clear
1840      * @param requestID
1841      *            request ID to clear
1842      * @return ReplyPacket for corresponding command
1843      */
clearEvent(byte eventKind, int requestID)1844     public ReplyPacket clearEvent(byte eventKind, int requestID) {
1845         // Create new command packet
1846         CommandPacket commandPacket = new CommandPacket();
1847 
1848         // Set command. "2" - is ID of Clear command in EventRequest Command Set
1849         commandPacket
1850                 .setCommand(JDWPCommands.EventRequestCommandSet.ClearCommand);
1851 
1852         // Set command set. "15" - is ID of EventRequest Command Set
1853         commandPacket
1854                 .setCommandSet(JDWPCommands.EventRequestCommandSet.CommandSetID);
1855 
1856         // Set outgoing data
1857         // Set event type to clear
1858         commandPacket.setNextValueAsByte(eventKind);
1859 
1860         // Set ID of request to clear
1861         commandPacket.setNextValueAsInt(requestID);
1862 
1863         // Send packet
1864         return checkReply(performCommand(commandPacket));
1865     }
1866 
1867     /**
1868      * Sends CommandPacket to debuggee VM and waits for ReplyPacket using
1869      * default timeout. All thrown exceptions are wrapped into
1870      * TestErrorException. Consider using checkReply() for checking error code
1871      * in reply packet.
1872      *
1873      * @param command
1874      *            Command packet to be sent
1875      * @return received ReplyPacket
1876      */
performCommand(CommandPacket command)1877     public ReplyPacket performCommand(CommandPacket command)
1878             throws TestErrorException {
1879         ReplyPacket replyPacket = null;
1880         try {
1881             replyPacket = packetDispatcher.performCommand(command);
1882         } catch (IOException e) {
1883             throw new TestErrorException(e);
1884         } catch (InterruptedException e) {
1885             throw new TestErrorException(e);
1886         }
1887 
1888         return replyPacket;
1889     }
1890 
1891     /**
1892      * Sends CommandPacket to debuggee VM and waits for ReplyPacket using
1893      * specified timeout.
1894      *
1895      * @param command
1896      *            Command packet to be sent
1897      * @param timeout
1898      *            Timeout in milliseconds for waiting reply packet
1899      * @return received ReplyPacket
1900      * @throws InterruptedException
1901      * @throws IOException
1902      * @throws TimeoutException
1903      */
performCommand(CommandPacket command, long timeout)1904     public ReplyPacket performCommand(CommandPacket command, long timeout)
1905             throws IOException, InterruptedException, TimeoutException {
1906 
1907         return packetDispatcher.performCommand(command, timeout);
1908     }
1909 
1910     /**
1911      * Sends CommandPacket to debuggee VM without waiting for the reply. This
1912      * method is intended for special cases when there is need to divide
1913      * command's performing into two actions: command's sending and receiving
1914      * reply (e.g. for asynchronous JDWP commands' testing). After this method
1915      * the 'receiveReply()' method must be used latter for receiving reply for
1916      * sent command. It is NOT recommended to use this method for usual cases -
1917      * 'performCommand()' method must be used.
1918      *
1919      * @param command
1920      *            Command packet to be sent
1921      * @return command ID of sent command
1922      * @throws IOException
1923      *             if any connection error occurred
1924      */
sendCommand(CommandPacket command)1925     public int sendCommand(CommandPacket command) throws IOException {
1926         return packetDispatcher.sendCommand(command);
1927     }
1928 
1929     /**
1930      * Waits for reply for command which was sent before by 'sendCommand()'
1931      * method. Default timeout is used as time limit for waiting. This method
1932      * (jointly with 'sendCommand()') is intended for special cases when there
1933      * is need to divide command's performing into two actions: command's
1934      * sending and receiving reply (e.g. for asynchronous JDWP commands'
1935      * testing). It is NOT recommended to use 'sendCommand()- receiveReply()'
1936      * pair for usual cases - 'performCommand()' method must be used.
1937      *
1938      * @param commandId
1939      *            Command ID of sent before command, reply from which is
1940      *            expected to be received
1941      * @return received ReplyPacket
1942      * @throws IOException
1943      *             if any connection error occurred
1944      * @throws InterruptedException
1945      *             if reply packet's waiting was interrupted
1946      * @throws TimeoutException
1947      *             if timeout exceeded
1948      */
receiveReply(int commandId)1949     public ReplyPacket receiveReply(int commandId) throws InterruptedException,
1950             IOException, TimeoutException {
1951         return packetDispatcher.receiveReply(commandId, config.getTimeout());
1952     }
1953 
1954     /**
1955      * Waits for reply for command which was sent before by 'sendCommand()'
1956      * method. Specified timeout is used as time limit for waiting. This method
1957      * (jointly with 'sendCommand()') is intended for special cases when there
1958      * is need to divide command's performing into two actions: command's
1959      * sending and receiving reply (e.g. for asynchronous JDWP commands'
1960      * testing). It is NOT recommended to use 'sendCommand()- receiveReply()'
1961      * pair for usual cases - 'performCommand()' method must be used.
1962      *
1963      * @param commandId
1964      *            Command ID of sent before command, reply from which is
1965      *            expected to be received
1966      * @param timeout
1967      *            Specified timeout in milliseconds to wait for reply
1968      * @return received ReplyPacket
1969      * @throws IOException
1970      *             if any connection error occurred
1971      * @throws InterruptedException
1972      *             if reply packet's waiting was interrupted
1973      * @throws TimeoutException
1974      *             if timeout exceeded
1975      */
receiveReply(int commandId, long timeout)1976     public ReplyPacket receiveReply(int commandId, long timeout)
1977             throws InterruptedException, IOException, TimeoutException {
1978         return packetDispatcher.receiveReply(commandId, timeout);
1979     }
1980 
1981     /**
1982      * Waits for EventPacket using default timeout. All thrown exceptions are
1983      * wrapped into TestErrorException.
1984      *
1985      * @return received EventPacket
1986      */
receiveEvent()1987     public EventPacket receiveEvent() throws TestErrorException {
1988         try {
1989             return receiveEvent(config.getTimeout());
1990         } catch (IOException e) {
1991             throw new TestErrorException(e);
1992         } catch (InterruptedException e) {
1993             throw new TestErrorException(e);
1994         }
1995     }
1996 
1997     /**
1998      * Waits for EventPacket using specified timeout.
1999      *
2000      * @param timeout
2001      *            Timeout in milliseconds to wait for event
2002      * @return received EventPacket
2003      * @throws IOException
2004      * @throws InterruptedException
2005      * @throws TimeoutException
2006      */
receiveEvent(long timeout)2007     public EventPacket receiveEvent(long timeout) throws IOException,
2008             InterruptedException, TimeoutException {
2009 
2010         return packetDispatcher.receiveEvent(timeout);
2011     }
2012 
2013     /**
2014      * Waits for expected event kind using default timeout. Throws
2015      * TestErrorException if received event is not of expected kind or not a
2016      * single event in the received event set.
2017      *
2018      * @param eventKind
2019      *            Type of expected event -
2020      * @see JDWPConstants.EventKind
2021      * @return received EventPacket
2022      */
receiveCertainEvent(byte eventKind)2023     public EventPacket receiveCertainEvent(byte eventKind)
2024             throws TestErrorException {
2025 
2026         EventPacket eventPacket = receiveEvent();
2027         ParsedEvent[] parsedEvents = ParsedEvent.parseEventPacket(eventPacket);
2028 
2029         if (parsedEvents.length == 1
2030                 && parsedEvents[0].getEventKind() == eventKind)
2031             return eventPacket;
2032 
2033         switch (parsedEvents.length) {
2034         case (0):
2035             throw new TestErrorException(
2036                     "Unexpected event received: zero length");
2037         case (1):
2038             throw new TestErrorException("Unexpected event received: "
2039                     + parsedEvents[0].getEventKind());
2040         default:
2041             throw new TestErrorException(
2042                     "Unexpected event received: Event was grouped in a composite event");
2043         }
2044     }
2045 
2046     /**
2047      * Returns JDWP connection channel used by this VmMirror.
2048      *
2049      * @return connection channel
2050      */
getConnection()2051     public TransportWrapper getConnection() {
2052         return connection;
2053     }
2054 
2055     /**
2056      * Sets established connection channel to be used with this VmMirror and
2057      * starts reading packets.
2058      *
2059      * @param connection
2060      *            connection channel to be set
2061      */
setConnection(TransportWrapper connection)2062     public void setConnection(TransportWrapper connection) {
2063         this.connection = connection;
2064         packetDispatcher = new PacketDispatcher(connection, config, logWriter);
2065     }
2066 
2067     /**
2068      * Closes connection channel used with this VmMirror and stops reading
2069      * packets.
2070      *
2071      */
closeConnection()2072     public void closeConnection() throws IOException {
2073         if (connection != null && connection.isOpen())
2074             connection.close();
2075 
2076         // wait for packetDispatcher is closed
2077         if (packetDispatcher != null) {
2078             try {
2079                 packetDispatcher.join();
2080             } catch (InterruptedException e) {
2081                 // do nothing but print a stack trace
2082                 e.printStackTrace();
2083             }
2084         }
2085     }
2086 
2087     /**
2088      * Returns the count of frames on this thread's stack
2089      *
2090      * @param threadID
2091      *            The thread object ID.
2092      * @return The count of frames on this thread's stack
2093      */
getFrameCount(long threadID)2094     public final int getFrameCount(long threadID) {
2095         CommandPacket command = new CommandPacket(
2096                 JDWPCommands.ThreadReferenceCommandSet.CommandSetID,
2097                 JDWPCommands.ThreadReferenceCommandSet.FrameCountCommand);
2098         command.setNextValueAsThreadID(threadID);
2099         ReplyPacket reply = checkReply(performCommand(command));
2100         return reply.getNextValueAsInt();
2101     }
2102 
2103     /**
2104      * Returns a list containing all frames of a certain thread
2105      *
2106      * @param threadID
2107      *            ID of the thread
2108      * @return A list of frames
2109      */
getAllThreadFrames(long threadID)2110     public final List getAllThreadFrames(long threadID) {
2111         if (!isThreadSuspended(threadID)) {
2112             return new ArrayList(0);
2113         }
2114 
2115         ReplyPacket reply = getThreadFrames(threadID, 0, -1);
2116         int framesCount = reply.getNextValueAsInt();
2117         if (framesCount == 0) {
2118             return new ArrayList(0);
2119         }
2120 
2121         ArrayList<Frame> frames = new ArrayList<Frame>(framesCount);
2122         for (int i = 0; i < framesCount; i++) {
2123             Frame frame = new Frame();
2124             frame.setThreadID(threadID);
2125             frame.setID(reply.getNextValueAsFrameID());
2126             frame.setLocation(reply.getNextValueAsLocation());
2127             frames.add(frame);
2128         }
2129 
2130         return frames;
2131     }
2132 
2133     /**
2134      * Returns a set of frames of a certain suspended thread
2135      *
2136      * @param threadID
2137      *            ID of the thread whose frames to obtain
2138      * @param startIndex
2139      *            The index of the first frame to retrieve.
2140      * @param length
2141      *            The count of frames to retrieve (-1 means all remaining).
2142      * @return ReplyPacket for corresponding command
2143      */
getThreadFrames(long threadID, int startIndex, int length)2144     public final ReplyPacket getThreadFrames(long threadID, int startIndex,
2145             int length) {
2146         CommandPacket command = new CommandPacket(
2147                 JDWPCommands.ThreadReferenceCommandSet.CommandSetID,
2148                 JDWPCommands.ThreadReferenceCommandSet.FramesCommand);
2149         command.setNextValueAsThreadID(threadID);
2150         command.setNextValueAsInt(startIndex); // start frame's index
2151         command.setNextValueAsInt(length); // get all remaining frames;
2152         return checkReply(performCommand(command));
2153     }
2154 
2155     /**
2156      * Returns variable information for the method
2157      *
2158      * @param classID
2159      *            The class ID
2160      * @param methodID
2161      *            The method ID
2162      * @return A list containing all variables (arguments and locals) declared
2163      *         within the method.
2164      */
getVariableTable(long classID, long methodID)2165     public final List getVariableTable(long classID, long methodID) {
2166         CommandPacket command = new CommandPacket(
2167                 JDWPCommands.MethodCommandSet.CommandSetID,
2168                 JDWPCommands.MethodCommandSet.VariableTableCommand);
2169         command.setNextValueAsReferenceTypeID(classID);
2170         command.setNextValueAsMethodID(methodID);
2171         // ReplyPacket reply =
2172         // debuggeeWrapper.vmMirror.checkReply(debuggeeWrapper.vmMirror.performCommand(command));
2173         ReplyPacket reply = performCommand(command);
2174         if (reply.getErrorCode() == JDWPConstants.Error.ABSENT_INFORMATION
2175                 || reply.getErrorCode() == JDWPConstants.Error.NATIVE_METHOD) {
2176             return null;
2177         }
2178 
2179         checkReply(reply);
2180 
2181         reply.getNextValueAsInt(); // argCnt, is not used
2182         int slots = reply.getNextValueAsInt();
2183         if (slots == 0) {
2184             return null;
2185         }
2186 
2187         ArrayList<Variable> vars = new ArrayList<Variable>(slots);
2188         for (int i = 0; i < slots; i++) {
2189             Variable var = new Frame().new Variable();
2190             var.setCodeIndex(reply.getNextValueAsLong());
2191             var.setName(reply.getNextValueAsString());
2192             var.setSignature(reply.getNextValueAsString());
2193             var.setLength(reply.getNextValueAsInt());
2194             var.setSlot(reply.getNextValueAsInt());
2195             vars.add(var);
2196         }
2197 
2198         return vars;
2199     }
2200 
2201     /**
2202      * Returns values of local variables in a given frame
2203      *
2204      * @param frame
2205      *            Frame whose variables to get
2206      * @return An array of Value objects
2207      */
getFrameValues(Frame frame)2208     public final Value[] getFrameValues(Frame frame) {
2209         CommandPacket command = new CommandPacket(
2210                 JDWPCommands.StackFrameCommandSet.CommandSetID,
2211                 JDWPCommands.StackFrameCommandSet.GetValuesCommand);
2212         command.setNextValueAsThreadID(frame.getThreadID());
2213         command.setNextValueAsFrameID(frame.getID());
2214         int slots = frame.getVars().size();
2215         command.setNextValueAsInt(slots);
2216         Iterator it = frame.getVars().iterator();
2217         while (it.hasNext()) {
2218             Frame.Variable var = (Frame.Variable) it.next();
2219             command.setNextValueAsInt(var.getSlot());
2220             command.setNextValueAsByte(var.getTag());
2221         }
2222 
2223         ReplyPacket reply = checkReply(performCommand(command));
2224         reply.getNextValueAsInt(); // number of values , is not used
2225         Value[] values = new Value[slots];
2226         for (int i = 0; i < slots; i++) {
2227             values[i] = reply.getNextValueAsValue();
2228         }
2229 
2230         return values;
2231     }
2232 
2233     /**
2234      * Returns the immediate superclass of a class
2235      *
2236      * @param classID
2237      *            The class ID whose superclass ID is to get
2238      * @return The superclass ID (null if the class ID for java.lang.Object is
2239      *         specified).
2240      */
getSuperclassId(long classID)2241     public final long getSuperclassId(long classID) {
2242         CommandPacket command = new CommandPacket(
2243                 JDWPCommands.ClassTypeCommandSet.CommandSetID,
2244                 JDWPCommands.ClassTypeCommandSet.SuperclassCommand);
2245         command.setNextValueAsClassID(classID);
2246         ReplyPacket reply = checkReply(performCommand(command));
2247         return reply.getNextValueAsClassID();
2248     }
2249 
2250     /**
2251      * Returns the runtime type of the object
2252      *
2253      * @param objectID
2254      *            The object ID
2255      * @return The runtime reference type.
2256      */
getReferenceType(long objectID)2257     public final long getReferenceType(long objectID) {
2258         CommandPacket command = new CommandPacket(
2259                 JDWPCommands.ObjectReferenceCommandSet.CommandSetID,
2260                 JDWPCommands.ObjectReferenceCommandSet.ReferenceTypeCommand);
2261         command.setNextValueAsObjectID(objectID);
2262         ReplyPacket reply = checkReply(performCommand(command));
2263         reply.getNextValueAsByte();
2264         return reply.getNextValueAsLong();
2265     }
2266 
2267     /**
2268      * Returns the class object corresponding to this type
2269      *
2270      * @param refType
2271      *            The reference type ID.
2272      * @return The class object.
2273      */
getClassObjectId(long refType)2274     public final long getClassObjectId(long refType) {
2275         CommandPacket command = new CommandPacket(
2276                 JDWPCommands.ReferenceTypeCommandSet.CommandSetID,
2277                 JDWPCommands.ReferenceTypeCommandSet.ClassObjectCommand);
2278         command.setNextValueAsReferenceTypeID(refType);
2279         ReplyPacket reply = checkReply(performCommand(command));
2280         return reply.getNextValueAsObjectID();
2281     }
2282 
2283     /**
2284      * Returns line number information for the method, if present.
2285      *
2286      * @param refType
2287      *            The class ID
2288      * @param methodID
2289      *            The method ID
2290      * @return ReplyPacket for corresponding command.
2291      */
getLineTable(long refType, long methodID)2292     public final ReplyPacket getLineTable(long refType, long methodID) {
2293         CommandPacket command = new CommandPacket(
2294                 JDWPCommands.MethodCommandSet.CommandSetID,
2295                 JDWPCommands.MethodCommandSet.LineTableCommand);
2296         command.setNextValueAsReferenceTypeID(refType);
2297         command.setNextValueAsMethodID(methodID);
2298         // ReplyPacket reply =
2299         // debuggeeWrapper.vmMirror.checkReply(debuggeeWrapper.vmMirror.performCommand(command));
2300         // it is impossible to obtain line table information from native
2301         // methods, so reply checking is not performed
2302         ReplyPacket reply = performCommand(command);
2303         if (reply.getErrorCode() != JDWPConstants.Error.NONE) {
2304             if (reply.getErrorCode() == JDWPConstants.Error.NATIVE_METHOD) {
2305                 return reply;
2306             }
2307         }
2308 
2309         return checkReply(reply);
2310     }
2311 
2312     /**
2313      * Returns the value of one or more instance fields.
2314      *
2315      * @param objectID
2316      *            The object ID
2317      * @param fieldIDs
2318      *            IDs of fields to get
2319      * @return An array of Value objects representing each field's value
2320      */
getObjectReferenceValues(long objectID, long[] fieldIDs)2321     public final Value[] getObjectReferenceValues(long objectID, long[] fieldIDs) {
2322         int fieldsCount = fieldIDs.length;
2323         if (fieldsCount == 0) {
2324             return null;
2325         }
2326 
2327         CommandPacket command = new CommandPacket(
2328                 JDWPCommands.ObjectReferenceCommandSet.CommandSetID,
2329                 JDWPCommands.ObjectReferenceCommandSet.GetValuesCommand);
2330         command.setNextValueAsReferenceTypeID(objectID);
2331         command.setNextValueAsInt(fieldsCount);
2332         for (int i = 0; i < fieldsCount; i++) {
2333             command.setNextValueAsFieldID(fieldIDs[i]);
2334         }
2335 
2336         ReplyPacket reply = checkReply(performCommand(command));
2337         reply.getNextValueAsInt(); // fields returned, is not used
2338         Value[] values = new Value[fieldsCount];
2339         for (int i = 0; i < fieldsCount; i++) {
2340             values[i] = reply.getNextValueAsValue();
2341         }
2342 
2343         return values;
2344     }
2345 
2346     /**
2347      * Returns the value of one or more static fields of the reference type
2348      *
2349      * @param refTypeID
2350      *            The reference type ID.
2351      * @param fieldIDs
2352      *            IDs of fields to get
2353      * @return An array of Value objects representing each field's value
2354      */
getReferenceTypeValues(long refTypeID, long[] fieldIDs)2355     public final Value[] getReferenceTypeValues(long refTypeID, long[] fieldIDs) {
2356         int fieldsCount = fieldIDs.length;
2357         if (fieldsCount == 0) {
2358             return null;
2359         }
2360 
2361         CommandPacket command = new CommandPacket(
2362                 JDWPCommands.ReferenceTypeCommandSet.CommandSetID,
2363                 JDWPCommands.ReferenceTypeCommandSet.GetValuesCommand);
2364         command.setNextValueAsReferenceTypeID(refTypeID);
2365         command.setNextValueAsInt(fieldsCount);
2366         for (int i = 0; i < fieldsCount; i++) {
2367             command.setNextValueAsFieldID(fieldIDs[i]);
2368         }
2369 
2370         ReplyPacket reply = checkReply(performCommand(command));
2371         reply.getNextValueAsInt(); // fields returned, is not used
2372         Value[] values = new Value[fieldsCount];
2373         for (int i = 0; i < fieldsCount; i++) {
2374             values[i] = reply.getNextValueAsValue();
2375         }
2376 
2377         return values;
2378     }
2379 
2380     /**
2381      * Returns the value of one static field of the reference type
2382      *
2383      * @param refTypeID
2384      *            The reference type ID.
2385      * @param fieldID
2386      *            ID of field to get
2387      * @return A Value object representing the field's value
2388      */
getReferenceTypeValue(long refTypeID, long fieldID)2389     public final Value getReferenceTypeValue(long refTypeID, long fieldID) {
2390         Value[] values = getReferenceTypeValues(refTypeID, new long[]{fieldID});
2391         return values[0];
2392     }
2393 
2394     /**
2395      * Returns the value of the 'this' reference for this frame
2396      *
2397      * @param threadID
2398      *            The frame's thread ID
2399      * @param frameID
2400      *            The frame ID.
2401      * @return The 'this' object ID for this frame.
2402      */
getThisObject(long threadID, long frameID)2403     public final long getThisObject(long threadID, long frameID) {
2404         CommandPacket command = new CommandPacket(
2405                 JDWPCommands.StackFrameCommandSet.CommandSetID,
2406                 JDWPCommands.StackFrameCommandSet.ThisObjectCommand);
2407         command.setNextValueAsThreadID(threadID);
2408         command.setNextValueAsFrameID(frameID);
2409         ReplyPacket reply = checkReply(performCommand(command));
2410         TaggedObject taggedObject = reply.getNextValueAsTaggedObject();
2411         return taggedObject.objectID;
2412     }
2413 
2414     /**
2415      * Returns information for each field in a reference type including
2416      * inherited fields
2417      *
2418      * @param classID
2419      *            The reference type ID
2420      * @return A list of Field objects representing each field of the class
2421      */
getAllFields(long classID)2422     public final List getAllFields(long classID) {
2423         ArrayList<Field> fields = new ArrayList<Field>(0);
2424 
2425         long superID = getSuperclassId(classID);
2426         if (superID != 0) {
2427             List superClassFields = getAllFields(superID);
2428             for (int i = 0; i < superClassFields.size(); i++) {
2429                 fields.add((Field) superClassFields.toArray()[i]);
2430             }
2431         }
2432 
2433         ReplyPacket reply = getFieldsInClass(classID);
2434         int fieldsCount = reply.getNextValueAsInt();
2435         for (int i = 0; i < fieldsCount; i++) {
2436             Field field = new Field(reply.getNextValueAsFieldID(), classID,
2437                     reply.getNextValueAsString(), reply.getNextValueAsString(),
2438                     reply.getNextValueAsInt());
2439             fields.add(field);
2440         }
2441 
2442         return fields;
2443     }
2444 
2445     /**
2446      * Returns the reference type reflected by this class object
2447      *
2448      * @param classObjectID
2449      *            The class object ID.
2450      * @return ReplyPacket for corresponding command
2451      */
getReflectedType(long classObjectID)2452     public final ReplyPacket getReflectedType(long classObjectID) {
2453         CommandPacket command = new CommandPacket(
2454                 JDWPCommands.ClassObjectReferenceCommandSet.CommandSetID,
2455                 JDWPCommands.ClassObjectReferenceCommandSet.ReflectedTypeCommand);
2456         command.setNextValueAsClassObjectID(classObjectID);
2457         return checkReply(performCommand(command));
2458     }
2459 
2460     /**
2461      * Returns the JNI signature of a reference type. JNI signature formats are
2462      * described in the Java Native Interface Specification
2463      *
2464      * @param refTypeID
2465      *            The reference type ID.
2466      * @return The JNI signature for the reference type.
2467      */
getReferenceTypeSignature(long refTypeID)2468     public final String getReferenceTypeSignature(long refTypeID) {
2469         CommandPacket command = new CommandPacket(
2470                 JDWPCommands.ReferenceTypeCommandSet.CommandSetID,
2471                 JDWPCommands.ReferenceTypeCommandSet.SignatureCommand);
2472         command.setNextValueAsReferenceTypeID(refTypeID);
2473         ReplyPacket reply = checkReply(performCommand(command));
2474         return reply.getNextValueAsString();
2475     }
2476 
2477     /**
2478      * Returns the thread group that contains a given thread
2479      *
2480      * @param threadID
2481      *            The thread object ID.
2482      * @return The thread group ID of this thread.
2483      */
getThreadGroupID(long threadID)2484     public final long getThreadGroupID(long threadID) {
2485         CommandPacket command = new CommandPacket(
2486                 JDWPCommands.ThreadReferenceCommandSet.CommandSetID,
2487                 JDWPCommands.ThreadReferenceCommandSet.ThreadGroupCommand);
2488         command.setNextValueAsThreadID(threadID);
2489         ReplyPacket reply = checkReply(performCommand(command));
2490         return reply.getNextValueAsThreadGroupID();
2491     }
2492 
2493     /**
2494      * Checks whether a given thread is suspended or not
2495      *
2496      * @param threadID
2497      *            The thread object ID.
2498      * @return True if a given thread is suspended, false otherwise.
2499      */
isThreadSuspended(long threadID)2500     public final boolean isThreadSuspended(long threadID) {
2501         CommandPacket command = new CommandPacket(
2502                 JDWPCommands.ThreadReferenceCommandSet.CommandSetID,
2503                 JDWPCommands.ThreadReferenceCommandSet.StatusCommand);
2504         command.setNextValueAsThreadID(threadID);
2505         ReplyPacket reply = checkReply(performCommand(command));
2506         reply.getNextValueAsInt(); // the thread's status; is not used
2507         return reply.getNextValueAsInt() == JDWPConstants.SuspendStatus.SUSPEND_STATUS_SUSPENDED;
2508     }
2509 
2510     /**
2511      * Returns JNI signature of method.
2512      *
2513      * @param classID
2514      *            The reference type ID.
2515      * @param methodID
2516      *            The method ID.
2517      * @return JNI signature of method.
2518      */
getMethodSignature(long classID, long methodID)2519     public final String getMethodSignature(long classID, long methodID) {
2520         CommandPacket command = new CommandPacket(
2521                 JDWPCommands.ReferenceTypeCommandSet.CommandSetID,
2522                 JDWPCommands.ReferenceTypeCommandSet.MethodsCommand);
2523         command.setNextValueAsReferenceTypeID(classID);
2524         ReplyPacket reply = checkReply(performCommand(command));
2525         int methods = reply.getNextValueAsInt();
2526         String value = null;
2527         for (int i = 0; i < methods; i++) {
2528             long mID = reply.getNextValueAsMethodID();
2529             reply.getNextValueAsString(); // name of the method; is not used
2530             String methodSign = reply.getNextValueAsString();
2531             reply.getNextValueAsInt();
2532             if (mID == methodID) {
2533                 value = methodSign;
2534                 value = value.replaceAll("/", ".");
2535                 int lastRoundBracketIndex = value.lastIndexOf(")");
2536                 value = value.substring(0, lastRoundBracketIndex + 1);
2537                 break;
2538             }
2539         }
2540 
2541         return value;
2542     }
2543 
2544     /**
2545      * Returns the characters contained in the string
2546      *
2547      * @param objectID
2548      *            The String object ID.
2549      * @return A string value.
2550      */
getStringValue(long objectID)2551     public final String getStringValue(long objectID) {
2552         CommandPacket command = new CommandPacket(
2553                 JDWPCommands.StringReferenceCommandSet.CommandSetID,
2554                 JDWPCommands.StringReferenceCommandSet.ValueCommand);
2555         command.setNextValueAsObjectID(objectID);
2556         ReplyPacket reply = checkReply(performCommand(command));
2557         return reply.getNextValueAsString();
2558     }
2559 
2560     /**
2561      * Returns a range of array components
2562      *
2563      * @param objectID
2564      *            The array object ID.
2565      * @return The retrieved values.
2566      */
getArrayValues(long objectID)2567     public Value[] getArrayValues(long objectID) {
2568         CommandPacket command = new CommandPacket(
2569                 JDWPCommands.ArrayReferenceCommandSet.CommandSetID,
2570                 JDWPCommands.ArrayReferenceCommandSet.LengthCommand);
2571         command.setNextValueAsArrayID(objectID);
2572         ReplyPacket reply = checkReply(performCommand(command));
2573         int length = reply.getNextValueAsInt();
2574 
2575         if (length == 0) {
2576             return null;
2577         }
2578 
2579         command = new CommandPacket(
2580                 JDWPCommands.ArrayReferenceCommandSet.CommandSetID,
2581                 JDWPCommands.ArrayReferenceCommandSet.GetValuesCommand);
2582         command.setNextValueAsArrayID(objectID);
2583         command.setNextValueAsInt(0);
2584         command.setNextValueAsInt(length);
2585         reply = checkReply(performCommand(command));
2586         ArrayRegion arrayRegion = reply.getNextValueAsArrayRegion();
2587 
2588         Value[] values = new Value[length];
2589         for (int i = 0; i < length; i++) {
2590             values[i] = arrayRegion.getValue(i);
2591         }
2592 
2593         return values;
2594     }
2595 
2596     /**
2597      * Returns a source line number according to a corresponding line code index
2598      * in a method's line table.
2599      *
2600      * @param classID
2601      *            The class object ID.
2602      * @param methodID
2603      *            The method ID.
2604      * @param codeIndex
2605      *            The line code index.
2606      * @return An integer line number.
2607      */
getLineNumber(long classID, long methodID, long codeIndex)2608     public final int getLineNumber(long classID, long methodID, long codeIndex) {
2609         int lineNumber = -1;
2610         ReplyPacket reply = getLineTable(classID, methodID);
2611         if (reply.getErrorCode() != JDWPConstants.Error.NONE) {
2612             return lineNumber;
2613         }
2614 
2615         reply.getNextValueAsLong(); // start line index, is not used
2616         reply.getNextValueAsLong(); // end line index, is not used
2617         int lines = reply.getNextValueAsInt();
2618         for (int i = 0; i < lines; i++) {
2619             long lineCodeIndex = reply.getNextValueAsLong();
2620             lineNumber = reply.getNextValueAsInt();
2621             if (lineCodeIndex == codeIndex) {
2622                 break;
2623             }
2624 
2625             if (lineCodeIndex > codeIndex) {
2626                 --lineNumber;
2627                 break;
2628             }
2629         }
2630 
2631         return lineNumber;
2632     }
2633 
2634     /**
2635      * Returns a line code index according to a corresponding line number in a
2636      * method's line table.
2637      *
2638      * @param classID
2639      *            The class object ID.
2640      * @param methodID
2641      *            The method ID.
2642      * @param lineNumber
2643      *            A source line number.
2644      * @return An integer representing the line code index.
2645      */
getLineCodeIndex(long classID, long methodID, int lineNumber)2646     public final long getLineCodeIndex(long classID, long methodID,
2647             int lineNumber) {
2648         ReplyPacket reply = getLineTable(classID, methodID);
2649         if (reply.getErrorCode() != JDWPConstants.Error.NONE) {
2650             return -1L;
2651         }
2652 
2653         reply.getNextValueAsLong(); // start line index, is not used
2654         reply.getNextValueAsLong(); // end line index, is not used
2655         int lines = reply.getNextValueAsInt();
2656         for (int i = 0; i < lines; i++) {
2657             long lineCodeIndex = reply.getNextValueAsLong();
2658             if (lineNumber == reply.getNextValueAsInt()) {
2659                 return lineCodeIndex;
2660             }
2661         }
2662 
2663         return -1L;
2664     }
2665 
2666     /**
2667      * Returns all variables which are visible within the given frame.
2668      *
2669      * @param frame
2670      *            The frame whose visible local variables to retrieve.
2671      * @return A list of Variable objects representing each visible local
2672      *         variable within the given frame.
2673      */
getLocalVars(Frame frame)2674     public final List getLocalVars(Frame frame) {
2675         List vars = getVariableTable(frame.getLocation().classID, frame
2676                 .getLocation().methodID);
2677         if (vars == null) {
2678             return null;
2679         }
2680 
2681         // All variables that are not visible from within current frame must be
2682         // removed from the list
2683         long frameCodeIndex = frame.getLocation().index;
2684         for (int i = 0; i < vars.size(); i++) {
2685             Variable var = (Variable) vars.toArray()[i];
2686             long varCodeIndex = var.getCodeIndex();
2687             if (varCodeIndex > frameCodeIndex
2688                     || (frameCodeIndex >= varCodeIndex + var.getLength())) {
2689                 vars.remove(i);
2690                 --i;
2691                 continue;
2692             }
2693         }
2694 
2695         return vars;
2696     }
2697 
2698     /**
2699      * Sets the value of one or more local variables
2700      *
2701      * @param frame
2702      *            The frame ID.
2703      * @param vars
2704      *            An array of Variable objects whose values to set
2705      * @param values
2706      *            An array of Value objects to set
2707      */
setLocalVars(Frame frame, Variable[] vars, Value[] values)2708     public final void setLocalVars(Frame frame, Variable[] vars, Value[] values) {
2709         if (vars.length != values.length) {
2710             throw new TestErrorException(
2711                     "Number of variables doesn't correspond to number of their values");
2712         }
2713 
2714         CommandPacket command = new CommandPacket(
2715                 JDWPCommands.StackFrameCommandSet.CommandSetID,
2716                 JDWPCommands.StackFrameCommandSet.SetValuesCommand);
2717         command.setNextValueAsThreadID(frame.getThreadID());
2718         command.setNextValueAsFrameID(frame.getID());
2719         command.setNextValueAsInt(vars.length);
2720         for (int i = 0; i < vars.length; i++) {
2721             command.setNextValueAsInt(vars[i].getSlot());
2722             command.setNextValueAsValue(values[i]);
2723         }
2724 
2725         checkReply(performCommand(command));
2726     }
2727 
2728     /**
2729      * Sets the value of one or more instance fields
2730      *
2731      * @param objectID
2732      *            The object ID.
2733      * @param fieldIDs
2734      *            An array of fields IDs
2735      * @param values
2736      *            An array of Value objects representing each value to set
2737      */
setInstanceFieldsValues(long objectID, long[] fieldIDs, Value[] values)2738     public final void setInstanceFieldsValues(long objectID, long[] fieldIDs,
2739             Value[] values) {
2740         if (fieldIDs.length != values.length) {
2741             throw new TestErrorException(
2742                     "Number of fields doesn't correspond to number of their values");
2743         }
2744 
2745         CommandPacket command = new CommandPacket(
2746                 JDWPCommands.ObjectReferenceCommandSet.CommandSetID,
2747                 JDWPCommands.ObjectReferenceCommandSet.SetValuesCommand);
2748         command.setNextValueAsObjectID(objectID);
2749         command.setNextValueAsInt(fieldIDs.length);
2750         for (int i = 0; i < fieldIDs.length; i++) {
2751             command.setNextValueAsFieldID(fieldIDs[i]);
2752             command.setNextValueAsUntaggedValue(values[i]);
2753         }
2754 
2755         checkReply(performCommand(command));
2756     }
2757 
2758     /**
2759      * Sets a range of array components. The specified range must be within the
2760      * bounds of the array.
2761      *
2762      * @param arrayID
2763      *            The array object ID.
2764      * @param firstIndex
2765      *            The first index to set.
2766      * @param values
2767      *            An array of Value objects representing each value to set.
2768      */
setArrayValues(long arrayID, int firstIndex, Value[] values)2769     public final void setArrayValues(long arrayID, int firstIndex,
2770             Value[] values) {
2771         CommandPacket command = new CommandPacket(
2772                 JDWPCommands.ArrayReferenceCommandSet.CommandSetID,
2773                 JDWPCommands.ArrayReferenceCommandSet.SetValuesCommand);
2774         command.setNextValueAsArrayID(arrayID);
2775         command.setNextValueAsInt(firstIndex);
2776         command.setNextValueAsInt(values.length);
2777         for (int i = 0; i < values.length; i++) {
2778             command.setNextValueAsUntaggedValue(values[i]);
2779         }
2780 
2781         checkReply(performCommand(command));
2782     }
2783 
2784     /**
2785      * Sets the value of one or more static fields
2786      *
2787      * @param classID
2788      *            The class type ID.
2789      * @param fieldIDs
2790      *            An array of fields IDs
2791      * @param values
2792      *            An array of Value objects representing each value to set
2793      */
setStaticFieldsValues(long classID, long[] fieldIDs, Value[] values)2794     public final void setStaticFieldsValues(long classID, long[] fieldIDs,
2795             Value[] values) {
2796         if (fieldIDs.length != values.length) {
2797             throw new TestErrorException(
2798                     "Number of fields doesn't correspond to number of their values");
2799         }
2800 
2801         CommandPacket command = new CommandPacket(
2802                 JDWPCommands.ClassTypeCommandSet.CommandSetID,
2803                 JDWPCommands.ClassTypeCommandSet.SetValuesCommand);
2804         command.setNextValueAsClassID(classID);
2805         command.setNextValueAsInt(fieldIDs.length);
2806         for (int i = 0; i < fieldIDs.length; i++) {
2807             command.setNextValueAsFieldID(fieldIDs[i]);
2808             command.setNextValueAsUntaggedValue(values[i]);
2809         }
2810 
2811         checkReply(performCommand(command));
2812     }
2813 
2814     /**
2815      * Creates java String in target VM with the given value.
2816      *
2817      * @param value
2818      *            The value of the string.
2819      * @return The string id.
2820      */
createString(String value)2821     public final long createString(String value) {
2822         CommandPacket command = new CommandPacket(
2823                 JDWPCommands.VirtualMachineCommandSet.CommandSetID,
2824                 JDWPCommands.VirtualMachineCommandSet.CreateStringCommand);
2825         command.setNextValueAsString(value);
2826         ReplyPacket reply = checkReply(performCommand(command));
2827         return reply.getNextValueAsStringID();
2828     }
2829 
2830     /**
2831      * Processes JDWP PopFrames command from StackFrame command set.
2832      *
2833      * @param frame
2834      *            The instance of Frame.
2835      */
popFrame(Frame frame)2836     public final void popFrame(Frame frame) {
2837         CommandPacket command = new CommandPacket(
2838                 JDWPCommands.StackFrameCommandSet.CommandSetID,
2839                 JDWPCommands.StackFrameCommandSet.PopFramesCommand);
2840         command.setNextValueAsThreadID(frame.getThreadID());
2841         command.setNextValueAsFrameID(frame.getID());
2842         checkReply(performCommand(command));
2843     }
2844 
2845     /**
2846      * Invokes a member method of the given object.
2847      *
2848      * @param objectID
2849      *            The object ID.
2850      * @param threadID
2851      *            The thread ID.
2852      * @param methodName
2853      *            The name of method for the invocation.
2854      * @param args
2855      *            The arguments for the invocation.
2856      * @param options
2857      *            The invocation options.
2858      * @return ReplyPacket for corresponding command
2859      */
invokeInstanceMethod(long objectID, long threadID, String methodName, Value[] args, int options)2860     public final ReplyPacket invokeInstanceMethod(long objectID, long threadID,
2861             String methodName, Value[] args, int options) {
2862         long classID = getReferenceType(objectID);
2863         long methodID = getMethodID(classID, methodName);
2864         CommandPacket command = new CommandPacket(
2865                 JDWPCommands.ObjectReferenceCommandSet.CommandSetID,
2866                 JDWPCommands.ObjectReferenceCommandSet.InvokeMethodCommand);
2867         command.setNextValueAsObjectID(objectID);
2868         command.setNextValueAsThreadID(threadID);
2869         command.setNextValueAsClassID(classID);
2870         command.setNextValueAsMethodID(methodID);
2871         command.setNextValueAsInt(args.length);
2872         for (int i = 0; i < args.length; i++) {
2873             command.setNextValueAsValue(args[i]);
2874         }
2875         command.setNextValueAsInt(options);
2876 
2877         return checkReply(performCommand(command));
2878     }
2879 
2880     /**
2881      * Invokes a static method of the given class.
2882      *
2883      * @param classID
2884      *            The class type ID.
2885      * @param threadID
2886      *            The thread ID.
2887      * @param methodName
2888      *            The name of method for the invocation.
2889      * @param args
2890      *            The arguments for the invocation.
2891      * @param options
2892      *            The invocation options.
2893      * @return ReplyPacket for corresponding command
2894      */
invokeStaticMethod(long classID, long threadID, String methodName, Value[] args, int options)2895     public final ReplyPacket invokeStaticMethod(long classID, long threadID,
2896             String methodName, Value[] args, int options) {
2897         long methodID = getMethodID(classID, methodName);
2898         CommandPacket command = new CommandPacket(
2899                 JDWPCommands.ClassTypeCommandSet.CommandSetID,
2900                 JDWPCommands.ClassTypeCommandSet.InvokeMethodCommand);
2901         command.setNextValueAsClassID(classID);
2902         command.setNextValueAsThreadID(threadID);
2903         command.setNextValueAsMethodID(methodID);
2904         command.setNextValueAsInt(args.length);
2905         for (int i = 0; i < args.length; i++) {
2906             command.setNextValueAsValue(args[i]);
2907         }
2908         command.setNextValueAsInt(options);
2909 
2910         return checkReply(performCommand(command));
2911     }
2912 }
2913