001: /*******************************************************************************
002: * Copyright (c) 2000, 2005 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.jdi.internal;
011:
012: import java.io.ByteArrayOutputStream;
013: import java.io.DataInputStream;
014: import java.io.DataOutputStream;
015: import java.io.IOException;
016: import java.io.PrintWriter;
017: import java.util.Map;
018:
019: import org.eclipse.jdi.Bootstrap;
020: import org.eclipse.jdi.internal.jdwp.JdwpCommandPacket;
021: import org.eclipse.jdi.internal.jdwp.JdwpPacket;
022: import org.eclipse.jdi.internal.jdwp.JdwpReplyPacket;
023: import org.eclipse.jdi.internal.jdwp.JdwpString;
024:
025: import com.sun.jdi.ClassNotPreparedException;
026: import com.sun.jdi.InternalException;
027: import com.sun.jdi.InvalidStackFrameException;
028: import com.sun.jdi.Mirror;
029: import com.sun.jdi.NativeMethodException;
030: import com.sun.jdi.ObjectCollectedException;
031: import com.sun.jdi.VMDisconnectedException;
032: import com.sun.jdi.VMMismatchException;
033: import com.sun.jdi.VMOutOfMemoryException;
034: import com.sun.jdi.VirtualMachine;
035:
036: /**
037: * this class implements the corresponding interfaces
038: * declared by the JDI specification. See the com.sun.jdi package
039: * for more information.
040: *
041: */
042: public class MirrorImpl implements Mirror {
043:
044: /** Description of Mirror object. */
045: protected String fDescription;
046: /** Virtual Machine of Mirror object. */
047: private VirtualMachineImpl fVirtualMachineImpl;
048: /** VerboseWriter where verbose info is written to, null if no verbose must be given. */
049: protected VerboseWriter fVerboseWriter = null;
050: /** True if a Jdwp request has been sent to the VM and the response is not yet (fully) processed. */
051: private boolean fPendingJdwpRequest = false;
052:
053: /**
054: * Constructor only to be used by Virtual Machine objects: stores description of Mirror object and Virtual Machine.
055: */
056: public MirrorImpl(String description) {
057: fDescription = description;
058: fVirtualMachineImpl = (VirtualMachineImpl) this ;
059: PrintWriter writer = ((VirtualMachineManagerImpl) org.eclipse.jdi.Bootstrap
060: .virtualMachineManager()).verbosePrintWriter();
061: if (writer != null)
062: fVerboseWriter = new VerboseWriter(writer);
063: }
064:
065: /**
066: * Constructor stores description of Mirror object and its Virtual Machine.
067: */
068: public MirrorImpl(String description,
069: VirtualMachineImpl virtualMachineImpl) {
070: fVirtualMachineImpl = virtualMachineImpl;
071: fDescription = description;
072: PrintWriter writer = ((VirtualMachineManagerImpl) org.eclipse.jdi.Bootstrap
073: .virtualMachineManager()).verbosePrintWriter();
074: if (writer != null)
075: fVerboseWriter = new VerboseWriter(writer);
076: }
077:
078: /**
079: * @return Returns description of Mirror object.
080: */
081: public String toString() {
082: return fDescription;
083: }
084:
085: /**
086: * @return Returns Virtual Machine of Mirror object.
087: */
088: public VirtualMachine virtualMachine() {
089: return fVirtualMachineImpl;
090: }
091:
092: /**
093: * @return Returns Virtual Machine implementation of Mirror object.
094: */
095: public VirtualMachineImpl virtualMachineImpl() {
096: return fVirtualMachineImpl;
097: }
098:
099: /**
100: * Processing before each Jdwp event.
101: */
102: public void initJdwpEventSet(JdwpCommandPacket commandPacket) {
103: if (fVerboseWriter != null) {
104: fVerboseWriter.println("Received event set"); //$NON-NLS-1$
105: fVerboseWriter.println("length", commandPacket.getLength()); //$NON-NLS-1$
106: fVerboseWriter.println("id", commandPacket.getId()); //$NON-NLS-1$
107: fVerboseWriter
108: .println(
109: "flags", commandPacket.getFlags(), JdwpPacket.getFlagMap()); //$NON-NLS-1$
110: fVerboseWriter
111: .println(
112: "command set", (byte) (commandPacket.getCommand() >>> 8)); //$NON-NLS-1$
113: fVerboseWriter.println(
114: "command", (byte) commandPacket.getCommand()); //$NON-NLS-1$
115: }
116: }
117:
118: /**
119: * Processing after each Jdwp Event.
120: */
121: public void handledJdwpEventSet() {
122: if (fVerboseWriter != null) {
123: fVerboseWriter.println();
124: fVerboseWriter.flush();
125: }
126: }
127:
128: /**
129: * Processing before each Jdwp request.
130: * Note that this includes building the request message and parsing the response.
131: */
132: public void initJdwpRequest() {
133: if (fVerboseWriter != null) {
134: fVerboseWriter.gotoPosition(6);
135: }
136: }
137:
138: /**
139: * Writes command packet header if verbose is on.
140: */
141: public void writeVerboseCommandPacketHeader(
142: JdwpCommandPacket commandPacket) {
143: if (fVerboseWriter != null) {
144: int command = commandPacket.getCommand();
145: int currentPosition = fVerboseWriter.position();
146: fVerboseWriter.gotoPosition(0);
147: fVerboseWriter.print("Sending command ("); //$NON-NLS-1$
148: fVerboseWriter.printValue(command, JdwpCommandPacket
149: .commandMap());
150: fVerboseWriter.println(")"); //$NON-NLS-1$
151: fVerboseWriter.println("length", commandPacket.getLength()); //$NON-NLS-1$
152: fVerboseWriter.println("id", commandPacket.getId()); //$NON-NLS-1$
153: fVerboseWriter
154: .println(
155: "flags", commandPacket.getFlags(), JdwpPacket.getFlagMap()); //$NON-NLS-1$
156: fVerboseWriter.println(
157: "command set", (byte) (command >>> 8)); //$NON-NLS-1$
158: fVerboseWriter.println("command", (byte) command); //$NON-NLS-1$
159: fVerboseWriter.gotoPosition(currentPosition);
160: }
161: }
162:
163: /**
164: * Processing after each Jdwp Request.
165: */
166: public void handledJdwpRequest() {
167: if (fVerboseWriter != null && fPendingJdwpRequest) {
168: fVerboseWriter.println();
169: fVerboseWriter.flush();
170: }
171: fPendingJdwpRequest = false;
172: }
173:
174: /**
175: * Performs a VM request.
176: * @return Returns reply data.
177: */
178: public JdwpReplyPacket requestVM(int command, byte[] outData) {
179: JdwpCommandPacket commandPacket = new JdwpCommandPacket(command);
180: commandPacket.setData(outData);
181: fVirtualMachineImpl.packetSendManager().sendPacket(
182: commandPacket);
183: fPendingJdwpRequest = true;
184: writeVerboseCommandPacketHeader(commandPacket);
185:
186: JdwpReplyPacket reply = fVirtualMachineImpl
187: .packetReceiveManager().getReply(commandPacket);
188: if (fVerboseWriter != null) {
189: fVerboseWriter.println();
190: fVerboseWriter.println("Received reply"); //$NON-NLS-1$
191: fVerboseWriter.println("length", reply.getLength()); //$NON-NLS-1$
192: fVerboseWriter.println("id", reply.getId()); //$NON-NLS-1$
193: fVerboseWriter.println(
194: "flags", reply.getFlags(), JdwpPacket.getFlagMap()); //$NON-NLS-1$
195: fVerboseWriter
196: .println(
197: "error code", reply.errorCode(), JdwpReplyPacket.errorMap()); //$NON-NLS-1$
198: }
199:
200: return reply;
201: }
202:
203: /**
204: * Performs a VM request.
205: * @return Returns reply data.
206: */
207: public JdwpReplyPacket requestVM(int command,
208: ByteArrayOutputStream outData) {
209: return requestVM(command, outData.toByteArray());
210: }
211:
212: /**
213: * Performs a VM request for a specified object.
214: * @return Returns reply data.
215: */
216: public JdwpReplyPacket requestVM(int command,
217: ObjectReferenceImpl object) {
218: ByteArrayOutputStream byteOutStream = new ByteArrayOutputStream();
219: DataOutputStream dataOutStream = new DataOutputStream(
220: byteOutStream);
221: try {
222: object.write(this , dataOutStream);
223: } catch (IOException e) {
224: defaultIOExceptionHandler(e);
225: }
226: return requestVM(command, byteOutStream);
227: }
228:
229: /**
230: * Performs a VM request for a specified object.
231: * @return Returns reply data.
232: */
233: public JdwpReplyPacket requestVM(int command,
234: ReferenceTypeImpl refType) {
235: ByteArrayOutputStream byteOutStream = new ByteArrayOutputStream();
236: DataOutputStream dataOutStream = new DataOutputStream(
237: byteOutStream);
238: try {
239: refType.write(this , dataOutStream);
240: } catch (IOException e) {
241: defaultIOExceptionHandler(e);
242: }
243: return requestVM(command, byteOutStream);
244: }
245:
246: /**
247: * Performs a VM request.
248: * @return Returns reply data.
249: */
250: public JdwpReplyPacket requestVM(int command) {
251: return requestVM(command, (byte[]) null);
252: }
253:
254: /**
255: * Performs default error handling.
256: */
257: public void defaultReplyErrorHandler(int error) {
258: switch (error) {
259: case JdwpReplyPacket.NONE:
260: break;
261: case JdwpReplyPacket.INVALID_OBJECT:
262: throw new ObjectCollectedException();
263: case JdwpReplyPacket.INVALID_CLASS:
264: throw new ClassNotPreparedException();
265: case JdwpReplyPacket.CLASS_NOT_PREPARED:
266: throw new ClassNotPreparedException();
267: case JdwpReplyPacket.OUT_OF_MEMORY:
268: throw new VMOutOfMemoryException();
269: case JdwpReplyPacket.ILLEGAL_ARGUMENT:
270: throw new IllegalArgumentException();
271: case JdwpReplyPacket.NATIVE_METHOD:
272: throw new NativeMethodException();
273: case JdwpReplyPacket.INVALID_FRAMEID:
274: throw new InvalidStackFrameException();
275: case JdwpReplyPacket.NOT_IMPLEMENTED:
276: throw new UnsupportedOperationException();
277: case JdwpReplyPacket.HCR_OPERATION_REFUSED:
278: throw new org.eclipse.jdi.hcr.OperationRefusedException();
279: case JdwpReplyPacket.VM_DEAD:
280: throw new VMDisconnectedException();
281: default:
282: throw new InternalException(
283: JDIMessages.MirrorImpl_Got_error_code_in_reply___1
284: + error);
285: }
286: }
287:
288: /**
289: * Performs default handling of IOException in creating or interpreting a Jdwp packet.
290: */
291: public void defaultIOExceptionHandler(Exception e) {
292: throw new InternalException(
293: JDIMessages.MirrorImpl_Got_invalid_data___2 + e);
294: }
295:
296: /**
297: * Waits for a specified command packet from the VM.
298: * @return Returns Command Packet from VM.
299: */
300: public final JdwpCommandPacket getCommandVM(int command,
301: long timeout) throws InterruptedException {
302: return fVirtualMachineImpl.packetReceiveManager().getCommand(
303: command, timeout);
304: }
305:
306: /**
307: * @exception VMMismatchException is thrown if the Mirror argument and this mirror do not belong to the same VirtualMachine.
308: */
309: public void checkVM(Mirror mirror) throws VMMismatchException {
310: if (((MirrorImpl) mirror).virtualMachineImpl() != this
311: .virtualMachineImpl())
312: throw new VMMismatchException();
313: }
314:
315: /**
316: * Disconnects VM.
317: */
318: public void disconnectVM() {
319: fVirtualMachineImpl.setDisconnected(true);
320: fVirtualMachineImpl.packetSendManager().disconnectVM();
321: fVirtualMachineImpl.packetReceiveManager().disconnectVM();
322: ((VirtualMachineManagerImpl) Bootstrap.virtualMachineManager())
323: .removeConnectedVM(fVirtualMachineImpl);
324: }
325:
326: /**
327: * Reads Jdwp data and, if verbose is on, outputs verbose info.
328: * @return Returns value that has been read.
329: */
330: public byte readByte(String description, DataInputStream in)
331: throws IOException {
332: byte result = in.readByte();
333: if (fVerboseWriter != null) {
334: fVerboseWriter.println(description, result);
335: }
336: return result;
337: }
338:
339: /**
340: * Reads Jdwp data and, if verbose is on, outputs verbose info.
341: * @return Returns value that has been read.
342: */
343: public short readShort(String description, DataInputStream in)
344: throws IOException {
345: short result = in.readShort();
346: if (fVerboseWriter != null) {
347: fVerboseWriter.println(description, result);
348: }
349: return result;
350: }
351:
352: /**
353: * Reads Jdwp data and, if verbose is on, outputs verbose info.
354: * @return Returns value that has been read.
355: */
356: public int readInt(String description, DataInputStream in)
357: throws IOException {
358: int result = in.readInt();
359: if (fVerboseWriter != null) {
360: fVerboseWriter.println(description, result);
361: }
362: return result;
363: }
364:
365: /**
366: * Reads Jdwp data and, if verbose is on, outputs verbose info.
367: * @return Returns value that has been read.
368: */
369: public long readLong(String description, DataInputStream in)
370: throws IOException {
371: long result = in.readLong();
372: if (fVerboseWriter != null) {
373: fVerboseWriter.println(description, result);
374: }
375: return result;
376: }
377:
378: /**
379: * Reads Jdwp data and, if verbose is on, outputs verbose info.
380: * @return Returns value that has been read.
381: */
382: public byte readByte(String description, Map valueToString,
383: DataInputStream in) throws IOException {
384: byte result = in.readByte();
385: if (fVerboseWriter != null) {
386: fVerboseWriter.println(description, result, valueToString);
387: }
388: return result;
389: }
390:
391: /**
392: * Reads Jdwp data and, if verbose is on, outputs verbose info.
393: * @return Returns value that has been read.
394: */
395: public short readShort(String description, Map valueToString,
396: DataInputStream in) throws IOException {
397: short result = in.readShort();
398: if (fVerboseWriter != null) {
399: fVerboseWriter.println(description, result, valueToString);
400: }
401: return result;
402: }
403:
404: /**
405: * Reads Jdwp data and, if verbose is on, outputs verbose info.
406: * @return Returns value that has been read.
407: */
408: public int readInt(String description, Map valueToString,
409: DataInputStream in) throws IOException {
410: int result = in.readInt();
411: if (fVerboseWriter != null) {
412: fVerboseWriter.println(description, result, valueToString);
413: }
414: return result;
415: }
416:
417: /**
418: * Reads Jdwp data and, if verbose is on, outputs verbose info.
419: * @return Returns value that has been read.
420: */
421: public String readString(String description, DataInputStream in)
422: throws IOException {
423: String result = JdwpString.read(in);
424: if (fVerboseWriter != null) {
425: fVerboseWriter.println(description, result);
426: }
427: return result;
428: }
429:
430: /**
431: * Reads Jdwp data and, if verbose is on, outputs verbose info.
432: * @return Returns value that has been read.
433: */
434: public boolean readBoolean(String description, DataInputStream in)
435: throws IOException {
436: boolean result = in.readBoolean();
437: if (fVerboseWriter != null) {
438: fVerboseWriter.println(description, result);
439: }
440: return result;
441: }
442:
443: /**
444: * Reads Jdwp data and, if verbose is on, outputs verbose info.
445: * @return Returns value that has been read.
446: */
447: public char readChar(String description, DataInputStream in)
448: throws IOException {
449: char result = in.readChar();
450: if (fVerboseWriter != null) {
451: fVerboseWriter.println(description, result);
452: }
453: return result;
454: }
455:
456: /**
457: * Reads Jdwp data and, if verbose is on, outputs verbose info.
458: * @return Returns value that has been read.
459: */
460: public double readDouble(String description, DataInputStream in)
461: throws IOException {
462: double result = in.readDouble();
463: if (fVerboseWriter != null) {
464: fVerboseWriter.println(description, result);
465: }
466: return result;
467: }
468:
469: /**
470: * Reads Jdwp data and, if verbose is on, outputs verbose info.
471: * @return Returns value that has been read.
472: */
473: public float readFloat(String description, DataInputStream in)
474: throws IOException {
475: float result = in.readFloat();
476: if (fVerboseWriter != null) {
477: fVerboseWriter.println(description, result);
478: }
479: return result;
480: }
481:
482: /**
483: * Reads Jdwp data and, if verbose is on, outputs verbose info.
484: * @return Returns value that has been read.
485: */
486: public byte[] readByteArray(int length, String description,
487: DataInputStream in) throws IOException {
488: byte[] result = new byte[length];
489: in.readFully(result);
490: if (fVerboseWriter != null) {
491: fVerboseWriter.println(description, result);
492: }
493: return result;
494: }
495:
496: /**
497: * Writes Jdwp data and, if verbose is on, outputs verbose info.
498: */
499: public void writeByte(byte value, String description,
500: DataOutputStream out) throws IOException {
501: out.writeByte(value);
502: if (fVerboseWriter != null) {
503: fVerboseWriter.println(description, value);
504: }
505: }
506:
507: /**
508: * Writes Jdwp data and, if verbose is on, outputs verbose info.
509: */
510: public void writeShort(short value, String description,
511: DataOutputStream out) throws IOException {
512: out.writeShort(value);
513: if (fVerboseWriter != null) {
514: fVerboseWriter.println(description, value);
515: }
516: }
517:
518: /**
519: * Writes Jdwp data and, if verbose is on, outputs verbose info.
520: */
521: public void writeInt(int value, String description,
522: DataOutputStream out) throws IOException {
523: out.writeInt(value);
524: if (fVerboseWriter != null) {
525: fVerboseWriter.println(description, value);
526: }
527: }
528:
529: /**
530: * Writes Jdwp data and, if verbose is on, outputs verbose info.
531: */
532: public void writeLong(long value, String description,
533: DataOutputStream out) throws IOException {
534: out.writeLong(value);
535: if (fVerboseWriter != null) {
536: fVerboseWriter.println(description, value);
537: }
538: }
539:
540: /**
541: * Writes Jdwp data and, if verbose is on, outputs verbose info.
542: */
543: public void writeByte(byte value, String description,
544: Map valueToString, DataOutputStream out) throws IOException {
545: out.writeByte(value);
546: if (fVerboseWriter != null) {
547: fVerboseWriter.println(description, value, valueToString);
548: }
549: }
550:
551: /**
552: * Writes Jdwp data and, if verbose is on, outputs verbose info.
553: */
554: public void writeShort(short value, String description,
555: Map valueToString, DataOutputStream out) throws IOException {
556: out.writeShort(value);
557: if (fVerboseWriter != null) {
558: fVerboseWriter.println(description, value, valueToString);
559: }
560: }
561:
562: /**
563: * Writes Jdwp data and, if verbose is on, outputs verbose info.
564: */
565: public void writeInt(int value, String description,
566: Map valueToString, DataOutputStream out) throws IOException {
567: out.writeInt(value);
568: if (fVerboseWriter != null) {
569: fVerboseWriter.println(description, value, valueToString);
570: }
571: }
572:
573: /**
574: * Writes Jdwp data and, if verbose is on, outputs verbose info.
575: */
576: public void writeString(String value, String description,
577: DataOutputStream out) throws IOException {
578: JdwpString.write(value, out);
579: if (fVerboseWriter != null) {
580: fVerboseWriter.println(description, value);
581: }
582: }
583:
584: /**
585: * Writes Jdwp data and, if verbose is on, outputs verbose info.
586: */
587: public void writeBoolean(boolean value, String description,
588: DataOutputStream out) throws IOException {
589: out.writeBoolean(value);
590: if (fVerboseWriter != null) {
591: fVerboseWriter.println(description, value);
592: }
593: }
594:
595: /**
596: * Writes Jdwp data and, if verbose is on, outputs verbose info.
597: */
598: public void writeChar(char value, String description,
599: DataOutputStream out) throws IOException {
600: out.writeChar(value);
601: if (fVerboseWriter != null) {
602: fVerboseWriter.println(description, value);
603: }
604: }
605:
606: /**
607: * Writes Jdwp data and, if verbose is on, outputs verbose info.
608: */
609: public void writeDouble(double value, String description,
610: DataOutputStream out) throws IOException {
611: out.writeDouble(value);
612: if (fVerboseWriter != null) {
613: fVerboseWriter.println(description, value);
614: }
615: }
616:
617: /**
618: * Writes Jdwp data and, if verbose is on, outputs verbose info.
619: */
620: public void writeFloat(float value, String description,
621: DataOutputStream out) throws IOException {
622: out.writeFloat(value);
623: if (fVerboseWriter != null) {
624: fVerboseWriter.println(description, value);
625: }
626: }
627:
628: /**
629: * Writes Jdwp data and, if verbose is on, outputs verbose info.
630: */
631: public void writeShort(short value, String description,
632: String[] bitNames, DataOutputStream out) throws IOException {
633: out.writeShort(value);
634: if (fVerboseWriter != null) {
635: fVerboseWriter.println(description, value, bitNames);
636: }
637: }
638:
639: /**
640: * Writes Jdwp data and, if verbose is on, outputs verbose info.
641: */
642: public void writeInt(int value, String description,
643: String[] bitNames, DataOutputStream out) throws IOException {
644: out.writeInt(value);
645: if (fVerboseWriter != null) {
646: fVerboseWriter.println(description, value, bitNames);
647: }
648: }
649:
650: /**
651: * Reads Jdwp data and, if verbose is on, outputs verbose info.
652: * @return Returns value that has been read.
653: */
654: public byte readByte(String description, String[] bitNames,
655: DataInputStream in) throws IOException {
656: byte result = in.readByte();
657: if (fVerboseWriter != null) {
658: fVerboseWriter.println(description, result, bitNames);
659: }
660: return result;
661: }
662:
663: /**
664: * Reads Jdwp data and, if verbose is on, outputs verbose info.
665: * @return Returns value that has been read.
666: */
667: public short readShort(String description, String[] bitNames,
668: DataInputStream in) throws IOException {
669: short result = in.readShort();
670: if (fVerboseWriter != null) {
671: fVerboseWriter.println(description, result, bitNames);
672: }
673: return result;
674: }
675:
676: /**
677: * Reads Jdwp data and, if verbose is on, outputs verbose info.
678: * @return Returns value that has been read.
679: */
680: public int readInt(String description, String[] bitNames,
681: DataInputStream in) throws IOException {
682: int result = in.readInt();
683: if (fVerboseWriter != null) {
684: fVerboseWriter.println(description, result, bitNames);
685: }
686: return result;
687: }
688:
689: /**
690: * Writes Jdwp data and, if verbose is on, outputs verbose info.
691: */
692: public void writeByte(byte value, String description,
693: String[] bitNames, DataOutputStream out) throws IOException {
694: out.writeByte(value);
695: if (fVerboseWriter != null) {
696: fVerboseWriter.println(description, value, bitNames);
697: }
698: }
699:
700: /**
701: * @return Returns VerboseWriter where verbose info is written to, null if no verbose must be given.
702: */
703: public VerboseWriter verboseWriter() {
704: return fVerboseWriter;
705: }
706: }
|