/*******************************************************************************
 * Copyright (c) 2000, 2015 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * 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<>();

		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<>();

		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<>();

		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<>();

		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<>();

		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<>();

		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<>();

		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 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<>();

		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 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<>();
		}
		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<>();
		}
		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 (ThreadStepFilter filter : fThreadStepFilters) {
				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 (FieldImpl field : fFieldFilters) {
				writeByte(MODIF_KIND_FIELDONLY,
						"modifier", modifierKindMap(), outData); //$NON-NLS-1$
				field.writeWithReferenceType(this,
						outData);
			}
		}
		if (fExceptionFilters != null) {
			for (ExceptionFilter filter : fExceptionFilters) {
				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 (LocationImpl locationFilter : fLocationFilters) {
				writeByte(MODIF_KIND_LOCATIONONLY,
						"modifier", modifierKindMap(), outData); //$NON-NLS-1$
				locationFilter.write(this, outData);
			}
		}
		if (fClassExclusionFilters != null) {
			for (String classExclusionFilter : fClassExclusionFilters) {
				writeByte(MODIF_KIND_CLASSEXCLUDE,
						"modifier", modifierKindMap(), outData); //$NON-NLS-1$
				writeString(classExclusionFilter,
						"class excl. filter", outData); //$NON-NLS-1$
			}
		}
		if (fClassFilters != null) {
			for (String classFilter : fClassFilters) {
				writeByte(MODIF_KIND_CLASSMATCH,
						"modifier", modifierKindMap(), outData); //$NON-NLS-1$
				writeString(classFilter,
						"class filter", outData); //$NON-NLS-1$
			}
		}
		if (fClassFilterRefs != null) {
			for (ReferenceType classFilterRef : fClassFilterRefs) {
				writeByte(MODIF_KIND_CLASSONLY,
						"modifier", modifierKindMap(), outData); //$NON-NLS-1$
				((ReferenceTypeImpl) classFilterRef).write(this,
						outData);
			}
		}
		if (fThreadFilters != null) {
			for (ThreadReference threadFilter : fThreadFilters) {
				writeByte(MODIF_KIND_THREADONLY,
						"modifier", modifierKindMap(), outData); //$NON-NLS-1$
				((ThreadReferenceImpl) threadFilter).write(this,
						outData);
			}
		}
		if (fCountFilters != null) {
			for (Integer countFilter : fCountFilters) {
				writeByte(MODIF_KIND_COUNT,
						"modifier", modifierKindMap(), outData); //$NON-NLS-1$
				writeInt(countFilter.intValue(),
						"count filter", outData); //$NON-NLS-1$
			}
		}
		if (fInstanceFilters != null) {
			for (ObjectReference instanceFilter : fInstanceFilters) {
				writeByte(MODIF_KIND_INSTANCE,
						"modifier", modifierKindMap(), outData); //$NON-NLS-1$
				((ObjectReferenceImpl) instanceFilter).write(this,
						outData);
			}
		}
		if (fSourceNameFilters != null) {
			if (supportsSourceNameFilters()) {
				for (String sourceNameFilter : fSourceNameFilters) {
					writeByte(MODIF_KIND_SOURCE_NAME_FILTER,
							"modifier", modifierKindMap(), outData); //$NON-NLS-1$
					writeString(sourceNameFilter,
							"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;

		fStepSizeMap = new HashMap<>();
		fStepDepthMap = new HashMap<>();
		fSuspendPolicyMap = new HashMap<>();
		fModifierKindMap = new HashMap<>();
		for (Field field : EventRequestImpl.class.getDeclaredFields()) {
			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;
	}
}
