0001: /*******************************************************************************
0002: * Copyright (c) 2000, 2007 IBM Corporation and others.
0003: * All rights reserved. This program and the accompanying materials
0004: * are made available under the terms of the Eclipse Public License v1.0
0005: * which accompanies this distribution, and is available at
0006: * http://www.eclipse.org/legal/epl-v10.html
0007: *
0008: * Contributors:
0009: * IBM Corporation - initial API and implementation
0010: * Yavor Boyadzhiev <yavor.vasilev.boyadzhiev@sap.com> - Bug 162399
0011: *******************************************************************************/package org.eclipse.jdi.internal;
0012:
0013: import java.io.ByteArrayOutputStream;
0014: import java.io.DataInputStream;
0015: import java.io.DataOutputStream;
0016: import java.io.IOException;
0017: import java.lang.reflect.Modifier;
0018: import java.util.ArrayList;
0019: import java.util.Collections;
0020: import java.util.HashMap;
0021: import java.util.HashSet;
0022: import java.util.Hashtable;
0023: import java.util.Iterator;
0024: import java.util.List;
0025: import java.util.Map;
0026: import java.util.Set;
0027:
0028: import org.eclipse.jdi.internal.jdwp.JdwpCommandPacket;
0029: import org.eclipse.jdi.internal.jdwp.JdwpFieldID;
0030: import org.eclipse.jdi.internal.jdwp.JdwpID;
0031: import org.eclipse.jdi.internal.jdwp.JdwpMethodID;
0032: import org.eclipse.jdi.internal.jdwp.JdwpReferenceTypeID;
0033: import org.eclipse.jdi.internal.jdwp.JdwpReplyPacket;
0034:
0035: import com.ibm.icu.text.MessageFormat;
0036: import com.sun.jdi.AbsentInformationException;
0037: import com.sun.jdi.ClassLoaderReference;
0038: import com.sun.jdi.ClassNotLoadedException;
0039: import com.sun.jdi.ClassNotPreparedException;
0040: import com.sun.jdi.ClassObjectReference;
0041: import com.sun.jdi.ClassType;
0042: import com.sun.jdi.Field;
0043: import com.sun.jdi.InternalException;
0044: import com.sun.jdi.NativeMethodException;
0045: import com.sun.jdi.ObjectCollectedException;
0046: import com.sun.jdi.ReferenceType;
0047: import com.sun.jdi.VMDisconnectedException;
0048: import com.sun.jdi.Value;
0049:
0050: /**
0051: * this class implements the corresponding interfaces
0052: * declared by the JDI specification. See the com.sun.jdi package
0053: * for more information.
0054: *
0055: */
0056: public abstract class ReferenceTypeImpl extends TypeImpl implements
0057: ReferenceType, org.eclipse.jdi.hcr.ReferenceType {
0058:
0059: /** ClassStatus Constants. */
0060: public static final int JDWP_CLASS_STATUS_VERIFIED = 1;
0061: public static final int JDWP_CLASS_STATUS_PREPARED = 2;
0062: public static final int JDWP_CLASS_STATUS_INITIALIZED = 4;
0063: public static final int JDWP_CLASS_STATUS_ERROR = 8;
0064:
0065: /** Mapping of command codes to strings. */
0066: private static String[] fgClassStatusStrings = null;
0067:
0068: /**
0069: * Represent the data about one file info contained in one stratum in the SMAP.
0070: */
0071: protected static class FileInfo {
0072:
0073: /**
0074: * The id.
0075: */
0076: protected int fFileId;
0077:
0078: /**
0079: * The name of the source file.
0080: */
0081: protected String fFileName;
0082:
0083: /**
0084: * The path of the source file.
0085: */
0086: protected String fAbsoluteFileName;
0087:
0088: /**
0089: * Map line number in the input source file
0090: * -> list of [start line in the output source file, range in the output source file].
0091: * (Integer -> List of int[2]).
0092: */
0093: private HashMap fLineInfo;
0094:
0095: /**
0096: * FileInfo constructor.
0097: *
0098: * @param fileId the id.
0099: * @param fileName the name of the source file.
0100: * @param absoluteFileName the path of the source file (can be <code>null</code>).
0101: */
0102: public FileInfo(int fileId, String fileName,
0103: String absoluteFileName) {
0104: fFileId = fileId;
0105: fFileName = fileName;
0106: fAbsoluteFileName = absoluteFileName;
0107: fLineInfo = new HashMap();
0108: }
0109:
0110: /**
0111: * Add information about the mapping of one line.
0112: * Associate a line in the input source file to a snippet of code
0113: * in the output source file.
0114: *
0115: * @param inputLine the line number in the input source file.
0116: * @param outputStartLine the number of the first line of the corresponding snippet in the output source file.
0117: * @param outputLineRange the size of the corresponding snippet in the output source file.
0118: */
0119: public void addLineInfo(int inputLine, int outputStartLine,
0120: int outputLineRange) {
0121: Integer key = new Integer(inputLine);
0122: List outputLines = (List) fLineInfo.get(key);
0123: if (outputLines == null) {
0124: outputLines = new ArrayList();
0125: fLineInfo.put(key, outputLines);
0126: }
0127: outputLines.add(new int[] { outputStartLine,
0128: outputLineRange });
0129: }
0130:
0131: /**
0132: * Return a list of line information about the code in the output source file
0133: * associated to the given line in the input source file.
0134: *
0135: * @param lineNumber the line number in the input source file.
0136: * @return a List of int[2].
0137: */
0138: public List getOutputLinesForLine(int lineNumber) {
0139: List list = new ArrayList();
0140: List outputLines = (List) fLineInfo.get(new Integer(
0141: lineNumber));
0142: if (outputLines != null) {
0143: for (Iterator iter = outputLines.iterator(); iter
0144: .hasNext();) {
0145: int[] info = (int[]) iter.next();
0146: int outputLineNumber = info[0];
0147: int length = info[1];
0148: if (length == 0) {
0149: length = length + 1;
0150: }
0151: for (int i = 0; i < length; i++) {
0152: list.add(new Integer(outputLineNumber++));
0153: }
0154: }
0155: }
0156: return list;
0157: }
0158:
0159: /**
0160: * @see java.lang.Object#equals(java.lang.Object)
0161: */
0162: public boolean equals(Object object) {
0163: if (!(object instanceof FileInfo)) {
0164: return false;
0165: }
0166: return fFileId == ((FileInfo) object).fFileId;
0167: }
0168:
0169: }
0170:
0171: /**
0172: * Represent the information contained in the SMAP about one stratum.
0173: */
0174: protected static class Stratum {
0175:
0176: /**
0177: * The id of this stratum.
0178: */
0179: private String fId;
0180:
0181: /**
0182: * The file info data associated to this stratum.
0183: */
0184: private List fFileInfos;
0185:
0186: /**
0187: * Id of the primary file for this stratum.
0188: */
0189: private int fPrimaryFileId;
0190:
0191: /**
0192: * Map line number in the output source file -> list of line numbers in the input source file.
0193: * (Integer -> List of Integer)
0194: */
0195: private HashMap fOutputLineToInputLine;
0196:
0197: /**
0198: * Stratum constructor.
0199: * @param id The id of this stratum.
0200: */
0201: public Stratum(String id) {
0202: fId = id;
0203: fFileInfos = new ArrayList();
0204: fOutputLineToInputLine = new HashMap();
0205: fPrimaryFileId = -1;
0206: }
0207:
0208: /**
0209: * Add a file info to this stratum.
0210: *
0211: * @param fileId the id.
0212: * @param fileName the name of the source file.
0213: */
0214: public void addFileInfo(int fileId, String fileName)
0215: throws AbsentInformationException {
0216: addFileInfo(fileId, fileName, null);
0217: }
0218:
0219: /**
0220: * Add a file info to this stratum.
0221: *
0222: * @param fileId the id.
0223: * @param fileName the name of the source file.
0224: * @param absoluteFileName the path of the source file.
0225: */
0226: public void addFileInfo(int fileId, String fileName,
0227: String absoluteFileName)
0228: throws AbsentInformationException {
0229: if (fPrimaryFileId == -1) {
0230: fPrimaryFileId = fileId;
0231: }
0232: FileInfo fileInfo = new FileInfo(fileId, fileName,
0233: absoluteFileName);
0234: if (fFileInfos.contains(fileInfo)) {
0235: throw new AbsentInformationException(
0236: MessageFormat
0237: .format(
0238: JDIMessages.ReferenceTypeImpl_28,
0239: new String[] {
0240: Integer
0241: .toString(fileId),
0242: fId }));
0243: }
0244: fFileInfos.add(fileInfo);
0245: }
0246:
0247: /**
0248: * Add line mapping information.
0249: *
0250: * @param inputStartLine number of the first line in the input source file.
0251: * @param lineFileId id of the input source file.
0252: * @param repeatCount number of iterations.
0253: * @param outputStartLine number of the first line in the output source file.
0254: * @param outputLineIncrement number of line to increment at each iteration.
0255: * @throws AbsentInformationException
0256: */
0257: public void addLineInfo(int inputStartLine, int lineFileId,
0258: int repeatCount, int outputStartLine,
0259: int outputLineIncrement)
0260: throws AbsentInformationException {
0261: FileInfo fileInfo = null;
0262: // get the FileInfo object
0263: for (Iterator iter = fFileInfos.iterator(); iter.hasNext();) {
0264: FileInfo element = (FileInfo) iter.next();
0265: if (element.fFileId == lineFileId) {
0266: fileInfo = element;
0267: }
0268: }
0269: if (fileInfo == null) {
0270: throw new AbsentInformationException(MessageFormat
0271: .format(JDIMessages.ReferenceTypeImpl_29,
0272: new String[] { Integer
0273: .toString(lineFileId) }));
0274: }
0275: // add the data to the different hash maps.
0276: for (int i = 0; i < repeatCount; i++, inputStartLine++) {
0277: fileInfo.addLineInfo(inputStartLine, outputStartLine,
0278: outputLineIncrement);
0279: if (outputLineIncrement == 0) {
0280: // see bug 40022
0281: addLineInfoToMap(inputStartLine, lineFileId,
0282: outputStartLine);
0283: } else {
0284: for (int j = 0; j < outputLineIncrement; j++, outputStartLine++) {
0285: addLineInfoToMap(inputStartLine, lineFileId,
0286: outputStartLine);
0287: }
0288: }
0289: }
0290: }
0291:
0292: /**
0293: * Add the data to the map.
0294: */
0295: private void addLineInfoToMap(int inputStartLine,
0296: int lineFileId, int outputStartLine) {
0297: Integer key = new Integer(outputStartLine);
0298: List inputLines = (List) fOutputLineToInputLine.get(key);
0299: if (inputLines == null) {
0300: inputLines = new ArrayList();
0301: fOutputLineToInputLine.put(key, inputLines);
0302: }
0303: inputLines.add(new int[] { lineFileId, inputStartLine });
0304: }
0305:
0306: /**
0307: * Return the FileInfo object for the specified source name.
0308: * Return <code>null</code> if the specified name is the source name of no file info.
0309: * @param sourceName the source name to search.
0310: */
0311: public FileInfo getFileInfo(String sourceName) {
0312: for (Iterator iter = fFileInfos.iterator(); iter.hasNext();) {
0313: FileInfo fileInfo = (FileInfo) iter.next();
0314: if (fileInfo.fFileName.equals(sourceName)) {
0315: return fileInfo;
0316: }
0317: }
0318: return null;
0319: }
0320:
0321: /**
0322: * @param outputLineNumber
0323: * @return
0324: */
0325: public List getInputLineInfos(int outputLineNumber) {
0326: return (List) fOutputLineToInputLine.get(new Integer(
0327: outputLineNumber));
0328: }
0329:
0330: }
0331:
0332: /** ReferenceTypeID that corresponds to this reference. */
0333: private JdwpReferenceTypeID fReferenceTypeID;
0334:
0335: /** The following are the stored results of JDWP calls. */
0336: protected List fInterfaces = null;
0337: private List fMethods = null;
0338: private Hashtable fMethodTable = null;
0339: private List fFields = null;
0340: private List fAllMethods = null;
0341: private List fVisibleMethods = null;
0342: private List fAllFields = null;
0343: private List fVisibleFields = null;
0344: private List fAllInterfaces = null;
0345: private Map fStratumAllLineLocations = null;
0346: private String fSourceName = null;
0347: private int fModifierBits = -1;
0348: private ClassLoaderReferenceImpl fClassLoader = null;
0349: private ClassObjectReferenceImpl fClassObject = null;
0350:
0351: private String fGenericSignature; // 1.5 addition
0352: private boolean fGenericSignatureKnown; // 1.5 addition
0353:
0354: private boolean fGotClassFileVersion = false; // HCR addition.
0355: private int fClassFileVersion; // HCR addition.
0356: private boolean fIsHCREligible; // HCR addition.
0357: private boolean fIsVersionKnown; // HCR addition.
0358:
0359: private boolean fSourceDebugExtensionAvailable = true; // JSR-045 addition
0360:
0361: /**
0362: * The default stratum id.
0363: */
0364: private String fDefaultStratumId; // JSR-045 addition
0365:
0366: /**
0367: * A map of the defined strata.
0368: * Map stratum id -> Stratum object.
0369: * (String -> Stratum).
0370: */
0371: private Map fStrata; // JSR-045 addition
0372:
0373: /**
0374: * The source map string returned by the VM.
0375: */
0376: private String fSmap; // JSR-045 addition
0377:
0378: /**
0379: * Creates new instance.
0380: */
0381: protected ReferenceTypeImpl(String description,
0382: VirtualMachineImpl vmImpl,
0383: JdwpReferenceTypeID referenceTypeID) {
0384: super (description, vmImpl);
0385: fReferenceTypeID = referenceTypeID;
0386: }
0387:
0388: /**
0389: * Creates new instance.
0390: */
0391: protected ReferenceTypeImpl(String description,
0392: VirtualMachineImpl vmImpl,
0393: JdwpReferenceTypeID referenceTypeID, String signature,
0394: String genericSignature) {
0395: super (description, vmImpl);
0396: fReferenceTypeID = referenceTypeID;
0397: setSignature(signature);
0398: setGenericSignature(genericSignature);
0399: }
0400:
0401: /**
0402: * @return Returns type tag.
0403: */
0404: public abstract byte typeTag();
0405:
0406: /**
0407: * Flushes all stored Jdwp results.
0408: */
0409: public void flushStoredJdwpResults() {
0410: Iterator iter;
0411:
0412: // Flush Methods.
0413: if (fMethods != null) {
0414: iter = fMethods.iterator();
0415: while (iter.hasNext()) {
0416: MethodImpl method = (MethodImpl) iter.next();
0417: method.flushStoredJdwpResults();
0418: }
0419: fMethods = null;
0420: fMethodTable = null;
0421: }
0422:
0423: // Flush Fields.
0424: if (fFields != null) {
0425: iter = fFields.iterator();
0426: while (iter.hasNext()) {
0427: FieldImpl field = (FieldImpl) iter.next();
0428: field.flushStoredJdwpResults();
0429: }
0430: fFields = null;
0431: }
0432:
0433: fInterfaces = null;
0434: fAllMethods = null;
0435: fVisibleMethods = null;
0436: fAllFields = null;
0437: fVisibleFields = null;
0438: fAllInterfaces = null;
0439: fStratumAllLineLocations = null;
0440: fSourceName = null;
0441: fModifierBits = -1;
0442: fClassLoader = null;
0443: fClassObject = null;
0444: fGotClassFileVersion = false;
0445: // java 1.5
0446: fGenericSignature = null;
0447: fGenericSignatureKnown = false;
0448:
0449: // JSR-045
0450: fSourceDebugExtensionAvailable = true;
0451: fDefaultStratumId = null;
0452: fStrata = null;
0453: fSmap = null;
0454:
0455: // The following cached results are stored higher up in the class hierarchy.
0456: fSignature = null;
0457: fSourceName = null;
0458: }
0459:
0460: /**
0461: * @return Returns the interfaces declared as implemented by this class. Interfaces indirectly implemented (extended by the implemented interface or implemented by a superclass) are not included.
0462: */
0463: public List allInterfaces() {
0464: if (fAllInterfaces != null) {
0465: return fAllInterfaces;
0466: }
0467:
0468: /* Recursion:
0469: * The interfaces that it directly implements;
0470: * All interfaces that are implemented by its interfaces;
0471: * If it is a class, all interfaces that are implemented by its superclass.
0472: */
0473: // The interfaces are maintained in a set, to avoid duplicates.
0474: // The interfaces of its own (own interfaces() command) are first inserted.
0475: HashSet allInterfacesSet = new HashSet(interfaces());
0476:
0477: // All interfaces of the interfaces it implements.
0478: Iterator interfaces = interfaces().iterator();
0479: InterfaceTypeImpl inter;
0480: while (interfaces.hasNext()) {
0481: inter = (InterfaceTypeImpl) interfaces.next();
0482: allInterfacesSet.addAll(inter.allInterfaces());
0483: }
0484:
0485: // If it is a class, all interfaces of it's superclass.
0486: if (this instanceof ClassType) {
0487: ClassType super class = ((ClassType) this ).super class();
0488: if (super class != null) {
0489: allInterfacesSet.addAll(super class.allInterfaces());
0490: }
0491: }
0492:
0493: fAllInterfaces = new ArrayList(allInterfacesSet);
0494: return fAllInterfaces;
0495: }
0496:
0497: /**
0498: * @return Returns Jdwp Reference ID.
0499: */
0500: public JdwpReferenceTypeID getRefTypeID() {
0501: return fReferenceTypeID;
0502: }
0503:
0504: /**
0505: * @return Returns modifier bits.
0506: */
0507: public int modifiers() {
0508: if (fModifierBits != -1)
0509: return fModifierBits;
0510:
0511: initJdwpRequest();
0512: try {
0513: JdwpReplyPacket replyPacket = requestVM(
0514: JdwpCommandPacket.RT_MODIFIERS, this );
0515: defaultReplyErrorHandler(replyPacket.errorCode());
0516: DataInputStream replyData = replyPacket.dataInStream();
0517: fModifierBits = readInt(
0518: "modifiers", AccessibleImpl.getModifierStrings(), replyData); //$NON-NLS-1$
0519: return fModifierBits;
0520: } catch (IOException e) {
0521: defaultIOExceptionHandler(e);
0522: return 0;
0523: } finally {
0524: handledJdwpRequest();
0525: }
0526: }
0527:
0528: /**
0529: * Add methods to a set of methods if they are not overridden, add new names+signature combinations to set of names+signature combinations.
0530: */
0531: private void addVisibleMethods(List inheritedMethods,
0532: Set nameAndSignatures, List resultMethods) {
0533: Iterator iter = inheritedMethods.iterator();
0534: MethodImpl inheritedMethod;
0535: while (iter.hasNext()) {
0536: inheritedMethod = (MethodImpl) iter.next();
0537: if (!nameAndSignatures.contains(inheritedMethod.name()
0538: + inheritedMethod.signature())) {
0539: resultMethods.add(inheritedMethod);
0540: }
0541: }
0542: }
0543:
0544: /**
0545: * @return Returns a list containing each visible and unambiguous Method in this type.
0546: */
0547: public List visibleMethods() {
0548: if (fVisibleMethods != null)
0549: return fVisibleMethods;
0550:
0551: /* Recursion:
0552: * The methods of its own (own methods() command);
0553: * All methods of the interfaces it implements;
0554: * If it is a class, all methods of it's superclass.
0555: */
0556: // The name+signature combinations of methods are maintained in a set, to avoid including methods that have been overridden.
0557: Set namesAndSignatures = new HashSet();
0558: List visibleMethods = new ArrayList();
0559:
0560: // The methods of its own (own methods() command).
0561: for (Iterator iter = methods().iterator(); iter.hasNext();) {
0562: MethodImpl method = (MethodImpl) iter.next();
0563: namesAndSignatures.add(method.name() + method.signature());
0564: visibleMethods.add(method);
0565: }
0566:
0567: // All methods of the interfaces it implements.
0568: Iterator interfaces = interfaces().iterator();
0569: InterfaceTypeImpl inter;
0570: while (interfaces.hasNext()) {
0571: inter = (InterfaceTypeImpl) interfaces.next();
0572: addVisibleMethods(inter.visibleMethods(),
0573: namesAndSignatures, visibleMethods);
0574: }
0575:
0576: // If it is a class, all methods of it's superclass.
0577: if (this instanceof ClassType) {
0578: ClassType super class = ((ClassType) this ).super class();
0579: if (super class != null)
0580: addVisibleMethods(super class.visibleMethods(),
0581: namesAndSignatures, visibleMethods);
0582: }
0583:
0584: fVisibleMethods = visibleMethods;
0585: return fVisibleMethods;
0586: }
0587:
0588: /**
0589: * @return Returns a list containing each Method declared in this type, and its super-classes, implemented interfaces, and/or super-interfaces.
0590: */
0591: public List allMethods() {
0592: if (fAllMethods != null)
0593: return fAllMethods;
0594:
0595: /* Recursion:
0596: * The methods of its own (own methods() command);
0597: * All methods of the interfaces it implements;
0598: * If it is a class, all methods of it's superclass.
0599: */
0600: // The name+signature combinations of methods are maintained in a set.
0601: HashSet resultSet = new HashSet();
0602:
0603: // The methods of its own (own methods() command).
0604: resultSet.addAll(methods());
0605:
0606: // All methods of the interfaces it implements.
0607: Iterator interfaces = interfaces().iterator();
0608: InterfaceTypeImpl inter;
0609: while (interfaces.hasNext()) {
0610: inter = (InterfaceTypeImpl) interfaces.next();
0611: resultSet.addAll(inter.allMethods());
0612: }
0613:
0614: // If it is a class, all methods of it's superclass.
0615: if (this instanceof ClassType) {
0616: ClassType super class = ((ClassType) this ).super class();
0617: if (super class != null)
0618: resultSet.addAll(super class.allMethods());
0619: }
0620:
0621: fAllMethods = new ArrayList(resultSet);
0622: return fAllMethods;
0623: }
0624:
0625: /**
0626: * @return Returns the interfaces declared as implemented by this class. Interfaces indirectly implemented (extended by the implemented interface or implemented by a superclass) are not included.
0627: */
0628: public List interfaces() {
0629: if (fInterfaces != null) {
0630: return fInterfaces;
0631: }
0632:
0633: initJdwpRequest();
0634: try {
0635: JdwpReplyPacket replyPacket = requestVM(
0636: JdwpCommandPacket.RT_INTERFACES, this );
0637: switch (replyPacket.errorCode()) {
0638: case JdwpReplyPacket.NOT_FOUND:
0639: // Workaround for problem in J2ME WTK (wireless toolkit)
0640: // @see Bug 12966
0641: return Collections.EMPTY_LIST;
0642: default:
0643: defaultReplyErrorHandler(replyPacket.errorCode());
0644: }
0645: DataInputStream replyData = replyPacket.dataInStream();
0646: List elements = new ArrayList();
0647: int nrOfElements = readInt("elements", replyData); //$NON-NLS-1$
0648: for (int i = 0; i < nrOfElements; i++) {
0649: InterfaceTypeImpl ref = InterfaceTypeImpl.read(this ,
0650: replyData);
0651: if (ref == null) {
0652: continue;
0653: }
0654: elements.add(ref);
0655: }
0656: fInterfaces = elements;
0657: return elements;
0658: } catch (IOException e) {
0659: defaultIOExceptionHandler(e);
0660: return null;
0661: } finally {
0662: handledJdwpRequest();
0663: }
0664: }
0665:
0666: /**
0667: * Add fields to a set of fields if they are not overridden, add new field names to set of field names.
0668: */
0669: private void addVisibleFields(List newFields, Set names,
0670: List resultFields) {
0671: Iterator iter = newFields.iterator();
0672: FieldImpl field;
0673: while (iter.hasNext()) {
0674: field = (FieldImpl) iter.next();
0675: String name = field.name();
0676: if (!names.contains(name)) {
0677: resultFields.add(field);
0678: names.add(name);
0679: }
0680: }
0681: }
0682:
0683: /**
0684: * @return Returns a list containing each visible and unambiguous Field in this type.
0685: */
0686: public List visibleFields() {
0687: if (fVisibleFields != null)
0688: return fVisibleFields;
0689:
0690: /* Recursion:
0691: * The fields of its own (own fields() command);
0692: * All fields of the interfaces it implements;
0693: * If it is a class, all fields of it's superclass.
0694: */
0695: // The names of fields are maintained in a set, to avoid including fields that have been overridden.
0696: HashSet fieldNames = new HashSet();
0697:
0698: // The fields of its own (own fields() command).
0699: List visibleFields = new ArrayList();
0700: addVisibleFields(fields(), fieldNames, visibleFields);
0701:
0702: // All fields of the interfaces it implements.
0703: Iterator interfaces = interfaces().iterator();
0704: InterfaceTypeImpl inter;
0705: while (interfaces.hasNext()) {
0706: inter = (InterfaceTypeImpl) interfaces.next();
0707: addVisibleFields(inter.visibleFields(), fieldNames,
0708: visibleFields);
0709: }
0710:
0711: // If it is a class, all fields of it's superclass.
0712: if (this instanceof ClassType) {
0713: ClassType super class = ((ClassType) this ).super class();
0714: if (super class != null)
0715: addVisibleFields(super class.visibleFields(),
0716: fieldNames, visibleFields);
0717: }
0718:
0719: fVisibleFields = visibleFields;
0720: return fVisibleFields;
0721: }
0722:
0723: /**
0724: * @return Returns a list containing each Field declared in this type, and its super-classes, implemented interfaces, and/or super-interfaces.
0725: */
0726: public List allFields() {
0727: if (fAllFields != null)
0728: return fAllFields;
0729:
0730: /* Recursion:
0731: * The fields of its own (own fields() command);
0732: * All fields of the interfaces it implements;
0733: * If it is a class, all fields of it's superclass.
0734: */
0735: // The names of fields are maintained in a set, to avoid including fields that have been inherited double.
0736: HashSet resultSet = new HashSet();
0737:
0738: // The fields of its own (own fields() command).
0739: resultSet.addAll(fields());
0740:
0741: // All fields of the interfaces it implements.
0742: Iterator interfaces = interfaces().iterator();
0743: InterfaceTypeImpl inter;
0744: while (interfaces.hasNext()) {
0745: inter = (InterfaceTypeImpl) interfaces.next();
0746: resultSet.addAll(inter.allFields());
0747: }
0748:
0749: // If it is a class, all fields of it's superclass.
0750: if (this instanceof ClassType) {
0751: ClassType super class = ((ClassType) this ).super class();
0752: if (super class != null)
0753: resultSet.addAll(super class.allFields());
0754: }
0755:
0756: fAllFields = new ArrayList(resultSet);
0757: return fAllFields;
0758: }
0759:
0760: /**
0761: * @return Returns the class loader object which loaded the class corresponding to this type.
0762: */
0763: public ClassLoaderReference classLoader() {
0764: if (fClassLoader != null)
0765: return fClassLoader;
0766:
0767: initJdwpRequest();
0768: try {
0769: JdwpReplyPacket replyPacket = requestVM(
0770: JdwpCommandPacket.RT_CLASS_LOADER, this );
0771: defaultReplyErrorHandler(replyPacket.errorCode());
0772: DataInputStream replyData = replyPacket.dataInStream();
0773: fClassLoader = ClassLoaderReferenceImpl.read(this ,
0774: replyData);
0775: return fClassLoader;
0776: } catch (IOException e) {
0777: defaultIOExceptionHandler(e);
0778: return null;
0779: } finally {
0780: handledJdwpRequest();
0781: }
0782: }
0783:
0784: /**
0785: * @return Returns the class object that corresponds to this type in the target VM.
0786: */
0787: public ClassObjectReference classObject() {
0788: if (fClassObject != null)
0789: return fClassObject;
0790:
0791: initJdwpRequest();
0792: try {
0793: JdwpReplyPacket replyPacket = requestVM(
0794: JdwpCommandPacket.RT_CLASS_OBJECT, this );
0795: defaultReplyErrorHandler(replyPacket.errorCode());
0796: DataInputStream replyData = replyPacket.dataInStream();
0797: fClassObject = ClassObjectReferenceImpl.read(this ,
0798: replyData);
0799: return fClassObject;
0800: } catch (IOException e) {
0801: defaultIOExceptionHandler(e);
0802: return null;
0803: } finally {
0804: handledJdwpRequest();
0805: }
0806: }
0807:
0808: /**
0809: * @return Returns status of class/interface.
0810: */
0811: protected int status() {
0812: // Note that this information should not be cached.
0813: initJdwpRequest();
0814: try {
0815: JdwpReplyPacket replyPacket = requestVM(
0816: JdwpCommandPacket.RT_STATUS, this );
0817: defaultReplyErrorHandler(replyPacket.errorCode());
0818: DataInputStream replyData = replyPacket.dataInStream();
0819: int status = readInt(
0820: "status", classStatusStrings(), replyData); //$NON-NLS-1$
0821: return status;
0822: } catch (IOException e) {
0823: defaultIOExceptionHandler(e);
0824: return 0;
0825: } finally {
0826: handledJdwpRequest();
0827: }
0828: }
0829:
0830: /**
0831: * @return Returns true if initialization failed for this class.
0832: */
0833: public boolean failedToInitialize() {
0834: return (status() & JDWP_CLASS_STATUS_ERROR) != 0;
0835: }
0836:
0837: /**
0838: * @return Returns true if this type has been initialized.
0839: */
0840: public boolean isInitialized() {
0841: return (status() & JDWP_CLASS_STATUS_INITIALIZED) != 0;
0842: }
0843:
0844: /**
0845: * @return Returns true if this type has been prepared.
0846: */
0847: public boolean isPrepared() {
0848: return (status() & JDWP_CLASS_STATUS_PREPARED) != 0;
0849: }
0850:
0851: /**
0852: * @return Returns true if this type has been verified.
0853: */
0854: public boolean isVerified() {
0855: return (status() & JDWP_CLASS_STATUS_VERIFIED) != 0;
0856: }
0857:
0858: /**
0859: * @return Returns the visible Field with the given non-ambiguous name.
0860: */
0861: public Field fieldByName(String name) {
0862: Iterator iter = visibleFields().iterator();
0863: while (iter.hasNext()) {
0864: FieldImpl field = (FieldImpl) iter.next();
0865: if (field.name().equals(name))
0866: return field;
0867: }
0868: return null;
0869: }
0870:
0871: /**
0872: * @return Returns a list containing each Field declared in this type.
0873: */
0874: public List fields() {
0875: if (fFields != null) {
0876: return fFields;
0877: }
0878:
0879: // Note: Fields are returned in the order they occur in the class file, therefore their
0880: // order in this list can be used for comparisons.
0881: initJdwpRequest();
0882: try {
0883: boolean withGenericSignature = virtualMachineImpl()
0884: .isJdwpVersionGreaterOrEqual(1, 5);
0885: int jdwpCommand = withGenericSignature ? JdwpCommandPacket.RT_FIELDS_WITH_GENERIC
0886: : JdwpCommandPacket.RT_FIELDS;
0887: JdwpReplyPacket replyPacket = requestVM(jdwpCommand, this );
0888: defaultReplyErrorHandler(replyPacket.errorCode());
0889: DataInputStream replyData = replyPacket.dataInStream();
0890: List elements = new ArrayList();
0891: int nrOfElements = readInt("elements", replyData); //$NON-NLS-1$
0892: for (int i = 0; i < nrOfElements; i++) {
0893: FieldImpl elt = FieldImpl
0894: .readWithNameSignatureModifiers(this , this ,
0895: withGenericSignature, replyData);
0896: if (elt == null) {
0897: continue;
0898: }
0899: elements.add(elt);
0900: }
0901: fFields = elements;
0902: return fFields;
0903: } catch (IOException e) {
0904: defaultIOExceptionHandler(e);
0905: return null;
0906: } finally {
0907: handledJdwpRequest();
0908: }
0909: }
0910:
0911: /**
0912: * @return Returns FieldImpl of a field in the reference specified by a given fieldID, or null if not found.
0913: */
0914: public FieldImpl findField(JdwpFieldID fieldID) {
0915: Iterator iter = fields().iterator();
0916: while (iter.hasNext()) {
0917: FieldImpl field = (FieldImpl) iter.next();
0918: if (field.getFieldID().equals(fieldID))
0919: return field;
0920: }
0921: return null;
0922: }
0923:
0924: /**
0925: * @return Returns MethodImpl of a method in the reference specified by a given methodID, or null if not found.
0926: */
0927: public MethodImpl findMethod(JdwpMethodID methodID) {
0928: if (methodID.value() == 0) {
0929: return new MethodImpl(virtualMachineImpl(), this , methodID,
0930: JDIMessages.ReferenceTypeImpl_Obsolete_method_1,
0931: "", null, -1); //$NON-NLS-1$
0932: }
0933: if (fMethodTable == null) {
0934: fMethodTable = new Hashtable();
0935: Iterator iter = methods().iterator();
0936: while (iter.hasNext()) {
0937: MethodImpl method = (MethodImpl) iter.next();
0938: fMethodTable.put(method.getMethodID(), method);
0939: }
0940: }
0941: return (MethodImpl) fMethodTable.get(methodID);
0942: }
0943:
0944: /**
0945: * @return Returns the Value of a given static Field in this type.
0946: */
0947: public Value getValue(Field field) {
0948: ArrayList list = new ArrayList(1);
0949: list.add(field);
0950: return (ValueImpl) getValues(list).get(field);
0951: }
0952:
0953: /**
0954: * @return a Map of the requested static Field objects with their Value.
0955: */
0956: public Map getValues(List fields) {
0957: // if the field list is empty, nothing to do
0958: if (fields.isEmpty()) {
0959: return new HashMap();
0960: }
0961: // Note that this information should not be cached.
0962: initJdwpRequest();
0963: try {
0964: ByteArrayOutputStream outBytes = new ByteArrayOutputStream();
0965: DataOutputStream outData = new DataOutputStream(outBytes);
0966: int fieldsSize = fields.size();
0967: write(this , outData);
0968: writeInt(fieldsSize, "size", outData); //$NON-NLS-1$
0969: for (int i = 0; i < fieldsSize; i++) {
0970: FieldImpl field = (FieldImpl) fields.get(i);
0971: checkVM(field);
0972: field.getFieldID().write(outData);
0973: }
0974:
0975: JdwpReplyPacket replyPacket = requestVM(
0976: JdwpCommandPacket.RT_GET_VALUES, outBytes);
0977: defaultReplyErrorHandler(replyPacket.errorCode());
0978:
0979: DataInputStream replyData = replyPacket.dataInStream();
0980: HashMap map = new HashMap();
0981: int nrOfElements = readInt("elements", replyData); //$NON-NLS-1$
0982: if (nrOfElements != fieldsSize)
0983: throw new InternalError(
0984: JDIMessages.ReferenceTypeImpl_Retrieved_a_different_number_of_values_from_the_VM_than_requested_3);
0985:
0986: for (int i = 0; i < nrOfElements; i++) {
0987: map.put(fields.get(i), ValueImpl.readWithTag(this ,
0988: replyData));
0989: }
0990: return map;
0991: } catch (IOException e) {
0992: defaultIOExceptionHandler(e);
0993: return null;
0994: } finally {
0995: handledJdwpRequest();
0996: }
0997: }
0998:
0999: /**
1000: * @return Returns the hash code value.
1001: */
1002: public int hashCode() {
1003: return fReferenceTypeID.hashCode();
1004: }
1005:
1006: /**
1007: * @return Returns true if two mirrors refer to the same entity in the target VM.
1008: * @see java.lang.Object#equals(Object)
1009: */
1010: public boolean equals(Object object) {
1011: return object != null
1012: && object.getClass().equals(this .getClass())
1013: && fReferenceTypeID
1014: .equals(((ReferenceTypeImpl) object).fReferenceTypeID)
1015: && virtualMachine().equals(
1016: ((MirrorImpl) object).virtualMachine());
1017: }
1018:
1019: /**
1020: * @return Returns a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified object.
1021: */
1022: public int compareTo(Object object) {
1023: if (object == null
1024: || !object.getClass().equals(this .getClass()))
1025: throw new ClassCastException(
1026: JDIMessages.ReferenceTypeImpl_Can__t_compare_reference_type_to_given_object_4);
1027: return name().compareTo(((ReferenceType) object).name());
1028: }
1029:
1030: /**
1031: * @return Returns true if the type was declared abstract.
1032: */
1033: public boolean isAbstract() {
1034: return (modifiers() & MODIFIER_ACC_ABSTRACT) != 0;
1035: }
1036:
1037: /**
1038: * @return Returns true if the type was declared final.
1039: */
1040: public boolean isFinal() {
1041: return (modifiers() & MODIFIER_ACC_FINAL) != 0;
1042: }
1043:
1044: /**
1045: * @return Returns true if the type was declared static.
1046: */
1047: public boolean isStatic() {
1048: return (modifiers() & MODIFIER_ACC_STATIC) != 0;
1049: }
1050:
1051: /**
1052: * @return Returns a List filled with all Location objects that map to the given line number.
1053: */
1054: public List locationsOfLine(int line)
1055: throws AbsentInformationException {
1056: return locationsOfLine(virtualMachine().getDefaultStratum(),
1057: null, line);
1058: }
1059:
1060: /**
1061: * @return Returns a list containing each Method declared directly in this type.
1062: */
1063: public List methods() {
1064: // Note that ArrayReference overwrites this method by returning an empty list.
1065: if (fMethods != null)
1066: return fMethods;
1067:
1068: // Note: Methods are returned in the order they occur in the class file, therefore their
1069: // order in this list can be used for comparisons.
1070: initJdwpRequest();
1071: try {
1072: boolean withGenericSignature = virtualMachineImpl()
1073: .isJdwpVersionGreaterOrEqual(1, 5);
1074: int jdwpCommand = withGenericSignature ? JdwpCommandPacket.RT_METHODS_WITH_GENERIC
1075: : JdwpCommandPacket.RT_METHODS;
1076: JdwpReplyPacket replyPacket = requestVM(jdwpCommand, this );
1077: defaultReplyErrorHandler(replyPacket.errorCode());
1078: DataInputStream replyData = replyPacket.dataInStream();
1079: List elements = new ArrayList();
1080: int nrOfElements = readInt("elements", replyData); //$NON-NLS-1$
1081: for (int i = 0; i < nrOfElements; i++) {
1082: MethodImpl elt = MethodImpl
1083: .readWithNameSignatureModifiers(this , this ,
1084: withGenericSignature, replyData);
1085: if (elt == null) {
1086: continue;
1087: }
1088: elements.add(elt);
1089: }
1090: fMethods = elements;
1091: return fMethods;
1092: } catch (IOException e) {
1093: defaultIOExceptionHandler(e);
1094: return null;
1095: } finally {
1096: handledJdwpRequest();
1097: }
1098: }
1099:
1100: /**
1101: * @return Returns a List containing each visible Method that has the given name.
1102: */
1103: public List methodsByName(String name) {
1104: List elements = new ArrayList();
1105: Iterator iter = visibleMethods().iterator();
1106: while (iter.hasNext()) {
1107: MethodImpl method = (MethodImpl) iter.next();
1108: if (method.name().equals(name)) {
1109: elements.add(method);
1110: }
1111: }
1112: return elements;
1113: }
1114:
1115: /**
1116: * @return Returns a List containing each visible Method that has the given name and signature.
1117: */
1118: public List methodsByName(String name, String signature) {
1119: List elements = new ArrayList();
1120: Iterator iter = visibleMethods().iterator();
1121: while (iter.hasNext()) {
1122: MethodImpl method = (MethodImpl) iter.next();
1123: if (method.name().equals(name)
1124: && method.signature().equals(signature)) {
1125: elements.add(method);
1126: }
1127: }
1128: return elements;
1129: }
1130:
1131: /**
1132: * @return Returns the fully qualified name of this type.
1133: */
1134: public String name() {
1135: // Make sure that we know the signature, from which the name is derived.
1136: if (fName == null) {
1137: setName(signatureToName(signature()));
1138: }
1139: return fName;
1140: }
1141:
1142: /**
1143: * @return Returns the JNI-style signature for this type.
1144: */
1145: public String signature() {
1146: if (fSignature != null) {
1147: return fSignature;
1148: }
1149: initJdwpRequest();
1150: try {
1151: JdwpReplyPacket replyPacket = requestVM(
1152: JdwpCommandPacket.RT_SIGNATURE, this );
1153: defaultReplyErrorHandler(replyPacket.errorCode());
1154: DataInputStream replyData = replyPacket.dataInStream();
1155: setSignature(readString("signature", replyData)); //$NON-NLS-1$
1156: return fSignature;
1157: } catch (IOException e) {
1158: defaultIOExceptionHandler(e);
1159: return null;
1160: } finally {
1161: handledJdwpRequest();
1162: }
1163: }
1164:
1165: /**
1166: * @return Returns a List containing each ReferenceType declared within this type.
1167: */
1168: public List nestedTypes() {
1169: // Note that the VM gives an empty reply on RT_NESTED_TYPES, therefore we search for the
1170: // nested types in the loaded types.
1171: List result = new ArrayList();
1172: Iterator itr = virtualMachineImpl().allRefTypes();
1173: while (itr.hasNext()) {
1174: try {
1175: ReferenceTypeImpl refType = (ReferenceTypeImpl) itr
1176: .next();
1177: String refName = refType.name();
1178: if (refName.length() > name().length()
1179: && refName.startsWith(name())
1180: && refName.charAt(name().length()) == '$') {
1181: result.add(refType);
1182: }
1183: } catch (ClassNotPreparedException e) {
1184: continue;
1185: }
1186: }
1187: return result;
1188: }
1189:
1190: /**
1191: * @return Returns an identifying name for the source corresponding to the declaration of this type.
1192: */
1193: public String sourceName() throws AbsentInformationException {
1194: // sourceNames list in never empty, an AbsentInformationException is thrown
1195: // if the source name is not known.
1196: return (String) sourceNames(
1197: virtualMachine().getDefaultStratum()).get(0);
1198: }
1199:
1200: /**
1201: * @return Returns the CRC-32 of the given reference type, undefined if unknown.
1202: */
1203: public int getClassFileVersion() {
1204: virtualMachineImpl().checkHCRSupported();
1205: if (fGotClassFileVersion)
1206: return fClassFileVersion;
1207:
1208: initJdwpRequest();
1209: try {
1210: JdwpReplyPacket replyPacket = requestVM(
1211: JdwpCommandPacket.HCR_GET_CLASS_VERSION, this );
1212: defaultReplyErrorHandler(replyPacket.errorCode());
1213: DataInputStream replyData = replyPacket.dataInStream();
1214: fIsHCREligible = readBoolean("HCR eligible", replyData); //$NON-NLS-1$
1215: fIsVersionKnown = readBoolean("version known", replyData); //$NON-NLS-1$
1216: fClassFileVersion = readInt("class file version", replyData); //$NON-NLS-1$
1217: fGotClassFileVersion = true;
1218: return fClassFileVersion;
1219: } catch (IOException e) {
1220: defaultIOExceptionHandler(e);
1221: return 0;
1222: } finally {
1223: handledJdwpRequest();
1224: }
1225: }
1226:
1227: /**
1228: * @return Returns whether the CRC-32 of the given reference type is known.
1229: */
1230: public boolean isVersionKnown() {
1231: getClassFileVersion();
1232: return fIsVersionKnown;
1233: }
1234:
1235: /**
1236: * @return Returns whether the reference type is HCR-eligible.
1237: */
1238: public boolean isHCREligible() {
1239: getClassFileVersion();
1240: return fIsHCREligible;
1241: }
1242:
1243: /**
1244: * Writes JDWP representation.
1245: */
1246: public void write(MirrorImpl target, DataOutputStream out)
1247: throws IOException {
1248: fReferenceTypeID.write(out);
1249: if (target.fVerboseWriter != null)
1250: target.fVerboseWriter.println(
1251: "referenceType", fReferenceTypeID.value()); //$NON-NLS-1$
1252: }
1253:
1254: /**
1255: * Writes representation of null referenceType.
1256: */
1257: public static void writeNull(MirrorImpl target, DataOutputStream out)
1258: throws IOException {
1259: // create null id
1260: JdwpReferenceTypeID ID = new JdwpReferenceTypeID(target
1261: .virtualMachineImpl());
1262: ID.write(out);
1263: if (target.fVerboseWriter != null)
1264: target.fVerboseWriter.println("referenceType", ID.value()); //$NON-NLS-1$
1265: }
1266:
1267: /**
1268: * Writes JDWP representation.
1269: */
1270: public void writeWithTag(MirrorImpl target, DataOutputStream out)
1271: throws IOException {
1272: target.writeByte(typeTag(),
1273: "type tag", JdwpID.typeTagMap(), out); //$NON-NLS-1$
1274: write(target, out);
1275: }
1276:
1277: /**
1278: * @return Reads JDWP representation and returns new or cached instance.
1279: */
1280: public static ReferenceTypeImpl readWithTypeTag(MirrorImpl target,
1281: DataInputStream in) throws IOException {
1282: byte typeTag = target.readByte(
1283: "type tag", JdwpID.typeTagMap(), in); //$NON-NLS-1$
1284: switch (typeTag) {
1285: case 0:
1286: return null;
1287: case ArrayTypeImpl.typeTag:
1288: return ArrayTypeImpl.read(target, in);
1289: case ClassTypeImpl.typeTag:
1290: return ClassTypeImpl.read(target, in);
1291: case InterfaceTypeImpl.typeTag:
1292: return InterfaceTypeImpl.read(target, in);
1293: }
1294: throw new InternalException(
1295: JDIMessages.ReferenceTypeImpl_Invalid_ReferenceTypeID_tag_encountered___8
1296: + typeTag);
1297: }
1298:
1299: /**
1300: * @return Returns the Location objects for each executable source line in this reference type.
1301: */
1302: public List allLineLocations() throws AbsentInformationException {
1303: return allLineLocations(virtualMachine().getDefaultStratum(),
1304: null);
1305: }
1306:
1307: /**
1308: * @return Reads JDWP representation and returns new or cached instance.
1309: */
1310: public static ReferenceTypeImpl readWithTypeTagAndSignature(
1311: MirrorImpl target, boolean withGenericSignature,
1312: DataInputStream in) throws IOException {
1313: byte typeTag = target.readByte(
1314: "type tag", JdwpID.typeTagMap(), in); //$NON-NLS-1$
1315: switch (typeTag) {
1316: case 0:
1317: return null;
1318: case ArrayTypeImpl.typeTag:
1319: return ArrayTypeImpl.readWithSignature(target,
1320: withGenericSignature, in);
1321: case ClassTypeImpl.typeTag:
1322: return ClassTypeImpl.readWithSignature(target,
1323: withGenericSignature, in);
1324: case InterfaceTypeImpl.typeTag:
1325: return InterfaceTypeImpl.readWithSignature(target,
1326: withGenericSignature, in);
1327: }
1328: throw new InternalException(
1329: JDIMessages.ReferenceTypeImpl_Invalid_ReferenceTypeID_tag_encountered___8
1330: + typeTag);
1331: }
1332:
1333: /**
1334: * @return Returns new instance based on signature and classLoader.
1335: * @throws ClassNotLoadedException when the ReferenceType has not been loaded by the specified class loader.
1336: */
1337: public static TypeImpl create(VirtualMachineImpl vmImpl,
1338: String signature, ClassLoaderReference classLoader)
1339: throws ClassNotLoadedException {
1340: ReferenceTypeImpl refTypeBootstrap = null;
1341: List classes = vmImpl.classesBySignature(signature);
1342: ReferenceTypeImpl type;
1343: Iterator iter = classes.iterator();
1344: while (iter.hasNext()) {
1345: // First pass. Look for a class loaded by the given class loader
1346: type = (ReferenceTypeImpl) iter.next();
1347: if (type.classLoader() == null) { // bootstrap classloader
1348: if (classLoader == null) {
1349: return type;
1350: }
1351: refTypeBootstrap = type;
1352: }
1353: if (classLoader != null
1354: && classLoader.equals(type.classLoader())) {
1355: return type;
1356: }
1357: }
1358: // If no ReferenceType is found with the specified classloader, but there is one with the
1359: // bootstrap classloader, the latter is returned.
1360: if (refTypeBootstrap != null) {
1361: return refTypeBootstrap;
1362: }
1363:
1364: List visibleTypes;
1365: iter = classes.iterator();
1366: while (iter.hasNext()) {
1367: // Second pass. Look for a class that is visible to
1368: // the given class loader
1369: type = (ReferenceTypeImpl) iter.next();
1370: visibleTypes = classLoader.visibleClasses();
1371: Iterator visibleIter = visibleTypes.iterator();
1372: while (visibleIter.hasNext()) {
1373: if (type.equals(visibleIter.next())) {
1374: return type;
1375: }
1376: }
1377: }
1378:
1379: throw new ClassNotLoadedException(
1380: classSignatureToName(signature),
1381: JDIMessages.ReferenceTypeImpl_Type_has_not_been_loaded_10);
1382: }
1383:
1384: /**
1385: * Retrieves constant mappings.
1386: */
1387: public static void getConstantMaps() {
1388: if (fgClassStatusStrings != null) {
1389: return;
1390: }
1391:
1392: java.lang.reflect.Field[] fields = ReferenceTypeImpl.class
1393: .getDeclaredFields();
1394: fgClassStatusStrings = new String[32];
1395:
1396: for (int i = 0; i < fields.length; i++) {
1397: java.lang.reflect.Field field = fields[i];
1398: if ((field.getModifiers() & Modifier.PUBLIC) == 0
1399: || (field.getModifiers() & Modifier.STATIC) == 0
1400: || (field.getModifiers() & Modifier.FINAL) == 0) {
1401: continue;
1402: }
1403:
1404: String name = field.getName();
1405: if (!name.startsWith("JDWP_CLASS_STATUS_")) { //$NON-NLS-1$
1406: continue;
1407: }
1408:
1409: name = name.substring(18);
1410:
1411: try {
1412: int value = field.getInt(null);
1413:
1414: for (int j = 0; j < fgClassStatusStrings.length; j++) {
1415: if ((1 << j & value) != 0) {
1416: fgClassStatusStrings[j] = name;
1417: break;
1418: }
1419: }
1420: } catch (IllegalAccessException e) {
1421: // Will not occur for own class.
1422: } catch (IllegalArgumentException e) {
1423: // Should not occur.
1424: // We should take care that all public static final constants
1425: // in this class are numbers that are convertible to int.
1426: }
1427: }
1428: }
1429:
1430: /**
1431: * @return Returns a map with string representations of tags.
1432: */
1433: public static String[] classStatusStrings() {
1434: getConstantMaps();
1435: return fgClassStatusStrings;
1436: }
1437:
1438: /**
1439: * @see TypeImpl#createNullValue()
1440: */
1441: public Value createNullValue() {
1442: return null;
1443: }
1444:
1445: /**
1446: * @see ReferenceType#sourceNames(String)
1447: */
1448: public List sourceNames(String stratumId)
1449: throws AbsentInformationException {
1450: List list = new ArrayList();
1451: Stratum stratum = getStratum(stratumId);
1452: if (stratum != null) {
1453: // return the source names defined for this stratum in the SMAP.
1454: List fileInfos = stratum.fFileInfos;
1455: if (fileInfos.isEmpty()) {
1456: throw new AbsentInformationException(
1457: JDIMessages.ReferenceTypeImpl_30);
1458: }
1459: for (Iterator iter = stratum.fFileInfos.iterator(); iter
1460: .hasNext();) {
1461: list.add(((FileInfo) iter.next()).fFileName);
1462: }
1463: return list;
1464: }
1465: // Java stratum
1466: if (fSourceName == null) {
1467: getSourceName();
1468: }
1469: list.add(fSourceName);
1470: return list;
1471: }
1472:
1473: /**
1474: * @see ReferenceType#sourcePaths(String)
1475: */
1476: public List sourcePaths(String stratumId)
1477: throws AbsentInformationException {
1478: List list = new ArrayList();
1479: Stratum stratum = getStratum(stratumId);
1480: if (stratum != null) {
1481: // return the source paths defined for this stratum in the SMAP.
1482: for (Iterator iter = stratum.fFileInfos.iterator(); iter
1483: .hasNext();) {
1484: FileInfo fileInfo = (FileInfo) iter.next();
1485: String path = fileInfo.fAbsoluteFileName;
1486: if (path == null) {
1487: path = getPath(fileInfo.fFileName);
1488: }
1489: list.add(path);
1490: }
1491: return list;
1492: }
1493: // Java stratum
1494: if (fSourceName == null) {
1495: getSourceName();
1496: }
1497: list.add(getPath(fSourceName));
1498: return list;
1499: }
1500:
1501: /**
1502: * @see ReferenceType#sourceDebugExtension()
1503: */
1504: public String sourceDebugExtension()
1505: throws AbsentInformationException {
1506: if (isSourceDebugExtensionAvailable()) {
1507: return fSmap;
1508: }
1509: if (!virtualMachine().canGetSourceDebugExtension()) {
1510: throw new UnsupportedOperationException();
1511: }
1512: throw new AbsentInformationException();
1513: }
1514:
1515: /**
1516: * @see ReferenceType#allLineLocations(String, String)
1517: */
1518: public List allLineLocations(String stratum, String sourceName)
1519: throws AbsentInformationException {
1520: Iterator allMethods = methods().iterator();
1521: if (stratum == null) { // if stratum not defined use the default stratum
1522: stratum = defaultStratum();
1523: }
1524: List allLineLocations = null;
1525: Map sourceNameAllLineLocations = null;
1526: if (fStratumAllLineLocations == null) { // the stratum map doesn't exist, create it
1527: fStratumAllLineLocations = new HashMap();
1528: } else {
1529: // get the source name map
1530: sourceNameAllLineLocations = (Map) fStratumAllLineLocations
1531: .get(stratum);
1532: }
1533: if (sourceNameAllLineLocations == null) { // the source name map doesn't exist, create it
1534: sourceNameAllLineLocations = new HashMap();
1535: fStratumAllLineLocations.put(stratum,
1536: sourceNameAllLineLocations);
1537: } else {
1538: // get the line locations
1539: allLineLocations = (List) sourceNameAllLineLocations
1540: .get(sourceName);
1541: }
1542: if (allLineLocations == null) { // the line locations are not know, compute and store them
1543: allLineLocations = new ArrayList();
1544: while (allMethods.hasNext()) {
1545: MethodImpl method = (MethodImpl) allMethods.next();
1546: if (method.isAbstract() || method.isNative()) {
1547: continue;
1548: }
1549: allLineLocations.addAll(method.allLineLocations(
1550: stratum, sourceName));
1551: }
1552: sourceNameAllLineLocations
1553: .put(sourceName, allLineLocations);
1554: }
1555: return allLineLocations;
1556: }
1557:
1558: /**
1559: * @see ReferenceType#locationsOfLine(String, String, int)
1560: */
1561: public List locationsOfLine(String stratum, String sourceName,
1562: int lineNumber) throws AbsentInformationException {
1563: Iterator allMethods = methods().iterator();
1564: List locations = new ArrayList();
1565: boolean hasLineInformation = false;
1566: AbsentInformationException exception = null;
1567: while (allMethods.hasNext()) {
1568: MethodImpl method = (MethodImpl) allMethods.next();
1569: if (method.isAbstract() || method.isNative()) {
1570: continue;
1571: }
1572: // one line in the input source can be translate in multiple lines in different
1573: // methods in the output source. We need all these locations.
1574: try {
1575: locations.addAll(locationsOfLine(stratum, sourceName,
1576: lineNumber, method));
1577: hasLineInformation = true;
1578: } catch (AbsentInformationException e) {
1579: exception = e;
1580: }
1581: }
1582: if (!hasLineInformation && exception != null) {
1583: throw exception;
1584: }
1585: return locations;
1586: }
1587:
1588: /**
1589: * @see ReferenceType#availableStrata()
1590: */
1591: public List availableStrata() {
1592: List list = new ArrayList();
1593: // The strata defined in the SMAP.
1594: if (isSourceDebugExtensionAvailable()) {
1595: list.addAll(fStrata.keySet());
1596: }
1597: // plus the Java stratum
1598: list.add(VirtualMachineImpl.JAVA_STRATUM_NAME);
1599: return list;
1600: }
1601:
1602: /**
1603: * @see ReferenceType#defaultStratum()
1604: */
1605: public String defaultStratum() {
1606: if (isSourceDebugExtensionAvailable()) {
1607: return fDefaultStratumId;
1608: }
1609: // if not defined, return Java.
1610: return VirtualMachineImpl.JAVA_STRATUM_NAME;
1611: }
1612:
1613: /**
1614: * Generate a source path from the given source name.
1615: * The returned string is the package name of this type converted to a platform dependent path
1616: * followed by the given source name.
1617: * For example, on a Unix platform, the type org.my.TestJsp with the source name test.jsp would
1618: * return "org/my/test.jsp".
1619: */
1620: private String getPath(String sourceName) {
1621: String name = name();
1622: int lastDotOffset = name.lastIndexOf('.');
1623: if (lastDotOffset == -1) {
1624: return sourceName;
1625: }
1626: char fileSeparator = System
1627: .getProperty("file.separator").charAt(0); //$NON-NLS-1$
1628: return name.substring(0, lastDotOffset).replace('.',
1629: fileSeparator)
1630: + fileSeparator + sourceName;
1631: }
1632:
1633: /**
1634: * Return the stratum object for this stratum Id.
1635: * If the the specified stratum id is not defined for this reference type,
1636: * return the stratum object for the default stratum.
1637: * If the specified stratum id (or the default stratum id, if the specified
1638: * stratum id is not defined) is <code>Java</code>, return <code>null</code>.
1639: */
1640: private Stratum getStratum(String stratumId) {
1641: if (!VirtualMachineImpl.JAVA_STRATUM_NAME.equals(stratumId)
1642: && isSourceDebugExtensionAvailable()) {
1643: if (stratumId == null
1644: || !fStrata.keySet().contains(stratumId)) {
1645: stratumId = fDefaultStratumId;
1646: }
1647: if (!VirtualMachineImpl.JAVA_STRATUM_NAME.equals(stratumId)) {
1648: return (Stratum) fStrata.get(stratumId);
1649: }
1650: }
1651: return null;
1652: }
1653:
1654: /**
1655: * Get the source debug extension from the VM.
1656: * @throws AbsentInformationException
1657: */
1658: private void getSourceDebugExtension()
1659: throws AbsentInformationException {
1660: initJdwpRequest();
1661: try {
1662: JdwpReplyPacket replyPacket = requestVM(
1663: JdwpCommandPacket.RT_SOURCE_DEBUG_EXTENSION, this );
1664: if (replyPacket.errorCode() == JdwpReplyPacket.ABSENT_INFORMATION) {
1665: throw new AbsentInformationException(
1666: JDIMessages.ReferenceTypeImpl_31);
1667: }
1668: defaultReplyErrorHandler(replyPacket.errorCode());
1669: DataInputStream replyData = replyPacket.dataInStream();
1670: fSmap = readString(JDIMessages.ReferenceTypeImpl_32,
1671: replyData);
1672: } catch (IOException e) {
1673: defaultIOExceptionHandler(e);
1674: } finally {
1675: handledJdwpRequest();
1676: }
1677: // TODO: remove the workaround when the J9SC20030415 bug is fixed (see bug 96485 of the vendor bug system).
1678: // Workaround to a J9SC bug. It returns an empty string instead of a ABSENT_INFORMATION
1679: // error if the source debug extension is not available.
1680: if ("".equals(fSmap)) { //$NON-NLS-1$
1681: throw new AbsentInformationException(
1682: JDIMessages.ReferenceTypeImpl_31);
1683: }
1684: // parse the source map.
1685: fStrata = new HashMap();
1686: SourceDebugExtensionParser.parse(fSmap, this );
1687: }
1688:
1689: /**
1690: * Get the name of the Java source file from the VM.
1691: * @throws AbsentInformationException
1692: */
1693: private void getSourceName() throws AbsentInformationException {
1694: if (fSourceName != null || isSourceDebugExtensionAvailable()) {
1695: return;
1696: }
1697: initJdwpRequest();
1698: try {
1699: JdwpReplyPacket replyPacket = requestVM(
1700: JdwpCommandPacket.RT_SOURCE_FILE, this );
1701: if (replyPacket.errorCode() == JdwpReplyPacket.ABSENT_INFORMATION) {
1702: throw new AbsentInformationException(
1703: JDIMessages.ReferenceTypeImpl_Source_name_is_not_known_7);
1704: }
1705:
1706: defaultReplyErrorHandler(replyPacket.errorCode());
1707:
1708: DataInputStream replyData = replyPacket.dataInStream();
1709: fSourceName = readString("source name", replyData); //$NON-NLS-1$
1710: } catch (IOException e) {
1711: defaultIOExceptionHandler(e);
1712: } finally {
1713: handledJdwpRequest();
1714: }
1715: }
1716:
1717: /**
1718: * Check in the source debug extension is available.
1719: * To call before doing operations which need data from the SMAP.
1720: * Return <code>false</code> if the source debug extension is not available
1721: * for any reason. <code>true</code> indicates that the source debug extension
1722: * is available and the information has been parsed and stored in the
1723: * maps and lists.
1724: */
1725: private synchronized boolean isSourceDebugExtensionAvailable() {
1726: if (!fSourceDebugExtensionAvailable) {
1727: return false;
1728: }
1729: if (!virtualMachine().canGetSourceDebugExtension()) {
1730: fSourceDebugExtensionAvailable = false;
1731: return false;
1732: }
1733: if (fSmap == null) {
1734: try {
1735: getSourceDebugExtension();
1736: } catch (AbsentInformationException e) {
1737: fSourceDebugExtensionAvailable = false;
1738: return false;
1739: }
1740: }
1741: return true;
1742: }
1743:
1744: /**
1745: * Set the output file name, i.e. the .java file used to generate
1746: * the bytecode.
1747: */
1748: protected void setOutputFileName(String outputFileName) {
1749: fSourceName = outputFileName;
1750: }
1751:
1752: /**
1753: * Set the default stratum. This stratum will be used for the method
1754: * on strata related data, but with no stratum parameter.
1755: */
1756: protected void setDefaultStratumId(String defaultStratumId) {
1757: fDefaultStratumId = defaultStratumId;
1758: }
1759:
1760: /**
1761: * Add a new stratum to this type.
1762: */
1763: protected void addStratum(Stratum stratum) {
1764: fStrata.put(stratum.fId, stratum);
1765: }
1766:
1767: /**
1768: * Return the name of the input source file of which the given code index
1769: * is part of the translation, for this stratum.
1770: * If the code at the given index is not a part of the translation of
1771: * the given stratum code, return the name of the primary input source file.
1772: *
1773: * @param codeIndex the index of the code.
1774: * @param method the method where is the code.
1775: * @param stratumId
1776: */
1777: protected String sourceName(long codeIndex, MethodImpl method,
1778: String stratumId) throws AbsentInformationException {
1779: Stratum stratum = getStratum(stratumId);
1780: if (stratum != null) {
1781: FileInfo fileInfo = fileInfo(codeIndex, method, stratum);
1782: if (fileInfo != null) {
1783: return fileInfo.fFileName;
1784: }
1785: }
1786: // Java stratum
1787: if (fSourceName == null) {
1788: getSourceName();
1789: }
1790: return fSourceName;
1791: }
1792:
1793: /**
1794: * Return the FileInfo object of the input source file of which the given code index
1795: * is part of the translation, for this stratum.
1796: * If the code at the given index is not a part of the translation of
1797: * the given stratum code, return the FileInfo of the primary input source file.
1798: *
1799: * @param codeIndex the index of the code.
1800: * @param method the method where is the code.
1801: * @param stratum
1802: */
1803: private FileInfo fileInfo(long codeIndex, MethodImpl method,
1804: Stratum stratum) {
1805: int fileId = stratum.fPrimaryFileId;
1806: if (stratum.fFileInfos.size() > 1) {
1807: List lineInfos = null;
1808: try {
1809: lineInfos = lineInfos(codeIndex, method, stratum);
1810: } catch (AbsentInformationException e) {
1811: // nothing to do, use the primary file id.
1812: }
1813: if (lineInfos != null) {
1814: fileId = ((int[]) lineInfos.get(0))[0];
1815: }
1816: }
1817: for (Iterator iter = stratum.fFileInfos.iterator(); iter
1818: .hasNext();) {
1819: FileInfo fileInfo = (FileInfo) iter.next();
1820: if (fileInfo.fFileId == fileId) {
1821: return fileInfo;
1822: }
1823: }
1824: // should never return null
1825: return null;
1826: }
1827:
1828: /**
1829: * Return the list of line number in the input files of the stratum associated
1830: * with the code at the given address.
1831: *
1832: * @param codeIndex the index of the code.
1833: * @param method the method where is the code.
1834: * @param stratum
1835: * @return List of int[2]: [fileId, inputLineNumber]
1836: */
1837: private List lineInfos(long codeIndex, MethodImpl method,
1838: Stratum stratum) throws AbsentInformationException {
1839: int outputLineNumber = -1;
1840: try {
1841: outputLineNumber = method.javaStratumLineNumber(codeIndex);
1842: } catch (NativeMethodException e) { // Occurs in SUN VM.
1843: return null;
1844: }
1845: if (outputLineNumber != -1) {
1846: return stratum.getInputLineInfos(outputLineNumber);
1847: }
1848: return null;
1849: }
1850:
1851: /**
1852: * Return the path of the input source file of which the given code index
1853: * is part of the translation, for this stratum.
1854: * If the code at the given index is not a part of the translation of
1855: * the given stratum code, return the path of the primary input source file.
1856: *
1857: * @param codeIndex the index of the code.
1858: * @param method the method where is the code.
1859: * @param stratumId
1860: */
1861: protected String sourcePath(long codeIndex, MethodImpl method,
1862: String stratumId) throws AbsentInformationException {
1863: Stratum stratum = getStratum(stratumId);
1864: if (stratum != null) {
1865: FileInfo fileInfo = fileInfo(codeIndex, method, stratum);
1866: if (fileInfo != null) {
1867: String path = fileInfo.fAbsoluteFileName;
1868: if (path == null) {
1869: return getPath(fileInfo.fFileName);
1870: }
1871: return path;
1872: }
1873: }
1874: // Java stratum
1875: if (fSourceName == null) {
1876: getSourceName();
1877: }
1878: return getPath(fSourceName);
1879: }
1880:
1881: /**
1882: * Return the number of the line of which the given code index
1883: * is part of the translation, for this stratum.
1884: *
1885: * @param codeIndex the index of the code.
1886: * @param method the method where is the code.
1887: * @param stratumId
1888: */
1889: protected int lineNumber(long codeIndex, MethodImpl method,
1890: String stratumId) {
1891: Stratum stratum = getStratum(stratumId);
1892: try {
1893: if (stratum != null) {
1894: List lineInfos = lineInfos(codeIndex, method, stratum);
1895: if (lineInfos != null) {
1896: return ((int[]) lineInfos.get(0))[1];
1897: }
1898: return LocationImpl.LINE_NR_NOT_AVAILABLE;
1899: }
1900: // Java stratum
1901: try {
1902: return method.javaStratumLineNumber(codeIndex);
1903: } catch (NativeMethodException e) { // Occurs in SUN VM.
1904: return LocationImpl.LINE_NR_NOT_AVAILABLE;
1905: }
1906: } catch (AbsentInformationException e) {
1907: return LocationImpl.LINE_NR_NOT_AVAILABLE;
1908: }
1909: }
1910:
1911: /**
1912: * Return the location which are part of the translation of the given line,
1913: * in the given stratum in the source file with the given source name.
1914: * If sourceName is <code>null</code>, return the locations for all source file
1915: * in the given stratum.
1916: * The returned location are in the given method.
1917: *
1918: * @param stratumId the stratum id.
1919: * @param sourceName the name of the source file.
1920: * @param lineNumber the number of the line.
1921: * @param method
1922: * @throws AbsentInformationException if the specified sourceName is not valid.
1923: */
1924: public List locationsOfLine(String stratumId, String sourceName,
1925: int lineNumber, MethodImpl method)
1926: throws AbsentInformationException {
1927: Stratum stratum = getStratum(stratumId);
1928: List javaLines = new ArrayList();
1929: if (stratum != null) {
1930: boolean found = false;
1931: for (Iterator iter = stratum.fFileInfos.iterator(); iter
1932: .hasNext()
1933: && !found;) {
1934: FileInfo fileInfo = (FileInfo) iter.next();
1935: if (sourceName == null
1936: || (found = sourceName
1937: .equals(fileInfo.fFileName))) {
1938: javaLines.addAll(fileInfo
1939: .getOutputLinesForLine(lineNumber));
1940: }
1941: }
1942: if (sourceName != null && !found) {
1943: throw new AbsentInformationException(
1944: JDIMessages.ReferenceTypeImpl_34);
1945: }
1946: } else { // Java stratum
1947: javaLines.add(new Integer(lineNumber));
1948: }
1949: return method.javaStratumLocationsOfLines(javaLines);
1950: }
1951:
1952: /**
1953: * Return the locations of all lines in the given source file of the given stratum which
1954: * are included in the given method.
1955: * If sourceName is <code>null</code>, return the locations for all source file
1956: * in the given stratum.
1957: *
1958: * @param stratumId the stratum id
1959: * @param sourceName the name of the source file
1960: * @param method
1961: * @param codeIndexTable the list of code indexes for the method, as get from the VM/JDWP
1962: * @param javaStratumLineNumberTable the list of line numbers in the java stratum for the method, as get from the VM/JDWP
1963: * @return
1964: */
1965: public List allLineLocations(String stratumId, String sourceName,
1966: MethodImpl method, long[] codeIndexTable,
1967: int[] javaStratumLineNumberTable)
1968: throws AbsentInformationException {
1969: Stratum stratum = getStratum(stratumId);
1970: if (stratum != null) {
1971: int[][] lineInfoTable = new int[codeIndexTable.length][];
1972: if (sourceName == null) {
1973: int lastIndex = 0;
1974: for (int i = 0, length = javaStratumLineNumberTable.length; i < length; i++) {
1975: // for each executable line in the java source, get the associated lines in the stratum source
1976: List lineInfos = stratum
1977: .getInputLineInfos(javaStratumLineNumberTable[i]);
1978: if (lineInfos != null) {
1979: int[] lineInfo = (int[]) lineInfos.get(0);
1980: if (!lineInfo.equals(lineInfoTable[lastIndex])) {
1981: lineInfoTable[i] = lineInfo;
1982: lastIndex = i;
1983: }
1984: }
1985: }
1986: } else { // sourceName != null
1987: FileInfo fileInfo = stratum.getFileInfo(sourceName);
1988: if (fileInfo == null) {
1989: throw new AbsentInformationException(
1990: JDIMessages.ReferenceTypeImpl_34);
1991: }
1992: int fileId = fileInfo.fFileId;
1993: int lastIndex = 0;
1994: for (int i = 0, length = javaStratumLineNumberTable.length; i < length; i++) {
1995: List lineInfos = stratum
1996: .getInputLineInfos(javaStratumLineNumberTable[i]);
1997: if (lineInfos != null) {
1998: for (Iterator iter = lineInfos.iterator(); iter
1999: .hasNext();) {
2000: int[] lineInfo = (int[]) iter.next();
2001: if (lineInfo[0] == fileId) {
2002: if (!lineInfo
2003: .equals(lineInfoTable[lastIndex])) {
2004: lineInfoTable[i] = lineInfo;
2005: lastIndex = i;
2006: }
2007: break;
2008: }
2009: }
2010: }
2011: }
2012: }
2013: List locations = new ArrayList();
2014: for (int i = 0, length = lineInfoTable.length; i < length; i++) {
2015: if (lineInfoTable[i] != null) {
2016: locations.add(new LocationImpl(
2017: virtualMachineImpl(), method,
2018: codeIndexTable[i]));
2019: }
2020: }
2021: return locations;
2022: }
2023: // Java stratum
2024: List result = new ArrayList();
2025: for (int i = 0; i < codeIndexTable.length; i++) {
2026: result.add(new LocationImpl(virtualMachineImpl(), method,
2027: codeIndexTable[i]));
2028: }
2029: return result;
2030: }
2031:
2032: /*
2033: * @since 3.0
2034: * @since java 1.5
2035: */
2036: public String genericSignature() {
2037: if (fGenericSignatureKnown) {
2038: return fGenericSignature;
2039: }
2040: if (virtualMachineImpl().isJdwpVersionGreaterOrEqual(1, 5)) {
2041: initJdwpRequest();
2042: try {
2043: JdwpReplyPacket replyPacket = requestVM(
2044: JdwpCommandPacket.RT_SIGNATURE_WITH_GENERIC,
2045: this );
2046: defaultReplyErrorHandler(replyPacket.errorCode());
2047: DataInputStream replyData = replyPacket.dataInStream();
2048: setSignature(readString("signature", replyData)); //$NON-NLS-1$
2049: fGenericSignature = readString(
2050: "generic signature", replyData); //$NON-NLS-1$
2051: if (fGenericSignature.length() == 0) {
2052: fGenericSignature = null;
2053: }
2054: fGenericSignatureKnown = true;
2055: } catch (IOException e) {
2056: defaultIOExceptionHandler(e);
2057: return null;
2058: } finally {
2059: handledJdwpRequest();
2060: }
2061: } else {
2062: fGenericSignatureKnown = true;
2063: }
2064: return fGenericSignature;
2065: }
2066:
2067: /**
2068: * if genericSignature is <code>null</code>, the generic signature is set to not-known
2069: * (genericSignature() will ask the VM for the generic signature)
2070: * if genericSignature is an empty String, the generic signature is set to no-generic-signature
2071: * (genericSignature() will return null)
2072: * if genericSignature is an non-empty String, the generic signature is set to the specified value
2073: * (genericSignature() will return the specified value)
2074: * @since 3.0
2075: */
2076: public void setGenericSignature(String genericSignature) {
2077: if (genericSignature == null) {
2078: fGenericSignature = null;
2079: fGenericSignatureKnown = false;
2080: } else {
2081: if (genericSignature.length() == 0) {
2082: fGenericSignature = null;
2083: } else {
2084: fGenericSignature = genericSignature;
2085: }
2086: fGenericSignatureKnown = true;
2087: }
2088: }
2089:
2090: /**
2091: * @see com.sun.jdi.ReferenceType#instances(long)
2092: * @since 3.3
2093: */
2094: public List instances(long maxInstances) {
2095: try {
2096: int max = (int) maxInstances;
2097: if (maxInstances >= Integer.MAX_VALUE) {
2098: max = Integer.MAX_VALUE;
2099: }
2100: ByteArrayOutputStream outBytes = new ByteArrayOutputStream();
2101: DataOutputStream outData = new DataOutputStream(outBytes);
2102: write(this , outData);
2103: writeInt(max, "max instances", outData); //$NON-NLS-1$
2104:
2105: JdwpReplyPacket replyPacket = requestVM(
2106: JdwpCommandPacket.RT_INSTANCES, outBytes);
2107: switch (replyPacket.errorCode()) {
2108: case JdwpReplyPacket.INVALID_OBJECT:
2109: case JdwpReplyPacket.INVALID_CLASS:
2110: throw new ObjectCollectedException(
2111: JDIMessages.class_or_object_not_known);
2112: case JdwpReplyPacket.NOT_IMPLEMENTED:
2113: throw new UnsupportedOperationException(
2114: JDIMessages.ReferenceTypeImpl_27);
2115: case JdwpReplyPacket.ILLEGAL_ARGUMENT:
2116: throw new IllegalArgumentException(
2117: JDIMessages.ReferenceTypeImpl_26);
2118: case JdwpReplyPacket.VM_DEAD:
2119: throw new VMDisconnectedException(JDIMessages.vm_dead);
2120: }
2121: defaultReplyErrorHandler(replyPacket.errorCode());
2122:
2123: DataInputStream replyData = replyPacket.dataInStream();
2124: int elements = readInt("element count", replyData); //$NON-NLS-1$
2125: if (max > 0 && elements > max) {
2126: elements = max;
2127: }
2128: ArrayList list = new ArrayList();
2129: for (int i = 0; i < elements; i++) {
2130: list.add(ValueImpl.readWithTag(this , replyData));
2131: }
2132: return list;
2133: } catch (IOException e) {
2134: defaultIOExceptionHandler(e);
2135: return null;
2136: } finally {
2137: handledJdwpRequest();
2138: }
2139: }
2140:
2141: /**
2142: * @see com.sun.jdi.ReferenceType#majorVersion()
2143: * @since 3.3
2144: */
2145: public int majorVersion() {
2146: try {
2147: ByteArrayOutputStream outBytes = new ByteArrayOutputStream();
2148: DataOutputStream outData = new DataOutputStream(outBytes);
2149: getRefTypeID().write(outData);
2150:
2151: JdwpReplyPacket replyPacket = requestVM(
2152: JdwpCommandPacket.RT_CLASS_VERSION, outBytes);
2153: switch (replyPacket.errorCode()) {
2154: case JdwpReplyPacket.INVALID_CLASS:
2155: case JdwpReplyPacket.INVALID_OBJECT:
2156: throw new ObjectCollectedException(
2157: JDIMessages.class_or_object_not_known);
2158: case JdwpReplyPacket.ABSENT_INFORMATION:
2159: return 0;
2160: case JdwpReplyPacket.NOT_IMPLEMENTED:
2161: throw new UnsupportedOperationException(
2162: JDIMessages.ReferenceTypeImpl_no_class_version_support24);
2163: case JdwpReplyPacket.VM_DEAD:
2164: throw new VMDisconnectedException(JDIMessages.vm_dead);
2165: }
2166: defaultReplyErrorHandler(replyPacket.errorCode());
2167:
2168: DataInputStream replyData = replyPacket.dataInStream();
2169: return readInt("major version", replyData); //$NON-NLS-1$
2170: } catch (IOException e) {
2171: defaultIOExceptionHandler(e);
2172: return 0;
2173: } finally {
2174: handledJdwpRequest();
2175: }
2176: }
2177:
2178: /**
2179: * @see com.sun.jdi.ReferenceType#minorVersion()
2180: * @since 3.3
2181: */
2182: public int minorVersion() {
2183: try {
2184: ByteArrayOutputStream outBytes = new ByteArrayOutputStream();
2185: DataOutputStream outData = new DataOutputStream(outBytes);
2186: getRefTypeID().write(outData);
2187:
2188: JdwpReplyPacket replyPacket = requestVM(
2189: JdwpCommandPacket.RT_CLASS_VERSION, outBytes);
2190: switch (replyPacket.errorCode()) {
2191: case JdwpReplyPacket.INVALID_CLASS:
2192: case JdwpReplyPacket.INVALID_OBJECT:
2193: throw new ObjectCollectedException(
2194: JDIMessages.class_or_object_not_known);
2195: case JdwpReplyPacket.ABSENT_INFORMATION:
2196: return 0;
2197: case JdwpReplyPacket.NOT_IMPLEMENTED:
2198: throw new UnsupportedOperationException(
2199: JDIMessages.ReferenceTypeImpl_no_class_version_support24);
2200: case JdwpReplyPacket.VM_DEAD:
2201: throw new VMDisconnectedException(JDIMessages.vm_dead);
2202: }
2203: defaultReplyErrorHandler(replyPacket.errorCode());
2204:
2205: DataInputStream replyData = replyPacket.dataInStream();
2206: readInt("major version", replyData); //$NON-NLS-1$
2207: return readInt("minor version", replyData); //$NON-NLS-1$
2208: } catch (IOException e) {
2209: defaultIOExceptionHandler(e);
2210: return 0;
2211: } finally {
2212: handledJdwpRequest();
2213: }
2214: }
2215:
2216: /**
2217: * @see com.sun.jdi.ReferenceType#constantPoolCount()
2218: * @since 3.3
2219: */
2220: public int constantPoolCount() {
2221: try {
2222: ByteArrayOutputStream outBytes = new ByteArrayOutputStream();
2223: DataOutputStream outData = new DataOutputStream(outBytes);
2224: this .getRefTypeID().write(outData);
2225:
2226: JdwpReplyPacket replyPacket = requestVM(
2227: JdwpCommandPacket.RT_CONSTANT_POOL, outBytes);
2228: switch (replyPacket.errorCode()) {
2229: case JdwpReplyPacket.INVALID_CLASS:
2230: case JdwpReplyPacket.INVALID_OBJECT:
2231: throw new ObjectCollectedException(
2232: JDIMessages.class_or_object_not_known);
2233: case JdwpReplyPacket.ABSENT_INFORMATION:
2234: return 0;
2235: case JdwpReplyPacket.NOT_IMPLEMENTED:
2236: throw new UnsupportedOperationException(
2237: JDIMessages.ReferenceTypeImpl_no_constant_pool_support);
2238: case JdwpReplyPacket.VM_DEAD:
2239: throw new VMDisconnectedException(JDIMessages.vm_dead);
2240: }
2241: defaultReplyErrorHandler(replyPacket.errorCode());
2242:
2243: DataInputStream replyData = replyPacket.dataInStream();
2244: return readInt("pool count", replyData); //$NON-NLS-1$
2245: } catch (IOException e) {
2246: defaultIOExceptionHandler(e);
2247: return 0;
2248: } finally {
2249: handledJdwpRequest();
2250: }
2251: }
2252:
2253: /**
2254: * @see com.sun.jdi.ReferenceType#constantPool()
2255: * @since 3.3
2256: */
2257: public byte[] constantPool() {
2258: try {
2259: ByteArrayOutputStream outBytes = new ByteArrayOutputStream();
2260: DataOutputStream outData = new DataOutputStream(outBytes);
2261: this .getRefTypeID().write(outData);
2262:
2263: JdwpReplyPacket replyPacket = requestVM(
2264: JdwpCommandPacket.RT_CONSTANT_POOL, outBytes);
2265: switch (replyPacket.errorCode()) {
2266: case JdwpReplyPacket.INVALID_CLASS:
2267: case JdwpReplyPacket.INVALID_OBJECT:
2268: throw new ObjectCollectedException(
2269: JDIMessages.class_or_object_not_known);
2270: case JdwpReplyPacket.ABSENT_INFORMATION:
2271: return new byte[0];
2272: case JdwpReplyPacket.NOT_IMPLEMENTED:
2273: throw new UnsupportedOperationException(
2274: JDIMessages.ReferenceTypeImpl_no_constant_pool_support);
2275: case JdwpReplyPacket.VM_DEAD:
2276: throw new VMDisconnectedException(JDIMessages.vm_dead);
2277: }
2278: defaultReplyErrorHandler(replyPacket.errorCode());
2279:
2280: DataInputStream replyData = replyPacket.dataInStream();
2281: readInt("pool count", replyData); //$NON-NLS-1$
2282: int bytes = readInt("byte count", replyData); //$NON-NLS-1$
2283: byte[] array = new byte[bytes];
2284: for (int i = 0; i < bytes; i++) {
2285: array[i] = readByte("byte read", replyData); //$NON-NLS-1$
2286: }
2287: return array;
2288: } catch (IOException e) {
2289: defaultIOExceptionHandler(e);
2290: return null;
2291: } finally {
2292: handledJdwpRequest();
2293: }
2294: }
2295: }
|