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

		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 (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<>();
		fStepDepthMap = new HashMap<>();
		fSuspendPolicyMap = new HashMap<>();
		fModifierKindMap = new HashMap<>();
		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;
	}
}
