0001: /*
0002: * Licensed to the Apache Software Foundation (ASF) under one or more
0003: * contributor license agreements. See the NOTICE file distributed with
0004: * this work for additional information regarding copyright ownership.
0005: * The ASF licenses this file to You under the Apache License, Version 2.0
0006: * (the "License"); you may not use this file except in compliance with
0007: * the License. You may obtain a copy of the License at
0008: *
0009: * http://www.apache.org/licenses/LICENSE-2.0
0010: *
0011: * Unless required by applicable law or agreed to in writing, software
0012: * distributed under the License is distributed on an "AS IS" BASIS,
0013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014: *
0015: * See the License for the specific language governing permissions and
0016: * limitations under the License.
0017: */
0018:
0019: /**
0020: * @author Vitaly A. Provodin
0021: * @version $Revision: 1.7 $
0022: */package org.apache.harmony.jpda.tests.framework.jdwp;
0023:
0024: import java.io.IOException;
0025: import java.util.ArrayList;
0026: import java.util.Iterator;
0027: import java.util.List;
0028:
0029: import org.apache.harmony.jpda.tests.framework.Breakpoint;
0030: import org.apache.harmony.jpda.tests.framework.LogWriter;
0031: import org.apache.harmony.jpda.tests.framework.TestErrorException;
0032: import org.apache.harmony.jpda.tests.framework.TestOptions;
0033: import org.apache.harmony.jpda.tests.framework.jdwp.Capabilities;
0034: import org.apache.harmony.jpda.tests.framework.jdwp.CommandPacket;
0035: import org.apache.harmony.jpda.tests.framework.jdwp.Event;
0036: import org.apache.harmony.jpda.tests.framework.jdwp.EventMod;
0037: import org.apache.harmony.jpda.tests.framework.jdwp.JDWPConstants;
0038: import org.apache.harmony.jpda.tests.framework.jdwp.Location;
0039: import org.apache.harmony.jpda.tests.framework.jdwp.ReplyPacket;
0040: import org.apache.harmony.jpda.tests.framework.jdwp.TransportWrapper;
0041: import org.apache.harmony.jpda.tests.framework.jdwp.TypesLengths;
0042: import org.apache.harmony.jpda.tests.framework.jdwp.Frame.Variable;
0043: import org.apache.harmony.jpda.tests.framework.jdwp.exceptions.ReplyErrorCodeException;
0044: import org.apache.harmony.jpda.tests.framework.jdwp.exceptions.TimeoutException;
0045:
0046: /**
0047: * This class provides convenient way for communicating with debuggee VM using
0048: * JDWP packets.
0049: * <p>
0050: * Most methods can throw ReplyErrorCodeException if error occurred in execution
0051: * of corresponding JDWP command or TestErrorException if any other error
0052: * occurred.
0053: */
0054: public class VmMirror {
0055:
0056: /** Target VM Capabilities. */
0057: public Capabilities targetVMCapabilities;
0058:
0059: /** Transport used to sent and receive packets. */
0060: private TransportWrapper connection;
0061:
0062: /** PacketDispatcher thread used for asynchronous reading packets. */
0063: private PacketDispatcher packetDispatcher;
0064:
0065: /** Test run options. */
0066: protected TestOptions config;
0067:
0068: /** Log to write messages. */
0069: protected LogWriter logWriter;
0070:
0071: /**
0072: * Creates new VmMirror instance for given test run options.
0073: *
0074: * @param config test run options
0075: * @param logWriter log writer
0076: */
0077: public VmMirror(TestOptions config, LogWriter logWriter) {
0078: connection = null;
0079: this .config = config;
0080: this .logWriter = logWriter;
0081: }
0082:
0083: /**
0084: * Checks error code of given reply packet and throws
0085: * ReplyErrorCodeException if any error detected.
0086: *
0087: * @param reply
0088: * reply packet to check
0089: * @return ReplyPacket unchanged reply packet
0090: */
0091: public ReplyPacket checkReply(ReplyPacket reply) {
0092: if (reply.getErrorCode() != JDWPConstants.Error.NONE)
0093: throw new ReplyErrorCodeException(reply.getErrorCode());
0094: return reply;
0095: }
0096:
0097: /**
0098: * Sets breakpoint to given location.
0099: *
0100: * @param typeTag
0101: * @param breakpoint
0102: * @return ReplyPacket for corresponding command
0103: */
0104: public ReplyPacket setBreakpoint(byte typeTag, Breakpoint breakpoint) {
0105:
0106: return setBreakpoint(typeTag, breakpoint,
0107: JDWPConstants.SuspendPolicy.ALL);
0108: }
0109:
0110: /**
0111: * Sets breakpoint to given location.
0112: *
0113: * @param typeTag
0114: * @param breakpoint
0115: * @param suspendPolicy
0116: * Suspend policy for a breakpoint being created
0117: * @return ReplyPacket for corresponding command
0118: */
0119: public ReplyPacket setBreakpoint(byte typeTag,
0120: Breakpoint breakpoint, byte suspendPolicy) {
0121: // Get Class reference ID
0122: long typeID = getTypeID(breakpoint.className, typeTag);
0123:
0124: // Get Method reference ID
0125: long methodID = getMethodID(typeID, breakpoint.methodName);
0126:
0127: // Fill location
0128: Location location = new Location(typeTag, typeID, methodID,
0129: breakpoint.index);
0130:
0131: // Set breakpoint
0132: return setBreakpoint(location, suspendPolicy);
0133: }
0134:
0135: /**
0136: * Sets breakpoint to given location.
0137: *
0138: * @param location
0139: * Location of breakpoint
0140: * @return ReplyPacket for corresponding command
0141: */
0142: public ReplyPacket setBreakpoint(Location location) {
0143:
0144: return setBreakpoint(location, JDWPConstants.SuspendPolicy.ALL);
0145: }
0146:
0147: /**
0148: * Sets breakpoint to given location
0149: *
0150: * @param location
0151: * Location of breakpoint
0152: * @param suspendPolicy
0153: * Suspend policy for a breakpoint being created
0154: * @return ReplyPacket for corresponding command
0155: */
0156: public ReplyPacket setBreakpoint(Location location,
0157: byte suspendPolicy) {
0158: // Prepare corresponding event
0159: byte eventKind = JDWPConstants.EventKind.BREAKPOINT;
0160:
0161: // EventMod[] mods = new EventMod[1];
0162: EventMod[] mods = new EventMod[] { new EventMod() };
0163:
0164: mods[0].loc = location;
0165: mods[0].modKind = EventMod.ModKind.LocationOnly;
0166: Event event = new Event(eventKind, suspendPolicy, mods);
0167:
0168: // Set breakpoint
0169: return setEvent(event);
0170: }
0171:
0172: /**
0173: * Sets breakpoint that triggers only on a certain occurrence to a given
0174: * location
0175: *
0176: * @param typeTag
0177: * @param breakpoint
0178: * @param suspendPolicy
0179: * Suspend policy for a breakpoint being created
0180: * @param count
0181: * Limit the requested event to be reported at most once after a
0182: * given number of occurrences
0183: * @return ReplyPacket for corresponding command
0184: */
0185: public ReplyPacket setCountableBreakpoint(byte typeTag,
0186: Breakpoint breakpoint, byte suspendPolicy, int count) {
0187: long typeID = getTypeID(breakpoint.className, typeTag);
0188:
0189: // Get Method reference ID
0190: long methodID = getMethodID(typeID, breakpoint.methodName);
0191:
0192: byte eventKind = JDWPConstants.EventKind.BREAKPOINT;
0193:
0194: EventMod mod1 = new EventMod();
0195: mod1.modKind = EventMod.ModKind.LocationOnly;
0196: mod1.loc = new Location(typeTag, typeID, methodID,
0197: breakpoint.index);
0198:
0199: EventMod mod2 = new EventMod();
0200: mod2.modKind = EventMod.ModKind.Count;
0201: mod2.count = count;
0202:
0203: EventMod[] mods = new EventMod[] { mod1, mod2 };
0204: Event event = new Event(eventKind, suspendPolicy, mods);
0205:
0206: // Set breakpoint
0207: return setEvent(event);
0208: }
0209:
0210: /**
0211: * Sets breakpoint at the beginning of method with name <i>methodName</i>.
0212: *
0213: * @param classID
0214: * id of class with required method
0215: * @param methodName
0216: * name of required method
0217: * @return requestID id of request
0218: */
0219: public long setBreakpointAtMethodBegin(long classID,
0220: String methodName) {
0221: long requestID;
0222:
0223: long methodID = getMethodID(classID, methodName);
0224:
0225: ReplyPacket lineTableReply = getLineTable(classID, methodID);
0226: if (lineTableReply.getErrorCode() != JDWPConstants.Error.NONE) {
0227: throw new TestErrorException(
0228: "Command getLineTable returned error code: "
0229: + lineTableReply.getErrorCode()
0230: + " - "
0231: + JDWPConstants.Error
0232: .getName(lineTableReply
0233: .getErrorCode()));
0234: }
0235:
0236: lineTableReply.getNextValueAsLong();
0237: // Lowest valid code index for the method
0238:
0239: lineTableReply.getNextValueAsLong();
0240: // Highest valid code index for the method
0241:
0242: // int numberOfLines =
0243: lineTableReply.getNextValueAsInt();
0244:
0245: long lineCodeIndex = lineTableReply.getNextValueAsLong();
0246:
0247: // set breakpoint inside checked method
0248: Location breakpointLocation = new Location(
0249: JDWPConstants.TypeTag.CLASS, classID, methodID,
0250: lineCodeIndex);
0251:
0252: ReplyPacket reply = setBreakpoint(breakpointLocation);
0253: checkReply(reply);
0254:
0255: requestID = reply.getNextValueAsInt();
0256:
0257: return requestID;
0258: }
0259:
0260: /**
0261: * Waits for stop on breakpoint and gets id of thread where it stopped.
0262: *
0263: * @param requestID
0264: * id of request for breakpoint
0265: * @return threadID id of thread, where we stop on breakpoint
0266: */
0267: public long waitForBreakpoint(long requestID) {
0268: // receive event
0269: CommandPacket event = null;
0270: event = receiveEvent();
0271:
0272: event.getNextValueAsByte();
0273: // suspendPolicy - is not used here
0274:
0275: // int numberOfEvents =
0276: event.getNextValueAsInt();
0277:
0278: long breakpointThreadID = 0;
0279: ParsedEvent[] eventParsed = ParsedEvent.parseEventPacket(event);
0280:
0281: if (eventParsed.length != 1) {
0282: throw new TestErrorException("Received "
0283: + eventParsed.length
0284: + " events instead of 1 BREAKPOINT_EVENT");
0285: }
0286:
0287: // check if received event is for breakpoint
0288: if (eventParsed[0].getEventKind() == JDWPConstants.EventKind.BREAKPOINT) {
0289: breakpointThreadID = ((ParsedEvent.Event_BREAKPOINT) eventParsed[0])
0290: .getThreadID();
0291:
0292: } else {
0293: throw new TestErrorException(
0294: "Kind of received event is not BREAKPOINT_EVENT: "
0295: + eventParsed[0].getEventKind());
0296:
0297: }
0298:
0299: if (eventParsed[0].getRequestID() != requestID) {
0300: throw new TestErrorException(
0301: "Received BREAKPOINT_EVENT with another requestID: "
0302: + eventParsed[0].getRequestID());
0303: }
0304:
0305: return breakpointThreadID;
0306: }
0307:
0308: /**
0309: * Removes breakpoint according to specified requestID.
0310: *
0311: * @param requestID
0312: * for given breakpoint
0313: * @return ReplyPacket for corresponding command
0314: */
0315: public ReplyPacket clearBreakpoint(int requestID) {
0316:
0317: // Create new command packet
0318: CommandPacket commandPacket = new CommandPacket();
0319:
0320: // Set command. "2" - is ID of Clear command in EventRequest Command Set
0321: commandPacket
0322: .setCommand(JDWPCommands.EventRequestCommandSet.ClearCommand);
0323:
0324: // Set command set. "15" - is ID of EventRequest Command Set
0325: commandPacket
0326: .setCommandSet(JDWPCommands.EventRequestCommandSet.CommandSetID);
0327:
0328: // Set outgoing data
0329: // Set eventKind
0330: commandPacket
0331: .setNextValueAsByte(JDWPConstants.EventKind.BREAKPOINT);
0332:
0333: // Set suspendPolicy
0334: commandPacket.setNextValueAsInt(requestID);
0335:
0336: // Send packet
0337: return checkReply(performCommand(commandPacket));
0338: }
0339:
0340: /**
0341: * Removes all breakpoints.
0342: *
0343: * @return ReplyPacket for corresponding command
0344: */
0345: public ReplyPacket ClearAllBreakpoints() {
0346:
0347: // Create new command packet
0348: CommandPacket commandPacket = new CommandPacket();
0349:
0350: // Set command. "3" - is ID of ClearAllBreakpoints command in
0351: // EventRequest Command Set
0352: commandPacket
0353: .setCommand(JDWPCommands.EventRequestCommandSet.ClearAllBreakpointsCommand);
0354:
0355: // Set command set. "15" - is ID of EventRequest Command Set
0356: commandPacket
0357: .setCommandSet(JDWPCommands.EventRequestCommandSet.CommandSetID);
0358:
0359: // Send packet
0360: return checkReply(performCommand(commandPacket));
0361: }
0362:
0363: /**
0364: * Requests debuggee VM capabilities. Function parses reply packet of
0365: * VirtualMachine::CapabilitiesNew command, creates and fills class Capabilities with
0366: * returned info.
0367: *
0368: * @return ReplyPacket useless, already parsed reply packet.
0369: */
0370: public ReplyPacket capabilities() {
0371:
0372: // Create new command packet
0373: CommandPacket commandPacket = new CommandPacket();
0374:
0375: // Set command. "17" - is ID of CapabilitiesNew command in
0376: // VirtualMachine Command Set
0377: commandPacket
0378: .setCommand(JDWPCommands.VirtualMachineCommandSet.CapabilitiesNewCommand);
0379:
0380: // Set command set. "1" - is ID of VirtualMachine Command Set
0381: commandPacket
0382: .setCommandSet(JDWPCommands.VirtualMachineCommandSet.CommandSetID);
0383:
0384: // Send packet
0385: ReplyPacket replyPacket = checkReply(performCommand(commandPacket));
0386:
0387: targetVMCapabilities = new Capabilities();
0388:
0389: // Set capabilities
0390: targetVMCapabilities.canWatchFieldModification = replyPacket
0391: .getNextValueAsBoolean();
0392: targetVMCapabilities.canWatchFieldAccess = replyPacket
0393: .getNextValueAsBoolean();
0394: targetVMCapabilities.canGetBytecodes = replyPacket
0395: .getNextValueAsBoolean();
0396: targetVMCapabilities.canGetSyntheticAttribute = replyPacket
0397: .getNextValueAsBoolean();
0398: targetVMCapabilities.canGetOwnedMonitorInfo = replyPacket
0399: .getNextValueAsBoolean();
0400: targetVMCapabilities.canGetCurrentContendedMonitor = replyPacket
0401: .getNextValueAsBoolean();
0402: targetVMCapabilities.canGetMonitorInfo = replyPacket
0403: .getNextValueAsBoolean();
0404: targetVMCapabilities.canRedefineClasses = replyPacket
0405: .getNextValueAsBoolean();
0406: targetVMCapabilities.canAddMethod = replyPacket
0407: .getNextValueAsBoolean();
0408: targetVMCapabilities.canUnrestrictedlyRedefineClasses = replyPacket
0409: .getNextValueAsBoolean();
0410: targetVMCapabilities.canPopFrames = replyPacket
0411: .getNextValueAsBoolean();
0412: targetVMCapabilities.canUseInstanceFilters = replyPacket
0413: .getNextValueAsBoolean();
0414: targetVMCapabilities.canGetSourceDebugExtension = replyPacket
0415: .getNextValueAsBoolean();
0416: targetVMCapabilities.canRequestVMDeathEvent = replyPacket
0417: .getNextValueAsBoolean();
0418: targetVMCapabilities.canSetDefaultStratum = replyPacket
0419: .getNextValueAsBoolean();
0420: targetVMCapabilities.reserved16 = replyPacket
0421: .getNextValueAsBoolean();
0422: targetVMCapabilities.reserved17 = replyPacket
0423: .getNextValueAsBoolean();
0424: targetVMCapabilities.reserved18 = replyPacket
0425: .getNextValueAsBoolean();
0426: targetVMCapabilities.reserved19 = replyPacket
0427: .getNextValueAsBoolean();
0428: targetVMCapabilities.reserved20 = replyPacket
0429: .getNextValueAsBoolean();
0430: targetVMCapabilities.reserved21 = replyPacket
0431: .getNextValueAsBoolean();
0432: targetVMCapabilities.reserved22 = replyPacket
0433: .getNextValueAsBoolean();
0434: targetVMCapabilities.reserved23 = replyPacket
0435: .getNextValueAsBoolean();
0436: targetVMCapabilities.reserved24 = replyPacket
0437: .getNextValueAsBoolean();
0438: targetVMCapabilities.reserved25 = replyPacket
0439: .getNextValueAsBoolean();
0440: targetVMCapabilities.reserved26 = replyPacket
0441: .getNextValueAsBoolean();
0442: targetVMCapabilities.reserved27 = replyPacket
0443: .getNextValueAsBoolean();
0444: targetVMCapabilities.reserved28 = replyPacket
0445: .getNextValueAsBoolean();
0446: targetVMCapabilities.reserved29 = replyPacket
0447: .getNextValueAsBoolean();
0448: targetVMCapabilities.reserved30 = replyPacket
0449: .getNextValueAsBoolean();
0450: targetVMCapabilities.reserved31 = replyPacket
0451: .getNextValueAsBoolean();
0452: targetVMCapabilities.reserved32 = replyPacket
0453: .getNextValueAsBoolean();
0454:
0455: return replyPacket;
0456: }
0457:
0458: /**
0459: * Resumes debuggee VM.
0460: *
0461: * @return ReplyPacket for corresponding command
0462: */
0463: public ReplyPacket resume() {
0464: CommandPacket commandPacket = new CommandPacket(
0465: JDWPCommands.VirtualMachineCommandSet.CommandSetID,
0466: JDWPCommands.VirtualMachineCommandSet.ResumeCommand);
0467:
0468: return checkReply(performCommand(commandPacket));
0469: }
0470:
0471: /**
0472: * Resumes specified thread on target Virtual Machine
0473: *
0474: * @return ReplyPacket for corresponding command
0475: */
0476: public ReplyPacket resumeThread(long threadID) {
0477: CommandPacket commandPacket = new CommandPacket(
0478: JDWPCommands.ThreadReferenceCommandSet.CommandSetID,
0479: JDWPCommands.ThreadReferenceCommandSet.ResumeCommand);
0480:
0481: commandPacket.setNextValueAsThreadID(threadID);
0482: return checkReply(performCommand(commandPacket));
0483: }
0484:
0485: /**
0486: * Suspends debuggee VM.
0487: *
0488: * @return ReplyPacket for corresponding command
0489: */
0490: public ReplyPacket suspend() {
0491: CommandPacket commandPacket = new CommandPacket(
0492: JDWPCommands.VirtualMachineCommandSet.CommandSetID,
0493: JDWPCommands.VirtualMachineCommandSet.SuspendCommand);
0494:
0495: return checkReply(performCommand(commandPacket));
0496: }
0497:
0498: /**
0499: * Suspends specified thread in debuggee VM.
0500: *
0501: * @return ReplyPacket for corresponding command
0502: */
0503: public ReplyPacket suspendThread(long threadID) {
0504: CommandPacket commandPacket = new CommandPacket(
0505: JDWPCommands.ThreadReferenceCommandSet.CommandSetID,
0506: JDWPCommands.ThreadReferenceCommandSet.SuspendCommand);
0507:
0508: commandPacket.setNextValueAsThreadID(threadID);
0509: return checkReply(performCommand(commandPacket));
0510: }
0511:
0512: /**
0513: * Disposes connection to debuggee VM.
0514: *
0515: * @return ReplyPacket for corresponding command
0516: */
0517: public ReplyPacket dispose() {
0518: // Create new command packet
0519: CommandPacket commandPacket = new CommandPacket();
0520: commandPacket
0521: .setCommand(JDWPCommands.VirtualMachineCommandSet.DisposeCommand);
0522: commandPacket
0523: .setCommandSet(JDWPCommands.VirtualMachineCommandSet.CommandSetID);
0524:
0525: // Send packet
0526: return checkReply(performCommand(commandPacket));
0527: }
0528:
0529: /**
0530: * Exits debuggee VM process.
0531: *
0532: * @return ReplyPacket for corresponding command
0533: */
0534: public ReplyPacket exit(int exitCode) {
0535: // Create new command packet
0536: CommandPacket commandPacket = new CommandPacket();
0537: commandPacket
0538: .setCommand(JDWPCommands.VirtualMachineCommandSet.ExitCommand);
0539: commandPacket
0540: .setCommandSet(JDWPCommands.VirtualMachineCommandSet.CommandSetID);
0541: commandPacket.setNextValueAsInt(exitCode);
0542:
0543: // Send packet
0544: return checkReply(performCommand(commandPacket));
0545: }
0546:
0547: /**
0548: * Adjusts lengths for all VM-specific types.
0549: *
0550: * @return ReplyPacket for corresponding command
0551: */
0552: public ReplyPacket adjustTypeLength() {
0553: // Create new command packet
0554: CommandPacket commandPacket = new CommandPacket();
0555: commandPacket
0556: .setCommand(JDWPCommands.VirtualMachineCommandSet.IDSizesCommand);
0557: commandPacket
0558: .setCommandSet(JDWPCommands.VirtualMachineCommandSet.CommandSetID);
0559:
0560: // Send packet
0561: ReplyPacket replyPacket = checkReply(performCommand(commandPacket));
0562:
0563: // Get FieldIDSize from ReplyPacket
0564: TypesLengths.setTypeLength(TypesLengths.FIELD_ID, replyPacket
0565: .getNextValueAsInt());
0566:
0567: // Get MethodIDSize from ReplyPacket
0568: TypesLengths.setTypeLength(TypesLengths.METHOD_ID, replyPacket
0569: .getNextValueAsInt());
0570:
0571: // Get ObjectIDSize from ReplyPacket
0572: TypesLengths.setTypeLength(TypesLengths.OBJECT_ID, replyPacket
0573: .getNextValueAsInt());
0574:
0575: // Get ReferenceTypeIDSize from ReplyPacket
0576: TypesLengths.setTypeLength(TypesLengths.REFERENCE_TYPE_ID,
0577: replyPacket.getNextValueAsInt());
0578:
0579: // Get FrameIDSize from ReplyPacket
0580: TypesLengths.setTypeLength(TypesLengths.FRAME_ID, replyPacket
0581: .getNextValueAsInt());
0582:
0583: // Adjust all other types lengths
0584: TypesLengths.setTypeLength(TypesLengths.ARRAY_ID, TypesLengths
0585: .getTypeLength(TypesLengths.OBJECT_ID));
0586: TypesLengths.setTypeLength(TypesLengths.STRING_ID, TypesLengths
0587: .getTypeLength(TypesLengths.OBJECT_ID));
0588: TypesLengths.setTypeLength(TypesLengths.THREAD_ID, TypesLengths
0589: .getTypeLength(TypesLengths.OBJECT_ID));
0590: TypesLengths.setTypeLength(TypesLengths.THREADGROUP_ID,
0591: TypesLengths.getTypeLength(TypesLengths.OBJECT_ID));
0592: TypesLengths.setTypeLength(TypesLengths.LOCATION_ID,
0593: TypesLengths.getTypeLength(TypesLengths.OBJECT_ID));
0594: TypesLengths.setTypeLength(TypesLengths.CLASS_ID, TypesLengths
0595: .getTypeLength(TypesLengths.OBJECT_ID));
0596: TypesLengths.setTypeLength(TypesLengths.CLASSLOADER_ID,
0597: TypesLengths.getTypeLength(TypesLengths.OBJECT_ID));
0598: TypesLengths.setTypeLength(TypesLengths.CLASSOBJECT_ID,
0599: TypesLengths.getTypeLength(TypesLengths.OBJECT_ID));
0600: return replyPacket;
0601: }
0602:
0603: /**
0604: * Gets TypeID for specified type signature and type tag.
0605: *
0606: * @param typeSignature
0607: * type signature
0608: * @param classTypeTag
0609: * type tag
0610: * @return received TypeID
0611: */
0612: public long getTypeID(String typeSignature, byte classTypeTag) {
0613: int classes = 0;
0614: byte refTypeTag = 0;
0615: long typeID = -1;
0616:
0617: // Request referenceTypeID for exception
0618: ReplyPacket classReference = getClassBySignature(typeSignature);
0619:
0620: // Get referenceTypeID from received packet
0621: classes = classReference.getNextValueAsInt();
0622: for (int i = 0; i < classes; i++) {
0623: refTypeTag = classReference.getNextValueAsByte();
0624: if (refTypeTag == classTypeTag) {
0625: typeID = classReference.getNextValueAsReferenceTypeID();
0626: classReference.getNextValueAsInt();
0627: break;
0628: } else {
0629: classReference.getNextValueAsReferenceTypeID();
0630: classReference.getNextValueAsInt();
0631: refTypeTag = 0;
0632: }
0633: }
0634: return typeID;
0635: }
0636:
0637: /**
0638: * Gets ClassID for specified class signature.
0639: *
0640: * @param classSignature
0641: * class signature
0642: * @return received ClassID
0643: */
0644: public long getClassID(String classSignature) {
0645: return getTypeID(classSignature, JDWPConstants.TypeTag.CLASS);
0646: }
0647:
0648: /**
0649: * Gets ThreadID for specified thread name.
0650: *
0651: * @param threadName
0652: * thread name
0653: * @return received ThreadID
0654: */
0655: public long getThreadID(String threadName) {
0656: ReplyPacket request = null;
0657: long threadID = -1;
0658: long thread = -1;
0659: String name = null;
0660: int threads = -1;
0661:
0662: // Get All Threads IDs
0663: request = getAllThreadID();
0664:
0665: // Get thread ID for threadName
0666: threads = request.getNextValueAsInt();
0667: for (int i = 0; i < threads; i++) {
0668: thread = request.getNextValueAsThreadID();
0669: name = getThreadName(thread);
0670: if (threadName.equals(name)) {
0671: threadID = thread;
0672: break;
0673: }
0674: }
0675:
0676: return threadID;
0677: }
0678:
0679: /**
0680: * Returns all running thread IDs.
0681: *
0682: * @return received reply packet
0683: */
0684: public ReplyPacket getAllThreadID() {
0685: // Create new command packet
0686: CommandPacket commandPacket = new CommandPacket(
0687: JDWPCommands.VirtualMachineCommandSet.CommandSetID,
0688: JDWPCommands.VirtualMachineCommandSet.AllThreadsCommand);
0689:
0690: return checkReply(performCommand(commandPacket));
0691: }
0692:
0693: /**
0694: * Gets class signature for specified class ID.
0695: *
0696: * @param classID
0697: * class ID
0698: * @return received class signature
0699: */
0700: public String getClassSignature(long classID) {
0701: // Create new command packet
0702: CommandPacket commandPacket = new CommandPacket(
0703: JDWPCommands.ReferenceTypeCommandSet.CommandSetID,
0704: JDWPCommands.ReferenceTypeCommandSet.SignatureCommand);
0705: commandPacket.setNextValueAsReferenceTypeID(classID);
0706: ReplyPacket replyPacket = checkReply(performCommand(commandPacket));
0707: return replyPacket.getNextValueAsString();
0708: }
0709:
0710: /**
0711: * Returns thread name for specified <code>threadID</code>.
0712: *
0713: * @param threadID
0714: * thread ID
0715: * @return thread name
0716: */
0717: public String getThreadName(long threadID) {
0718: // Create new command packet
0719: CommandPacket commandPacket = new CommandPacket(
0720: JDWPCommands.ThreadReferenceCommandSet.CommandSetID,
0721: JDWPCommands.ThreadReferenceCommandSet.NameCommand);
0722: commandPacket.setNextValueAsThreadID(threadID);
0723: ReplyPacket replyPacket = checkReply(performCommand(commandPacket));
0724: return replyPacket.getNextValueAsString();
0725: }
0726:
0727: /**
0728: * Returns thread status for specified <code>threadID</code>.
0729: *
0730: * @param threadID
0731: * thread ID
0732: * @return thread status
0733: */
0734: public int getThreadStatus(long threadID) {
0735: CommandPacket commandPacket = new CommandPacket(
0736: JDWPCommands.ThreadReferenceCommandSet.CommandSetID,
0737: JDWPCommands.ThreadReferenceCommandSet.StatusCommand);
0738: commandPacket.setNextValueAsThreadID(threadID);
0739: ReplyPacket replyPacket = checkReply(performCommand(commandPacket));
0740: return replyPacket.getNextValueAsInt();
0741: }
0742:
0743: /**
0744: * Returns name of thread group for specified <code>groupID</code>
0745: *
0746: * @param groupID
0747: * thread group ID
0748: *
0749: * @return name of thread group
0750: */
0751: public String getThreadGroupName(long groupID) {
0752: // Create new command packet
0753: CommandPacket commandPacket = new CommandPacket(
0754: JDWPCommands.ThreadGroupReferenceCommandSet.CommandSetID,
0755: JDWPCommands.ThreadGroupReferenceCommandSet.NameCommand);
0756: commandPacket.setNextValueAsReferenceTypeID(groupID);
0757: ReplyPacket replyPacket = checkReply(performCommand(commandPacket));
0758: return replyPacket.getNextValueAsString();
0759: }
0760:
0761: /**
0762: * Gets InterfaceID for specified interface signature.
0763: *
0764: * @param interfaceSignature
0765: * interface signature
0766: * @return received ClassID
0767: */
0768: public long getInterfaceID(String interfaceSignature) {
0769: return getTypeID(interfaceSignature,
0770: JDWPConstants.TypeTag.INTERFACE);
0771: }
0772:
0773: /**
0774: * Gets ArrayID for specified array signature.
0775: *
0776: * @param arraySignature
0777: * array signature
0778: * @return received ArrayID
0779: */
0780: public long getArrayID(String arraySignature) {
0781: return getTypeID(arraySignature,
0782: JDWPConstants.TypeTag.INTERFACE);
0783: }
0784:
0785: /**
0786: * Gets RequestID from specified ReplyPacket.
0787: *
0788: * @param request
0789: * ReplyPacket with RequestID
0790: * @return received RequestID
0791: */
0792: public int getRequestID(ReplyPacket request) {
0793: return request.getNextValueAsInt();
0794: }
0795:
0796: /**
0797: * Returns FieldID for specified class and field name.
0798: *
0799: * @param classID
0800: * ClassID to find field
0801: * @param fieldName
0802: * field name
0803: * @return received FieldID
0804: */
0805: public long getFieldID(long classID, String fieldName) {
0806: ReplyPacket reply = getFieldsInClass(classID);
0807: return getFieldID(reply, fieldName);
0808: }
0809:
0810: /**
0811: * Gets FieldID from ReplyPacket.
0812: *
0813: * @param request
0814: * ReplyPacket for request
0815: * @param field
0816: * field name to get ID for
0817: * @return received FieldID
0818: */
0819: public long getFieldID(ReplyPacket request, String field) {
0820: long fieldID = -1;
0821: String fieldName;
0822: // Get fieldID from received packet
0823: int count = request.getNextValueAsInt();
0824: for (int i = 0; i < count; i++) {
0825: fieldID = request.getNextValueAsFieldID();
0826: fieldName = request.getNextValueAsString();
0827: if (field.equals(fieldName)) {
0828: request.getNextValueAsString();
0829: request.getNextValueAsInt();
0830: break;
0831: } else {
0832: request.getNextValueAsString();
0833: request.getNextValueAsInt();
0834: fieldID = 0;
0835: fieldName = null;
0836: }
0837: }
0838: return fieldID;
0839: }
0840:
0841: /**
0842: * Gets Method ID for specified class and method name.
0843: *
0844: * @param classID
0845: * class to find method
0846: * @param methodName
0847: * method name
0848: * @return received MethodID
0849: */
0850: public long getMethodID(long classID, String methodName) {
0851: ReplyPacket reply;
0852: int declared = 0;
0853: String method = null;
0854: long methodID = -1;
0855:
0856: // Get Method reference ID
0857: reply = getMethods(classID);
0858:
0859: // Get methodID from received packet
0860: declared = reply.getNextValueAsInt();
0861: for (int i = 0; i < declared; i++) {
0862: methodID = reply.getNextValueAsMethodID();
0863: method = reply.getNextValueAsString();
0864: if (methodName.equals(method)) {
0865: // If this method name is the same as requested
0866: reply.getNextValueAsString();
0867: reply.getNextValueAsInt();
0868: break;
0869: } else {
0870: // If this method name is not the requested one
0871: reply.getNextValueAsString();
0872: reply.getNextValueAsInt();
0873: methodID = -1;
0874: method = null;
0875: }
0876: }
0877: return methodID;
0878: }
0879:
0880: /**
0881: * Returns method name for specified pair of classID and methodID.
0882: *
0883: * @param classID
0884: * @param methodID
0885: * @return method name
0886: */
0887: public String getMethodName(long classID, long methodID) {
0888: CommandPacket packet = new CommandPacket(
0889: JDWPCommands.ReferenceTypeCommandSet.CommandSetID,
0890: JDWPCommands.ReferenceTypeCommandSet.MethodsCommand);
0891: packet.setNextValueAsReferenceTypeID(classID);
0892: ReplyPacket reply = performCommand(packet);
0893:
0894: int declared = reply.getNextValueAsInt();
0895: long mID;
0896: String value = null;
0897: String methodName = "";
0898: for (int i = 0; i < declared; i++) {
0899: mID = reply.getNextValueAsMethodID();
0900: methodName = reply.getNextValueAsString();
0901: reply.getNextValueAsString();
0902: reply.getNextValueAsInt();
0903: if (mID == methodID) {
0904: value = methodName;
0905: break;
0906: }
0907: }
0908: return value;
0909: }
0910:
0911: /**
0912: * Sets ClassPrepare event request for given class name pattern.
0913: *
0914: * @param classRegexp
0915: * Required class pattern. Matches are limited to exact matches
0916: * of the given class pattern and matches of patterns that begin
0917: * or end with '*'; for example, "*.Foo" or "java.*".
0918: * @return ReplyPacket for setting request.
0919: */
0920: public ReplyPacket setClassPrepared(String classRegexp) {
0921: // Prepare corresponding event
0922: byte eventKind = JDWPConstants.EventKind.CLASS_PREPARE;
0923: byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL;
0924: // EventMod[] mods = new EventMod[1];
0925: EventMod[] mods = new EventMod[] { new EventMod() };
0926: mods[0].classPattern = classRegexp;
0927: mods[0].modKind = EventMod.ModKind.ClassMatch;
0928: Event event = new Event(eventKind, suspendPolicy, mods);
0929:
0930: // Set event
0931: return setEvent(event);
0932: }
0933:
0934: /**
0935: * Set ClassPrepare event request for given class ID.
0936: *
0937: * @param referenceTypeID
0938: * class referenceTypeID
0939: * @return ReplyPacket for setting request
0940: */
0941: public ReplyPacket setClassPrepared(long referenceTypeID) {
0942: // Prepare corresponding event
0943: byte eventKind = JDWPConstants.EventKind.CLASS_PREPARE;
0944: byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL;
0945: // EventMod[] mods = new EventMod[1];
0946: EventMod[] mods = new EventMod[] { new EventMod() };
0947: mods[0].clazz = referenceTypeID;
0948: mods[0].modKind = EventMod.ModKind.ClassOnly;
0949: Event event = new Event(eventKind, suspendPolicy, mods);
0950:
0951: // Set event
0952: return setEvent(event);
0953: }
0954:
0955: /**
0956: * Sets ClassUnload event request for given class name pattern.
0957: *
0958: * @param classSignature
0959: * class signature
0960: * @return ReplyPacket for setting request
0961: */
0962: public ReplyPacket setClassUnload(String classRegexp) {
0963: // Prepare corresponding event
0964: byte eventKind = JDWPConstants.EventKind.CLASS_UNLOAD;
0965: byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL;
0966: // EventMod[] mods = new EventMod[1];
0967: EventMod[] mods = new EventMod[] { new EventMod() };
0968: mods[0].classPattern = classRegexp;
0969: mods[0].modKind = EventMod.ModKind.ClassMatch;
0970: Event event = new Event(eventKind, suspendPolicy, mods);
0971:
0972: // Set event
0973: return setEvent(event);
0974: }
0975:
0976: /**
0977: * Set ClassUnload event request for given class ID.
0978: *
0979: * @param referenceTypeID
0980: * class referenceTypeID
0981: * @return ReplyPacket for setting request
0982: */
0983: public ReplyPacket setClassUnload(long referenceTypeID) {
0984: // Prepare corresponding event
0985: byte eventKind = JDWPConstants.EventKind.CLASS_UNLOAD;
0986: byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL;
0987: // EventMod[] mods = new EventMod[1];
0988: EventMod[] mods = new EventMod[] { new EventMod() };
0989: mods[0].clazz = referenceTypeID;
0990: mods[0].modKind = EventMod.ModKind.ClassOnly;
0991: Event event = new Event(eventKind, suspendPolicy, mods);
0992:
0993: // Set event
0994: return setEvent(event);
0995: }
0996:
0997: /**
0998: * Sets ClassLoad event request for given class signature.
0999: *
1000: * @param classSignature
1001: * class signature
1002: * @return ReplyPacket for setting request
1003: */
1004: public ReplyPacket setClassLoad(String classSignature) {
1005: long typeID;
1006:
1007: // Request referenceTypeID for class
1008: typeID = getClassID(classSignature);
1009:
1010: // Set corresponding event
1011: return setClassLoad(typeID);
1012: }
1013:
1014: /**
1015: * Set ClassLoad event request for given class ID.
1016: *
1017: * @param referenceTypeID
1018: * class referenceTypeID
1019: * @return ReplyPacket for setting request
1020: */
1021: public ReplyPacket setClassLoad(long referenceTypeID) {
1022: // Prepare corresponding event
1023: byte eventKind = JDWPConstants.EventKind.CLASS_LOAD;
1024: byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL;
1025: EventMod[] mods = new EventMod[] { new EventMod() };
1026: mods[0].clazz = referenceTypeID;
1027: mods[0].modKind = EventMod.ModKind.ClassOnly;
1028: Event event = new Event(eventKind, suspendPolicy, mods);
1029:
1030: // Set event
1031: return setEvent(event);
1032: }
1033:
1034: /**
1035: * Set event request for given event.
1036: *
1037: * @param event
1038: * event to set request for
1039: * @return ReplyPacket for setting request
1040: */
1041: public ReplyPacket setEvent(Event event) {
1042: // Create new command packet
1043: CommandPacket commandPacket = new CommandPacket(
1044: JDWPCommands.EventRequestCommandSet.CommandSetID,
1045: JDWPCommands.EventRequestCommandSet.SetCommand);
1046:
1047: // Set eventKind
1048: commandPacket.setNextValueAsByte(event.eventKind);
1049: // Set suspendPolicy
1050: commandPacket.setNextValueAsByte(event.suspendPolicy);
1051:
1052: // Set modifiers
1053: commandPacket.setNextValueAsInt(event.modifiers);
1054:
1055: for (int i = 0; i < event.modifiers; i++) {
1056:
1057: commandPacket.setNextValueAsByte(event.mods[i].modKind);
1058:
1059: switch (event.mods[i].modKind) {
1060: case EventMod.ModKind.Count: {
1061: // Case Count
1062: commandPacket.setNextValueAsInt(event.mods[i].count);
1063: break;
1064: }
1065: case EventMod.ModKind.Conditional: {
1066: // Case Conditional
1067: commandPacket.setNextValueAsInt(event.mods[i].exprID);
1068: break;
1069: }
1070: case EventMod.ModKind.ThreadOnly: {
1071: // Case ThreadOnly
1072: commandPacket
1073: .setNextValueAsThreadID(event.mods[i].thread);
1074: break;
1075: }
1076: case EventMod.ModKind.ClassOnly: {
1077: // Case ClassOnly
1078: commandPacket
1079: .setNextValueAsReferenceTypeID(event.mods[i].clazz);
1080: break;
1081: }
1082: case EventMod.ModKind.ClassMatch: {
1083: // Case ClassMatch
1084: commandPacket
1085: .setNextValueAsString(event.mods[i].classPattern);
1086: break;
1087: }
1088: case EventMod.ModKind.ClassExclude: {
1089: // Case ClassExclude
1090: commandPacket
1091: .setNextValueAsString(event.mods[i].classPattern);
1092: break;
1093: }
1094: case EventMod.ModKind.LocationOnly: {
1095: // Case LocationOnly
1096: commandPacket.setNextValueAsLocation(event.mods[i].loc);
1097: break;
1098: }
1099: case EventMod.ModKind.ExceptionOnly:
1100: // Case ExceptionOnly
1101: commandPacket
1102: .setNextValueAsReferenceTypeID(event.mods[i].exceptionOrNull);
1103: commandPacket
1104: .setNextValueAsBoolean(event.mods[i].caught);
1105: commandPacket
1106: .setNextValueAsBoolean(event.mods[i].uncaught);
1107: break;
1108: case EventMod.ModKind.FieldOnly: {
1109: // Case FieldOnly
1110: commandPacket
1111: .setNextValueAsReferenceTypeID(event.mods[i].declaring);
1112: commandPacket
1113: .setNextValueAsFieldID(event.mods[i].fieldID);
1114: break;
1115: }
1116: case EventMod.ModKind.Step: {
1117: // Case Step
1118: commandPacket
1119: .setNextValueAsThreadID(event.mods[i].thread);
1120: commandPacket.setNextValueAsInt(event.mods[i].size);
1121: commandPacket.setNextValueAsInt(event.mods[i].depth);
1122: break;
1123: }
1124: case EventMod.ModKind.InstanceOnly: {
1125: // Case InstanceOnly
1126: commandPacket
1127: .setNextValueAsObjectID(event.mods[i].instance);
1128: break;
1129: }
1130: }
1131: }
1132:
1133: // Send packet
1134: return checkReply(performCommand(commandPacket));
1135: }
1136:
1137: /**
1138: * Gets method reference by signature.
1139: *
1140: * @param classReferenceTypeID
1141: * class referenceTypeID.
1142: * @return ReplyPacket for corresponding command
1143: */
1144: public ReplyPacket getMethods(long classReferenceTypeID) {
1145: // Create new command packet
1146: CommandPacket commandPacket = new CommandPacket();
1147:
1148: // Set command. "5" - is ID of Methods command in ReferenceType Command
1149: // Set
1150: commandPacket
1151: .setCommand(JDWPCommands.ReferenceTypeCommandSet.MethodsCommand);
1152:
1153: // Set command set. "2" - is ID of ReferenceType Command Set
1154: commandPacket
1155: .setCommandSet(JDWPCommands.ReferenceTypeCommandSet.CommandSetID);
1156:
1157: // Set outgoing data
1158: // Set referenceTypeID
1159: commandPacket.setNextValueAsObjectID(classReferenceTypeID);
1160:
1161: // Send packet
1162: return checkReply(performCommand(commandPacket));
1163: }
1164:
1165: /**
1166: * Gets class reference by signature.
1167: *
1168: * @param classSignature
1169: * class signature.
1170: * @return ReplyPacket for corresponding command
1171: */
1172: public ReplyPacket getClassBySignature(String classSignature) {
1173: CommandPacket commandPacket = new CommandPacket(
1174: JDWPCommands.VirtualMachineCommandSet.CommandSetID,
1175: JDWPCommands.VirtualMachineCommandSet.ClassesBySignatureCommand);
1176: commandPacket.setNextValueAsString(classSignature);
1177: return checkReply(performCommand(commandPacket));
1178: }
1179:
1180: /**
1181: * Gets class fields by class referenceTypeID.
1182: *
1183: * @param referenceTypeID
1184: * class referenceTypeID.
1185: * @return ReplyPacket for corresponding command
1186: */
1187: public ReplyPacket getFieldsInClass(long referenceTypeID) {
1188: CommandPacket commandPacket = new CommandPacket(
1189: JDWPCommands.ReferenceTypeCommandSet.CommandSetID,
1190: JDWPCommands.ReferenceTypeCommandSet.FieldsCommand);
1191: commandPacket.setNextValueAsReferenceTypeID(referenceTypeID);
1192: return checkReply(performCommand(commandPacket));
1193: }
1194:
1195: /**
1196: * Sets exception event request for given exception class signature.
1197: *
1198: * @param exceptionSignature
1199: * exception signature.
1200: * @param caught
1201: * is exception caught
1202: * @param uncaught
1203: * is exception uncaught
1204: * @return ReplyPacket for corresponding command
1205: */
1206: public ReplyPacket setException(String exceptionSignature,
1207: boolean caught, boolean uncaught) {
1208: // Request referenceTypeID for exception
1209: long typeID = getClassID(exceptionSignature);
1210: return setException(typeID, caught, uncaught);
1211: }
1212:
1213: /**
1214: * Sets exception event request for given exception class ID.
1215: *
1216: * @param exceptionID
1217: * exception referenceTypeID.
1218: * @param caught
1219: * is exception caught
1220: * @param uncaught
1221: * is exception uncaught
1222: * @return ReplyPacket for corresponding command
1223: */
1224: public ReplyPacket setException(long exceptionID, boolean caught,
1225: boolean uncaught) {
1226: // Prepare corresponding event
1227: byte eventKind = JDWPConstants.EventKind.EXCEPTION;
1228: byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL;
1229: EventMod[] mods = new EventMod[1];
1230: mods[0] = new EventMod();
1231: mods[0].modKind = EventMod.ModKind.ExceptionOnly;
1232: mods[0].caught = caught;
1233: mods[0].uncaught = uncaught;
1234: mods[0].exceptionOrNull = exceptionID;
1235: Event event = new Event(eventKind, suspendPolicy, mods);
1236:
1237: return setEvent(event);
1238: }
1239:
1240: /**
1241: * Sets exception event request for given exception class signature.
1242: *
1243: * @param exceptionSignature
1244: * exception signature.
1245: * @param caught
1246: * is exception caught
1247: * @param uncaught
1248: * is exception uncaught
1249: * @param count
1250: * Limit the requested event to be reported at most once after a
1251: * given number of occurrences
1252: * @return ReplyPacket for corresponding command
1253: */
1254: public ReplyPacket setCountableException(String exceptionSignature,
1255: boolean caught, boolean uncaught, int count) {
1256: // Request referenceTypeID for exception
1257: long exceptionID = getClassID(exceptionSignature);
1258: byte eventKind = JDWPConstants.EventKind.EXCEPTION;
1259: byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL;
1260: EventMod[] mods = new EventMod[2];
1261: mods[0] = new EventMod();
1262: mods[0].modKind = EventMod.ModKind.ExceptionOnly;
1263: mods[0].caught = caught;
1264: mods[0].uncaught = uncaught;
1265: mods[0].exceptionOrNull = exceptionID;
1266:
1267: mods[1] = new EventMod();
1268: mods[1].modKind = EventMod.ModKind.Count;
1269: mods[1].count = count;
1270: Event event = new Event(eventKind, suspendPolicy, mods);
1271:
1272: return setEvent(event);
1273: }
1274:
1275: /**
1276: * Sets METHOD_ENTRY event request for specified class name pattern.
1277: *
1278: * @param classRegexp
1279: * class name pattern or null for no pattern
1280: *
1281: * @return ReplyPacket for corresponding command
1282: */
1283: public ReplyPacket setMethodEntry(String classRegexp) {
1284: // Prepare corresponding event
1285: byte eventKind = JDWPConstants.EventKind.METHOD_ENTRY;
1286: byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL;
1287: EventMod[] mods = null;
1288: if (classRegexp == null) {
1289: mods = new EventMod[0];
1290: } else {
1291: mods = new EventMod[1];
1292: mods[0] = new EventMod();
1293: mods[0].modKind = EventMod.ModKind.ClassMatch;
1294: mods[0].classPattern = classRegexp;
1295: }
1296: Event event = new Event(eventKind, suspendPolicy, mods);
1297:
1298: return setEvent(event);
1299: }
1300:
1301: /**
1302: * Sets METHOD_ENTRY event request for specified class name pattern.
1303: *
1304: * @param classRegexp
1305: * class name pattern or null for no pattern
1306: * @param count
1307: * Limit the requested event to be reported at most once after a
1308: * given number of occurrences
1309: * @return ReplyPacket for corresponding command
1310: */
1311: public ReplyPacket setCountableMethodEntry(String classRegexp,
1312: int count) {
1313: byte eventKind = JDWPConstants.EventKind.METHOD_ENTRY;
1314: byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL;
1315: EventMod[] mods = null;
1316: if (classRegexp == null) {
1317: mods = new EventMod[] { new EventMod() };
1318: mods[0].modKind = EventMod.ModKind.Count;
1319: mods[0].count = count;
1320: } else {
1321: mods = new EventMod[2];
1322: mods[0] = new EventMod();
1323: mods[0].modKind = EventMod.ModKind.ClassMatch;
1324: mods[0].classPattern = classRegexp;
1325:
1326: mods[1] = new EventMod();
1327: mods[1].modKind = EventMod.ModKind.Count;
1328: mods[1].count = count;
1329: }
1330: Event event = new Event(eventKind, suspendPolicy, mods);
1331:
1332: return setEvent(event);
1333: }
1334:
1335: /**
1336: * Sets METHOD_EXIT event request for specified class name pattern.
1337: *
1338: * @param classRegexp
1339: * class name pattern or null for no pattern
1340: *
1341: * @return ReplyPacket for corresponding command
1342: */
1343: public ReplyPacket setMethodExit(String classRegexp) {
1344: // Prepare corresponding event
1345: byte eventKind = JDWPConstants.EventKind.METHOD_EXIT;
1346: byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL;
1347: EventMod[] mods = null;
1348: if (classRegexp == null) {
1349: mods = new EventMod[0];
1350: } else {
1351: mods = new EventMod[1];
1352: mods[0] = new EventMod();
1353: mods[0].modKind = EventMod.ModKind.ClassMatch;
1354: mods[0].classPattern = classRegexp;
1355: }
1356: Event event = new Event(eventKind, suspendPolicy, mods);
1357:
1358: return setEvent(event);
1359: }
1360:
1361: /**
1362: * Sets METHOD_EXIT event request for specified class name pattern.
1363: *
1364: * @param classRegexp
1365: * classRegexp class name pattern or null for no pattern
1366: * @param count
1367: * Limit the requested event to be reported at most once after a
1368: * given number of occurrences
1369: * @return ReplyPacket for corresponding command
1370: */
1371: public ReplyPacket setCountableMethodExit(String classRegexp,
1372: int count) {
1373: byte eventKind = JDWPConstants.EventKind.METHOD_EXIT;
1374: byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL;
1375: EventMod[] mods = null;
1376: if (classRegexp == null) {
1377: mods = new EventMod[] { new EventMod() };
1378: mods[0].modKind = EventMod.ModKind.Count;
1379: mods[0].count = count;
1380: } else {
1381: mods = new EventMod[2];
1382: mods[0] = new EventMod();
1383: mods[0].modKind = EventMod.ModKind.ClassMatch;
1384: mods[0].classPattern = classRegexp;
1385:
1386: mods[1] = new EventMod();
1387: mods[1].modKind = EventMod.ModKind.Count;
1388: mods[1].count = count;
1389: }
1390: Event event = new Event(eventKind, suspendPolicy, mods);
1391:
1392: return setEvent(event);
1393:
1394: }
1395:
1396: /**
1397: * Sets field access event request for specified class signature and field
1398: * name.
1399: *
1400: * @param classTypeTag
1401: * class Type Tag (class/interface/array)
1402: * @param classSignature
1403: * class signature
1404: * @param fieldName
1405: * field name
1406: * @return ReplyPacket if breakpoint is set
1407: * @throws ReplyErrorCodeException
1408: */
1409: public ReplyPacket setFieldAccess(String classSignature,
1410: byte classTypeTag, String fieldName)
1411: throws ReplyErrorCodeException {
1412: ReplyPacket request = null;
1413: long typeID = -1;
1414: long fieldID = -1;
1415:
1416: // Request referenceTypeID for class
1417: typeID = getClassID(classSignature);
1418:
1419: // Request fields in class
1420: request = getFieldsInClass(typeID);
1421:
1422: // Get fieldID from received packet
1423: fieldID = getFieldID(request, fieldName);
1424:
1425: // Prepare corresponding event
1426: byte eventKind = JDWPConstants.EventKind.FIELD_ACCESS;
1427: byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL;
1428: // EventMod[] mods = new EventMod[1];
1429: EventMod[] mods = new EventMod[] { new EventMod() };
1430: mods[0].fieldID = fieldID;
1431: mods[0].declaring = typeID;
1432: mods[0].modKind = EventMod.ModKind.FieldOnly;
1433: Event event = new Event(eventKind, suspendPolicy, mods);
1434:
1435: // Set exception
1436: return setEvent(event);
1437: }
1438:
1439: /**
1440: * Sets field modification event request for specified class signature and
1441: * field name.
1442: *
1443: * @param classTypeTag
1444: * class Type Tag (class/interface/array)
1445: * @param classSignature
1446: * class signature
1447: * @param fieldName
1448: * field name
1449: * @return ReplyPacket for corresponding command
1450: * @throws ReplyErrorCodeException
1451: */
1452: public ReplyPacket setFieldModification(String classSignature,
1453: byte classTypeTag, String fieldName)
1454: throws ReplyErrorCodeException {
1455: ReplyPacket request = null;
1456: long typeID = -1;
1457: long fieldID = -1;
1458:
1459: // Request referenceTypeID for class
1460: typeID = getClassID(classSignature);
1461:
1462: // Request fields in class
1463: request = getFieldsInClass(typeID);
1464:
1465: // Get fieldID from received packet
1466: fieldID = getFieldID(request, fieldName);
1467:
1468: // Prepare corresponding event
1469: byte eventKind = JDWPConstants.EventKind.FIELD_MODIFICATION;
1470: byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL;
1471: // EventMod[] mods = new EventMod[1];
1472: EventMod[] mods = new EventMod[] { new EventMod() };
1473: mods[0].fieldID = fieldID;
1474: mods[0].declaring = typeID;
1475: mods[0].modKind = EventMod.ModKind.FieldOnly;
1476: Event event = new Event(eventKind, suspendPolicy, mods);
1477:
1478: // Set event
1479: return setEvent(event);
1480: }
1481:
1482: /**
1483: * Sets step event request for given thread name.
1484: *
1485: * @param threadName
1486: * thread name
1487: * @param stepSize
1488: * @param stepDepth
1489: * @return ReplyPacket for corresponding command
1490: */
1491: public ReplyPacket setStep(String threadName, int stepSize,
1492: int stepDepth) {
1493: long typeID = -1;
1494:
1495: // Request referenceTypeID for class
1496: typeID = getThreadID(threadName);
1497:
1498: // Prepare corresponding event
1499: byte eventKind = JDWPConstants.EventKind.SINGLE_STEP;
1500: byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL;
1501: // EventMod[] mods = new EventMod[1];
1502: EventMod[] mods = new EventMod[] { new EventMod() };
1503: mods[0].thread = typeID;
1504: mods[0].modKind = EventMod.ModKind.Step;
1505: mods[0].size = stepSize;
1506: mods[0].depth = stepDepth;
1507: Event event = new Event(eventKind, suspendPolicy, mods);
1508:
1509: // Set event
1510: return setEvent(event);
1511: }
1512:
1513: /**
1514: * Sets SINGLE_STEP event request for classes whose name does not match the
1515: * given restricted regular expression
1516: *
1517: * @param classRegexp
1518: * Disallowed class patterns. Matches are limited to exact
1519: * matches of the given class pattern and matches of patterns
1520: * that begin or end with '*'; for example, "*.Foo" or "java.*".
1521: * @param stepSize
1522: * @param stepDepth
1523: * @return ReplyPacket for setting request.
1524: */
1525: public ReplyPacket setStep(String[] classRegexp, long threadID,
1526: int stepSize, int stepDepth) {
1527: // Prepare corresponding event
1528: byte eventKind = JDWPConstants.EventKind.SINGLE_STEP;
1529: byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL;
1530: int modsSize = classRegexp.length + 1;
1531: EventMod[] mods = new EventMod[modsSize];
1532: for (int i = 0; i < classRegexp.length; i++) {
1533: mods[i] = new EventMod();
1534: mods[i].classPattern = classRegexp[i];
1535: mods[i].modKind = EventMod.ModKind.ClassExclude;
1536: }
1537:
1538: int index = modsSize - 1;
1539: mods[index] = new EventMod();
1540: mods[index].modKind = EventMod.ModKind.Step;
1541: mods[index].thread = threadID;
1542: mods[index].size = stepSize;
1543: mods[index].depth = stepDepth;
1544:
1545: Event event = new Event(eventKind, suspendPolicy, mods);
1546:
1547: // Set event
1548: return setEvent(event);
1549: }
1550:
1551: /**
1552: * Sets THREAD_START event request.
1553: *
1554: * @return ReplyPacket for corresponding command
1555: */
1556: public ReplyPacket setThreadStart() {
1557: // Prepare corresponding event
1558: byte eventKind = JDWPConstants.EventKind.THREAD_START;
1559: byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL;
1560: EventMod[] mods = new EventMod[0];
1561: Event event = new Event(eventKind, suspendPolicy, mods);
1562:
1563: return setEvent(event);
1564: }
1565:
1566: /**
1567: * Sets THREAD_END event request.
1568: *
1569: * @return ReplyPacket for corresponding command
1570: */
1571: public ReplyPacket setThreadEnd() {
1572: // Prepare corresponding event
1573: byte eventKind = JDWPConstants.EventKind.THREAD_END;
1574: byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL;
1575: EventMod[] mods = new EventMod[0];
1576: Event event = new Event(eventKind, suspendPolicy, mods);
1577:
1578: return setEvent(event);
1579: }
1580:
1581: /**
1582: * Clear an event request for specified request ID.
1583: *
1584: * @param eventKind
1585: * event type to clear
1586: * @param requestID
1587: * request ID to clear
1588: * @return ReplyPacket for corresponding command
1589: */
1590: public ReplyPacket clearEvent(byte eventKind, int requestID) {
1591: // Create new command packet
1592: CommandPacket commandPacket = new CommandPacket();
1593:
1594: // Set command. "2" - is ID of Clear command in EventRequest Command Set
1595: commandPacket
1596: .setCommand(JDWPCommands.EventRequestCommandSet.ClearCommand);
1597:
1598: // Set command set. "15" - is ID of EventRequest Command Set
1599: commandPacket
1600: .setCommandSet(JDWPCommands.EventRequestCommandSet.CommandSetID);
1601:
1602: // Set outgoing data
1603: // Set event type to clear
1604: commandPacket.setNextValueAsByte(eventKind);
1605:
1606: // Set ID of request to clear
1607: commandPacket.setNextValueAsInt(requestID);
1608:
1609: // Send packet
1610: return checkReply(performCommand(commandPacket));
1611: }
1612:
1613: /**
1614: * Sends CommandPacket to debuggee VM and waits for ReplyPacket using
1615: * default timeout. All thrown exceptions are wrapped into
1616: * TestErrorException. Consider using checkReply() for checking error code
1617: * in reply packet.
1618: *
1619: * @param command
1620: * Command packet to be sent
1621: * @return received ReplyPacket
1622: */
1623: public ReplyPacket performCommand(CommandPacket command)
1624: throws TestErrorException {
1625: ReplyPacket replyPacket = null;
1626: try {
1627: replyPacket = packetDispatcher.performCommand(command);
1628: } catch (IOException e) {
1629: throw new TestErrorException(e);
1630: } catch (InterruptedException e) {
1631: throw new TestErrorException(e);
1632: }
1633:
1634: return replyPacket;
1635: }
1636:
1637: /**
1638: * Sends CommandPacket to debuggee VM and waits for ReplyPacket using
1639: * specified timeout.
1640: *
1641: * @param command
1642: * Command packet to be sent
1643: * @param timeout
1644: * Timeout in milliseconds for waiting reply packet
1645: * @return received ReplyPacket
1646: * @throws InterruptedException
1647: * @throws IOException
1648: * @throws TimeoutException
1649: */
1650: public ReplyPacket performCommand(CommandPacket command,
1651: long timeout) throws IOException, InterruptedException,
1652: TimeoutException {
1653:
1654: return packetDispatcher.performCommand(command, timeout);
1655: }
1656:
1657: /**
1658: * Sends CommandPacket to debuggee VM without waiting for the reply. This
1659: * method is intended for special cases when there is need to divide
1660: * command's performing into two actions: command's sending and receiving
1661: * reply (e.g. for asynchronous JDWP commands' testing). After this method
1662: * the 'receiveReply()' method must be used latter for receiving reply for
1663: * sent command. It is NOT recommended to use this method for usual cases -
1664: * 'performCommand()' method must be used.
1665: *
1666: * @param command
1667: * Command packet to be sent
1668: * @return command ID of sent command
1669: * @throws IOException
1670: * if any connection error occurred
1671: */
1672: public int sendCommand(CommandPacket command) throws IOException {
1673: return packetDispatcher.sendCommand(command);
1674: }
1675:
1676: /**
1677: * Waits for reply for command which was sent before by 'sendCommand()'
1678: * method. Default timeout is used as time limit for waiting. This method
1679: * (jointly with 'sendCommand()') is intended for special cases when there
1680: * is need to divide command's performing into two actions: command's
1681: * sending and receiving reply (e.g. for asynchronous JDWP commands'
1682: * testing). It is NOT recommended to use 'sendCommand()- receiveReply()'
1683: * pair for usual cases - 'performCommand()' method must be used.
1684: *
1685: * @param commandId
1686: * Command ID of sent before command, reply from which is
1687: * expected to be received
1688: * @return received ReplyPacket
1689: * @throws IOException
1690: * if any connection error occurred
1691: * @throws InterruptedException
1692: * if reply packet's waiting was interrupted
1693: * @throws TimeoutException
1694: * if timeout exceeded
1695: */
1696: public ReplyPacket receiveReply(int commandId)
1697: throws InterruptedException, IOException, TimeoutException {
1698: return packetDispatcher.receiveReply(commandId, config
1699: .getTimeout());
1700: }
1701:
1702: /**
1703: * Waits for reply for command which was sent before by 'sendCommand()'
1704: * method. Specified timeout is used as time limit for waiting. This method
1705: * (jointly with 'sendCommand()') is intended for special cases when there
1706: * is need to divide command's performing into two actions: command's
1707: * sending and receiving reply (e.g. for asynchronous JDWP commands'
1708: * testing). It is NOT recommended to use 'sendCommand()- receiveReply()'
1709: * pair for usual cases - 'performCommand()' method must be used.
1710: *
1711: * @param commandId
1712: * Command ID of sent before command, reply from which is
1713: * expected to be received
1714: * @param timeout
1715: * Specified timeout in milliseconds to wait for reply
1716: * @return received ReplyPacket
1717: * @throws IOException
1718: * if any connection error occurred
1719: * @throws InterruptedException
1720: * if reply packet's waiting was interrupted
1721: * @throws TimeoutException
1722: * if timeout exceeded
1723: */
1724: public ReplyPacket receiveReply(int commandId, long timeout)
1725: throws InterruptedException, IOException, TimeoutException {
1726: return packetDispatcher.receiveReply(commandId, timeout);
1727: }
1728:
1729: /**
1730: * Waits for EventPacket using default timeout. All thrown exceptions are
1731: * wrapped into TestErrorException.
1732: *
1733: * @return received EventPacket
1734: */
1735: public EventPacket receiveEvent() throws TestErrorException {
1736: try {
1737: return receiveEvent(config.getTimeout());
1738: } catch (IOException e) {
1739: throw new TestErrorException(e);
1740: } catch (InterruptedException e) {
1741: throw new TestErrorException(e);
1742: }
1743: }
1744:
1745: /**
1746: * Waits for EventPacket using specified timeout.
1747: *
1748: * @param timeout
1749: * Timeout in milliseconds to wait for event
1750: * @return received EventPacket
1751: * @throws IOException
1752: * @throws InterruptedException
1753: * @throws TimeoutException
1754: */
1755: public EventPacket receiveEvent(long timeout) throws IOException,
1756: InterruptedException, TimeoutException {
1757:
1758: return packetDispatcher.receiveEvent(timeout);
1759: }
1760:
1761: /**
1762: * Waits for expected event kind using default timeout. Throws
1763: * TestErrorException if received event is not of expected kind or not a
1764: * single event in the received event set.
1765: *
1766: * @param eventKind
1767: * Type of expected event -
1768: * @see JDWPConstants.EventKind
1769: * @return received EventPacket
1770: */
1771: public EventPacket receiveCertainEvent(byte eventKind)
1772: throws TestErrorException {
1773:
1774: EventPacket eventPacket = receiveEvent();
1775: ParsedEvent[] parsedEvents = ParsedEvent
1776: .parseEventPacket(eventPacket);
1777:
1778: if (parsedEvents.length == 1
1779: && parsedEvents[0].getEventKind() == eventKind)
1780: return eventPacket;
1781:
1782: switch (parsedEvents.length) {
1783: case (0):
1784: throw new TestErrorException(
1785: "Unexpected event received: zero length");
1786: case (1):
1787: throw new TestErrorException("Unexpected event received: "
1788: + parsedEvents[0].getEventKind());
1789: default:
1790: throw new TestErrorException(
1791: "Unexpected event received: Event was grouped in a composite event");
1792: }
1793: }
1794:
1795: /**
1796: * Returns JDWP connection channel used by this VmMirror.
1797: *
1798: * @return connection channel
1799: */
1800: public TransportWrapper getConnection() {
1801: return connection;
1802: }
1803:
1804: /**
1805: * Sets established connection channel to be used with this VmMirror and
1806: * starts reading packets.
1807: *
1808: * @param connection
1809: * connection channel to be set
1810: */
1811: public void setConnection(TransportWrapper connection) {
1812: this .connection = connection;
1813: packetDispatcher = new PacketDispatcher(connection, config,
1814: logWriter);
1815: }
1816:
1817: /**
1818: * Closes connection channel used with this VmMirror and stops reading
1819: * packets.
1820: *
1821: */
1822: public void closeConnection() throws IOException {
1823: if (connection != null && connection.isOpen())
1824: connection.close();
1825:
1826: // wait for packetDispatcher is closed
1827: if (packetDispatcher != null) {
1828: try {
1829: packetDispatcher.join();
1830: } catch (InterruptedException e) {
1831: // do nothing but print a stack trace
1832: e.printStackTrace();
1833: }
1834: }
1835: }
1836:
1837: /**
1838: * Returns the count of frames on this thread's stack
1839: *
1840: * @param threadID
1841: * The thread object ID.
1842: * @return The count of frames on this thread's stack
1843: */
1844: public final int getFrameCount(long threadID) {
1845: CommandPacket command = new CommandPacket(
1846: JDWPCommands.ThreadReferenceCommandSet.CommandSetID,
1847: JDWPCommands.ThreadReferenceCommandSet.FrameCountCommand);
1848: command.setNextValueAsThreadID(threadID);
1849: ReplyPacket reply = checkReply(performCommand(command));
1850: return reply.getNextValueAsInt();
1851: }
1852:
1853: /**
1854: * Returns a list containing all frames of a certain thread
1855: *
1856: * @param threadID
1857: * ID of the thread
1858: * @return A list of frames
1859: */
1860: public final List getAllThreadFrames(long threadID) {
1861: if (!isThreadSuspended(threadID)) {
1862: return new ArrayList(0);
1863: }
1864:
1865: ReplyPacket reply = getThreadFrames(threadID, 0, -1);
1866: int framesCount = reply.getNextValueAsInt();
1867: if (framesCount == 0) {
1868: return new ArrayList(0);
1869: }
1870:
1871: ArrayList<Frame> frames = new ArrayList<Frame>(framesCount);
1872: for (int i = 0; i < framesCount; i++) {
1873: Frame frame = new Frame();
1874: frame.setThreadID(threadID);
1875: frame.setID(reply.getNextValueAsFrameID());
1876: frame.setLocation(reply.getNextValueAsLocation());
1877: frames.add(frame);
1878: }
1879:
1880: return frames;
1881: }
1882:
1883: /**
1884: * Returns a set of frames of a certain suspended thread
1885: *
1886: * @param threadID
1887: * ID of the thread whose frames to obtain
1888: * @param startIndex
1889: * The index of the first frame to retrieve.
1890: * @param length
1891: * The count of frames to retrieve (-1 means all remaining).
1892: * @return ReplyPacket for corresponding command
1893: */
1894: public final ReplyPacket getThreadFrames(long threadID,
1895: int startIndex, int length) {
1896: CommandPacket command = new CommandPacket(
1897: JDWPCommands.ThreadReferenceCommandSet.CommandSetID,
1898: JDWPCommands.ThreadReferenceCommandSet.FramesCommand);
1899: command.setNextValueAsThreadID(threadID);
1900: command.setNextValueAsInt(startIndex); // start frame's index
1901: command.setNextValueAsInt(length); // get all remaining frames;
1902: return checkReply(performCommand(command));
1903: }
1904:
1905: /**
1906: * Returns variable information for the method
1907: *
1908: * @param classID
1909: * The class ID
1910: * @param methodID
1911: * The method ID
1912: * @return A list containing all variables (arguments and locals) declared
1913: * within the method.
1914: */
1915: public final List getVariableTable(long classID, long methodID) {
1916: CommandPacket command = new CommandPacket(
1917: JDWPCommands.MethodCommandSet.CommandSetID,
1918: JDWPCommands.MethodCommandSet.VariableTableCommand);
1919: command.setNextValueAsReferenceTypeID(classID);
1920: command.setNextValueAsMethodID(methodID);
1921: // ReplyPacket reply =
1922: // debuggeeWrapper.vmMirror.checkReply(debuggeeWrapper.vmMirror.performCommand(command));
1923: ReplyPacket reply = performCommand(command);
1924: if (reply.getErrorCode() == JDWPConstants.Error.ABSENT_INFORMATION
1925: || reply.getErrorCode() == JDWPConstants.Error.NATIVE_METHOD) {
1926: return null;
1927: }
1928:
1929: checkReply(reply);
1930:
1931: reply.getNextValueAsInt(); // argCnt, is not used
1932: int slots = reply.getNextValueAsInt();
1933: if (slots == 0) {
1934: return null;
1935: }
1936:
1937: ArrayList<Variable> vars = new ArrayList<Variable>(slots);
1938: for (int i = 0; i < slots; i++) {
1939: Variable var = new Frame().new Variable();
1940: var.setCodeIndex(reply.getNextValueAsLong());
1941: var.setName(reply.getNextValueAsString());
1942: var.setSignature(reply.getNextValueAsString());
1943: var.setLength(reply.getNextValueAsInt());
1944: var.setSlot(reply.getNextValueAsInt());
1945: vars.add(var);
1946: }
1947:
1948: return vars;
1949: }
1950:
1951: /**
1952: * Returns values of local variables in a given frame
1953: *
1954: * @param frame
1955: * Frame whose variables to get
1956: * @return An array of Value objects
1957: */
1958: public final Value[] getFrameValues(Frame frame) {
1959: CommandPacket command = new CommandPacket(
1960: JDWPCommands.StackFrameCommandSet.CommandSetID,
1961: JDWPCommands.StackFrameCommandSet.GetValuesCommand);
1962: command.setNextValueAsThreadID(frame.getThreadID());
1963: command.setNextValueAsFrameID(frame.getID());
1964: int slots = frame.getVars().size();
1965: command.setNextValueAsInt(slots);
1966: Iterator it = frame.getVars().iterator();
1967: while (it.hasNext()) {
1968: Frame.Variable var = (Frame.Variable) it.next();
1969: command.setNextValueAsInt(var.getSlot());
1970: command.setNextValueAsByte(var.getTag());
1971: }
1972:
1973: ReplyPacket reply = checkReply(performCommand(command));
1974: reply.getNextValueAsInt(); // number of values , is not used
1975: Value[] values = new Value[slots];
1976: for (int i = 0; i < slots; i++) {
1977: values[i] = reply.getNextValueAsValue();
1978: }
1979:
1980: return values;
1981: }
1982:
1983: /**
1984: * Returns the immediate superclass of a class
1985: *
1986: * @param classID
1987: * The class ID whose superclass ID is to get
1988: * @return The superclass ID (null if the class ID for java.lang.Object is
1989: * specified).
1990: */
1991: public final long getSuperclassId(long classID) {
1992: CommandPacket command = new CommandPacket(
1993: JDWPCommands.ClassTypeCommandSet.CommandSetID,
1994: JDWPCommands.ClassTypeCommandSet.SuperclassCommand);
1995: command.setNextValueAsClassID(classID);
1996: ReplyPacket reply = checkReply(performCommand(command));
1997: return reply.getNextValueAsClassID();
1998: }
1999:
2000: /**
2001: * Returns the runtime type of the object
2002: *
2003: * @param objectID
2004: * The object ID
2005: * @return The runtime reference type.
2006: */
2007: public final long getReferenceType(long objectID) {
2008: CommandPacket command = new CommandPacket(
2009: JDWPCommands.ObjectReferenceCommandSet.CommandSetID,
2010: JDWPCommands.ObjectReferenceCommandSet.ReferenceTypeCommand);
2011: command.setNextValueAsObjectID(objectID);
2012: ReplyPacket reply = checkReply(performCommand(command));
2013: reply.getNextValueAsByte();
2014: return reply.getNextValueAsLong();
2015: }
2016:
2017: /**
2018: * Returns the class object corresponding to this type
2019: *
2020: * @param refType
2021: * The reference type ID.
2022: * @return The class object.
2023: */
2024: public final long getClassObjectId(long refType) {
2025: CommandPacket command = new CommandPacket(
2026: JDWPCommands.ReferenceTypeCommandSet.CommandSetID,
2027: JDWPCommands.ReferenceTypeCommandSet.ClassObjectCommand);
2028: command.setNextValueAsReferenceTypeID(refType);
2029: ReplyPacket reply = checkReply(performCommand(command));
2030: return reply.getNextValueAsObjectID();
2031: }
2032:
2033: /**
2034: * Returns line number information for the method, if present.
2035: *
2036: * @param refType
2037: * The class ID
2038: * @param methodID
2039: * The method ID
2040: * @return ReplyPacket for corresponding command.
2041: */
2042: public final ReplyPacket getLineTable(long refType, long methodID) {
2043: CommandPacket command = new CommandPacket(
2044: JDWPCommands.MethodCommandSet.CommandSetID,
2045: JDWPCommands.MethodCommandSet.LineTableCommand);
2046: command.setNextValueAsReferenceTypeID(refType);
2047: command.setNextValueAsMethodID(methodID);
2048: // ReplyPacket reply =
2049: // debuggeeWrapper.vmMirror.checkReply(debuggeeWrapper.vmMirror.performCommand(command));
2050: // it is impossible to obtain line table information from native
2051: // methods, so reply checking is not performed
2052: ReplyPacket reply = performCommand(command);
2053: if (reply.getErrorCode() != JDWPConstants.Error.NONE) {
2054: if (reply.getErrorCode() == JDWPConstants.Error.NATIVE_METHOD) {
2055: return reply;
2056: }
2057: }
2058:
2059: return checkReply(reply);
2060: }
2061:
2062: /**
2063: * Returns the value of one or more instance fields.
2064: *
2065: * @param objectID
2066: * The object ID
2067: * @param fieldIDs
2068: * IDs of fields to get
2069: * @return An array of Value objects representing each field's value
2070: */
2071: public final Value[] getObjectReferenceValues(long objectID,
2072: long[] fieldIDs) {
2073: int fieldsCount = fieldIDs.length;
2074: if (fieldsCount == 0) {
2075: return null;
2076: }
2077:
2078: CommandPacket command = new CommandPacket(
2079: JDWPCommands.ObjectReferenceCommandSet.CommandSetID,
2080: JDWPCommands.ObjectReferenceCommandSet.GetValuesCommand);
2081: command.setNextValueAsReferenceTypeID(objectID);
2082: command.setNextValueAsInt(fieldsCount);
2083: for (int i = 0; i < fieldsCount; i++) {
2084: command.setNextValueAsFieldID(fieldIDs[i]);
2085: }
2086:
2087: ReplyPacket reply = checkReply(performCommand(command));
2088: reply.getNextValueAsInt(); // fields returned, is not used
2089: Value[] values = new Value[fieldsCount];
2090: for (int i = 0; i < fieldsCount; i++) {
2091: values[i] = reply.getNextValueAsValue();
2092: }
2093:
2094: return values;
2095: }
2096:
2097: /**
2098: * Returns the value of one or more static fields of the reference type
2099: *
2100: * @param refTypeID
2101: * The reference type ID.
2102: * @param fieldIDs
2103: * IDs of fields to get
2104: * @return An array of Value objects representing each field's value
2105: */
2106: public final Value[] getReferenceTypeValues(long refTypeID,
2107: long[] fieldIDs) {
2108: int fieldsCount = fieldIDs.length;
2109: if (fieldsCount == 0) {
2110: return null;
2111: }
2112:
2113: CommandPacket command = new CommandPacket(
2114: JDWPCommands.ReferenceTypeCommandSet.CommandSetID,
2115: JDWPCommands.ReferenceTypeCommandSet.GetValuesCommand);
2116: command.setNextValueAsReferenceTypeID(refTypeID);
2117: command.setNextValueAsInt(fieldsCount);
2118: for (int i = 0; i < fieldsCount; i++) {
2119: command.setNextValueAsFieldID(fieldIDs[i]);
2120: }
2121:
2122: ReplyPacket reply = checkReply(performCommand(command));
2123: reply.getNextValueAsInt(); // fields returned, is not used
2124: Value[] values = new Value[fieldsCount];
2125: for (int i = 0; i < fieldsCount; i++) {
2126: values[i] = reply.getNextValueAsValue();
2127: }
2128:
2129: return values;
2130: }
2131:
2132: /**
2133: * Returns the value of the 'this' reference for this frame
2134: *
2135: * @param threadID
2136: * The frame's thread ID
2137: * @param frameID
2138: * The frame ID.
2139: * @return The 'this' object ID for this frame.
2140: */
2141: public final long getThisObject(long threadID, long frameID) {
2142: CommandPacket command = new CommandPacket(
2143: JDWPCommands.StackFrameCommandSet.CommandSetID,
2144: JDWPCommands.StackFrameCommandSet.ThisObjectCommand);
2145: command.setNextValueAsThreadID(threadID);
2146: command.setNextValueAsFrameID(frameID);
2147: ReplyPacket reply = checkReply(performCommand(command));
2148: TaggedObject taggedObject = reply.getNextValueAsTaggedObject();
2149: return taggedObject.objectID;
2150: }
2151:
2152: /**
2153: * Returns information for each field in a reference type including
2154: * inherited fields
2155: *
2156: * @param classID
2157: * The reference type ID
2158: * @return A list of Field objects representing each field of the class
2159: */
2160: public final List getAllFields(long classID) {
2161: ArrayList<Field> fields = new ArrayList<Field>(0);
2162:
2163: long super ID = getSuperclassId(classID);
2164: if (super ID != 0) {
2165: List super ClassFields = getAllFields(super ID);
2166: for (int i = 0; i < super ClassFields.size(); i++) {
2167: fields.add((Field) super ClassFields.toArray()[i]);
2168: }
2169: }
2170:
2171: ReplyPacket reply = getFieldsInClass(classID);
2172: int fieldsCount = reply.getNextValueAsInt();
2173: for (int i = 0; i < fieldsCount; i++) {
2174: Field field = new Field(reply.getNextValueAsFieldID(),
2175: classID, reply.getNextValueAsString(), reply
2176: .getNextValueAsString(), reply
2177: .getNextValueAsInt());
2178: fields.add(field);
2179: }
2180:
2181: return fields;
2182: }
2183:
2184: /**
2185: * Returns the reference type reflected by this class object
2186: *
2187: * @param classObjectID
2188: * The class object ID.
2189: * @return ReplyPacket for corresponding command
2190: */
2191: public final ReplyPacket getReflectedType(long classObjectID) {
2192: CommandPacket command = new CommandPacket(
2193: JDWPCommands.ClassObjectReferenceCommandSet.CommandSetID,
2194: JDWPCommands.ClassObjectReferenceCommandSet.ReflectedTypeCommand);
2195: command.setNextValueAsClassObjectID(classObjectID);
2196: return checkReply(performCommand(command));
2197: }
2198:
2199: /**
2200: * Returns the JNI signature of a reference type. JNI signature formats are
2201: * described in the Java Native Interface Specification
2202: *
2203: * @param refTypeID
2204: * The reference type ID.
2205: * @return The JNI signature for the reference type.
2206: */
2207: public final String getReferenceTypeSignature(long refTypeID) {
2208: CommandPacket command = new CommandPacket(
2209: JDWPCommands.ReferenceTypeCommandSet.CommandSetID,
2210: JDWPCommands.ReferenceTypeCommandSet.SignatureCommand);
2211: command.setNextValueAsReferenceTypeID(refTypeID);
2212: ReplyPacket reply = checkReply(performCommand(command));
2213: return reply.getNextValueAsString();
2214: }
2215:
2216: /**
2217: * Returns the thread group that contains a given thread
2218: *
2219: * @param threadID
2220: * The thread object ID.
2221: * @return The thread group ID of this thread.
2222: */
2223: public final long getThreadGroupID(long threadID) {
2224: CommandPacket command = new CommandPacket(
2225: JDWPCommands.ThreadReferenceCommandSet.CommandSetID,
2226: JDWPCommands.ThreadReferenceCommandSet.ThreadGroupCommand);
2227: command.setNextValueAsThreadID(threadID);
2228: ReplyPacket reply = checkReply(performCommand(command));
2229: return reply.getNextValueAsThreadGroupID();
2230: }
2231:
2232: /**
2233: * Checks whether a given thread is suspended or not
2234: *
2235: * @param threadID
2236: * The thread object ID.
2237: * @return True if a given thread is suspended, false otherwise.
2238: */
2239: public final boolean isThreadSuspended(long threadID) {
2240: CommandPacket command = new CommandPacket(
2241: JDWPCommands.ThreadReferenceCommandSet.CommandSetID,
2242: JDWPCommands.ThreadReferenceCommandSet.StatusCommand);
2243: command.setNextValueAsThreadID(threadID);
2244: ReplyPacket reply = checkReply(performCommand(command));
2245: reply.getNextValueAsInt(); // the thread's status; is not used
2246: return reply.getNextValueAsInt() == JDWPConstants.SuspendStatus.SUSPEND_STATUS_SUSPENDED;
2247: }
2248:
2249: /**
2250: * Returns JNI signature of method.
2251: *
2252: * @param classID
2253: * The reference type ID.
2254: * @param methodID
2255: * The method ID.
2256: * @return JNI signature of method.
2257: */
2258: public final String getMethodSignature(long classID, long methodID) {
2259: CommandPacket command = new CommandPacket(
2260: JDWPCommands.ReferenceTypeCommandSet.CommandSetID,
2261: JDWPCommands.ReferenceTypeCommandSet.MethodsCommand);
2262: command.setNextValueAsReferenceTypeID(classID);
2263: ReplyPacket reply = checkReply(performCommand(command));
2264: int methods = reply.getNextValueAsInt();
2265: String value = null;
2266: for (int i = 0; i < methods; i++) {
2267: long mID = reply.getNextValueAsMethodID();
2268: reply.getNextValueAsString(); // name of the method; is not used
2269: String methodSign = reply.getNextValueAsString();
2270: reply.getNextValueAsInt();
2271: if (mID == methodID) {
2272: value = methodSign;
2273: value = value.replaceAll("/", ".");
2274: int lastRoundBracketIndex = value.lastIndexOf(")");
2275: value = value.substring(0, lastRoundBracketIndex + 1);
2276: break;
2277: }
2278: }
2279:
2280: return value;
2281: }
2282:
2283: /**
2284: * Returns the characters contained in the string
2285: *
2286: * @param objectID
2287: * The String object ID.
2288: * @return A string value.
2289: */
2290: public final String getStringValue(long objectID) {
2291: CommandPacket command = new CommandPacket(
2292: JDWPCommands.StringReferenceCommandSet.CommandSetID,
2293: JDWPCommands.StringReferenceCommandSet.ValueCommand);
2294: command.setNextValueAsObjectID(objectID);
2295: ReplyPacket reply = checkReply(performCommand(command));
2296: return reply.getNextValueAsString();
2297: }
2298:
2299: /**
2300: * Returns a range of array components
2301: *
2302: * @param objectID
2303: * The array object ID.
2304: * @return The retrieved values.
2305: */
2306: public Value[] getArrayValues(long objectID) {
2307: CommandPacket command = new CommandPacket(
2308: JDWPCommands.ArrayReferenceCommandSet.CommandSetID,
2309: JDWPCommands.ArrayReferenceCommandSet.LengthCommand);
2310: command.setNextValueAsArrayID(objectID);
2311: ReplyPacket reply = checkReply(performCommand(command));
2312: int length = reply.getNextValueAsInt();
2313:
2314: if (length == 0) {
2315: return null;
2316: }
2317:
2318: command = new CommandPacket(
2319: JDWPCommands.ArrayReferenceCommandSet.CommandSetID,
2320: JDWPCommands.ArrayReferenceCommandSet.GetValuesCommand);
2321: command.setNextValueAsArrayID(objectID);
2322: command.setNextValueAsInt(0);
2323: command.setNextValueAsInt(length);
2324: reply = checkReply(performCommand(command));
2325: ArrayRegion arrayRegion = reply.getNextValueAsArrayRegion();
2326:
2327: Value[] values = new Value[length];
2328: for (int i = 0; i < length; i++) {
2329: values[i] = arrayRegion.getValue(i);
2330: }
2331:
2332: return values;
2333: }
2334:
2335: /**
2336: * Returns a source line number according to a corresponding line code index
2337: * in a method's line table.
2338: *
2339: * @param classID
2340: * The class object ID.
2341: * @param methodID
2342: * The method ID.
2343: * @param codeIndex
2344: * The line code index.
2345: * @return An integer line number.
2346: */
2347: public final int getLineNumber(long classID, long methodID,
2348: long codeIndex) {
2349: int lineNumber = -1;
2350: ReplyPacket reply = getLineTable(classID, methodID);
2351: if (reply.getErrorCode() != JDWPConstants.Error.NONE) {
2352: return lineNumber;
2353: }
2354:
2355: reply.getNextValueAsLong(); // start line index, is not used
2356: reply.getNextValueAsLong(); // end line index, is not used
2357: int lines = reply.getNextValueAsInt();
2358: for (int i = 0; i < lines; i++) {
2359: long lineCodeIndex = reply.getNextValueAsLong();
2360: lineNumber = reply.getNextValueAsInt();
2361: if (lineCodeIndex == codeIndex) {
2362: break;
2363: }
2364:
2365: if (lineCodeIndex > codeIndex) {
2366: --lineNumber;
2367: break;
2368: }
2369: }
2370:
2371: return lineNumber;
2372: }
2373:
2374: /**
2375: * Returns a line code index according to a corresponding line number in a
2376: * method's line table.
2377: *
2378: * @param classID
2379: * The class object ID.
2380: * @param methodID
2381: * The method ID.
2382: * @param lineNumber
2383: * A source line number.
2384: * @return An integer representing the line code index.
2385: */
2386: public final long getLineCodeIndex(long classID, long methodID,
2387: int lineNumber) {
2388: ReplyPacket reply = getLineTable(classID, methodID);
2389: if (reply.getErrorCode() != JDWPConstants.Error.NONE) {
2390: return -1L;
2391: }
2392:
2393: reply.getNextValueAsLong(); // start line index, is not used
2394: reply.getNextValueAsLong(); // end line index, is not used
2395: int lines = reply.getNextValueAsInt();
2396: for (int i = 0; i < lines; i++) {
2397: long lineCodeIndex = reply.getNextValueAsLong();
2398: if (lineNumber == reply.getNextValueAsInt()) {
2399: return lineCodeIndex;
2400: }
2401: }
2402:
2403: return -1L;
2404: }
2405:
2406: /**
2407: * Returns all variables which are visible within the given frame.
2408: *
2409: * @param frame
2410: * The frame whose visible local variables to retrieve.
2411: * @return A list of Variable objects representing each visible local
2412: * variable within the given frame.
2413: */
2414: public final List getLocalVars(Frame frame) {
2415: List vars = getVariableTable(frame.getLocation().classID, frame
2416: .getLocation().methodID);
2417: if (vars == null) {
2418: return null;
2419: }
2420:
2421: // All variables that are not visible from within current frame must be
2422: // removed from the list
2423: long frameCodeIndex = frame.getLocation().index;
2424: for (int i = 0; i < vars.size(); i++) {
2425: Variable var = (Variable) vars.toArray()[i];
2426: long varCodeIndex = var.getCodeIndex();
2427: if (varCodeIndex > frameCodeIndex
2428: || (frameCodeIndex >= varCodeIndex
2429: + var.getLength())) {
2430: vars.remove(i);
2431: --i;
2432: continue;
2433: }
2434: }
2435:
2436: return vars;
2437: }
2438:
2439: /**
2440: * Sets the value of one or more local variables
2441: *
2442: * @param frame
2443: * The frame ID.
2444: * @param vars
2445: * An array of Variable objects whose values to set
2446: * @param values
2447: * An array of Value objects to set
2448: */
2449: public final void setLocalVars(Frame frame, Variable[] vars,
2450: Value[] values) {
2451: if (vars.length != values.length) {
2452: throw new TestErrorException(
2453: "Number of variables doesn't correspond to number of their values");
2454: }
2455:
2456: CommandPacket command = new CommandPacket(
2457: JDWPCommands.StackFrameCommandSet.CommandSetID,
2458: JDWPCommands.StackFrameCommandSet.SetValuesCommand);
2459: command.setNextValueAsThreadID(frame.getThreadID());
2460: command.setNextValueAsFrameID(frame.getID());
2461: command.setNextValueAsInt(vars.length);
2462: for (int i = 0; i < vars.length; i++) {
2463: command.setNextValueAsInt(vars[i].getSlot());
2464: command.setNextValueAsValue(values[i]);
2465: }
2466:
2467: checkReply(performCommand(command));
2468: }
2469:
2470: /**
2471: * Sets the value of one or more instance fields
2472: *
2473: * @param objectID
2474: * The object ID.
2475: * @param fieldIDs
2476: * An array of fields IDs
2477: * @param values
2478: * An array of Value objects representing each value to set
2479: */
2480: public final void setInstanceFieldsValues(long objectID,
2481: long[] fieldIDs, Value[] values) {
2482: if (fieldIDs.length != values.length) {
2483: throw new TestErrorException(
2484: "Number of fields doesn't correspond to number of their values");
2485: }
2486:
2487: CommandPacket command = new CommandPacket(
2488: JDWPCommands.ObjectReferenceCommandSet.CommandSetID,
2489: JDWPCommands.ObjectReferenceCommandSet.SetValuesCommand);
2490: command.setNextValueAsObjectID(objectID);
2491: command.setNextValueAsInt(fieldIDs.length);
2492: for (int i = 0; i < fieldIDs.length; i++) {
2493: command.setNextValueAsFieldID(fieldIDs[i]);
2494: command.setNextValueAsUntaggedValue(values[i]);
2495: }
2496:
2497: checkReply(performCommand(command));
2498: }
2499:
2500: /**
2501: * Sets a range of array components. The specified range must be within the
2502: * bounds of the array.
2503: *
2504: * @param arrayID
2505: * The array object ID.
2506: * @param firstIndex
2507: * The first index to set.
2508: * @param values
2509: * An array of Value objects representing each value to set.
2510: */
2511: public final void setArrayValues(long arrayID, int firstIndex,
2512: Value[] values) {
2513: CommandPacket command = new CommandPacket(
2514: JDWPCommands.ArrayReferenceCommandSet.CommandSetID,
2515: JDWPCommands.ArrayReferenceCommandSet.SetValuesCommand);
2516: command.setNextValueAsArrayID(arrayID);
2517: command.setNextValueAsInt(firstIndex);
2518: command.setNextValueAsInt(values.length);
2519: for (int i = 0; i < values.length; i++) {
2520: command.setNextValueAsUntaggedValue(values[i]);
2521: }
2522:
2523: checkReply(performCommand(command));
2524: }
2525:
2526: /**
2527: * Sets the value of one or more static fields
2528: *
2529: * @param classID
2530: * The class type ID.
2531: * @param fieldIDs
2532: * An array of fields IDs
2533: * @param values
2534: * An array of Value objects representing each value to set
2535: */
2536: public final void setStaticFieldsValues(long classID,
2537: long[] fieldIDs, Value[] values) {
2538: if (fieldIDs.length != values.length) {
2539: throw new TestErrorException(
2540: "Number of fields doesn't correspond to number of their values");
2541: }
2542:
2543: CommandPacket command = new CommandPacket(
2544: JDWPCommands.ClassTypeCommandSet.CommandSetID,
2545: JDWPCommands.ClassTypeCommandSet.SetValuesCommand);
2546: command.setNextValueAsClassID(classID);
2547: command.setNextValueAsInt(fieldIDs.length);
2548: for (int i = 0; i < fieldIDs.length; i++) {
2549: command.setNextValueAsFieldID(fieldIDs[i]);
2550: command.setNextValueAsUntaggedValue(values[i]);
2551: }
2552:
2553: checkReply(performCommand(command));
2554: }
2555:
2556: /**
2557: * Creates java String in target VM with the given value.
2558: *
2559: * @param value
2560: * The value of the string.
2561: * @return The string id.
2562: */
2563: public final long createString(String value) {
2564: CommandPacket command = new CommandPacket(
2565: JDWPCommands.VirtualMachineCommandSet.CommandSetID,
2566: JDWPCommands.VirtualMachineCommandSet.CreateStringCommand);
2567: command.setNextValueAsString(value);
2568: ReplyPacket reply = checkReply(performCommand(command));
2569: return reply.getNextValueAsStringID();
2570: }
2571:
2572: /**
2573: * Processes JDWP PopFrames command from StackFrame command set.
2574: *
2575: * @param frame
2576: * The instance of Frame.
2577: */
2578: public final void popFrame(Frame frame) {
2579: CommandPacket command = new CommandPacket(
2580: JDWPCommands.StackFrameCommandSet.CommandSetID,
2581: JDWPCommands.StackFrameCommandSet.PopFramesCommand);
2582: command.setNextValueAsThreadID(frame.getThreadID());
2583: command.setNextValueAsFrameID(frame.getID());
2584: checkReply(performCommand(command));
2585: }
2586:
2587: /**
2588: * Invokes a member method of the given object.
2589: *
2590: * @param objectID
2591: * The object ID.
2592: * @param threadID
2593: * The thread ID.
2594: * @param methodName
2595: * The name of method for the invocation.
2596: * @param args
2597: * The arguments for the invocation.
2598: * @param options
2599: * The invocation options.
2600: * @return ReplyPacket for corresponding command
2601: */
2602: public final ReplyPacket invokeInstanceMethod(long objectID,
2603: long threadID, String methodName, Value[] args, int options) {
2604: long classID = getReferenceType(objectID);
2605: long methodID = getMethodID(classID, methodName);
2606: CommandPacket command = new CommandPacket(
2607: JDWPCommands.ObjectReferenceCommandSet.CommandSetID,
2608: JDWPCommands.ObjectReferenceCommandSet.InvokeMethodCommand);
2609: command.setNextValueAsObjectID(objectID);
2610: command.setNextValueAsThreadID(threadID);
2611: command.setNextValueAsClassID(classID);
2612: command.setNextValueAsMethodID(methodID);
2613: command.setNextValueAsInt(args.length);
2614: for (int i = 0; i < args.length; i++) {
2615: command.setNextValueAsValue(args[i]);
2616: }
2617: command.setNextValueAsInt(options);
2618:
2619: return checkReply(performCommand(command));
2620: }
2621:
2622: /**
2623: * Invokes a static method of the given class.
2624: *
2625: * @param classID
2626: * The class type ID.
2627: * @param threadID
2628: * The thread ID.
2629: * @param methodName
2630: * The name of method for the invocation.
2631: * @param args
2632: * The arguments for the invocation.
2633: * @param options
2634: * The invocation options.
2635: * @return ReplyPacket for corresponding command
2636: */
2637: public final ReplyPacket invokeStaticMethod(long classID,
2638: long threadID, String methodName, Value[] args, int options) {
2639: long methodID = getMethodID(classID, methodName);
2640: CommandPacket command = new CommandPacket(
2641: JDWPCommands.ClassTypeCommandSet.CommandSetID,
2642: JDWPCommands.ClassTypeCommandSet.InvokeMethodCommand);
2643: command.setNextValueAsClassID(classID);
2644: command.setNextValueAsThreadID(threadID);
2645: command.setNextValueAsMethodID(methodID);
2646: command.setNextValueAsInt(args.length);
2647: for (int i = 0; i < args.length; i++) {
2648: command.setNextValueAsValue(args[i]);
2649: }
2650: command.setNextValueAsInt(options);
2651:
2652: return checkReply(performCommand(command));
2653: }
2654: }
|