| /******************************************************************************* |
| * Copyright (c) 2000, 2007 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| * Yavor Boyadzhiev <yavor.vasilev.boyadzhiev@sap.com> - Bug 162399 |
| *******************************************************************************/ |
| package org.eclipse.jdi.internal; |
| |
| |
| import java.io.ByteArrayOutputStream; |
| import java.io.DataInputStream; |
| import java.io.DataOutputStream; |
| import java.io.IOException; |
| import java.lang.reflect.Modifier; |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.Hashtable; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| |
| import org.eclipse.jdi.internal.jdwp.JdwpCommandPacket; |
| import org.eclipse.jdi.internal.jdwp.JdwpFieldID; |
| import org.eclipse.jdi.internal.jdwp.JdwpID; |
| import org.eclipse.jdi.internal.jdwp.JdwpMethodID; |
| import org.eclipse.jdi.internal.jdwp.JdwpReferenceTypeID; |
| import org.eclipse.jdi.internal.jdwp.JdwpReplyPacket; |
| |
| import com.ibm.icu.text.MessageFormat; |
| import com.sun.jdi.AbsentInformationException; |
| import com.sun.jdi.ClassLoaderReference; |
| import com.sun.jdi.ClassNotLoadedException; |
| import com.sun.jdi.ClassNotPreparedException; |
| import com.sun.jdi.ClassObjectReference; |
| import com.sun.jdi.ClassType; |
| import com.sun.jdi.Field; |
| import com.sun.jdi.InternalException; |
| import com.sun.jdi.NativeMethodException; |
| import com.sun.jdi.ObjectCollectedException; |
| import com.sun.jdi.ReferenceType; |
| import com.sun.jdi.VMDisconnectedException; |
| import com.sun.jdi.Value; |
| |
| /** |
| * this class implements the corresponding interfaces |
| * declared by the JDI specification. See the com.sun.jdi package |
| * for more information. |
| * |
| */ |
| public abstract class ReferenceTypeImpl extends TypeImpl implements ReferenceType, org.eclipse.jdi.hcr.ReferenceType { |
| |
| /** ClassStatus Constants. */ |
| public static final int JDWP_CLASS_STATUS_VERIFIED = 1; |
| public static final int JDWP_CLASS_STATUS_PREPARED = 2; |
| public static final int JDWP_CLASS_STATUS_INITIALIZED = 4; |
| public static final int JDWP_CLASS_STATUS_ERROR = 8; |
| |
| /** Mapping of command codes to strings. */ |
| private static String[] fgClassStatusStrings = null; |
| |
| /** |
| * Represent the data about one file info contained in one stratum in the SMAP. |
| */ |
| protected static class FileInfo { |
| |
| /** |
| * The id. |
| */ |
| protected int fFileId; |
| |
| /** |
| * The name of the source file. |
| */ |
| protected String fFileName; |
| |
| /** |
| * The path of the source file. |
| */ |
| protected String fAbsoluteFileName; |
| |
| /** |
| * Map line number in the input source file |
| * -> list of [start line in the output source file, range in the output source file]. |
| * (Integer -> List of int[2]). |
| */ |
| private HashMap fLineInfo; |
| |
| /** |
| * FileInfo constructor. |
| * |
| * @param fileId the id. |
| * @param fileName the name of the source file. |
| * @param absoluteFileName the path of the source file (can be <code>null</code>). |
| */ |
| public FileInfo(int fileId, String fileName, String absoluteFileName) { |
| fFileId= fileId; |
| fFileName= fileName; |
| fAbsoluteFileName= absoluteFileName; |
| fLineInfo= new HashMap(); |
| } |
| |
| /** |
| * Add information about the mapping of one line. |
| * Associate a line in the input source file to a snippet of code |
| * in the output source file. |
| * |
| * @param inputLine the line number in the input source file. |
| * @param outputStartLine the number of the first line of the corresponding snippet in the output source file. |
| * @param outputLineRange the size of the corresponding snippet in the output source file. |
| */ |
| public void addLineInfo(int inputLine, int outputStartLine, int outputLineRange) { |
| Integer key= new Integer(inputLine); |
| List outputLines= (List)fLineInfo.get(key); |
| if (outputLines == null) { |
| outputLines= new ArrayList(); |
| fLineInfo.put(key, outputLines); |
| } |
| outputLines.add(new int[] {outputStartLine, outputLineRange}); |
| } |
| |
| /** |
| * Return a list of line information about the code in the output source file |
| * associated to the given line in the input source file. |
| * |
| * @param lineNumber the line number in the input source file. |
| * @return a List of int[2]. |
| */ |
| public List getOutputLinesForLine(int lineNumber) { |
| List list= new ArrayList(); |
| List outputLines= (List)fLineInfo.get(new Integer(lineNumber)); |
| if (outputLines != null) { |
| for (Iterator iter = outputLines.iterator(); iter.hasNext();) { |
| int[] info = (int[])iter.next(); |
| int outputLineNumber= info[0]; |
| int length = info[1]; |
| if (length == 0){ |
| length = length + 1; |
| } |
| for (int i= 0; i < length; i++) { |
| list.add(new Integer(outputLineNumber++)); |
| } |
| } |
| } |
| return list; |
| } |
| |
| /** |
| * @see java.lang.Object#equals(java.lang.Object) |
| */ |
| public boolean equals(Object object) { |
| if (!(object instanceof FileInfo)) { |
| return false; |
| } |
| return fFileId == ((FileInfo)object).fFileId; |
| } |
| |
| } |
| |
| /** |
| * Represent the information contained in the SMAP about one stratum. |
| */ |
| protected static class Stratum { |
| |
| /** |
| * The id of this stratum. |
| */ |
| private String fId; |
| |
| /** |
| * The file info data associated to this stratum. |
| */ |
| private List fFileInfos; |
| |
| /** |
| * Id of the primary file for this stratum. |
| */ |
| private int fPrimaryFileId; |
| |
| /** |
| * Map line number in the output source file -> list of line numbers in the input source file. |
| * (Integer -> List of Integer) |
| */ |
| private HashMap fOutputLineToInputLine; |
| |
| /** |
| * Stratum constructor. |
| * @param id The id of this stratum. |
| */ |
| public Stratum(String id) { |
| fId= id; |
| fFileInfos= new ArrayList(); |
| fOutputLineToInputLine= new HashMap(); |
| fPrimaryFileId= -1; |
| } |
| |
| /** |
| * Add a file info to this stratum. |
| * |
| * @param fileId the id. |
| * @param fileName the name of the source file. |
| */ |
| public void addFileInfo(int fileId, String fileName) throws AbsentInformationException { |
| addFileInfo(fileId, fileName, null); |
| } |
| |
| /** |
| * Add a file info to this stratum. |
| * |
| * @param fileId the id. |
| * @param fileName the name of the source file. |
| * @param absoluteFileName the path of the source file. |
| */ |
| public void addFileInfo(int fileId, String fileName, String absoluteFileName) throws AbsentInformationException { |
| if (fPrimaryFileId == -1) { |
| fPrimaryFileId= fileId; |
| } |
| FileInfo fileInfo= new FileInfo(fileId, fileName, absoluteFileName); |
| if (fFileInfos.contains(fileInfo)) { |
| throw new AbsentInformationException(MessageFormat.format(JDIMessages.ReferenceTypeImpl_28, new String[] {Integer.toString(fileId), fId})); |
| } |
| fFileInfos.add(fileInfo); |
| } |
| |
| /** |
| * Add line mapping information. |
| * |
| * @param inputStartLine number of the first line in the input source file. |
| * @param lineFileId id of the input source file. |
| * @param repeatCount number of iterations. |
| * @param outputStartLine number of the first line in the output source file. |
| * @param outputLineIncrement number of line to increment at each iteration. |
| * @throws AbsentInformationException |
| */ |
| public void addLineInfo(int inputStartLine, int lineFileId, int repeatCount, int outputStartLine, int outputLineIncrement) throws AbsentInformationException { |
| FileInfo fileInfo= null; |
| // get the FileInfo object |
| for (Iterator iter = fFileInfos.iterator(); iter.hasNext();) { |
| FileInfo element = (FileInfo)iter.next(); |
| if (element.fFileId == lineFileId) { |
| fileInfo= element; |
| } |
| } |
| if (fileInfo == null) { |
| throw new AbsentInformationException(MessageFormat.format(JDIMessages.ReferenceTypeImpl_29, new String[] {Integer.toString(lineFileId)})); |
| } |
| // add the data to the different hash maps. |
| for (int i= 0; i < repeatCount; i++, inputStartLine++) { |
| fileInfo.addLineInfo(inputStartLine, outputStartLine, outputLineIncrement); |
| if (outputLineIncrement == 0) { |
| // see bug 40022 |
| addLineInfoToMap(inputStartLine, lineFileId, outputStartLine); |
| } else { |
| for (int j= 0; j < outputLineIncrement; j++, outputStartLine++) { |
| addLineInfoToMap(inputStartLine, lineFileId, outputStartLine); |
| } |
| } |
| } |
| } |
| |
| /** |
| * Add the data to the map. |
| */ |
| private void addLineInfoToMap(int inputStartLine, int lineFileId, int outputStartLine) { |
| Integer key= new Integer(outputStartLine); |
| List inputLines= (List)fOutputLineToInputLine.get(key); |
| if (inputLines == null) { |
| inputLines= new ArrayList(); |
| fOutputLineToInputLine.put(key, inputLines); |
| } |
| inputLines.add(new int[] {lineFileId, inputStartLine}); |
| } |
| |
| /** |
| * Return the FileInfo object for the specified source name. |
| * Return <code>null</code> if the specified name is the source name of no file info. |
| * @param sourceName the source name to search. |
| */ |
| public FileInfo getFileInfo(String sourceName) { |
| for (Iterator iter = fFileInfos.iterator(); iter.hasNext();) { |
| FileInfo fileInfo = (FileInfo)iter.next(); |
| if (fileInfo.fFileName.equals(sourceName)) { |
| return fileInfo; |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * @param outputLineNumber |
| * @return |
| */ |
| public List getInputLineInfos(int outputLineNumber) { |
| return (List)fOutputLineToInputLine.get(new Integer(outputLineNumber)); |
| } |
| |
| } |
| |
| |
| |
| /** ReferenceTypeID that corresponds to this reference. */ |
| private JdwpReferenceTypeID fReferenceTypeID; |
| |
| /** The following are the stored results of JDWP calls. */ |
| protected List fInterfaces = null; |
| private List fMethods = null; |
| private Hashtable fMethodTable= null; |
| private List fFields = null; |
| private List fAllMethods = null; |
| private List fVisibleMethods = null; |
| private List fAllFields = null; |
| private List fVisibleFields = null; |
| private List fAllInterfaces = null; |
| private Map fStratumAllLineLocations = null; |
| private String fSourceName = null; |
| private int fModifierBits = -1; |
| private ClassLoaderReferenceImpl fClassLoader = null; |
| private ClassObjectReferenceImpl fClassObject = null; |
| |
| private String fGenericSignature; // 1.5 addition |
| private boolean fGenericSignatureKnown; // 1.5 addition |
| |
| private boolean fGotClassFileVersion = false; // HCR addition. |
| private int fClassFileVersion; // HCR addition. |
| private boolean fIsHCREligible; // HCR addition. |
| private boolean fIsVersionKnown; // HCR addition. |
| |
| private boolean fSourceDebugExtensionAvailable= true; // JSR-045 addition |
| |
| /** |
| * The default stratum id. |
| */ |
| private String fDefaultStratumId; // JSR-045 addition |
| |
| /** |
| * A map of the defined strata. |
| * Map stratum id -> Stratum object. |
| * (String -> Stratum). |
| */ |
| private Map fStrata; // JSR-045 addition |
| |
| /** |
| * The source map string returned by the VM. |
| */ |
| private String fSmap; // JSR-045 addition |
| |
| /** |
| * Creates new instance. |
| */ |
| protected ReferenceTypeImpl(String description, VirtualMachineImpl vmImpl, JdwpReferenceTypeID referenceTypeID) { |
| super(description, vmImpl); |
| fReferenceTypeID = referenceTypeID; |
| } |
| |
| /** |
| * Creates new instance. |
| */ |
| protected ReferenceTypeImpl(String description, VirtualMachineImpl vmImpl, JdwpReferenceTypeID referenceTypeID, String signature, String genericSignature) { |
| super(description, vmImpl); |
| fReferenceTypeID = referenceTypeID; |
| setSignature(signature); |
| setGenericSignature(genericSignature); |
| } |
| |
| /** |
| * @return Returns type tag. |
| */ |
| public abstract byte typeTag(); |
| |
| /** |
| * Flushes all stored Jdwp results. |
| */ |
| public void flushStoredJdwpResults() { |
| Iterator iter; |
| |
| // Flush Methods. |
| if (fMethods != null) { |
| iter = fMethods.iterator(); |
| while (iter.hasNext()) { |
| MethodImpl method = (MethodImpl)iter.next(); |
| method.flushStoredJdwpResults(); |
| } |
| fMethods = null; |
| fMethodTable= null; |
| } |
| |
| // Flush Fields. |
| if (fFields != null) { |
| iter = fFields.iterator(); |
| while (iter.hasNext()) { |
| FieldImpl field = (FieldImpl)iter.next(); |
| field.flushStoredJdwpResults(); |
| } |
| fFields = null; |
| } |
| |
| fInterfaces = null; |
| fAllMethods = null; |
| fVisibleMethods = null; |
| fAllFields = null; |
| fVisibleFields = null; |
| fAllInterfaces = null; |
| fStratumAllLineLocations = null; |
| fSourceName = null; |
| fModifierBits = -1; |
| fClassLoader = null; |
| fClassObject = null; |
| fGotClassFileVersion = false; |
| // java 1.5 |
| fGenericSignature= null; |
| fGenericSignatureKnown= false; |
| |
| // JSR-045 |
| fSourceDebugExtensionAvailable= true; |
| fDefaultStratumId= null; |
| fStrata= null; |
| fSmap= null; |
| |
| // The following cached results are stored higher up in the class hierarchy. |
| fSignature = null; |
| fSourceName = null; |
| } |
| |
| /** |
| * @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. |
| */ |
| public List allInterfaces() { |
| if (fAllInterfaces != null) { |
| return fAllInterfaces; |
| } |
| |
| /* Recursion: |
| * The interfaces that it directly implements; |
| * All interfaces that are implemented by its interfaces; |
| * If it is a class, all interfaces that are implemented by its superclass. |
| */ |
| // The interfaces are maintained in a set, to avoid duplicates. |
| // The interfaces of its own (own interfaces() command) are first inserted. |
| HashSet allInterfacesSet = new HashSet(interfaces()); |
| |
| // All interfaces of the interfaces it implements. |
| Iterator interfaces = interfaces().iterator(); |
| InterfaceTypeImpl inter; |
| while (interfaces.hasNext()) { |
| inter = (InterfaceTypeImpl)interfaces.next(); |
| allInterfacesSet.addAll(inter.allInterfaces()); |
| } |
| |
| // If it is a class, all interfaces of it's superclass. |
| if (this instanceof ClassType) { |
| ClassType superclass = ((ClassType)this).superclass(); |
| if (superclass != null) { |
| allInterfacesSet.addAll(superclass.allInterfaces()); |
| } |
| } |
| |
| fAllInterfaces = new ArrayList(allInterfacesSet); |
| return fAllInterfaces; |
| } |
| |
| /** |
| * @return Returns Jdwp Reference ID. |
| */ |
| public JdwpReferenceTypeID getRefTypeID() { |
| return fReferenceTypeID; |
| } |
| |
| /** |
| * @return Returns modifier bits. |
| */ |
| public int modifiers() { |
| if (fModifierBits != -1) |
| return fModifierBits; |
| |
| initJdwpRequest(); |
| try { |
| JdwpReplyPacket replyPacket = requestVM(JdwpCommandPacket.RT_MODIFIERS, this); |
| defaultReplyErrorHandler(replyPacket.errorCode()); |
| DataInputStream replyData = replyPacket.dataInStream(); |
| fModifierBits = readInt("modifiers", AccessibleImpl.getModifierStrings(), replyData); //$NON-NLS-1$ |
| return fModifierBits; |
| } catch (IOException e) { |
| defaultIOExceptionHandler(e); |
| return 0; |
| } finally { |
| handledJdwpRequest(); |
| } |
| } |
| |
| /** |
| * Add methods to a set of methods if they are not overridden, add new names+signature combinations to set of names+signature combinations. |
| */ |
| private void addVisibleMethods(List inheritedMethods, Set nameAndSignatures, List resultMethods) { |
| Iterator iter = inheritedMethods.iterator(); |
| MethodImpl inheritedMethod; |
| while (iter.hasNext()) { |
| inheritedMethod = (MethodImpl)iter.next(); |
| if (!nameAndSignatures.contains(inheritedMethod.name() + inheritedMethod.signature())) { |
| resultMethods.add(inheritedMethod); |
| } |
| } |
| } |
| |
| /** |
| * @return Returns a list containing each visible and unambiguous Method in this type. |
| */ |
| public List visibleMethods() { |
| if (fVisibleMethods != null) |
| return fVisibleMethods; |
| |
| /* Recursion: |
| * The methods of its own (own methods() command); |
| * All methods of the interfaces it implements; |
| * If it is a class, all methods of it's superclass. |
| */ |
| // The name+signature combinations of methods are maintained in a set, to avoid including methods that have been overridden. |
| Set namesAndSignatures = new HashSet(); |
| List visibleMethods= new ArrayList(); |
| |
| // The methods of its own (own methods() command). |
| for (Iterator iter= methods().iterator(); iter.hasNext();) { |
| MethodImpl method= (MethodImpl) iter.next(); |
| namesAndSignatures.add(method.name() + method.signature()); |
| visibleMethods.add(method); |
| } |
| |
| // All methods of the interfaces it implements. |
| Iterator interfaces = interfaces().iterator(); |
| InterfaceTypeImpl inter; |
| while (interfaces.hasNext()) { |
| inter = (InterfaceTypeImpl)interfaces.next(); |
| addVisibleMethods(inter.visibleMethods(), namesAndSignatures, visibleMethods); |
| } |
| |
| // If it is a class, all methods of it's superclass. |
| if (this instanceof ClassType) { |
| ClassType superclass = ((ClassType)this).superclass(); |
| if (superclass != null) |
| addVisibleMethods(superclass.visibleMethods(), namesAndSignatures, visibleMethods); |
| } |
| |
| fVisibleMethods= visibleMethods; |
| return fVisibleMethods; |
| } |
| |
| /** |
| * @return Returns a list containing each Method declared in this type, and its super-classes, implemented interfaces, and/or super-interfaces. |
| */ |
| public List allMethods() { |
| if (fAllMethods != null) |
| return fAllMethods; |
| |
| /* Recursion: |
| * The methods of its own (own methods() command); |
| * All methods of the interfaces it implements; |
| * If it is a class, all methods of it's superclass. |
| */ |
| // The name+signature combinations of methods are maintained in a set. |
| HashSet resultSet = new HashSet(); |
| |
| // The methods of its own (own methods() command). |
| resultSet.addAll(methods()); |
| |
| // All methods of the interfaces it implements. |
| Iterator interfaces = interfaces().iterator(); |
| InterfaceTypeImpl inter; |
| while (interfaces.hasNext()) { |
| inter = (InterfaceTypeImpl)interfaces.next(); |
| resultSet.addAll(inter.allMethods()); |
| } |
| |
| // If it is a class, all methods of it's superclass. |
| if (this instanceof ClassType) { |
| ClassType superclass = ((ClassType)this).superclass(); |
| if (superclass != null) |
| resultSet.addAll(superclass.allMethods()); |
| } |
| |
| fAllMethods = new ArrayList(resultSet); |
| return fAllMethods; |
| } |
| |
| /** |
| * @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. |
| */ |
| public List interfaces() { |
| if (fInterfaces != null) { |
| return fInterfaces; |
| } |
| |
| initJdwpRequest(); |
| try { |
| JdwpReplyPacket replyPacket = requestVM(JdwpCommandPacket.RT_INTERFACES, this); |
| switch (replyPacket.errorCode()) { |
| case JdwpReplyPacket.NOT_FOUND: |
| // Workaround for problem in J2ME WTK (wireless toolkit) |
| // @see Bug 12966 |
| return Collections.EMPTY_LIST; |
| default: |
| defaultReplyErrorHandler(replyPacket.errorCode()); |
| } |
| DataInputStream replyData = replyPacket.dataInStream(); |
| List elements = new ArrayList(); |
| int nrOfElements = readInt("elements", replyData); //$NON-NLS-1$ |
| for (int i = 0; i < nrOfElements; i++) { |
| InterfaceTypeImpl ref = InterfaceTypeImpl.read(this, replyData); |
| if (ref == null) { |
| continue; |
| } |
| elements.add(ref); |
| } |
| fInterfaces = elements; |
| return elements; |
| } catch (IOException e) { |
| defaultIOExceptionHandler(e); |
| return null; |
| } finally { |
| handledJdwpRequest(); |
| } |
| } |
| |
| /** |
| * Add fields to a set of fields if they are not overridden, add new field names to set of field names. |
| */ |
| private void addVisibleFields(List newFields, Set names, List resultFields) { |
| Iterator iter = newFields.iterator(); |
| FieldImpl field; |
| while (iter.hasNext()) { |
| field = (FieldImpl)iter.next(); |
| String name = field.name(); |
| if (!names.contains(name)) { |
| resultFields.add(field); |
| names.add(name); |
| } |
| } |
| } |
| |
| /** |
| * @return Returns a list containing each visible and unambiguous Field in this type. |
| */ |
| public List visibleFields() { |
| if (fVisibleFields != null) |
| return fVisibleFields; |
| |
| /* Recursion: |
| * The fields of its own (own fields() command); |
| * All fields of the interfaces it implements; |
| * If it is a class, all fields of it's superclass. |
| */ |
| // The names of fields are maintained in a set, to avoid including fields that have been overridden. |
| HashSet fieldNames = new HashSet(); |
| |
| // The fields of its own (own fields() command). |
| List visibleFields = new ArrayList(); |
| addVisibleFields(fields(), fieldNames, visibleFields); |
| |
| // All fields of the interfaces it implements. |
| Iterator interfaces = interfaces().iterator(); |
| InterfaceTypeImpl inter; |
| while (interfaces.hasNext()) { |
| inter = (InterfaceTypeImpl)interfaces.next(); |
| addVisibleFields(inter.visibleFields(), fieldNames, visibleFields); |
| } |
| |
| // If it is a class, all fields of it's superclass. |
| if (this instanceof ClassType) { |
| ClassType superclass = ((ClassType)this).superclass(); |
| if (superclass != null) |
| addVisibleFields(superclass.visibleFields(), fieldNames, visibleFields); |
| } |
| |
| fVisibleFields = visibleFields; |
| return fVisibleFields; |
| } |
| |
| /** |
| * @return Returns a list containing each Field declared in this type, and its super-classes, implemented interfaces, and/or super-interfaces. |
| */ |
| public List allFields() { |
| if (fAllFields != null) |
| return fAllFields; |
| |
| /* Recursion: |
| * The fields of its own (own fields() command); |
| * All fields of the interfaces it implements; |
| * If it is a class, all fields of it's superclass. |
| */ |
| // The names of fields are maintained in a set, to avoid including fields that have been inherited double. |
| HashSet resultSet = new HashSet(); |
| |
| // The fields of its own (own fields() command). |
| resultSet.addAll(fields()); |
| |
| // All fields of the interfaces it implements. |
| Iterator interfaces = interfaces().iterator(); |
| InterfaceTypeImpl inter; |
| while (interfaces.hasNext()) { |
| inter = (InterfaceTypeImpl)interfaces.next(); |
| resultSet.addAll(inter.allFields()); |
| } |
| |
| // If it is a class, all fields of it's superclass. |
| if (this instanceof ClassType) { |
| ClassType superclass = ((ClassType)this).superclass(); |
| if (superclass != null) |
| resultSet.addAll(superclass.allFields()); |
| } |
| |
| fAllFields = new ArrayList(resultSet); |
| return fAllFields; |
| } |
| |
| /** |
| * @return Returns the class loader object which loaded the class corresponding to this type. |
| */ |
| public ClassLoaderReference classLoader() { |
| if (fClassLoader != null) |
| return fClassLoader; |
| |
| initJdwpRequest(); |
| try { |
| JdwpReplyPacket replyPacket = requestVM(JdwpCommandPacket.RT_CLASS_LOADER, this); |
| defaultReplyErrorHandler(replyPacket.errorCode()); |
| DataInputStream replyData = replyPacket.dataInStream(); |
| fClassLoader = ClassLoaderReferenceImpl.read(this, replyData); |
| return fClassLoader; |
| } catch (IOException e) { |
| defaultIOExceptionHandler(e); |
| return null; |
| } finally { |
| handledJdwpRequest(); |
| } |
| } |
| |
| /** |
| * @return Returns the class object that corresponds to this type in the target VM. |
| */ |
| public ClassObjectReference classObject() { |
| if (fClassObject != null) |
| return fClassObject; |
| |
| initJdwpRequest(); |
| try { |
| JdwpReplyPacket replyPacket = requestVM(JdwpCommandPacket.RT_CLASS_OBJECT, this); |
| defaultReplyErrorHandler(replyPacket.errorCode()); |
| DataInputStream replyData = replyPacket.dataInStream(); |
| fClassObject = ClassObjectReferenceImpl.read(this, replyData); |
| return fClassObject; |
| } catch (IOException e) { |
| defaultIOExceptionHandler(e); |
| return null; |
| } finally { |
| handledJdwpRequest(); |
| } |
| } |
| |
| /** |
| * @return Returns status of class/interface. |
| */ |
| protected int status() { |
| // Note that this information should not be cached. |
| initJdwpRequest(); |
| try { |
| JdwpReplyPacket replyPacket = requestVM(JdwpCommandPacket.RT_STATUS, this); |
| defaultReplyErrorHandler(replyPacket.errorCode()); |
| DataInputStream replyData = replyPacket.dataInStream(); |
| int status = readInt("status", classStatusStrings(), replyData); //$NON-NLS-1$ |
| return status; |
| } catch (IOException e) { |
| defaultIOExceptionHandler(e); |
| return 0; |
| } finally { |
| handledJdwpRequest(); |
| } |
| } |
| |
| /** |
| * @return Returns true if initialization failed for this class. |
| */ |
| public boolean failedToInitialize() { |
| return (status() & JDWP_CLASS_STATUS_ERROR) != 0; |
| } |
| |
| /** |
| * @return Returns true if this type has been initialized. |
| */ |
| public boolean isInitialized() { |
| return (status() & JDWP_CLASS_STATUS_INITIALIZED) != 0; |
| } |
| |
| /** |
| * @return Returns true if this type has been prepared. |
| */ |
| public boolean isPrepared() { |
| return (status() & JDWP_CLASS_STATUS_PREPARED) != 0; |
| } |
| |
| /** |
| * @return Returns true if this type has been verified. |
| */ |
| public boolean isVerified() { |
| return (status() & JDWP_CLASS_STATUS_VERIFIED) != 0; |
| } |
| |
| /** |
| * @return Returns the visible Field with the given non-ambiguous name. |
| */ |
| public Field fieldByName(String name) { |
| Iterator iter = visibleFields().iterator(); |
| while (iter.hasNext()) { |
| FieldImpl field = (FieldImpl)iter.next(); |
| if (field.name().equals(name)) |
| return field; |
| } |
| return null; |
| } |
| |
| /** |
| * @return Returns a list containing each Field declared in this type. |
| */ |
| public List fields() { |
| if (fFields != null) { |
| return fFields; |
| } |
| |
| // Note: Fields are returned in the order they occur in the class file, therefore their |
| // order in this list can be used for comparisons. |
| initJdwpRequest(); |
| try { |
| boolean withGenericSignature= virtualMachineImpl().isJdwpVersionGreaterOrEqual(1, 5); |
| int jdwpCommand= withGenericSignature ? JdwpCommandPacket.RT_FIELDS_WITH_GENERIC : JdwpCommandPacket.RT_FIELDS; |
| JdwpReplyPacket replyPacket = requestVM(jdwpCommand, this); |
| defaultReplyErrorHandler(replyPacket.errorCode()); |
| DataInputStream replyData = replyPacket.dataInStream(); |
| List elements = new ArrayList(); |
| int nrOfElements = readInt("elements", replyData); //$NON-NLS-1$ |
| for (int i = 0; i < nrOfElements; i++) { |
| FieldImpl elt = FieldImpl.readWithNameSignatureModifiers(this, this, withGenericSignature, replyData); |
| if (elt == null) { |
| continue; |
| } |
| elements.add(elt); |
| } |
| fFields = elements; |
| return fFields; |
| } catch (IOException e) { |
| defaultIOExceptionHandler(e); |
| return null; |
| } finally { |
| handledJdwpRequest(); |
| } |
| } |
| |
| /** |
| * @return Returns FieldImpl of a field in the reference specified by a given fieldID, or null if not found. |
| */ |
| public FieldImpl findField(JdwpFieldID fieldID) { |
| Iterator iter = fields().iterator(); |
| while(iter.hasNext()) { |
| FieldImpl field = (FieldImpl)iter.next(); |
| if (field.getFieldID().equals(fieldID)) |
| return field; |
| } |
| return null; |
| } |
| |
| /** |
| * @return Returns MethodImpl of a method in the reference specified by a given methodID, or null if not found. |
| */ |
| public MethodImpl findMethod(JdwpMethodID methodID) { |
| if (methodID.value() == 0) { |
| return new MethodImpl(virtualMachineImpl(), this, methodID, JDIMessages.ReferenceTypeImpl_Obsolete_method_1, "", null, -1); //$NON-NLS-1$ |
| } |
| if (fMethodTable == null) { |
| fMethodTable= new Hashtable(); |
| Iterator iter = methods().iterator(); |
| while(iter.hasNext()) { |
| MethodImpl method = (MethodImpl)iter.next(); |
| fMethodTable.put(method.getMethodID(), method); |
| } |
| } |
| return (MethodImpl)fMethodTable.get(methodID); |
| } |
| |
| /** |
| * @return Returns the Value of a given static Field in this type. |
| */ |
| public Value getValue(Field field) { |
| ArrayList list = new ArrayList(1); |
| list.add(field); |
| return (ValueImpl)getValues(list).get(field); |
| } |
| |
| /** |
| * @return a Map of the requested static Field objects with their Value. |
| */ |
| public Map getValues(List fields) { |
| // if the field list is empty, nothing to do |
| if (fields.isEmpty()) { |
| return new HashMap(); |
| } |
| // Note that this information should not be cached. |
| initJdwpRequest(); |
| try { |
| ByteArrayOutputStream outBytes = new ByteArrayOutputStream(); |
| DataOutputStream outData = new DataOutputStream(outBytes); |
| int fieldsSize = fields.size(); |
| write(this, outData); |
| writeInt(fieldsSize, "size", outData); //$NON-NLS-1$ |
| for (int i = 0; i < fieldsSize; i++) { |
| FieldImpl field = (FieldImpl)fields.get(i); |
| checkVM(field); |
| field.getFieldID().write(outData); |
| } |
| |
| JdwpReplyPacket replyPacket = requestVM(JdwpCommandPacket.RT_GET_VALUES, outBytes); |
| defaultReplyErrorHandler(replyPacket.errorCode()); |
| |
| DataInputStream replyData = replyPacket.dataInStream(); |
| HashMap map = new HashMap(); |
| int nrOfElements = readInt("elements", replyData); //$NON-NLS-1$ |
| if (nrOfElements != fieldsSize) |
| throw new InternalError(JDIMessages.ReferenceTypeImpl_Retrieved_a_different_number_of_values_from_the_VM_than_requested_3); |
| |
| for (int i = 0; i < nrOfElements; i++) { |
| map.put(fields.get(i), ValueImpl.readWithTag(this, replyData)); |
| } |
| return map; |
| } catch (IOException e) { |
| defaultIOExceptionHandler(e); |
| return null; |
| } finally { |
| handledJdwpRequest(); |
| } |
| } |
| |
| /** |
| * @return Returns the hash code value. |
| */ |
| public int hashCode() { |
| return fReferenceTypeID.hashCode(); |
| } |
| |
| /** |
| * @return Returns true if two mirrors refer to the same entity in the target VM. |
| * @see java.lang.Object#equals(Object) |
| */ |
| public boolean equals(Object object) { |
| return object != null |
| && object.getClass().equals(this.getClass()) |
| && fReferenceTypeID.equals(((ReferenceTypeImpl)object).fReferenceTypeID) |
| && virtualMachine().equals(((MirrorImpl)object).virtualMachine()); |
| } |
| |
| /** |
| * @return Returns a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified object. |
| */ |
| public int compareTo(Object object) { |
| if (object == null || !object.getClass().equals(this.getClass())) |
| throw new ClassCastException(JDIMessages.ReferenceTypeImpl_Can__t_compare_reference_type_to_given_object_4); |
| return name().compareTo(((ReferenceType)object).name()); |
| } |
| |
| /** |
| * @return Returns true if the type was declared abstract. |
| */ |
| public boolean isAbstract() { |
| return (modifiers() & MODIFIER_ACC_ABSTRACT) != 0; |
| } |
| |
| /** |
| * @return Returns true if the type was declared final. |
| */ |
| public boolean isFinal() { |
| return (modifiers() & MODIFIER_ACC_FINAL) != 0; |
| } |
| |
| /** |
| * @return Returns true if the type was declared static. |
| */ |
| public boolean isStatic() { |
| return (modifiers() & MODIFIER_ACC_STATIC) != 0; |
| } |
| |
| /** |
| * @return Returns a List filled with all Location objects that map to the given line number. |
| */ |
| public List locationsOfLine(int line) throws AbsentInformationException { |
| return locationsOfLine(virtualMachine().getDefaultStratum(), null, line); |
| } |
| |
| /** |
| * @return Returns a list containing each Method declared directly in this type. |
| */ |
| public List methods() { |
| // Note that ArrayReference overwrites this method by returning an empty list. |
| if (fMethods != null) |
| return fMethods; |
| |
| // Note: Methods are returned in the order they occur in the class file, therefore their |
| // order in this list can be used for comparisons. |
| initJdwpRequest(); |
| try { |
| boolean withGenericSignature= virtualMachineImpl().isJdwpVersionGreaterOrEqual(1, 5); |
| int jdwpCommand= withGenericSignature ? JdwpCommandPacket.RT_METHODS_WITH_GENERIC : JdwpCommandPacket.RT_METHODS; |
| JdwpReplyPacket replyPacket = requestVM(jdwpCommand, this); |
| defaultReplyErrorHandler(replyPacket.errorCode()); |
| DataInputStream replyData = replyPacket.dataInStream(); |
| List elements = new ArrayList(); |
| int nrOfElements = readInt("elements", replyData); //$NON-NLS-1$ |
| for (int i = 0; i < nrOfElements; i++) { |
| MethodImpl elt = MethodImpl.readWithNameSignatureModifiers(this, this, withGenericSignature, replyData); |
| if (elt == null) { |
| continue; |
| } |
| elements.add(elt); |
| } |
| fMethods = elements; |
| return fMethods; |
| } catch (IOException e) { |
| defaultIOExceptionHandler(e); |
| return null; |
| } finally { |
| handledJdwpRequest(); |
| } |
| } |
| |
| /** |
| * @return Returns a List containing each visible Method that has the given name. |
| */ |
| public List methodsByName(String name) { |
| List elements = new ArrayList(); |
| Iterator iter = visibleMethods().iterator(); |
| while (iter.hasNext()) { |
| MethodImpl method = (MethodImpl)iter.next(); |
| if (method.name().equals(name)){ |
| elements.add(method); |
| } |
| } |
| return elements; |
| } |
| |
| /** |
| * @return Returns a List containing each visible Method that has the given name and signature. |
| */ |
| public List methodsByName(String name, String signature) { |
| List elements = new ArrayList(); |
| Iterator iter = visibleMethods().iterator(); |
| while (iter.hasNext()) { |
| MethodImpl method = (MethodImpl)iter.next(); |
| if (method.name().equals(name) && method.signature().equals(signature)) { |
| elements.add(method); |
| } |
| } |
| return elements; |
| } |
| |
| /** |
| * @return Returns the fully qualified name of this type. |
| */ |
| public String name() { |
| // Make sure that we know the signature, from which the name is derived. |
| if (fName == null) { |
| setName(signatureToName(signature())); |
| } |
| return fName; |
| } |
| |
| /** |
| * @return Returns the JNI-style signature for this type. |
| */ |
| public String signature() { |
| if (fSignature != null) { |
| return fSignature; |
| } |
| initJdwpRequest(); |
| try { |
| JdwpReplyPacket replyPacket = requestVM(JdwpCommandPacket.RT_SIGNATURE, this); |
| defaultReplyErrorHandler(replyPacket.errorCode()); |
| DataInputStream replyData = replyPacket.dataInStream(); |
| setSignature(readString("signature", replyData)); //$NON-NLS-1$ |
| return fSignature; |
| } catch (IOException e) { |
| defaultIOExceptionHandler(e); |
| return null; |
| } finally { |
| handledJdwpRequest(); |
| } |
| } |
| |
| /** |
| * @return Returns a List containing each ReferenceType declared within this type. |
| */ |
| public List nestedTypes() { |
| // Note that the VM gives an empty reply on RT_NESTED_TYPES, therefore we search for the |
| // nested types in the loaded types. |
| List result = new ArrayList(); |
| Iterator itr = virtualMachineImpl().allRefTypes(); |
| while (itr.hasNext()) { |
| try { |
| ReferenceTypeImpl refType = (ReferenceTypeImpl)itr.next(); |
| String refName = refType.name(); |
| if (refName.length() > name().length() && refName.startsWith(name()) && refName.charAt(name().length()) == '$') { |
| result.add(refType); |
| } |
| } catch (ClassNotPreparedException e) { |
| continue; |
| } |
| } |
| return result; |
| } |
| |
| /** |
| * @return Returns an identifying name for the source corresponding to the declaration of this type. |
| */ |
| public String sourceName() throws AbsentInformationException { |
| // sourceNames list in never empty, an AbsentInformationException is thrown |
| // if the source name is not known. |
| return (String)sourceNames(virtualMachine().getDefaultStratum()).get(0); |
| } |
| |
| /** |
| * @return Returns the CRC-32 of the given reference type, undefined if unknown. |
| */ |
| public int getClassFileVersion() { |
| virtualMachineImpl().checkHCRSupported(); |
| if (fGotClassFileVersion) |
| return fClassFileVersion; |
| |
| initJdwpRequest(); |
| try { |
| JdwpReplyPacket replyPacket = requestVM(JdwpCommandPacket.HCR_GET_CLASS_VERSION, this); |
| defaultReplyErrorHandler(replyPacket.errorCode()); |
| DataInputStream replyData = replyPacket.dataInStream(); |
| fIsHCREligible = readBoolean("HCR eligible", replyData); //$NON-NLS-1$ |
| fIsVersionKnown = readBoolean("version known", replyData); //$NON-NLS-1$ |
| fClassFileVersion = readInt("class file version", replyData); //$NON-NLS-1$ |
| fGotClassFileVersion = true; |
| return fClassFileVersion; |
| } catch (IOException e) { |
| defaultIOExceptionHandler(e); |
| return 0; |
| } finally { |
| handledJdwpRequest(); |
| } |
| } |
| |
| /** |
| * @return Returns whether the CRC-32 of the given reference type is known. |
| */ |
| public boolean isVersionKnown() { |
| getClassFileVersion(); |
| return fIsVersionKnown; |
| } |
| |
| /** |
| * @return Returns whether the reference type is HCR-eligible. |
| */ |
| public boolean isHCREligible() { |
| getClassFileVersion(); |
| return fIsHCREligible; |
| } |
| |
| /** |
| * Writes JDWP representation. |
| */ |
| public void write(MirrorImpl target, DataOutputStream out) throws IOException { |
| fReferenceTypeID.write(out); |
| if (target.fVerboseWriter != null) |
| target.fVerboseWriter.println("referenceType", fReferenceTypeID.value()); //$NON-NLS-1$ |
| } |
| |
| /** |
| * Writes representation of null referenceType. |
| */ |
| public static void writeNull(MirrorImpl target, DataOutputStream out) throws IOException { |
| // create null id |
| JdwpReferenceTypeID ID = new JdwpReferenceTypeID(target.virtualMachineImpl()); |
| ID.write(out); |
| if (target.fVerboseWriter != null) |
| target.fVerboseWriter.println("referenceType", ID.value()); //$NON-NLS-1$ |
| } |
| |
| /** |
| * Writes JDWP representation. |
| */ |
| public void writeWithTag(MirrorImpl target, DataOutputStream out) throws IOException { |
| target.writeByte(typeTag(), "type tag", JdwpID.typeTagMap(), out); //$NON-NLS-1$ |
| write(target, out); |
| } |
| |
| /** |
| * @return Reads JDWP representation and returns new or cached instance. |
| */ |
| public static ReferenceTypeImpl readWithTypeTag(MirrorImpl target, DataInputStream in) throws IOException { |
| byte typeTag = target.readByte("type tag", JdwpID.typeTagMap(), in); //$NON-NLS-1$ |
| switch (typeTag) { |
| case 0: |
| return null; |
| case ArrayTypeImpl.typeTag: |
| return ArrayTypeImpl.read(target, in); |
| case ClassTypeImpl.typeTag: |
| return ClassTypeImpl.read(target, in); |
| case InterfaceTypeImpl.typeTag: |
| return InterfaceTypeImpl.read(target, in); |
| } |
| throw new InternalException(JDIMessages.ReferenceTypeImpl_Invalid_ReferenceTypeID_tag_encountered___8 + typeTag); |
| } |
| |
| /** |
| * @return Returns the Location objects for each executable source line in this reference type. |
| */ |
| public List allLineLocations() throws AbsentInformationException { |
| return allLineLocations(virtualMachine().getDefaultStratum(), null); |
| } |
| |
| /** |
| * @return Reads JDWP representation and returns new or cached instance. |
| */ |
| public static ReferenceTypeImpl readWithTypeTagAndSignature(MirrorImpl target, boolean withGenericSignature, DataInputStream in) throws IOException { |
| byte typeTag = target.readByte("type tag", JdwpID.typeTagMap(), in); //$NON-NLS-1$ |
| switch (typeTag) { |
| case 0: |
| return null; |
| case ArrayTypeImpl.typeTag: |
| return ArrayTypeImpl.readWithSignature(target, withGenericSignature, in); |
| case ClassTypeImpl.typeTag: |
| return ClassTypeImpl.readWithSignature(target, withGenericSignature, in); |
| case InterfaceTypeImpl.typeTag: |
| return InterfaceTypeImpl.readWithSignature(target, withGenericSignature, in); |
| } |
| throw new InternalException(JDIMessages.ReferenceTypeImpl_Invalid_ReferenceTypeID_tag_encountered___8 + typeTag); |
| } |
| |
| /** |
| * @return Returns new instance based on signature and classLoader. |
| * @throws ClassNotLoadedException when the ReferenceType has not been loaded by the specified class loader. |
| */ |
| public static TypeImpl create(VirtualMachineImpl vmImpl, String signature, ClassLoaderReference classLoader) throws ClassNotLoadedException { |
| ReferenceTypeImpl refTypeBootstrap = null; |
| List classes= vmImpl.classesBySignature(signature); |
| ReferenceTypeImpl type; |
| Iterator iter= classes.iterator(); |
| while (iter.hasNext()) { |
| // First pass. Look for a class loaded by the given class loader |
| type = (ReferenceTypeImpl)iter.next(); |
| if (type.classLoader() == null) { // bootstrap classloader |
| if (classLoader == null) { |
| return type; |
| } |
| refTypeBootstrap = type; |
| } |
| if (classLoader != null && classLoader.equals(type.classLoader())) { |
| return type; |
| } |
| } |
| // If no ReferenceType is found with the specified classloader, but there is one with the |
| // bootstrap classloader, the latter is returned. |
| if (refTypeBootstrap != null) { |
| return refTypeBootstrap; |
| } |
| |
| List visibleTypes; |
| iter= classes.iterator(); |
| while (iter.hasNext()) { |
| // Second pass. Look for a class that is visible to |
| // the given class loader |
| type = (ReferenceTypeImpl)iter.next(); |
| visibleTypes= classLoader.visibleClasses(); |
| Iterator visibleIter= visibleTypes.iterator(); |
| while (visibleIter.hasNext()) { |
| if (type.equals(visibleIter.next())) { |
| return type; |
| } |
| } |
| } |
| |
| throw new ClassNotLoadedException(classSignatureToName(signature), JDIMessages.ReferenceTypeImpl_Type_has_not_been_loaded_10); |
| } |
| |
| /** |
| * Retrieves constant mappings. |
| */ |
| public static void getConstantMaps() { |
| if (fgClassStatusStrings != null) { |
| return; |
| } |
| |
| java.lang.reflect.Field[] fields = ReferenceTypeImpl.class.getDeclaredFields(); |
| fgClassStatusStrings = new String[32]; |
| |
| for (int i = 0; i < fields.length; i++) { |
| java.lang.reflect.Field field = fields[i]; |
| if ((field.getModifiers() & Modifier.PUBLIC) == 0 || (field.getModifiers() & Modifier.STATIC) == 0 || (field.getModifiers() & Modifier.FINAL) == 0) { |
| continue; |
| } |
| |
| String name = field.getName(); |
| if (!name.startsWith("JDWP_CLASS_STATUS_")) { //$NON-NLS-1$ |
| continue; |
| } |
| |
| name = name.substring(18); |
| |
| try { |
| int value = field.getInt(null); |
| |
| for (int j = 0; j < fgClassStatusStrings.length; j++) { |
| if ((1 << j & value) != 0) { |
| fgClassStatusStrings[j]= name; |
| break; |
| } |
| } |
| } catch (IllegalAccessException e) { |
| // Will not occur for own class. |
| } catch (IllegalArgumentException e) { |
| // Should not occur. |
| // We should take care that all public static final constants |
| // in this class are numbers that are convertible to int. |
| } |
| } |
| } |
| |
| /** |
| * @return Returns a map with string representations of tags. |
| */ |
| public static String[] classStatusStrings() { |
| getConstantMaps(); |
| return fgClassStatusStrings; |
| } |
| |
| /** |
| * @see TypeImpl#createNullValue() |
| */ |
| public Value createNullValue() { |
| return null; |
| } |
| |
| /** |
| * @see ReferenceType#sourceNames(String) |
| */ |
| public List sourceNames(String stratumId) throws AbsentInformationException { |
| List list= new ArrayList(); |
| Stratum stratum= getStratum(stratumId); |
| if (stratum != null) { |
| // return the source names defined for this stratum in the SMAP. |
| List fileInfos= stratum.fFileInfos; |
| if (fileInfos.isEmpty()) { |
| throw new AbsentInformationException(JDIMessages.ReferenceTypeImpl_30); |
| } |
| for (Iterator iter = stratum.fFileInfos.iterator(); iter.hasNext();) { |
| list.add(((FileInfo) iter.next()).fFileName); |
| } |
| return list; |
| } |
| // Java stratum |
| if (fSourceName == null) { |
| getSourceName(); |
| } |
| list.add(fSourceName); |
| return list; |
| } |
| |
| /** |
| * @see ReferenceType#sourcePaths(String) |
| */ |
| public List sourcePaths(String stratumId) throws AbsentInformationException { |
| List list= new ArrayList(); |
| Stratum stratum= getStratum(stratumId); |
| if (stratum != null) { |
| // return the source paths defined for this stratum in the SMAP. |
| for (Iterator iter = stratum.fFileInfos.iterator(); iter.hasNext();) { |
| FileInfo fileInfo= (FileInfo) iter.next(); |
| String path= fileInfo.fAbsoluteFileName; |
| if (path == null) { |
| path= getPath(fileInfo.fFileName); |
| } |
| list.add(path); |
| } |
| return list; |
| } |
| // Java stratum |
| if (fSourceName == null) { |
| getSourceName(); |
| } |
| list.add(getPath(fSourceName)); |
| return list; |
| } |
| |
| /** |
| * @see ReferenceType#sourceDebugExtension() |
| */ |
| public String sourceDebugExtension() throws AbsentInformationException { |
| if (isSourceDebugExtensionAvailable()) { |
| return fSmap; |
| } |
| if (!virtualMachine().canGetSourceDebugExtension()) { |
| throw new UnsupportedOperationException(); |
| } |
| throw new AbsentInformationException(); |
| } |
| |
| /** |
| * @see ReferenceType#allLineLocations(String, String) |
| */ |
| public List allLineLocations(String stratum, String sourceName) throws AbsentInformationException { |
| Iterator allMethods = methods().iterator(); |
| if (stratum == null) { // if stratum not defined use the default stratum |
| stratum= defaultStratum(); |
| } |
| List allLineLocations= null; |
| Map sourceNameAllLineLocations= null; |
| if (fStratumAllLineLocations == null) { // the stratum map doesn't exist, create it |
| fStratumAllLineLocations= new HashMap(); |
| } else { |
| // get the source name map |
| sourceNameAllLineLocations= (Map)fStratumAllLineLocations.get(stratum); |
| } |
| if (sourceNameAllLineLocations == null) { // the source name map doesn't exist, create it |
| sourceNameAllLineLocations= new HashMap(); |
| fStratumAllLineLocations.put(stratum, sourceNameAllLineLocations); |
| } else { |
| // get the line locations |
| allLineLocations= (List)sourceNameAllLineLocations.get(sourceName); |
| } |
| if (allLineLocations == null) { // the line locations are not know, compute and store them |
| allLineLocations = new ArrayList(); |
| while (allMethods.hasNext()) { |
| MethodImpl method = (MethodImpl)allMethods.next(); |
| if (method.isAbstract() || method.isNative()) { |
| continue; |
| } |
| allLineLocations.addAll(method.allLineLocations(stratum, sourceName)); |
| } |
| sourceNameAllLineLocations.put(sourceName, allLineLocations); |
| } |
| return allLineLocations; |
| } |
| |
| /** |
| * @see ReferenceType#locationsOfLine(String, String, int) |
| */ |
| public List locationsOfLine(String stratum, String sourceName, int lineNumber) throws AbsentInformationException { |
| Iterator allMethods = methods().iterator(); |
| List locations= new ArrayList(); |
| boolean hasLineInformation= false; |
| AbsentInformationException exception= null; |
| while (allMethods.hasNext()) { |
| MethodImpl method = (MethodImpl)allMethods.next(); |
| if (method.isAbstract() || method.isNative()) { |
| continue; |
| } |
| // one line in the input source can be translate in multiple lines in different |
| // methods in the output source. We need all these locations. |
| try { |
| locations.addAll(locationsOfLine(stratum, sourceName, lineNumber, method)); |
| hasLineInformation= true; |
| } catch (AbsentInformationException e) { |
| exception= e; |
| } |
| } |
| if (!hasLineInformation && exception != null) { |
| throw exception; |
| } |
| return locations; |
| } |
| |
| /** |
| * @see ReferenceType#availableStrata() |
| */ |
| public List availableStrata() { |
| List list= new ArrayList(); |
| // The strata defined in the SMAP. |
| if (isSourceDebugExtensionAvailable()) { |
| list.addAll(fStrata.keySet()); |
| } |
| // plus the Java stratum |
| list.add(VirtualMachineImpl.JAVA_STRATUM_NAME); |
| return list; |
| } |
| |
| /** |
| * @see ReferenceType#defaultStratum() |
| */ |
| public String defaultStratum() { |
| if (isSourceDebugExtensionAvailable()) { |
| return fDefaultStratumId; |
| } |
| // if not defined, return Java. |
| return VirtualMachineImpl.JAVA_STRATUM_NAME; |
| } |
| |
| /** |
| * Generate a source path from the given source name. |
| * The returned string is the package name of this type converted to a platform dependent path |
| * followed by the given source name. |
| * For example, on a Unix platform, the type org.my.TestJsp with the source name test.jsp would |
| * return "org/my/test.jsp". |
| */ |
| private String getPath(String sourceName) { |
| String name= name(); |
| int lastDotOffset= name.lastIndexOf('.'); |
| if (lastDotOffset == -1) { |
| return sourceName; |
| } |
| char fileSeparator= System.getProperty("file.separator").charAt(0); //$NON-NLS-1$ |
| return name.substring(0, lastDotOffset).replace('.', fileSeparator) + fileSeparator + sourceName; |
| } |
| |
| /** |
| * Return the stratum object for this stratum Id. |
| * If the the specified stratum id is not defined for this reference type, |
| * return the stratum object for the default stratum. |
| * If the specified stratum id (or the default stratum id, if the specified |
| * stratum id is not defined) is <code>Java</code>, return <code>null</code>. |
| */ |
| private Stratum getStratum(String stratumId) { |
| if (!VirtualMachineImpl.JAVA_STRATUM_NAME.equals(stratumId) && isSourceDebugExtensionAvailable()) { |
| if (stratumId == null || !fStrata.keySet().contains(stratumId)) { |
| stratumId= fDefaultStratumId; |
| } |
| if (!VirtualMachineImpl.JAVA_STRATUM_NAME.equals(stratumId)) { |
| return (Stratum)fStrata.get(stratumId); |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * Get the source debug extension from the VM. |
| * @throws AbsentInformationException |
| */ |
| private void getSourceDebugExtension() throws AbsentInformationException { |
| initJdwpRequest(); |
| try { |
| JdwpReplyPacket replyPacket = requestVM(JdwpCommandPacket.RT_SOURCE_DEBUG_EXTENSION, this); |
| if (replyPacket.errorCode() == JdwpReplyPacket.ABSENT_INFORMATION) { |
| throw new AbsentInformationException(JDIMessages.ReferenceTypeImpl_31); |
| } |
| defaultReplyErrorHandler(replyPacket.errorCode()); |
| DataInputStream replyData = replyPacket.dataInStream(); |
| fSmap= readString(JDIMessages.ReferenceTypeImpl_32, replyData); |
| } catch (IOException e) { |
| defaultIOExceptionHandler(e); |
| } finally { |
| handledJdwpRequest(); |
| } |
| // TODO: remove the workaround when the J9SC20030415 bug is fixed (see bug 96485 of the vendor bug system). |
| // Workaround to a J9SC bug. It returns an empty string instead of a ABSENT_INFORMATION |
| // error if the source debug extension is not available. |
| if ("".equals(fSmap)) { //$NON-NLS-1$ |
| throw new AbsentInformationException(JDIMessages.ReferenceTypeImpl_31); |
| } |
| // parse the source map. |
| fStrata= new HashMap(); |
| SourceDebugExtensionParser.parse(fSmap, this); |
| } |
| |
| /** |
| * Get the name of the Java source file from the VM. |
| * @throws AbsentInformationException |
| */ |
| private void getSourceName() throws AbsentInformationException { |
| if (fSourceName != null || isSourceDebugExtensionAvailable()) { |
| return; |
| } |
| initJdwpRequest(); |
| try { |
| JdwpReplyPacket replyPacket = requestVM(JdwpCommandPacket.RT_SOURCE_FILE, this); |
| if (replyPacket.errorCode() == JdwpReplyPacket.ABSENT_INFORMATION) { |
| throw new AbsentInformationException(JDIMessages.ReferenceTypeImpl_Source_name_is_not_known_7); |
| } |
| |
| defaultReplyErrorHandler(replyPacket.errorCode()); |
| |
| DataInputStream replyData = replyPacket.dataInStream(); |
| fSourceName = readString("source name", replyData); //$NON-NLS-1$ |
| } catch (IOException e) { |
| defaultIOExceptionHandler(e); |
| } finally { |
| handledJdwpRequest(); |
| } |
| } |
| |
| /** |
| * Check in the source debug extension is available. |
| * To call before doing operations which need data from the SMAP. |
| * Return <code>false</code> if the source debug extension is not available |
| * for any reason. <code>true</code> indicates that the source debug extension |
| * is available and the information has been parsed and stored in the |
| * maps and lists. |
| */ |
| private synchronized boolean isSourceDebugExtensionAvailable() { |
| if (!fSourceDebugExtensionAvailable) { |
| return false; |
| } |
| if (!virtualMachine().canGetSourceDebugExtension()) { |
| fSourceDebugExtensionAvailable= false; |
| return false; |
| } |
| if (fSmap == null) { |
| try { |
| getSourceDebugExtension(); |
| } catch (AbsentInformationException e) { |
| fSourceDebugExtensionAvailable= false; |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| /** |
| * Set the output file name, i.e. the .java file used to generate |
| * the bytecode. |
| */ |
| protected void setOutputFileName(String outputFileName) { |
| fSourceName= outputFileName; |
| } |
| |
| /** |
| * Set the default stratum. This stratum will be used for the method |
| * on strata related data, but with no stratum parameter. |
| */ |
| protected void setDefaultStratumId(String defaultStratumId) { |
| fDefaultStratumId= defaultStratumId; |
| } |
| |
| /** |
| * Add a new stratum to this type. |
| */ |
| protected void addStratum(Stratum stratum) { |
| fStrata.put(stratum.fId, stratum); |
| } |
| |
| /** |
| * Return the name of the input source file of which the given code index |
| * is part of the translation, for this stratum. |
| * If the code at the given index is not a part of the translation of |
| * the given stratum code, return the name of the primary input source file. |
| * |
| * @param codeIndex the index of the code. |
| * @param method the method where is the code. |
| * @param stratumId |
| */ |
| protected String sourceName(long codeIndex, MethodImpl method, String stratumId) throws AbsentInformationException { |
| Stratum stratum= getStratum(stratumId); |
| if (stratum != null) { |
| FileInfo fileInfo= fileInfo(codeIndex, method, stratum); |
| if (fileInfo != null) { |
| return fileInfo.fFileName; |
| } |
| } |
| // Java stratum |
| if (fSourceName == null) { |
| getSourceName(); |
| } |
| return fSourceName; |
| } |
| |
| /** |
| * Return the FileInfo object of the input source file of which the given code index |
| * is part of the translation, for this stratum. |
| * If the code at the given index is not a part of the translation of |
| * the given stratum code, return the FileInfo of the primary input source file. |
| * |
| * @param codeIndex the index of the code. |
| * @param method the method where is the code. |
| * @param stratum |
| */ |
| private FileInfo fileInfo(long codeIndex, MethodImpl method, Stratum stratum) { |
| int fileId= stratum.fPrimaryFileId; |
| if (stratum.fFileInfos.size() > 1) { |
| List lineInfos= null; |
| try { |
| lineInfos = lineInfos(codeIndex, method, stratum); |
| } catch (AbsentInformationException e) { |
| // nothing to do, use the primary file id. |
| } |
| if (lineInfos != null) { |
| fileId= ((int[])lineInfos.get(0))[0]; |
| } |
| } |
| for (Iterator iter = stratum.fFileInfos.iterator(); iter.hasNext();) { |
| FileInfo fileInfo = (FileInfo)iter.next(); |
| if (fileInfo.fFileId == fileId) { |
| return fileInfo; |
| } |
| } |
| // should never return null |
| return null; |
| } |
| |
| /** |
| * Return the list of line number in the input files of the stratum associated |
| * with the code at the given address. |
| * |
| * @param codeIndex the index of the code. |
| * @param method the method where is the code. |
| * @param stratum |
| * @return List of int[2]: [fileId, inputLineNumber] |
| */ |
| private List lineInfos(long codeIndex, MethodImpl method, Stratum stratum) throws AbsentInformationException { |
| int outputLineNumber= -1; |
| try { |
| outputLineNumber = method.javaStratumLineNumber(codeIndex); |
| } catch (NativeMethodException e) { // Occurs in SUN VM. |
| return null; |
| } |
| if (outputLineNumber != -1) { |
| return stratum.getInputLineInfos(outputLineNumber); |
| } |
| return null; |
| } |
| |
| /** |
| * Return the path of the input source file of which the given code index |
| * is part of the translation, for this stratum. |
| * If the code at the given index is not a part of the translation of |
| * the given stratum code, return the path of the primary input source file. |
| * |
| * @param codeIndex the index of the code. |
| * @param method the method where is the code. |
| * @param stratumId |
| */ |
| protected String sourcePath(long codeIndex, MethodImpl method, String stratumId) throws AbsentInformationException { |
| Stratum stratum= getStratum(stratumId); |
| if (stratum != null) { |
| FileInfo fileInfo= fileInfo(codeIndex, method, stratum); |
| if (fileInfo != null) { |
| String path= fileInfo.fAbsoluteFileName; |
| if (path == null) { |
| return getPath(fileInfo.fFileName); |
| } |
| return path; |
| } |
| } |
| // Java stratum |
| if (fSourceName == null) { |
| getSourceName(); |
| } |
| return getPath(fSourceName); |
| } |
| |
| /** |
| * Return the number of the line of which the given code index |
| * is part of the translation, for this stratum. |
| * |
| * @param codeIndex the index of the code. |
| * @param method the method where is the code. |
| * @param stratumId |
| */ |
| protected int lineNumber(long codeIndex, MethodImpl method, String stratumId) { |
| Stratum stratum= getStratum(stratumId); |
| try { |
| if (stratum != null) { |
| List lineInfos = lineInfos(codeIndex, method, stratum); |
| if (lineInfos != null) { |
| return ((int[])lineInfos.get(0))[1]; |
| } |
| return LocationImpl.LINE_NR_NOT_AVAILABLE; |
| } |
| // Java stratum |
| try { |
| return method.javaStratumLineNumber(codeIndex); |
| } catch (NativeMethodException e) { // Occurs in SUN VM. |
| return LocationImpl.LINE_NR_NOT_AVAILABLE; |
| } |
| } catch (AbsentInformationException e) { |
| return LocationImpl.LINE_NR_NOT_AVAILABLE; |
| } |
| } |
| |
| /** |
| * Return the location which are part of the translation of the given line, |
| * in the given stratum in the source file with the given source name. |
| * If sourceName is <code>null</code>, return the locations for all source file |
| * in the given stratum. |
| * The returned location are in the given method. |
| * |
| * @param stratumId the stratum id. |
| * @param sourceName the name of the source file. |
| * @param lineNumber the number of the line. |
| * @param method |
| * @throws AbsentInformationException if the specified sourceName is not valid. |
| */ |
| public List locationsOfLine(String stratumId, String sourceName, int lineNumber, MethodImpl method) throws AbsentInformationException { |
| Stratum stratum= getStratum(stratumId); |
| List javaLines= new ArrayList(); |
| if (stratum != null) { |
| boolean found= false; |
| for (Iterator iter = stratum.fFileInfos.iterator(); iter.hasNext() && !found;) { |
| FileInfo fileInfo = (FileInfo)iter.next(); |
| if (sourceName == null || (found= sourceName.equals(fileInfo.fFileName))) { |
| javaLines.addAll(fileInfo.getOutputLinesForLine(lineNumber)); |
| } |
| } |
| if (sourceName != null && !found) { |
| throw new AbsentInformationException(JDIMessages.ReferenceTypeImpl_34); |
| } |
| } else { // Java stratum |
| javaLines.add(new Integer(lineNumber)); |
| } |
| return method.javaStratumLocationsOfLines(javaLines); |
| } |
| |
| /** |
| * Return the locations of all lines in the given source file of the given stratum which |
| * are included in the given method. |
| * If sourceName is <code>null</code>, return the locations for all source file |
| * in the given stratum. |
| * |
| * @param stratumId the stratum id |
| * @param sourceName the name of the source file |
| * @param method |
| * @param codeIndexTable the list of code indexes for the method, as get from the VM/JDWP |
| * @param javaStratumLineNumberTable the list of line numbers in the java stratum for the method, as get from the VM/JDWP |
| * @return |
| */ |
| public List allLineLocations(String stratumId, String sourceName, MethodImpl method, long[] codeIndexTable, int[] javaStratumLineNumberTable) throws AbsentInformationException { |
| Stratum stratum= getStratum(stratumId); |
| if (stratum != null) { |
| int[][] lineInfoTable= new int[codeIndexTable.length][]; |
| if (sourceName == null) { |
| int lastIndex=0; |
| for (int i = 0, length= javaStratumLineNumberTable.length; i < length; i++) { |
| // for each executable line in the java source, get the associated lines in the stratum source |
| List lineInfos= stratum.getInputLineInfos(javaStratumLineNumberTable[i]); |
| if (lineInfos != null) { |
| int[] lineInfo= (int[])lineInfos.get(0); |
| if (!lineInfo.equals(lineInfoTable[lastIndex])) { |
| lineInfoTable[i]= lineInfo; |
| lastIndex= i; |
| } |
| } |
| } |
| } else { // sourceName != null |
| FileInfo fileInfo= stratum.getFileInfo(sourceName); |
| if (fileInfo == null) { |
| throw new AbsentInformationException(JDIMessages.ReferenceTypeImpl_34); |
| } |
| int fileId= fileInfo.fFileId; |
| int lastIndex= 0; |
| for (int i = 0, length= javaStratumLineNumberTable.length; i < length; i++) { |
| List lineInfos= stratum.getInputLineInfos(javaStratumLineNumberTable[i]); |
| if (lineInfos != null) { |
| for (Iterator iter = lineInfos.iterator(); iter.hasNext();) { |
| int[] lineInfo= (int[])iter.next(); |
| if (lineInfo[0] == fileId) { |
| if (!lineInfo.equals(lineInfoTable[lastIndex])) { |
| lineInfoTable[i]= lineInfo; |
| lastIndex= i; |
| } |
| break; |
| } |
| } |
| } |
| } |
| } |
| List locations= new ArrayList(); |
| for (int i = 0, length= lineInfoTable.length; i < length; i++) { |
| if (lineInfoTable[i] != null) { |
| locations.add(new LocationImpl(virtualMachineImpl(), method, codeIndexTable[i])); |
| } |
| } |
| return locations; |
| } |
| // Java stratum |
| List result = new ArrayList(); |
| for (int i = 0; i < codeIndexTable.length; i++) { |
| result.add(new LocationImpl(virtualMachineImpl(), method, codeIndexTable[i])); |
| } |
| return result; |
| } |
| |
| /* |
| * @since 3.0 |
| * @since java 1.5 |
| */ |
| public String genericSignature() { |
| if (fGenericSignatureKnown) { |
| return fGenericSignature; |
| } |
| if (virtualMachineImpl().isJdwpVersionGreaterOrEqual(1, 5)) { |
| initJdwpRequest(); |
| try { |
| JdwpReplyPacket replyPacket = requestVM(JdwpCommandPacket.RT_SIGNATURE_WITH_GENERIC, this); |
| defaultReplyErrorHandler(replyPacket.errorCode()); |
| DataInputStream replyData = replyPacket.dataInStream(); |
| setSignature(readString("signature", replyData)); //$NON-NLS-1$ |
| fGenericSignature= readString("generic signature", replyData); //$NON-NLS-1$ |
| if (fGenericSignature.length() == 0) { |
| fGenericSignature= null; |
| } |
| fGenericSignatureKnown= true; |
| } catch (IOException e) { |
| defaultIOExceptionHandler(e); |
| return null; |
| } finally { |
| handledJdwpRequest(); |
| } |
| } else { |
| fGenericSignatureKnown= true; |
| } |
| return fGenericSignature; |
| } |
| |
| /** |
| * if genericSignature is <code>null</code>, the generic signature is set to not-known |
| * (genericSignature() will ask the VM for the generic signature) |
| * if genericSignature is an empty String, the generic signature is set to no-generic-signature |
| * (genericSignature() will return null) |
| * if genericSignature is an non-empty String, the generic signature is set to the specified value |
| * (genericSignature() will return the specified value) |
| * @since 3.0 |
| */ |
| public void setGenericSignature(String genericSignature) { |
| if (genericSignature == null) { |
| fGenericSignature= null; |
| fGenericSignatureKnown= false; |
| } else { |
| if (genericSignature.length() == 0) { |
| fGenericSignature= null; |
| } else { |
| fGenericSignature= genericSignature; |
| } |
| fGenericSignatureKnown= true; |
| } |
| } |
| |
| /** |
| * @see com.sun.jdi.ReferenceType#instances(long) |
| * @since 3.3 |
| */ |
| public List instances(long maxInstances) { |
| try { |
| int max = (int)maxInstances; |
| if (maxInstances >= Integer.MAX_VALUE) { |
| max = Integer.MAX_VALUE; |
| } |
| ByteArrayOutputStream outBytes = new ByteArrayOutputStream(); |
| DataOutputStream outData = new DataOutputStream(outBytes); |
| write(this, outData); |
| writeInt(max, "max instances", outData); //$NON-NLS-1$ |
| |
| JdwpReplyPacket replyPacket = requestVM(JdwpCommandPacket.RT_INSTANCES, outBytes); |
| switch(replyPacket.errorCode()) { |
| case JdwpReplyPacket.INVALID_OBJECT: |
| case JdwpReplyPacket.INVALID_CLASS: |
| throw new ObjectCollectedException(JDIMessages.class_or_object_not_known); |
| case JdwpReplyPacket.NOT_IMPLEMENTED: |
| throw new UnsupportedOperationException(JDIMessages.ReferenceTypeImpl_27); |
| case JdwpReplyPacket.ILLEGAL_ARGUMENT: |
| throw new IllegalArgumentException(JDIMessages.ReferenceTypeImpl_26); |
| case JdwpReplyPacket.VM_DEAD: |
| throw new VMDisconnectedException(JDIMessages.vm_dead); |
| } |
| defaultReplyErrorHandler(replyPacket.errorCode()); |
| |
| DataInputStream replyData = replyPacket.dataInStream(); |
| int elements = readInt("element count", replyData); //$NON-NLS-1$ |
| if(max > 0 && elements > max) { |
| elements = max; |
| } |
| ArrayList list = new ArrayList(); |
| for(int i = 0; i < elements; i++) { |
| list.add(ValueImpl.readWithTag(this, replyData)); |
| } |
| return list; |
| } |
| catch(IOException e) { |
| defaultIOExceptionHandler(e); |
| return null; |
| } finally { |
| handledJdwpRequest(); |
| } |
| } |
| |
| /** |
| * @see com.sun.jdi.ReferenceType#majorVersion() |
| * @since 3.3 |
| */ |
| public int majorVersion() { |
| try { |
| ByteArrayOutputStream outBytes = new ByteArrayOutputStream(); |
| DataOutputStream outData = new DataOutputStream(outBytes); |
| getRefTypeID().write(outData); |
| |
| JdwpReplyPacket replyPacket = requestVM(JdwpCommandPacket.RT_CLASS_VERSION, outBytes); |
| switch(replyPacket.errorCode()) { |
| case JdwpReplyPacket.INVALID_CLASS: |
| case JdwpReplyPacket.INVALID_OBJECT: |
| throw new ObjectCollectedException(JDIMessages.class_or_object_not_known); |
| case JdwpReplyPacket.ABSENT_INFORMATION: |
| return 0; |
| case JdwpReplyPacket.NOT_IMPLEMENTED: |
| throw new UnsupportedOperationException(JDIMessages.ReferenceTypeImpl_no_class_version_support24); |
| case JdwpReplyPacket.VM_DEAD: |
| throw new VMDisconnectedException(JDIMessages.vm_dead); |
| } |
| defaultReplyErrorHandler(replyPacket.errorCode()); |
| |
| DataInputStream replyData = replyPacket.dataInStream(); |
| return readInt("major version", replyData); //$NON-NLS-1$ |
| } |
| catch(IOException e) { |
| defaultIOExceptionHandler(e); |
| return 0; |
| } finally { |
| handledJdwpRequest(); |
| } |
| } |
| |
| /** |
| * @see com.sun.jdi.ReferenceType#minorVersion() |
| * @since 3.3 |
| */ |
| public int minorVersion() { |
| try { |
| ByteArrayOutputStream outBytes = new ByteArrayOutputStream(); |
| DataOutputStream outData = new DataOutputStream(outBytes); |
| getRefTypeID().write(outData); |
| |
| JdwpReplyPacket replyPacket = requestVM(JdwpCommandPacket.RT_CLASS_VERSION, outBytes); |
| switch(replyPacket.errorCode()) { |
| case JdwpReplyPacket.INVALID_CLASS: |
| case JdwpReplyPacket.INVALID_OBJECT: |
| throw new ObjectCollectedException(JDIMessages.class_or_object_not_known); |
| case JdwpReplyPacket.ABSENT_INFORMATION: |
| return 0; |
| case JdwpReplyPacket.NOT_IMPLEMENTED: |
| throw new UnsupportedOperationException(JDIMessages.ReferenceTypeImpl_no_class_version_support24); |
| case JdwpReplyPacket.VM_DEAD: |
| throw new VMDisconnectedException(JDIMessages.vm_dead); |
| } |
| defaultReplyErrorHandler(replyPacket.errorCode()); |
| |
| DataInputStream replyData = replyPacket.dataInStream(); |
| readInt("major version", replyData); //$NON-NLS-1$ |
| return readInt("minor version", replyData); //$NON-NLS-1$ |
| } |
| catch(IOException e) { |
| defaultIOExceptionHandler(e); |
| return 0; |
| } finally { |
| handledJdwpRequest(); |
| } |
| } |
| |
| /** |
| * @see com.sun.jdi.ReferenceType#constantPoolCount() |
| * @since 3.3 |
| */ |
| public int constantPoolCount() { |
| try { |
| ByteArrayOutputStream outBytes = new ByteArrayOutputStream(); |
| DataOutputStream outData = new DataOutputStream(outBytes); |
| this.getRefTypeID().write(outData); |
| |
| JdwpReplyPacket replyPacket = requestVM(JdwpCommandPacket.RT_CONSTANT_POOL, outBytes); |
| switch(replyPacket.errorCode()) { |
| case JdwpReplyPacket.INVALID_CLASS: |
| case JdwpReplyPacket.INVALID_OBJECT: |
| throw new ObjectCollectedException(JDIMessages.class_or_object_not_known); |
| case JdwpReplyPacket.ABSENT_INFORMATION: |
| return 0; |
| case JdwpReplyPacket.NOT_IMPLEMENTED: |
| throw new UnsupportedOperationException(JDIMessages.ReferenceTypeImpl_no_constant_pool_support); |
| case JdwpReplyPacket.VM_DEAD: |
| throw new VMDisconnectedException(JDIMessages.vm_dead); |
| } |
| defaultReplyErrorHandler(replyPacket.errorCode()); |
| |
| DataInputStream replyData = replyPacket.dataInStream(); |
| return readInt("pool count", replyData); //$NON-NLS-1$ |
| } |
| catch(IOException e) { |
| defaultIOExceptionHandler(e); |
| return 0; |
| } finally { |
| handledJdwpRequest(); |
| } |
| } |
| |
| /** |
| * @see com.sun.jdi.ReferenceType#constantPool() |
| * @since 3.3 |
| */ |
| public byte[] constantPool() { |
| try { |
| ByteArrayOutputStream outBytes = new ByteArrayOutputStream(); |
| DataOutputStream outData = new DataOutputStream(outBytes); |
| this.getRefTypeID().write(outData); |
| |
| JdwpReplyPacket replyPacket = requestVM(JdwpCommandPacket.RT_CONSTANT_POOL, outBytes); |
| switch(replyPacket.errorCode()) { |
| case JdwpReplyPacket.INVALID_CLASS: |
| case JdwpReplyPacket.INVALID_OBJECT: |
| throw new ObjectCollectedException(JDIMessages.class_or_object_not_known); |
| case JdwpReplyPacket.ABSENT_INFORMATION: |
| return new byte[0]; |
| case JdwpReplyPacket.NOT_IMPLEMENTED: |
| throw new UnsupportedOperationException(JDIMessages.ReferenceTypeImpl_no_constant_pool_support); |
| case JdwpReplyPacket.VM_DEAD: |
| throw new VMDisconnectedException(JDIMessages.vm_dead); |
| } |
| defaultReplyErrorHandler(replyPacket.errorCode()); |
| |
| DataInputStream replyData = replyPacket.dataInStream(); |
| readInt("pool count", replyData); //$NON-NLS-1$ |
| int bytes = readInt("byte count", replyData); //$NON-NLS-1$ |
| byte[] array = new byte[bytes]; |
| for (int i = 0; i < bytes; i++) { |
| array[i] = readByte("byte read", replyData); //$NON-NLS-1$ |
| } |
| return array; |
| } |
| catch(IOException e) { |
| defaultIOExceptionHandler(e); |
| return null; |
| } finally { |
| handledJdwpRequest(); |
| } |
| } |
| } |