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