| /******************************************************************************* |
| * Copyright (c) 2000, 2015 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 |
| *******************************************************************************/ |
| package org.eclipse.jdi.internal.request; |
| |
| import java.io.ByteArrayOutputStream; |
| import java.io.DataInputStream; |
| import java.io.DataOutputStream; |
| import java.io.IOException; |
| import java.lang.reflect.Field; |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.Map; |
| |
| import org.eclipse.jdi.internal.FieldImpl; |
| import org.eclipse.jdi.internal.LocationImpl; |
| import org.eclipse.jdi.internal.MirrorImpl; |
| import org.eclipse.jdi.internal.ObjectReferenceImpl; |
| import org.eclipse.jdi.internal.ReferenceTypeImpl; |
| import org.eclipse.jdi.internal.ThreadReferenceImpl; |
| import org.eclipse.jdi.internal.VirtualMachineImpl; |
| import org.eclipse.jdi.internal.event.EventImpl; |
| import org.eclipse.jdi.internal.jdwp.JdwpCommandPacket; |
| import org.eclipse.jdi.internal.jdwp.JdwpReplyPacket; |
| |
| import com.sun.jdi.InternalException; |
| import com.sun.jdi.ObjectCollectedException; |
| import com.sun.jdi.ObjectReference; |
| import com.sun.jdi.ReferenceType; |
| import com.sun.jdi.ThreadReference; |
| import com.sun.jdi.VMMismatchException; |
| import com.sun.jdi.request.EventRequest; |
| import com.sun.jdi.request.InvalidRequestStateException; |
| import com.sun.jdi.request.StepRequest; |
| |
| /** |
| * this class implements the corresponding interfaces declared by the JDI |
| * specification. See the com.sun.jdi package for more information. |
| * |
| */ |
| public abstract class EventRequestImpl extends MirrorImpl implements |
| EventRequest { |
| /** Jdwp constants for StepRequests. */ |
| public static final byte STEP_SIZE_MIN_JDWP = 0; |
| public static final byte STEP_SIZE_LINE_JDWP = 1; |
| public static final byte STEP_DEPTH_INTO_JDWP = 0; |
| public static final byte STEP_DEPTH_OVER_JDWP = 1; |
| public static final byte STEP_DEPTH_OUT_JDWP = 2; |
| public static final byte STEP_DEPTH_REENTER_JDWP_HCR = 3; // OTI specific |
| // for Hot Code |
| // Replacement. |
| |
| /** Jdwp constants for SuspendPolicy. */ |
| public static final byte SUSPENDPOL_NONE_JDWP = 0; |
| public static final byte SUSPENDPOL_EVENT_THREAD_JDWP = 1; |
| public static final byte SUSPENDPOL_ALL_JDWP = 2; |
| |
| /** Constants for ModifierKind. */ |
| public static final byte MODIF_KIND_COUNT = 1; |
| public static final byte MODIF_KIND_CONDITIONAL = 2; |
| public static final byte MODIF_KIND_THREADONLY = 3; |
| public static final byte MODIF_KIND_CLASSONLY = 4; |
| public static final byte MODIF_KIND_CLASSMATCH = 5; |
| public static final byte MODIF_KIND_CLASSEXCLUDE = 6; |
| public static final byte MODIF_KIND_LOCATIONONLY = 7; |
| public static final byte MODIF_KIND_EXCEPTIONONLY = 8; |
| public static final byte MODIF_KIND_FIELDONLY = 9; |
| public static final byte MODIF_KIND_STEP = 10; |
| public static final byte MODIF_KIND_INSTANCE = 11; |
| public static final byte MODIF_KIND_SOURCE_NAME_FILTER = 12; |
| |
| /** Mapping of command codes to strings. */ |
| private static HashMap<Integer, String> fStepSizeMap = null; |
| private static HashMap<Integer, String> fStepDepthMap = null; |
| private static HashMap<Integer, String> fSuspendPolicyMap = null; |
| private static HashMap<Integer, String> fModifierKindMap = null; |
| |
| /** |
| * Flag that indicates the request was generated from inside of this JDI |
| * implementation. |
| */ |
| private boolean fGeneratedInside = false; |
| |
| /** User property map. */ |
| private HashMap<Object, Object> fPropertyMap; |
| |
| /** |
| * RequestId of EventRequest, assigned by the reply data of the JDWP Event |
| * Reuqest Set command, null if request had not yet been enabled. |
| */ |
| protected RequestID fRequestID = null; |
| /** |
| * Determines the threads to suspend when the requested event occurs in the |
| * target VM. |
| */ |
| private byte fSuspendPolicy = SUSPEND_ALL; // Default is as specified by JDI |
| // spec. |
| |
| /** |
| * Modifiers. |
| */ |
| /** Count filters. */ |
| protected ArrayList<Integer> fCountFilters; |
| |
| /** Thread filters. */ |
| protected ArrayList<ThreadReference> fThreadFilters = null; |
| |
| /** Class filters. */ |
| protected ArrayList<String> fClassFilters = null; |
| |
| /** Class filters. */ |
| protected ArrayList<ReferenceType> fClassFilterRefs = null; |
| |
| /** Class Exclusion filters. */ |
| protected ArrayList<String> fClassExclusionFilters = null; |
| |
| /** Location filters. */ |
| protected ArrayList<LocationImpl> fLocationFilters = null; |
| |
| /** Exception filters. */ |
| protected ArrayList<ExceptionFilter> fExceptionFilters = null; |
| |
| /** Field filters. */ |
| protected ArrayList<FieldImpl> fFieldFilters = null; |
| |
| /** Thread step filters. */ |
| protected ArrayList<ThreadStepFilter> fThreadStepFilters = null; |
| |
| /** Instance filters. */ |
| protected ArrayList<ObjectReference> fInstanceFilters = null; |
| /** |
| * source name filters |
| * |
| * @since 3.3 |
| */ |
| protected ArrayList<String> fSourceNameFilters = null; |
| |
| /** |
| * Creates new EventRequest. |
| */ |
| protected EventRequestImpl(String description, VirtualMachineImpl vmImpl) { |
| super(description, vmImpl); |
| } |
| |
| /** |
| * @return Returns string representation. |
| */ |
| @Override |
| public String toString() { |
| return super.toString() |
| + (fRequestID == null ? RequestMessages.EventRequestImpl___not_enabled__1 |
| : RequestMessages.EventRequestImpl____2 + fRequestID); // |
| } |
| |
| /** |
| * @return Returns the value of the property with the specified key. |
| */ |
| @Override |
| public Object getProperty(Object key) { |
| if (fPropertyMap == null) { |
| return null; |
| } |
| |
| return fPropertyMap.get(key); |
| } |
| |
| /** |
| * Add an arbitrary key/value "property" to this request. |
| */ |
| @Override |
| public void putProperty(Object key, Object value) { |
| if (fPropertyMap == null) |
| fPropertyMap = new HashMap<Object, Object>(); |
| |
| if (value == null) |
| fPropertyMap.remove(key); |
| else |
| fPropertyMap.put(key, value); |
| } |
| |
| /** |
| * Sets the generated inside flag. Used for requests that are not generated |
| * by JDI requests from outside. |
| */ |
| public void setGeneratedInside() { |
| fGeneratedInside = true; |
| } |
| |
| /** |
| * @return Returns whether the event request was generated from inside of |
| * this JDI implementation. |
| */ |
| public final boolean isGeneratedInside() { |
| return fGeneratedInside; |
| } |
| |
| /** |
| * Disables event request. |
| */ |
| @Override |
| public synchronized void disable() { |
| if (!isEnabled()) |
| return; |
| |
| initJdwpRequest(); |
| try { |
| ByteArrayOutputStream outBytes = new ByteArrayOutputStream(); |
| DataOutputStream outData = new DataOutputStream(outBytes); |
| writeByte(eventKind(), |
| "event kind", EventImpl.eventKindMap(), outData); //$NON-NLS-1$ |
| fRequestID.write(this, outData); |
| |
| JdwpReplyPacket replyPacket = requestVM(JdwpCommandPacket.ER_CLEAR, |
| outBytes); |
| switch (replyPacket.errorCode()) { |
| case JdwpReplyPacket.NOT_FOUND: |
| throw new InvalidRequestStateException(); |
| } |
| defaultReplyErrorHandler(replyPacket.errorCode()); |
| |
| virtualMachineImpl().eventRequestManagerImpl() |
| .removeRequestIDMapping(this); |
| fRequestID = null; |
| } catch (IOException e) { |
| defaultIOExceptionHandler(e); |
| } finally { |
| handledJdwpRequest(); |
| } |
| } |
| |
| /** |
| * Enables event request. |
| */ |
| @Override |
| public synchronized void enable() { |
| if (isEnabled()) |
| return; |
| |
| initJdwpRequest(); |
| try { |
| ByteArrayOutputStream outBytes = new ByteArrayOutputStream(); |
| DataOutputStream outData = new DataOutputStream(outBytes); |
| writeByte(eventKind(), |
| "event kind", EventImpl.eventKindMap(), outData); //$NON-NLS-1$ |
| writeByte( |
| suspendPolicyJDWP(), |
| "suspend policy", EventRequestImpl.suspendPolicyMap(), outData); //$NON-NLS-1$ |
| writeInt(modifierCount(), "modifiers", outData); //$NON-NLS-1$ |
| writeModifiers(outData); |
| |
| JdwpReplyPacket replyPacket = requestVM(JdwpCommandPacket.ER_SET, |
| outBytes); |
| defaultReplyErrorHandler(replyPacket.errorCode()); |
| DataInputStream replyData = replyPacket.dataInStream(); |
| fRequestID = RequestID.read(this, replyData); |
| virtualMachineImpl().eventRequestManagerImpl().addRequestIDMapping(this); |
| } catch (IOException e) { |
| defaultIOExceptionHandler(e); |
| } finally { |
| handledJdwpRequest(); |
| } |
| } |
| |
| /** |
| * Clear all breakpoints (used by EventRequestManager). |
| */ |
| public static void clearAllBreakpoints(MirrorImpl mirror) { |
| mirror.initJdwpRequest(); |
| try { |
| JdwpReplyPacket replyPacket = mirror |
| .requestVM(JdwpCommandPacket.ER_CLEAR_ALL_BREAKPOINTS); |
| mirror.defaultReplyErrorHandler(replyPacket.errorCode()); |
| } finally { |
| mirror.handledJdwpRequest(); |
| } |
| } |
| |
| /** |
| * @return Returns whether event request is enabled. |
| */ |
| @Override |
| public synchronized final boolean isEnabled() { |
| return fRequestID != null; |
| } |
| |
| /** |
| * Disables or enables event request. |
| */ |
| @Override |
| public void setEnabled(boolean enable) { |
| if (enable) |
| enable(); |
| else |
| disable(); |
| } |
| |
| /** |
| * @exception InvalidRequestStateException |
| * is thrown if this request is enabled. |
| */ |
| public void checkDisabled() throws InvalidRequestStateException { |
| if (isEnabled()) |
| throw new InvalidRequestStateException(); |
| } |
| |
| /** |
| * Sets suspend policy. |
| */ |
| @Override |
| public void setSuspendPolicy(int suspendPolicy) { |
| fSuspendPolicy = (byte) suspendPolicy; |
| if (isEnabled()) { |
| disable(); |
| enable(); |
| } |
| } |
| |
| /** |
| * @return Returns suspend policy. |
| */ |
| @Override |
| public int suspendPolicy() { |
| return fSuspendPolicy; |
| } |
| |
| /** |
| * @return Returns requestID, or null if request ID is not (yet) assigned. |
| */ |
| public final RequestID requestID() { |
| return fRequestID; |
| } |
| |
| /** |
| * Sets countfilter. |
| */ |
| @Override |
| public void addCountFilter(int count) throws InvalidRequestStateException { |
| checkDisabled(); |
| if (fCountFilters == null) |
| fCountFilters = new ArrayList<Integer>(); |
| |
| fCountFilters.add(new Integer(count)); |
| } |
| |
| /** |
| * Restricts reported events to those in the given thread. |
| */ |
| public void addThreadFilter(ThreadReference threadFilter) |
| throws ObjectCollectedException, VMMismatchException, |
| InvalidRequestStateException { |
| checkVM(threadFilter); |
| checkDisabled(); |
| if (threadFilter.isCollected()) |
| throw new ObjectCollectedException(); |
| if (fThreadFilters == null) |
| fThreadFilters = new ArrayList<ThreadReference>(); |
| |
| fThreadFilters.add(threadFilter); |
| } |
| |
| /** |
| * Restricts the events generated by this request to the preparation of |
| * reference types whose name matches this restricted regular expression. |
| */ |
| public void addClassFilter(ReferenceType filter) |
| throws VMMismatchException, InvalidRequestStateException { |
| checkVM(filter); |
| checkDisabled(); |
| if (fClassFilterRefs == null) |
| fClassFilterRefs = new ArrayList<ReferenceType>(); |
| |
| fClassFilterRefs.add(filter); |
| } |
| |
| /** |
| * Restricts the events generated by this request to be the preparation of |
| * the given reference type and any subtypes. |
| */ |
| public void addClassFilter(String filter) |
| throws InvalidRequestStateException { |
| checkDisabled(); |
| if (fClassFilters == null) |
| fClassFilters = new ArrayList<String>(); |
| |
| fClassFilters.add(filter); |
| } |
| |
| /** |
| * Restricts the events generated by this request to the preparation of |
| * reference types whose name does not match this restricted regular |
| * expression. |
| */ |
| public void addClassExclusionFilter(String filter) |
| throws InvalidRequestStateException { |
| checkDisabled(); |
| if (fClassExclusionFilters == null) |
| fClassExclusionFilters = new ArrayList<String>(); |
| |
| fClassExclusionFilters.add(filter); |
| } |
| |
| /** |
| * Restricts the events generated by this request to those that occur at the |
| * given location. |
| */ |
| public void addLocationFilter(LocationImpl location) |
| throws VMMismatchException { |
| checkDisabled(); |
| // Used in createBreakpointRequest. |
| checkVM(location); |
| if (fLocationFilters == null) |
| fLocationFilters = new ArrayList<LocationImpl>(); |
| |
| fLocationFilters.add(location); |
| } |
| |
| /** |
| * Restricts reported exceptions by their class and whether they are caught |
| * or uncaught. |
| */ |
| public void addExceptionFilter(ReferenceTypeImpl refType, |
| boolean notifyCaught, boolean notifyUncaught) |
| throws VMMismatchException { |
| checkDisabled(); |
| // refType Null means report exceptions of all types. |
| if (refType != null) |
| checkVM(refType); |
| |
| if (fExceptionFilters == null) |
| fExceptionFilters = new ArrayList<ExceptionFilter>(); |
| |
| ExceptionFilter filter = new ExceptionFilter(); |
| filter.fException = refType; |
| filter.fNotifyCaught = notifyCaught; |
| filter.fNotifyUncaught = notifyUncaught; |
| fExceptionFilters.add(filter); |
| } |
| |
| /** |
| * Restricts reported events to those that occur for a given field. |
| */ |
| public void addFieldFilter(FieldImpl field) throws VMMismatchException { |
| checkDisabled(); |
| // Used in createXWatchpointRequest methods. |
| checkVM(field); |
| if (fFieldFilters == null) |
| fFieldFilters = new ArrayList<FieldImpl>(); |
| |
| fFieldFilters.add(field); |
| } |
| |
| /** |
| * Restricts reported step events to those which satisfy depth and size |
| * constraints. |
| */ |
| public void addStepFilter(ThreadReferenceImpl thread, int size, int depth) |
| throws VMMismatchException { |
| checkDisabled(); |
| // Used in createStepRequest. |
| checkVM(thread); |
| |
| if (fThreadStepFilters == null) |
| fThreadStepFilters = new ArrayList<ThreadStepFilter>(); |
| |
| ThreadStepFilter filter = new ThreadStepFilter(); |
| filter.fThread = thread; |
| filter.fThreadStepSize = size; |
| filter.fThreadStepDepth = depth; |
| fThreadStepFilters.add(filter); |
| } |
| |
| /** |
| * Helper method which allows instance filters to be added |
| * |
| * @param instance |
| * the object ref instance to add to the listing |
| */ |
| public void addInstanceFilter(ObjectReference instance) { |
| checkDisabled(); |
| checkVM(instance); |
| if (fInstanceFilters == null) { |
| fInstanceFilters = new ArrayList<ObjectReference>(); |
| } |
| fInstanceFilters.add(instance); |
| } |
| |
| /** |
| * Adds a source name filter to the request. An exact match or pattern |
| * beginning OR ending in '*'. |
| * |
| * @param pattern |
| * source name pattern |
| * @since 3.3 |
| */ |
| public void addSourceNameFilter(String pattern) { |
| checkDisabled(); |
| if (fSourceNameFilters == null) { |
| fSourceNameFilters = new ArrayList<String>(); |
| } |
| fSourceNameFilters.add(pattern); |
| } |
| |
| /** |
| * From here on JDWP functionality of EventRequest is implemented. |
| */ |
| |
| /** |
| * @return Returns JDWP constant for suspend policy. |
| */ |
| public byte suspendPolicyJDWP() { |
| switch (fSuspendPolicy) { |
| case SUSPEND_NONE: |
| return SUSPENDPOL_NONE_JDWP; |
| case SUSPEND_EVENT_THREAD: |
| return SUSPENDPOL_EVENT_THREAD_JDWP; |
| case SUSPEND_ALL: |
| return SUSPENDPOL_ALL_JDWP; |
| default: |
| throw new InternalException( |
| RequestMessages.EventRequestImpl_Invalid_suspend_policy_encountered___3 |
| + fSuspendPolicy); |
| } |
| } |
| |
| /** |
| * @return Returns JDWP constant for step size. |
| */ |
| public int threadStepSizeJDWP(int threadStepSize) { |
| switch (threadStepSize) { |
| case StepRequest.STEP_MIN: |
| return STEP_SIZE_MIN_JDWP; |
| case StepRequest.STEP_LINE: |
| return STEP_SIZE_LINE_JDWP; |
| default: |
| throw new InternalException( |
| RequestMessages.EventRequestImpl_Invalid_step_size_encountered___4 |
| + threadStepSize); |
| } |
| } |
| |
| /** |
| * @return Returns JDWP constant for step depth. |
| */ |
| public int threadStepDepthJDWP(int threadStepDepth) { |
| switch (threadStepDepth) { |
| case StepRequest.STEP_INTO: |
| return STEP_DEPTH_INTO_JDWP; |
| case StepRequest.STEP_OVER: |
| return STEP_DEPTH_OVER_JDWP; |
| case StepRequest.STEP_OUT: |
| return STEP_DEPTH_OUT_JDWP; |
| default: |
| throw new InternalException( |
| RequestMessages.EventRequestImpl_Invalid_step_depth_encountered___5 |
| + threadStepDepth); |
| } |
| } |
| |
| /** |
| * @return Returns JDWP EventKind. |
| */ |
| protected abstract byte eventKind(); |
| |
| /** |
| * @return Returns number of modifiers. |
| */ |
| protected int modifierCount() { |
| int count = 0; |
| |
| if (fCountFilters != null) |
| count += fCountFilters.size(); |
| if (fThreadFilters != null) |
| count += fThreadFilters.size(); |
| if (fClassFilterRefs != null) |
| count += fClassFilterRefs.size(); |
| if (fClassFilters != null) |
| count += fClassFilters.size(); |
| if (fClassExclusionFilters != null) |
| count += fClassExclusionFilters.size(); |
| if (fLocationFilters != null) |
| count += fLocationFilters.size(); |
| if (fExceptionFilters != null) |
| count += fExceptionFilters.size(); |
| if (fFieldFilters != null) |
| count += fFieldFilters.size(); |
| if (fThreadStepFilters != null) |
| count += fThreadStepFilters.size(); |
| if (fInstanceFilters != null) |
| count += fInstanceFilters.size(); |
| if (fSourceNameFilters != null) { |
| if (supportsSourceNameFilters()) { |
| count += fSourceNameFilters.size(); |
| } |
| } |
| return count; |
| } |
| |
| /** |
| * Writes JDWP bytestream representation of modifiers. |
| */ |
| protected void writeModifiers(DataOutputStream outData) throws IOException { |
| // Note: for some reason the order of these modifiers matters when |
| // communicating with SUN's VM. |
| // It seems to expect them 'the wrong way around'. |
| if (fThreadStepFilters != null) { |
| for (int i = 0; i < fThreadStepFilters.size(); i++) { |
| ThreadStepFilter filter = fThreadStepFilters |
| .get(i); |
| writeByte(MODIF_KIND_STEP, |
| "modifier", modifierKindMap(), outData); //$NON-NLS-1$ |
| filter.fThread.write(this, outData); |
| writeInt(threadStepSizeJDWP(filter.fThreadStepSize), |
| "step size", outData); //$NON-NLS-1$ |
| writeInt(threadStepDepthJDWP(filter.fThreadStepDepth), |
| "step depth", outData); //$NON-NLS-1$ |
| } |
| } |
| if (fFieldFilters != null) { |
| for (int i = 0; i < fFieldFilters.size(); i++) { |
| writeByte(MODIF_KIND_FIELDONLY, |
| "modifier", modifierKindMap(), outData); //$NON-NLS-1$ |
| fFieldFilters.get(i).writeWithReferenceType(this, |
| outData); |
| } |
| } |
| if (fExceptionFilters != null) { |
| for (int i = 0; i < fExceptionFilters.size(); i++) { |
| ExceptionFilter filter = fExceptionFilters |
| .get(i); |
| writeByte(MODIF_KIND_EXCEPTIONONLY, |
| "modifier", modifierKindMap(), outData); //$NON-NLS-1$ |
| if (filter.fException != null) |
| filter.fException.write(this, outData); |
| else |
| ReferenceTypeImpl.writeNull(this, outData); |
| |
| writeBoolean(filter.fNotifyCaught, "notify caught", outData); //$NON-NLS-1$ |
| writeBoolean(filter.fNotifyUncaught, "notify uncaught", outData); //$NON-NLS-1$ |
| } |
| } |
| if (fLocationFilters != null) { |
| for (int i = 0; i < fLocationFilters.size(); i++) { |
| writeByte(MODIF_KIND_LOCATIONONLY, |
| "modifier", modifierKindMap(), outData); //$NON-NLS-1$ |
| fLocationFilters.get(i).write(this, outData); |
| } |
| } |
| if (fClassExclusionFilters != null) { |
| for (int i = 0; i < fClassExclusionFilters.size(); i++) { |
| writeByte(MODIF_KIND_CLASSEXCLUDE, |
| "modifier", modifierKindMap(), outData); //$NON-NLS-1$ |
| writeString(fClassExclusionFilters.get(i), |
| "class excl. filter", outData); //$NON-NLS-1$ |
| } |
| } |
| if (fClassFilters != null) { |
| for (int i = 0; i < fClassFilters.size(); i++) { |
| writeByte(MODIF_KIND_CLASSMATCH, |
| "modifier", modifierKindMap(), outData); //$NON-NLS-1$ |
| writeString(fClassFilters.get(i), |
| "class filter", outData); //$NON-NLS-1$ |
| } |
| } |
| if (fClassFilterRefs != null) { |
| for (int i = 0; i < fClassFilterRefs.size(); i++) { |
| writeByte(MODIF_KIND_CLASSONLY, |
| "modifier", modifierKindMap(), outData); //$NON-NLS-1$ |
| ((ReferenceTypeImpl) fClassFilterRefs.get(i)).write(this, |
| outData); |
| } |
| } |
| if (fThreadFilters != null) { |
| for (int i = 0; i < fThreadFilters.size(); i++) { |
| writeByte(MODIF_KIND_THREADONLY, |
| "modifier", modifierKindMap(), outData); //$NON-NLS-1$ |
| ((ThreadReferenceImpl) fThreadFilters.get(i)).write(this, |
| outData); |
| } |
| } |
| if (fCountFilters != null) { |
| for (int i = 0; i < fCountFilters.size(); i++) { |
| writeByte(MODIF_KIND_COUNT, |
| "modifier", modifierKindMap(), outData); //$NON-NLS-1$ |
| writeInt(fCountFilters.get(i).intValue(), |
| "count filter", outData); //$NON-NLS-1$ |
| } |
| } |
| if (fInstanceFilters != null) { |
| for (int i = 0; i < fInstanceFilters.size(); i++) { |
| writeByte(MODIF_KIND_INSTANCE, |
| "modifier", modifierKindMap(), outData); //$NON-NLS-1$ |
| ((ObjectReferenceImpl) fInstanceFilters.get(i)).write(this, |
| outData); |
| } |
| } |
| if (fSourceNameFilters != null) { |
| if (supportsSourceNameFilters()) { |
| for (int i = 0; i < fSourceNameFilters.size(); i++) { |
| writeByte(MODIF_KIND_SOURCE_NAME_FILTER, |
| "modifier", modifierKindMap(), outData); //$NON-NLS-1$ |
| writeString(fSourceNameFilters.get(i), |
| "modifier", outData); //$NON-NLS-1$ |
| } |
| } |
| } |
| } |
| |
| /** |
| * Returns whether JDWP supports source name filters (a 1.6 feature). |
| * |
| * @return whether JDWP supports source name filters |
| */ |
| private boolean supportsSourceNameFilters() { |
| return ((VirtualMachineImpl) virtualMachine()) |
| .isJdwpVersionGreaterOrEqual(1, 6); |
| } |
| |
| /** |
| * Retrieves constant mappings. |
| */ |
| public static void getConstantMaps() { |
| if (fStepSizeMap != null) |
| return; |
| |
| java.lang.reflect.Field[] fields = EventRequestImpl.class |
| .getDeclaredFields(); |
| fStepSizeMap = new HashMap<Integer, String>(); |
| fStepDepthMap = new HashMap<Integer, String>(); |
| fSuspendPolicyMap = new HashMap<Integer, String>(); |
| fModifierKindMap = new HashMap<Integer, String>(); |
| for (Field field : fields) { |
| if ((field.getModifiers() & java.lang.reflect.Modifier.PUBLIC) == 0 |
| || (field.getModifiers() & java.lang.reflect.Modifier.STATIC) == 0 |
| || (field.getModifiers() & java.lang.reflect.Modifier.FINAL) == 0) |
| continue; |
| |
| try { |
| String name = field.getName(); |
| Integer intValue = new Integer(field.getInt(null)); |
| if (name.startsWith("STEP_SIZE_")) { //$NON-NLS-1$ |
| name = name.substring(10); |
| fStepSizeMap.put(intValue, name); |
| } else if (name.startsWith("STEP_DEPTH_")) { //$NON-NLS-1$ |
| name = name.substring(11); |
| fStepDepthMap.put(intValue, name); |
| } else if (name.startsWith("SUSPENDPOL_")) { //$NON-NLS-1$ |
| name = name.substring(11); |
| fSuspendPolicyMap.put(intValue, name); |
| } else if (name.startsWith("MODIF_KIND_")) { //$NON-NLS-1$ |
| name = name.substring(11); |
| fModifierKindMap.put(intValue, name); |
| } |
| } 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 Map<Integer, String> stepSizeMap() { |
| getConstantMaps(); |
| return fStepSizeMap; |
| } |
| |
| /** |
| * @return Returns a map with string representations of tags. |
| */ |
| public static Map<Integer, String> stepDepthMap() { |
| getConstantMaps(); |
| return fStepDepthMap; |
| } |
| |
| /** |
| * @return Returns a map with string representations of type tags. |
| */ |
| public static Map<Integer, String> suspendPolicyMap() { |
| getConstantMaps(); |
| return fSuspendPolicyMap; |
| } |
| |
| /** |
| * @return Returns a map with string representations of type tags. |
| */ |
| public static Map<Integer, String> modifierKindMap() { |
| getConstantMaps(); |
| return fModifierKindMap; |
| } |
| |
| class ExceptionFilter { |
| /** |
| * If non-null, specifies that exceptions which are instances of |
| * fExceptionFilterRef will be reported. |
| */ |
| ReferenceTypeImpl fException = null; |
| /** If true, caught exceptions will be reported. */ |
| boolean fNotifyCaught = false; |
| /** If true, uncaught exceptions will be reported. */ |
| boolean fNotifyUncaught = false; |
| } |
| |
| class ThreadStepFilter { |
| /** ThreadReference of thread in which to step. */ |
| protected ThreadReferenceImpl fThread = null; |
| /** Size of each step. */ |
| protected int fThreadStepSize; |
| /** Relative call stack limit. */ |
| protected int fThreadStepDepth; |
| } |
| } |