/*******************************************************************************
 * Copyright (c) 2000, 2018 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
 *     BEA - Daniel R Somerfield - Bug 89643
 *     Jesper Steen Moller - Enhancement 254677 - filter getters/setters
 *     Jesper Steen Møller <jesper@selskabet.org> - Bug 430839
 *******************************************************************************/
package org.eclipse.jdt.internal.debug.core.model;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.ISchedulingRule;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.debug.core.DebugEvent;
import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.IStatusHandler;
import org.eclipse.debug.core.model.IBreakpoint;
import org.eclipse.debug.core.model.IStackFrame;
import org.eclipse.debug.core.model.IStep;
import org.eclipse.debug.core.model.IStepFilter;
import org.eclipse.debug.core.model.ISuspendResume;
import org.eclipse.debug.core.model.ITerminate;
import org.eclipse.debug.core.model.IThread;
import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.debug.core.IEvaluationRunnable;
import org.eclipse.jdt.debug.core.IJavaBreakpoint;
import org.eclipse.jdt.debug.core.IJavaBreakpointListener;
import org.eclipse.jdt.debug.core.IJavaObject;
import org.eclipse.jdt.debug.core.IJavaStackFrame;
import org.eclipse.jdt.debug.core.IJavaThread;
import org.eclipse.jdt.debug.core.IJavaThreadGroup;
import org.eclipse.jdt.debug.core.IJavaValue;
import org.eclipse.jdt.debug.core.IJavaVariable;
import org.eclipse.jdt.debug.core.JDIDebugModel;
import org.eclipse.jdt.internal.debug.core.IJDIEventListener;
import org.eclipse.jdt.internal.debug.core.JDIDebugPlugin;
import org.eclipse.jdt.internal.debug.core.breakpoints.ConditionalBreakpointHandler;
import org.eclipse.jdt.internal.debug.core.breakpoints.JavaBreakpoint;
import org.eclipse.jdt.internal.debug.core.breakpoints.JavaLineBreakpoint;
import org.eclipse.jdt.internal.debug.core.model.MethodResult.ResultType;

import com.ibm.icu.text.MessageFormat;
import com.sun.jdi.BooleanValue;
import com.sun.jdi.ClassNotLoadedException;
import com.sun.jdi.ClassType;
import com.sun.jdi.Field;
import com.sun.jdi.IncompatibleThreadStateException;
import com.sun.jdi.IntegerValue;
import com.sun.jdi.InterfaceType;
import com.sun.jdi.InvalidStackFrameException;
import com.sun.jdi.InvalidTypeException;
import com.sun.jdi.InvocationException;
import com.sun.jdi.Location;
import com.sun.jdi.Method;
import com.sun.jdi.ObjectCollectedException;
import com.sun.jdi.ObjectReference;
import com.sun.jdi.ReferenceType;
import com.sun.jdi.StackFrame;
import com.sun.jdi.ThreadGroupReference;
import com.sun.jdi.ThreadReference;
import com.sun.jdi.VMDisconnectedException;
import com.sun.jdi.Value;
import com.sun.jdi.event.Event;
import com.sun.jdi.event.EventSet;
import com.sun.jdi.event.ExceptionEvent;
import com.sun.jdi.event.MethodEntryEvent;
import com.sun.jdi.event.MethodExitEvent;
import com.sun.jdi.event.StepEvent;
import com.sun.jdi.request.EventRequest;
import com.sun.jdi.request.EventRequestManager;
import com.sun.jdi.request.ExceptionRequest;
import com.sun.jdi.request.MethodEntryRequest;
import com.sun.jdi.request.MethodExitRequest;
import com.sun.jdi.request.StepRequest;

/**
 * Model thread implementation for an underlying thread on a VM.
 */
public class JDIThread extends JDIDebugElement implements IJavaThread {

	/**
	 * Constant for the name of the default Java stratum
	 */
	private static final String JAVA_STRATUM_CONSTANT = "Java"; //$NON-NLS-1$

	/**
	 * Constant for the name of the main thread group.
	 */
	private static final String MAIN_THREAD_GROUP = "main"; //$NON-NLS-1$

	/**
	 * @since 3.5
	 */
	public static final int RESUME_QUIET = 500;

	/**
	 * @since 3.5
	 */
	public static final int SUSPEND_QUIET = 501;

	/**
	 * Status code indicating that a request to suspend this thread has timed
	 * out
	 */
	public static final int SUSPEND_TIMEOUT = 161;
	/**
	 * Underlying thread.
	 */
	private ThreadReference fThread;
	/**
	 * Cache of previous name, used in case thread is garbage collected.
	 */
	private String fPreviousName;
	/**
	 * Collection of stack frames
	 */
	private List<IJavaStackFrame> fStackFrames;
	/**
	 * Underlying thread group, cached on first access.
	 */
	private ThreadGroupReference fThreadGroup;
	/**
	 * Name of underlying thread group, cached on first access.
	 */
	private String fThreadGroupName;
	/**
	 * Whether children need to be refreshed. Set to <code>true</code> when
	 * stack frames are re-used on the next suspend.
	 */
	private boolean fRefreshChildren = true;
	/**
	 * Currently pending step handler, <code>null</code> when not performing a
	 * step.
	 */
	private StepHandler fStepHandler = null;
	/**
	 * Whether running.
	 */
	private boolean fRunning;
	/**
	 * Whether terminated.
	 */
	private boolean fTerminated;

	/**
	 * Whether this thread is a system thread.
	 */
	private boolean fIsSystemThread;

	/**
	 * Whether this thread is a daemon thread
	 *
	 * @since 3.3
	 */
	private boolean fIsDaemon = false;

	/**
	 * The collection of breakpoints that caused the last suspend, or an empty
	 * collection if the thread is not suspended or was not suspended by any
	 * breakpoint(s).
	 */
	private List<IBreakpoint> fCurrentBreakpoints = new ArrayList<>(2);
	/**
	 * Non-null when this thread is executing an evaluation runnable. An
	 * evaluation may involve a series of method invocations.
	 */
	private IEvaluationRunnable fEvaluationRunnable = null;

	/**
	 * Whether this thread was manually suspended during an evaluation.
	 */
	private boolean fEvaluationInterrupted = false;

	/**
	 * <code>true</code> when there has been a request to suspend this thread
	 * via {@link #suspend()}. Remains <code>true</code> until there is a
	 * request to resume this thread via {@link #resume()}.
	 */
	private boolean fClientSuspendRequest = false;

	/**
	 * Whether this thread is currently invoking a method. Nested method
	 * invocations cannot be performed.
	 */
	private boolean fIsInvokingMethod = false;

	/**
	 * Lock used to wait for method invocations to complete.
	 */
	private Object fInvocationLock = new Object();

	/**
	 * Lock used to wait for evaluations to complete.
	 */
	private Object fEvaluationLock = new Object();

	/**
	 * Whether or not this thread is currently honoring breakpoints. This flag
	 * allows breakpoints to be disabled during evaluations.
	 */
	private boolean fHonorBreakpoints = true;

	/**
	 * Whether a suspend vote is currently in progress. While voting this thread
	 * does not allow other breakpoints to be hit.
	 *
	 * @since 3.5
	 */
	private boolean fSuspendVoteInProgress = false;

	/**
	 * The kind of step that was originally requested. Zero or more 'secondary
	 * steps' may be performed programmatically after the original
	 * user-requested step, and this field tracks the type (step into, over,
	 * return) of the original step.
	 */
	private int fOriginalStepKind;
	/**
	 * The JDI Location from which an original user-requested step began.
	 */
	private Location fOriginalStepLocation;
	/**
	 * The total stack depth at the time an original (user-requested) step is
	 * initiated. This is used along with the original step Location to
	 * determine if a step into comes back to the starting location and needs to
	 * be 'nudged' forward. Checking the stack depth eliminates undesired
	 * 'nudging' in recursive methods.
	 */
	private int fOriginalStepStackDepth;

	/**
	 * Whether or not this thread is currently suspending (user-requested).
	 */
	private boolean fIsSuspending = false;

	private ThreadJob fAsyncJob;

	private ThreadJob fRunningAsyncJob;

	/**
	 * The current MethodExitRequest if a step-return or step-over is in progress.
	 */
	private MethodExitRequest fCurrentMethodExitRequest;

	/**
	 * The current ExceptionRequest if a step-return or step-over is in progress.
	 */
	private ExceptionRequest fCurrentExceptionRequest;

	/**
	 * The current MethodEntryRequest if a step-over is in progress.
	 */
	private MethodEntryRequest fCurrentMethodEntryRequest;

	/**
	 * Method for which a result value is expected
	 */
	private Method fStepResultMethod;

	/**
	 * The location if a step-over is in progress.
	 */
	private Location fStepOverLocation;

	/**
	 * The depth if a step-over is in progress.
	 */
	private int fStepOverFrameCount;

	/**
	 * Candidate for depth of stack that will be returned values belong to. Is copied to fStepReturnTargetDepth only when step-return is actually
	 * observed
	 */
	private int fStepReturnTargetFrameCount;

	private MethodResult fStepResultCandidate;

	/**
	 * Result of the last step step-over or step-return operation or method exit breakpoint of exception break point
	 */
	private MethodResult fMethodResult;

	/**
	 * Creates a new thread on the underlying thread reference in the given
	 * debug target.
	 *
	 * @param target
	 *            the debug target in which this thread is contained
	 * @param thread
	 *            the underlying thread on the VM
	 * @exception ObjectCollectedException
	 *                if the underlying thread has been garbage collected and
	 *                cannot be properly initialized
	 */
	public JDIThread(JDIDebugTarget target, ThreadReference thread)
			throws ObjectCollectedException {
		super(target);
		setUnderlyingThread(thread);
		initialize();
	}

	/**
	 * Thread initialization:
	 * <ul>
	 * <li>Determines if this thread is a system thread</li>
	 * <li>Sets terminated state to <code>false</code></li>
	 * <li>Determines suspended state from underlying thread</li>
	 * <li>Sets this threads stack frames to an empty collection</li>
	 * </ul>
	 *
	 * @exception ObjectCollectedException
	 *                if the thread has been garbage collected and cannot be
	 *                initialized
	 */
	protected void initialize() throws ObjectCollectedException {
		fStackFrames = new ArrayList<>();
		// system thread
		try {
			determineIfSystemThread();
		} catch (DebugException e) {
			Throwable underlyingException = e.getStatus().getException();
			if (underlyingException instanceof VMDisconnectedException) {
				// Threads may be created by the VM at shutdown
				// as finalizers. The VM may be disconnected by
				// the time we hear about the thread creation.
				disconnected();
				return;
			}
			if (underlyingException instanceof ObjectCollectedException) {
				throw (ObjectCollectedException) underlyingException;
			}
			logError(e);
		}

		try {
			determineIfDaemonThread();
		} catch (DebugException e) {
			Throwable underlyingException = e.getStatus().getException();
			if (underlyingException instanceof VMDisconnectedException) {
				// Threads may be created by the VM at shutdown
				// as finalizers. The VM may be disconnected by
				// the time we hear about the thread creation.
				disconnected();
				return;
			}
			logError(e);
		}

		try {
			ThreadGroupReference group = getUnderlyingThreadGroup();
			// might already be terminated
			if (group != null) {
				getJavaDebugTarget().addThreadGroup(group);
			}
		} catch (DebugException e1) {
		}

		// state
		setTerminated(false);
		setRunning(false);
		try {
			// see bug 30816
			if (fThread.status() == ThreadReference.THREAD_STATUS_UNKNOWN) {
				setRunning(true);
				return;
			}
		} catch (VMDisconnectedException e) {
			disconnected();
			return;
		} catch (ObjectCollectedException e) {
			throw e;
		} catch (RuntimeException e) {
			logError(e);
		}

		try {
			// This may be a transient suspend state (for example, a thread is
			// handling a
			// class prepare event quietly). The class prepare event handler
			// will notify
			// this thread when it resumes
			setRunning(!fThread.isSuspended());
		} catch (VMDisconnectedException e) {
			disconnected();
			return;
		} catch (ObjectCollectedException e) {
			throw e;
		} catch (RuntimeException e) {
			logError(e);
		}
	}

	/**
	 * Adds the given breakpoint to the list of breakpoints this thread is
	 * suspended at
	 *
	 * @param bp
	 *            the breakpoint to add to the listing
	 */
	protected void addCurrentBreakpoint(IBreakpoint bp) {
		fCurrentBreakpoints.add(bp);
	}

	/**
	 * Removes the given breakpoint from the list of breakpoints this thread is
	 * suspended at (called when a breakpoint is deleted, in case we are
	 * suspended at that breakpoint)
	 *
	 * @param bp
	 *            the breakpoint to remove from the listing
	 */
	protected void removeCurrentBreakpoint(IBreakpoint bp) {
		fCurrentBreakpoints.remove(bp);
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.debug.core.model.IThread#getBreakpoints()
	 */
	@Override
	public synchronized IBreakpoint[] getBreakpoints() {
		return fCurrentBreakpoints
				.toArray(new IBreakpoint[fCurrentBreakpoints.size()]);
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.debug.core.model.ISuspendResume#canResume()
	 */
	@Override
	public boolean canResume() {
		return isSuspended()
				&& (!isPerformingEvaluation() || isInvokingMethod())
				&& !isSuspendVoteInProgress()
				|| getDebugTarget().isSuspended();
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.debug.core.model.ISuspendResume#canSuspend()
	 */
	@Override
	public boolean canSuspend() {
		return !isSuspended()
				|| (isPerformingEvaluation() && !isInvokingMethod())
				|| isSuspendVoteInProgress();
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.debug.core.model.ITerminate#canTerminate()
	 */
	@Override
	public boolean canTerminate() {
		return getDebugTarget().canTerminate();
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.debug.core.model.IStep#canStepInto()
	 */
	@Override
	public boolean canStepInto() {
		return canStep();
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.debug.core.model.IStep#canStepOver()
	 */
	@Override
	public boolean canStepOver() {
		return canStep();
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.debug.core.model.IStep#canStepReturn()
	 */
	@Override
	public boolean canStepReturn() {
		return canStep();
	}

	/**
	 * Returns whether this thread is in a valid state to step.
	 *
	 * @return whether this thread is in a valid state to step
	 */
	protected boolean canStep() {
		try {
			return isSuspended()
					&& (!isPerformingEvaluation() || isInvokingMethod())
					&& !isSuspendVoteInProgress() && !isStepping()
					&& getTopStackFrame() != null
					&& !getJavaDebugTarget().isPerformingHotCodeReplace();
		} catch (DebugException e) {
			return false;
		}
	}

	/**
	 * Determines and sets whether this thread represents a system thread.
	 *
	 * @exception DebugException
	 *                if this method fails. Reasons include:
	 *                <ul>
	 *                <li>Failure communicating with the VM. The
	 *                DebugException's status code contains the underlying
	 *                exception responsible for the failure.</li>
	 *                </ul>
	 */
	protected void determineIfSystemThread() throws DebugException {
		fIsSystemThread = false;
		ThreadGroupReference tgr = getUnderlyingThreadGroup();
		fIsSystemThread = tgr != null;
		while (tgr != null) {
			String tgn = null;
			try {
				tgn = tgr.name();
				tgr = tgr.parent();
			} catch (UnsupportedOperationException e) {
				fIsSystemThread = false;
				break;
			} catch (RuntimeException e) {
				targetRequestFailed(
						MessageFormat.format(
								JDIDebugModelMessages.JDIThread_exception_determining_if_system_thread,
								e.toString()), e);
				// execution will not reach this line, as
				// #targetRequestFailed will throw an exception
				return;
			}
			if (tgn != null && tgn.equals(MAIN_THREAD_GROUP)) {
				fIsSystemThread = false;
				break;
			}
		}
	}

	/**
	 * Determines whether this is a daemon thread.
	 *
	 * @throws DebugException
	 *             on failure
	 */
	protected void determineIfDaemonThread() throws DebugException {
		fIsDaemon = false;
		try {
			ReferenceType referenceType = getUnderlyingThread().referenceType();
			Field field = referenceType.fieldByName("daemon"); //$NON-NLS-1$
			if (field == null) {
				field = referenceType.fieldByName("isDaemon"); //$NON-NLS-1$
			}
			if (field != null) {
				if (field.signature().equals(Signature.SIG_BOOLEAN)) {
					Value value = getUnderlyingThread().getValue(field);
					if (value instanceof BooleanValue) {
						fIsDaemon = ((BooleanValue) value).booleanValue();
					}
				}
			}
		} catch (ObjectCollectedException oce) {/*
												 * do nothing thread does not
												 * exist
												 */
		} catch (RuntimeException e) {
			targetRequestFailed(JDIDebugModelMessages.JDIThread_47, e);
		}
	}

	/**
	 * NOTE: this method returns a copy of this thread's stack frames.
	 *
	 * @see IThread#getStackFrames()
	 */
	@Override
	public synchronized IStackFrame[] getStackFrames() throws DebugException {
		List<IJavaStackFrame> list = computeStackFrames();
		return list.toArray(new IStackFrame[list.size()]);
	}

	/**
	 * @see #computeStackFrames()
	 *
	 * @param refreshChildren
	 *            whether or not this method should request new stack frames
	 *            from the VM
	 * @return the list of stackframes
	 * @throws DebugException
	 *             if an exception occurs retrieving frames
	 */
	protected synchronized List<IJavaStackFrame> computeStackFrames(boolean refreshChildren)
			throws DebugException {
		if (isSuspended()) {
			if (isTerminated()) {
				fStackFrames.clear();
			} else if (refreshChildren) {
				List<StackFrame> frames = getUnderlyingFrames();
				int oldSize = fStackFrames.size();
				if (oldSize > 0) {
					((JDIStackFrame) fStackFrames.get(0)).setIsTop(false);
				}
				int newSize = frames.size();
				int discard = oldSize - newSize; // number of old frames to
													// discard, if any
				for (int i = 0; i < discard; i++) {
					JDIStackFrame invalid = (JDIStackFrame) fStackFrames
							.remove(0);
					invalid.bind(null, -1);
				}
				int newFrames = newSize - oldSize; // number of frames to
													// create, if any
				int depth = oldSize;
				for (int i = newFrames - 1; i >= 0; i--) {
					fStackFrames.add(0, new JDIStackFrame(this,
							frames.get(i), depth));
					depth++;
				}
				int numToRebind = Math.min(newSize, oldSize); // number of
																// frames to
																// attempt to
																// re-bind
				int offset = newSize - 1;
				for (depth = 0; depth < numToRebind; depth++) {
					JDIStackFrame oldFrame = (JDIStackFrame) fStackFrames
							.get(offset);
					StackFrame frame = frames.get(offset);
					JDIStackFrame newFrame = oldFrame.bind(frame, depth);
					if (newFrame != oldFrame) {
						fStackFrames.set(offset, newFrame);
					}
					offset--;
				}
				if (newSize > 0) {
					((JDIStackFrame) fStackFrames.get(0)).setIsTop(true);
				}
			}
			fRefreshChildren = false;
		} else {
			return Collections.EMPTY_LIST;
		}
		return fStackFrames;
	}

	/**
	 * Returns this thread's current stack frames as a list, computing them if
	 * required. Returns an empty collection if this thread is not currently
	 * suspended, or this thread is terminated. This method should be used
	 * internally to get the current stack frames, instead of calling
	 * <code>#getStackFrames()</code>, which makes a copy of the current list.
	 * <p>
	 * Before a thread is resumed a call must be made to one of:
	 * <ul>
	 * <li><code>preserveStackFrames()</code></li>
	 * <li><code>disposeStackFrames()</code></li>
	 * </ul>
	 * If stack frames are disposed before a thread is resumed, stack frames are
	 * completely re-computed on the next call to this method. If stack frames
	 * are to be preserved, this method will attempt to re-use any stack frame
	 * objects which represent the same stack frame as on the previous suspend.
	 * Stack frames are cached until a subsequent call to preserve or dispose
	 * stack frames.
	 * </p>
	 *
	 * @return list of <code>IJavaStackFrame</code>
	 * @exception DebugException
	 *                if this method fails. Reasons include:
	 *                <ul>
	 *                <li>Failure communicating with the VM. The
	 *                DebugException's status code contains the underlying
	 *                exception responsible for the failure.</li>
	 *                </ul>
	 */
	public synchronized List<IJavaStackFrame> computeStackFrames() throws DebugException {
		return computeStackFrames(fRefreshChildren);
	}

	/**
	 * This method differs from computeStackFrames() in that it always requests
	 * new stack frames from the VM. As this is an expensive operation, this
	 * method should only be used by clients who know for certain that the stack
	 * frames on the VM have changed.
	 *
	 * @see JDIThread#computeStackFrames()
	 * @return the listing of stackframes or an empty list, never
	 *         <code>null</code>
	 * @throws DebugException
	 *             if an exception occurs retrieving the stackframes
	 */
	public List<IJavaStackFrame> computeNewStackFrames() throws DebugException {
		return computeStackFrames(true);
	}

	private List<StackFrame> getUnderlyingFrames() throws DebugException {
		if (!isSuspended()) {
			// Checking isSuspended here eliminates a race condition in resume
			// between the time stack frames are preserved and the time the
			// underlying thread is actually resumed.
			requestFailed(
					JDIDebugModelMessages.JDIThread_Unable_to_retrieve_stack_frame___thread_not_suspended__1,
					null, IJavaThread.ERR_THREAD_NOT_SUSPENDED);
		}
		try {
			return fThread.frames();
		} catch (IncompatibleThreadStateException e) {
			requestFailed(
					JDIDebugModelMessages.JDIThread_Unable_to_retrieve_stack_frame___thread_not_suspended__1,
					e, IJavaThread.ERR_THREAD_NOT_SUSPENDED);
		} catch (RuntimeException e) {
			targetRequestFailed(
					MessageFormat.format(
							JDIDebugModelMessages.JDIThread_exception_retrieving_stack_frames_2,
							e.toString()), e);
		} catch (InternalError e) {
			targetRequestFailed(
					MessageFormat.format(
							JDIDebugModelMessages.JDIThread_exception_retrieving_stack_frames_2,
							e.toString()), e);
		}
		// execution will not reach this line, as
		// #targetRequestFailed will thrown an exception
		return null;
	}

	/**
	 * Returns the number of frames on the stack from the underlying thread.
	 *
	 * @return number of frames on the stack
	 * @exception DebugException
	 *                if this method fails. Reasons include:
	 *                <ul>
	 *                <li>Failure communicating with the VM. The
	 *                DebugException's status code contains the underlying
	 *                exception responsible for the failure.</li>
	 *                <li>This thread is not suspended</li>
	 *                </ul>
	 */
	protected int getUnderlyingFrameCount() throws DebugException {
		try {
			return fThread.frameCount();
		} catch (RuntimeException e) {
			targetRequestFailed(
					MessageFormat.format(
							JDIDebugModelMessages.JDIThread_exception_retrieving_frame_count,
							e.toString()), e);
		} catch (IncompatibleThreadStateException e) {
			requestFailed(
					MessageFormat.format(
							JDIDebugModelMessages.JDIThread_exception_retrieving_frame_count,
							e.toString()), e,
					IJavaThread.ERR_THREAD_NOT_SUSPENDED);
		}
		// execution will not reach here - try block will either
		// return or exception will be thrown
		return -1;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see
	 * org.eclipse.jdt.debug.core.IJavaThread#runEvaluation(org.eclipse.jdt.
	 * debug.core.IEvaluationRunnable,
	 * org.eclipse.core.runtime.IProgressMonitor, int, boolean)
	 */
	@Override
	public void runEvaluation(IEvaluationRunnable evaluation,
			IProgressMonitor monitor, int evaluationDetail,
			boolean hitBreakpoints) throws DebugException {
		if (isPerformingEvaluation()) {
			requestFailed(
					JDIDebugModelMessages.JDIThread_Cannot_perform_nested_evaluations,
					null, IJavaThread.ERR_NESTED_METHOD_INVOCATION); //
		}

		if (!canRunEvaluation()) {
			requestFailed(
					JDIDebugModelMessages.JDIThread_Evaluation_failed___thread_not_suspended,
					null, IJavaThread.ERR_THREAD_NOT_SUSPENDED);
		}

		synchronized (fEvaluationLock) {
			fEvaluationRunnable = evaluation;
			fHonorBreakpoints = hitBreakpoints;
		}
		boolean quiet = isSuspendVoteInProgress();
		if (quiet) {
			// evaluations are quiet when a suspend vote is in progress
			// (conditional breakpoints, etc.).
			fireEvent(new DebugEvent(this, DebugEvent.MODEL_SPECIFIC,
					RESUME_QUIET));
		} else {
			fireResumeEvent(evaluationDetail);
		}
		// save and restore current breakpoint information - bug 30837
		IBreakpoint[] breakpoints = getBreakpoints();
		ISchedulingRule rule = null;
		if (evaluationDetail == DebugEvent.EVALUATION_IMPLICIT) {
			rule = getThreadRule();
		}
		try {
			if (rule != null) {
				Job.getJobManager().beginRule(rule, monitor);
			}
			if (monitor == null || !monitor.isCanceled()) {
				evaluation.run(this, monitor);
			}
		} catch (DebugException e) {
			throw e;
		} finally {
			if (rule != null) {
				Job.getJobManager().endRule(rule);
			}
			synchronized (fEvaluationLock) {
				fEvaluationRunnable = null;
				fHonorBreakpoints = true;
				fEvaluationLock.notifyAll();
			}
			if (getBreakpoints().length == 0 && breakpoints.length > 0) {
				for (IBreakpoint breakpoint : breakpoints) {
					addCurrentBreakpoint(breakpoint);
				}
			}
			if (quiet) {
				fireEvent(new DebugEvent(this, DebugEvent.MODEL_SPECIFIC,
						SUSPEND_QUIET));
			} else {
				fireSuspendEvent(evaluationDetail);
			}
			if (fEvaluationInterrupted
					&& (fAsyncJob == null || fAsyncJob.isEmpty())
					&& (fRunningAsyncJob == null || fRunningAsyncJob.isEmpty())) {
				// @see bug 31585:
				// When an evaluation was interrupted & resumed, the launch view
				// does
				// not update properly. It cannot know when it is safe to
				// display frames
				// since it does not know about queued evaluations. Thus, when
				// the queue
				// is empty, we fire a change event to force the view to update.
				fEvaluationInterrupted = false;
				fireChangeEvent(DebugEvent.CONTENT);
			}
		}
	}

	/**
	 * Returns whether this thread is in a valid state to run an evaluation.
	 *
	 * @return whether this thread is in a valid state to run an evaluation
	 */
	protected boolean canRunEvaluation() {
		// NOTE similar to #canStep, except an evaluation can be run when in the
		// middle of
		// a step (conditional breakpoint, breakpoint listener, etc.)
		try {
			return isSuspended()
					&& !(isPerformingEvaluation() || isInvokingMethod())
					&& getTopStackFrame() != null
					&& !getJavaDebugTarget().isPerformingHotCodeReplace();
		} catch (DebugException e) {
			return false;
		}
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see
	 * org.eclipse.jdt.debug.core.IJavaThread#queueRunnable(java.lang.Runnable)
	 */
	@Override
	public void queueRunnable(Runnable evaluation) {
		if (fAsyncJob == null) {
			fAsyncJob = new ThreadJob(this);
		}
		fAsyncJob.addRunnable(evaluation);
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.jdt.debug.core.IJavaThread#terminateEvaluation()
	 */
	@Override
	public void terminateEvaluation() throws DebugException {
		synchronized (fEvaluationLock) {
			if (canTerminateEvaluation()) {
				fEvaluationInterrupted = true;
				((ITerminate) fEvaluationRunnable).terminate();
			}
		}
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.jdt.debug.core.IJavaThread#canTerminateEvaluation()
	 */
	@Override
	public boolean canTerminateEvaluation() {
		synchronized (fEvaluationLock) {
			return fEvaluationRunnable instanceof ITerminate;
		}
	}

	/**
	 * Invokes a method on the target, in this thread, and returns the result.
	 * Only one receiver may be specified - either a class or an object, the
	 * other must be <code>null</code>. This thread is left suspended after the
	 * invocation is complete, unless a call is made to
	 * <code>abortEvaluation<code> while
	 * performing a method invocation. In that case, this thread is automatically
	 * resumed when/if this invocation (eventually) completes.
	 * <p>
	 * Method invocations cannot be nested. That is, this method must
	 * return before another call to this method can be made. This
	 * method does not return until the invocation is complete.
	 * Breakpoints can suspend a method invocation, and it is possible
	 * that an invocation will not complete due to an infinite loop
	 * or deadlock.
	 * </p>
	 * <p>
	 * Stack frames are preserved during method invocations, unless
	 * a timeout occurs. Although this thread's state is updated to
	 * running while performing an evaluation, no debug events are
	 * fired unless this invocation is interrupted by a breakpoint,
	 * or the invocation times out.
	 * </p>
	 * <p>
	 * When performing an invocation, the communication timeout with
	 * the target VM is set to infinite, as the invocation may not
	 * complete in a timely fashion, if at all. The timeout value
	 * is reset to its original value when the invocation completes.
	 * </p>
	 *
	 * @param receiverClass
	 *            the class in the target representing the receiver of a static
	 *            message send, or <code>null</code>
	 * @param receiverObject
	 *            the object in the target to be the receiver of the message
	 *            send, or <code>null</code>
	 * @param method
	 *            the underlying method to be invoked
	 * @param args
	 *            the arguments to invoke the method with (an empty list if
	 *            none)
	 * @param invokeNonvirtual
	 *            if the super-class method should be invoked
	 * @return the result of the method, as an underlying value
	 * @exception DebugException
	 *                if this method fails. Reasons include:
	 *                <ul>
	 *                <li>Failure communicating with the VM. The
	 *                DebugException's status code contains the underlying
	 *                exception responsible for the failure.</li>
	 *                <li>This thread is not suspended (status code
	 *                <code>IJavaThread.ERR_THREAD_NOT_SUSPENDED</code>)</li>
	 *                <li>This thread is already invoking a method (status code
	 *                <code>IJavaThread.ERR_NESTED_METHOD_INVOCATION</code>)</li>
	 *                <li>This thread is not suspended by a JDI request (status
	 *                code
	 *                <code>IJavaThread.ERR_INCOMPATIBLE_THREAD_STATE</code>)</li>
	 *                </ul>
	 */
	protected Value invokeMethod(ClassType receiverClass,
			ObjectReference receiverObject, Method method, List<? extends Value> args,
			boolean invokeNonvirtual) throws DebugException {
		if (receiverClass != null && receiverObject != null) {
			throw new IllegalArgumentException(
					JDIDebugModelMessages.JDIThread_can_only_specify_one_receiver_for_a_method_invocation);
		}
		Value result = null;
		int timeout = getRequestTimeout();
		try {
			// this is synchronized such that any other operation that
			// might be resuming this thread has a chance to complete before
			// we determine if it is safe to continue with a method invocation.
			// See bugs 6518, 14069
			synchronized (this) {
				if (!isSuspended()) {
					requestFailed(
							JDIDebugModelMessages.JDIThread_Evaluation_failed___thread_not_suspended,
							null, IJavaThread.ERR_THREAD_NOT_SUSPENDED);
				}
				if (isInvokingMethod()) {
					requestFailed(
							JDIDebugModelMessages.JDIThread_Cannot_perform_nested_evaluations,
							null, IJavaThread.ERR_NESTED_METHOD_INVOCATION);
				}
				// set the request timeout to be infinite
				setRequestTimeout(Integer.MAX_VALUE);
				setRunning(true);
				setInvokingMethod(true);
			}
			preserveStackFrames();
			int flags = ClassType.INVOKE_SINGLE_THREADED;
			if (invokeNonvirtual) {
				// Superclass method invocation must be performed non-virtual.
				flags |= ObjectReference.INVOKE_NONVIRTUAL;
			}
			if (receiverClass == null) {
				result = receiverObject.invokeMethod(fThread, method, args,
						flags);
			} else {
				result = receiverClass.invokeMethod(fThread, method, args,
						flags);
			}
		} catch (InvalidTypeException e) {
			invokeFailed(e, timeout);
		} catch (ClassNotLoadedException e) {
			invokeFailed(e, timeout);
		} catch (IncompatibleThreadStateException e) {
			invokeFailed(
					JDIDebugModelMessages.JDIThread_Thread_must_be_suspended_by_step_or_breakpoint_to_perform_method_invocation_1,
					IJavaThread.ERR_INCOMPATIBLE_THREAD_STATE, e, timeout);
		} catch (InvocationException e) {
			invokeFailed(e, timeout);
		} catch (RuntimeException e) {
			invokeFailed(e, timeout);
		}

		invokeComplete(timeout);
		return result;
	}

	/**
	 * Invokes a method on the target, in this thread, and returns the result.
	 * This thread is left suspended after the invocation is complete, unless
	 * a call is made to <code>abortEvaluation<code> while  performing a method
	 * invocation. In that case, this thread is automatically resumed when/if
	 * this invocation (eventually) completes.
	 * <p>
	 * Method invocations cannot be nested. That is, this method must
	 * return before another call to this method can be made. This
	 * method does not return until the invocation is complete.
	 * Breakpoints can suspend a method invocation, and it is possible
	 * that an invocation will not complete due to an infinite loop
	 * or deadlock.
	 * </p>
	 * <p>
	 * Stack frames are preserved during method invocations, unless
	 * a timeout occurs. Although this thread's state is updated to
	 * running while performing an evaluation, no debug events are
	 * fired unless this invocation is interrupted by a breakpoint,
	 * or the invocation times out.
	 * </p>
	 * <p>
	 * When performing an invocation, the communication timeout with
	 * the target VM is set to infinite, as the invocation may not
	 * complete in a timely fashion, if at all. The timeout value
	 * is reset to its original value when the invocation completes.
	 * </p>
	 *
	 * @param receiverInterface
	 *            the class in the target representing the receiver of a static
	 *            message send, or <code>null</code>
	 * @param method
	 *            the underlying method to be invoked
	 * @param args
	 *            the arguments to invoke the method with (an empty list if
	 *            none)
	 * @return the result of the method, as an underlying value
	 * @exception DebugException
	 *                if this method fails. Reasons include:
	 *                <ul>
	 *                <li>Failure communicating with the VM. The
	 *                DebugException's status code contains the underlying
	 *                exception responsible for the failure.</li>
	 *                <li>This thread is not suspended (status code
	 *                <code>IJavaThread.ERR_THREAD_NOT_SUSPENDED</code>)</li>
	 *                <li>This thread is already invoking a method (status code
	 *                <code>IJavaThread.ERR_NESTED_METHOD_INVOCATION</code>)</li>
	 *                <li>This thread is not suspended by a JDI request (status
	 *                code
	 *                <code>IJavaThread.ERR_INCOMPATIBLE_THREAD_STATE</code>)</li>
	 *                </ul>
	 */
	protected Value invokeMethod(InterfaceType receiverInterface,
			Method method, List<? extends Value> args) throws DebugException {
		Value result = null;
		int timeout = getRequestTimeout();
		try {
			// this is synchronized such that any other operation that
			// might be resuming this thread has a chance to complete before
			// we determine if it is safe to continue with a method invocation.
			// See bugs 6518, 14069
			synchronized (this) {
				if (!isSuspended()) {
					requestFailed(
							JDIDebugModelMessages.JDIThread_Evaluation_failed___thread_not_suspended,
							null, IJavaThread.ERR_THREAD_NOT_SUSPENDED);
				}
				if (isInvokingMethod()) {
					requestFailed(
							JDIDebugModelMessages.JDIThread_Cannot_perform_nested_evaluations,
							null, IJavaThread.ERR_NESTED_METHOD_INVOCATION);
				}
				// set the request timeout to be infinite
				setRequestTimeout(Integer.MAX_VALUE);
				setRunning(true);
				setInvokingMethod(true);
			}
			preserveStackFrames();
			int flags = ClassType.INVOKE_SINGLE_THREADED;
			result = receiverInterface.invokeMethod(fThread, method, args,
					flags);
		} catch (InvalidTypeException e) {
			invokeFailed(e, timeout);
		} catch (ClassNotLoadedException e) {
			invokeFailed(e, timeout);
		} catch (IncompatibleThreadStateException e) {
			invokeFailed(
					JDIDebugModelMessages.JDIThread_Thread_must_be_suspended_by_step_or_breakpoint_to_perform_method_invocation_1,
					IJavaThread.ERR_INCOMPATIBLE_THREAD_STATE, e, timeout);
		} catch (InvocationException e) {
			invokeFailed(e, timeout);
		} catch (RuntimeException e) {
			invokeFailed(e, timeout);
		}

		invokeComplete(timeout);
		return result;
	}

	/**
	 * Invokes a constructor in this thread, creating a new instance of the
	 * given class, and returns the result as an object reference. This thread
	 * is left suspended after the invocation is complete.
	 * <p>
	 * Method invocations cannot be nested. That is, this method must return
	 * before another call to this method can be made. This method does not
	 * return until the invocation is complete. Breakpoints can suspend a method
	 * invocation, and it is possible that an invocation will not complete due
	 * to an infinite loop or deadlock.
	 * </p>
	 * <p>
	 * Stack frames are preserved during method invocations, unless a timeout
	 * occurs. Although this thread's state is updated to running while
	 * performing an evaluation, no debug events are fired unless this
	 * invocation is interrupted by a breakpoint, or the invocation times out.
	 * </p>
	 * <p>
	 * When performing an invocation, the communication timeout with the target
	 * VM is set to infinite, as the invocation may not complete in a timely
	 * fashion, if at all. The timeout value is reset to its original value when
	 * the invocation completes.
	 * </p>
	 *
	 * @param receiverClass
	 *            the class in the target representing the receiver of the 'new'
	 *            message send
	 * @param constructor
	 *            the underlying constructor to be invoked
	 * @param args
	 *            the arguments to invoke the constructor with (an empty list if
	 *            none)
	 * @return a new object reference
	 * @exception DebugException
	 *                if this method fails. Reasons include:
	 *                <ul>
	 *                <li>Failure communicating with the VM. The
	 *                DebugException's status code contains the underlying
	 *                exception responsible for the failure.</li>
	 *                </ul>
	 */
	protected ObjectReference newInstance(ClassType receiverClass,
			Method constructor, List<? extends Value> args) throws DebugException {
		if (isInvokingMethod()) {
			requestFailed(
					JDIDebugModelMessages.JDIThread_Cannot_perform_nested_evaluations_2,
					null);
		}
		ObjectReference result = null;
		int timeout = getRequestTimeout();
		try {
			// set the request timeout to be infinite
			setRequestTimeout(Integer.MAX_VALUE);
			setRunning(true);
			setInvokingMethod(true);
			preserveStackFrames();
			result = receiverClass.newInstance(fThread, constructor, args,
					ClassType.INVOKE_SINGLE_THREADED);
		} catch (InvalidTypeException e) {
			invokeFailed(e, timeout);
		} catch (ClassNotLoadedException e) {
			invokeFailed(e, timeout);
		} catch (IncompatibleThreadStateException e) {
			invokeFailed(e, timeout);
		} catch (InvocationException e) {
			invokeFailed(e, timeout);
		} catch (RuntimeException e) {
			invokeFailed(e, timeout);
		}

		invokeComplete(timeout);
		return result;
	}

	/**
	 * Called when an invocation fails. Performs cleanup and throws an
	 * exception.
	 *
	 * @param e
	 *            the exception that caused the failure
	 * @param restoreTimeout
	 *            the communication timeout value, in milliseconds, that should
	 *            be reset
	 * @see #invokeComplete(int)
	 * @exception DebugException
	 *                Reasons include:
	 *                <ul>
	 *                <li>Failure communicating with the VM. The
	 *                DebugException's status code contains the underlying
	 *                exception responsible for the failure.</li>
	 *                </ul>
	 */
	protected void invokeFailed(Throwable e, int restoreTimeout)
			throws DebugException {
		invokeFailed(MessageFormat.format(
				JDIDebugModelMessages.JDIThread_exception_invoking_method,
				e.toString()),
				DebugException.TARGET_REQUEST_FAILED, e, restoreTimeout);
	}

	/**
	 * Called when an invocation fails. Performs cleanup and throws an
	 * exception.
	 *
	 * @param message
	 *            error message
	 * @param code
	 *            status code
	 * @param e
	 *            the exception that caused the failure
	 * @param restoreTimeout
	 *            the communication timeout value, in milliseconds, that should
	 *            be reset
	 * @see #invokeComplete(int)
	 * @exception DebugException
	 *                Reasons include:
	 *                <ul>
	 *                <li>Failure communicating with the VM. The
	 *                DebugException's status code contains the underlying
	 *                exception responsible for the failure.</li>
	 *                </ul>
	 */
	protected void invokeFailed(String message, int code, Throwable e,
			int restoreTimeout) throws DebugException {
		invokeComplete(restoreTimeout);
		requestFailed(message, e, code);
	}

	/**
	 * Called when a method invocation has returned, successfully or not. This
	 * method performs cleanup:
	 * <ul>
	 * <li>Resets the state of this thread to suspended</li>
	 * <li>Restores the communication timeout value</li>
	 * <li>Computes the new set of stack frames for this thread</code>
	 * </ul>
	 *
	 * @param restoreTimeout
	 *            the communication timeout value, in milliseconds, that should
	 *            be reset
	 * @see #invokeMethod(ClassType, ObjectReference, Method, List, boolean)
	 * @see #newInstance(ClassType, Method, List)
	 */
	protected synchronized void invokeComplete(int restoreTimeout) {
		setInvokingMethod(false);
		setRunning(false);
		setRequestTimeout(restoreTimeout);
		// update preserved stack frames
		try {
			computeStackFrames();
		} catch (DebugException e) {
			logError(e);
		}
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.debug.core.model.IThread#getName()
	 */
	@Override
	public String getName() throws DebugException {
		try {
			fPreviousName = fThread.name();
		} catch (RuntimeException e) {
			// Don't bother reporting the exception when retrieving the name
			// (bug 30785 & bug 33276)
			if (e instanceof ObjectCollectedException) {
				if (fPreviousName == null) {
					fPreviousName = JDIDebugModelMessages.JDIThread_garbage_collected_1;
				}
			} else if (e instanceof VMDisconnectedException) {
				if (fPreviousName == null) {
					fPreviousName = JDIDebugModelMessages.JDIThread_42;
				}
			} else {
				targetRequestFailed(
						MessageFormat.format(
								JDIDebugModelMessages.JDIThread_exception_retrieving_thread_name,
								e.toString()), e);
			}
		}
		return fPreviousName;
	}

	/**
	 * Returns the priority from the underlying {@link ReferenceType}, failing
	 * that the backing {@link Value} for the underlying {@link ThreadReference}
	 * is consulted
	 *
	 * @return the priority from the backing {@link ReferenceType} or
	 *         {@link Value}
	 * @throws DebugException
	 *             if an exception occurs retrieving the priority
	 * @see IThread#getPriority
	 */
	@Override
	public int getPriority() throws DebugException {
		// to get the priority, we must get the value from the "priority" field
		Field p = null;
		try {
			p = fThread.referenceType().fieldByName("priority"); //$NON-NLS-1$
			if (p == null) {
				requestFailed(
						JDIDebugModelMessages.JDIThread_no_priority_field, null);
			}
			Value v = fThread.getValue(p);
			if (v instanceof IntegerValue) {
				return ((IntegerValue) v).value();
			}
			requestFailed(
					JDIDebugModelMessages.JDIThread_priority_not_an_integer,
					null);
		} catch (RuntimeException e) {
			targetRequestFailed(
					MessageFormat.format(
							JDIDebugModelMessages.JDIThread_exception_retrieving_thread_priority,
							e.toString()), e);
		}
		// execution will not fall through to this line, as
		// #targetRequestFailed or #requestFailed will throw
		// an exception
		return -1;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.debug.core.model.IThread#getTopStackFrame()
	 */
	@Override
	public synchronized IStackFrame getTopStackFrame() throws DebugException {
		List<IJavaStackFrame> c = computeStackFrames();
		if (c.isEmpty()) {
			return null;
		}
		return c.get(0);
	}

	/**
	 * A breakpoint has suspended execution of this thread. Aborts any step
	 * currently in process and notifies listeners of the breakpoint to allow a
	 * vote to determine if the thread should suspend.
	 *
	 * @param breakpoint
	 *            the breakpoint that caused the suspend
	 * @param suspendVote
	 *            current vote before listeners are notified (for example, if a
	 *            step request happens at the same location as a breakpoint, the
	 *            step may have voted to suspend already - this allows a
	 *            conditional breakpoint to avoid evaluation)
	 * @return whether this thread suspended
	 */
	public boolean handleSuspendForBreakpoint(JavaBreakpoint breakpoint,
			boolean suspendVote) {
		int policy = IJavaBreakpoint.SUSPEND_THREAD;
		synchronized (this) {
			if (fClientSuspendRequest) {
				// a request to suspend has overridden the breakpoint request -
				// suspend and
				// ignore the breakpoint
				return true;
			}
			fSuspendVoteInProgress = true;
			addCurrentBreakpoint(breakpoint);
			try {
				policy = breakpoint.getSuspendPolicy();
			} catch (CoreException e) {
				logError(e);
				setRunning(true);
				return false;
			}

			// update state to suspended but don't actually
			// suspend unless a registered listener agrees
			if (policy == IJavaBreakpoint.SUSPEND_VM) {
				((JDIDebugTarget) getDebugTarget())
						.prepareToSuspendByBreakpoint(breakpoint);
			} else {
				setRunning(false);
			}
		}

		try {
			if (!(breakpoint.isTriggerPoint())) {
				if (DebugPlugin.getDefault().getBreakpointManager().hasActiveTriggerPoints()){
					fSuspendVoteInProgress = false;
					return false;
				}

			}
		}
		catch (CoreException e) {
			e.printStackTrace();
		}
		// Evaluate breakpoint condition (if any). The condition is evaluated
		// regardless of the current suspend vote status, since breakpoint
		// listeners
		// should only be notified when a condition is true (i.e. when the
		// breakpoint
		// is really hit).
		if (breakpoint instanceof JavaLineBreakpoint) {
			JavaLineBreakpoint lbp = (JavaLineBreakpoint) breakpoint;
			// evaluate condition unless we're in an evaluation already (bug
			// 284022)
			if (lbp.hasCondition() && !isPerformingEvaluation()) {
				ConditionalBreakpointHandler handler = new ConditionalBreakpointHandler();
				int vote = handler.breakpointHit(this, breakpoint);
				if (vote == IJavaBreakpointListener.DONT_SUSPEND) {
					// condition is false, breakpoint is not hit
					synchronized (this) {
						fSuspendVoteInProgress = false;
						return false;
					}
				}
				if (handler.hasErrors()) {
					// there were errors, suspend and do not notify listeners of
					// hit since
					// they were already notified of compilation/runtime errors
					synchronized (this) {
						fSuspendVoteInProgress = false;
						return true;
					}
				}
				DebugPlugin.getDefault().getBreakpointManager().enableTriggerPoints(null, false);
					// make a note that we auto-disabled the trigger point for this breakpoint.
					// we re enable it at cleanup of JDITarget
			}
		}

		// poll listeners without holding lock on thread
		boolean suspend = true;
		try {
			suspend = JDIDebugPlugin.getDefault().fireBreakpointHit(this,
					breakpoint);
		} finally {
			synchronized (this) {
				fSuspendVoteInProgress = false;
				if (fClientSuspendRequest) {
					// if a client has requested a suspend, then override the
					// vote to suspend
					suspend = true;
				}
			}
		}
		return suspend;
	}

	/**
	 * Called after an event set with a breakpoint is done being processed.
	 * Updates thread state based on the result of handling the event set.
	 * Aborts any step in progress and fires a suspend event is suspending.
	 *
	 * @param breakpoint
	 *            the breakpoint that was hit
	 * @param suspend
	 *            whether to suspend
	 * @param queue
	 *            whether to queue events or fire immediately
	 * @param set
	 *            event set handling is associated with
	 */
	public void completeBreakpointHandling(JavaBreakpoint breakpoint,
			boolean suspend, boolean queue, EventSet set) {
		synchronized (this) {
			try {
				int policy = breakpoint.getSuspendPolicy();
				// suspend or resume
				if (suspend) {
					if (policy == IJavaBreakpoint.SUSPEND_VM) {
						((JDIDebugTarget) getDebugTarget())
								.suspendedByBreakpoint(breakpoint, false, set);
					}
					abortStep();
					if (queue) {
						queueSuspendEvent(DebugEvent.BREAKPOINT, set);
					} else {
						fireSuspendEvent(DebugEvent.BREAKPOINT);
					}
				} else {
					if (policy == IJavaBreakpoint.SUSPEND_VM) {
						((JDIDebugTarget) getDebugTarget())
								.cancelSuspendByBreakpoint(breakpoint);
					} else {
						setRunning(true);
						// dispose cached stack frames so we re-retrieve on the
						// next breakpoint
						preserveStackFrames();
					}
				}
			} catch (CoreException e) {
				logError(e);
				setRunning(true);
			}
		}

	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.debug.core.model.IStep#isStepping()
	 */
	@Override
	public boolean isStepping() {
		return getPendingStepHandler() != null;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.debug.core.model.ISuspendResume#isSuspended()
	 */
	@Override
	public boolean isSuspended() {
		return !fRunning && !fTerminated;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.jdt.debug.core.IJavaThread#isSystemThread()
	 */
	@Override
	public boolean isSystemThread() {
		return fIsSystemThread;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.jdt.debug.core.IJavaThread#isDaemon()
	 */
	@Override
	public boolean isDaemon() throws DebugException {
		return fIsDaemon;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.jdt.debug.core.IJavaThread#getThreadGroupName()
	 */
	@Override
	public String getThreadGroupName() throws DebugException {
		if (fThreadGroupName == null) {
			ThreadGroupReference tgr = getUnderlyingThreadGroup();

			// bug# 20370
			if (tgr == null) {
				return null;
			}

			try {
				fThreadGroupName = tgr.name();
			} catch (RuntimeException e) {
				targetRequestFailed(
						MessageFormat.format(
								JDIDebugModelMessages.JDIThread_exception_retrieving_thread_group_name,
								e.toString()), e);
				// execution will not reach this line, as
				// #targetRequestFailed will thrown an exception
				return null;
			}
		}
		return fThreadGroupName;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.debug.core.model.ITerminate#isTerminated()
	 */
	@Override
	public boolean isTerminated() {
		return fTerminated;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.jdt.debug.core.IJavaThread#isOutOfSynch()
	 */
	@Override
	public synchronized boolean isOutOfSynch() throws DebugException {
		if (isSuspended() && ((JDIDebugTarget) getDebugTarget()).hasHCRFailed()) {
			List<IJavaStackFrame> frames = computeStackFrames();
			for(IJavaStackFrame frame : frames) {
				if(((JDIStackFrame)frame).isOutOfSynch()) {
					return true;
				}
			}
			return false;
		}
		// If the thread is not suspended, there's no way to
		// say for certain that it is running out of synch code
		return false;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.jdt.debug.core.IJavaThread#mayBeOutOfSynch()
	 */
	@Override
	public boolean mayBeOutOfSynch() {
		if (!isSuspended()) {
			return ((JDIDebugTarget) getDebugTarget()).hasHCRFailed();
		}
		return false;
	}

	/**
	 * Sets whether this thread is terminated
	 *
	 * @param terminated
	 *            whether this thread is terminated
	 */
	protected void setTerminated(boolean terminated) {
		fTerminated = terminated;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.debug.core.model.ISuspendResume#resume()
	 */
	@Override
	public synchronized void resume() throws DebugException {
		if (!isSuspended() && getDebugTarget().isSuspended()) {
			getDebugTarget().resume();
		} else {
			fClientSuspendRequest = false;
			resumeThread(true);
		}
	}

	/**
	 *
	 * Updates the state of this thread, but only fires notification to
	 * listeners if <code>fireNotification</code> is <code>true</code>.
	 *
	 * @see ISuspendResume#resume()
	 * @param fireNotification
	 *            if a resume event should be fired
	 * @throws DebugException
	 *             if an exception occurs trying to resume the thread
	 */
	private synchronized void resumeThread(boolean fireNotification)
			throws DebugException {
		if (!isSuspended() || (isPerformingEvaluation() && !isInvokingMethod())) {
			return;
		}
		try {
			setRunning(true);
			clearMethodResult();
			if (fireNotification) {
				fireResumeEvent(DebugEvent.CLIENT_REQUEST);
			}
			preserveStackFrames();
			fThread.resume();
		} catch (VMDisconnectedException e) {
			disconnected();
		} catch (RuntimeException e) {
			setRunning(false);
			fireSuspendEvent(DebugEvent.CLIENT_REQUEST);
			targetRequestFailed(MessageFormat.format(
					JDIDebugModelMessages.JDIThread_exception_resuming,
					e.toString()), e);
		}
	}

	/**
	 * Sets whether this thread is currently executing. When set to
	 * <code>true</code>, this thread's current breakpoints are cleared.
	 *
	 * @param running
	 *            whether this thread is executing
	 */
	protected void setRunning(boolean running) {
		fRunning = running;
		if (running) {
			fCurrentBreakpoints.clear();
		}
	}

	private void clearMethodResult() {
		setMethodResult(null);
	}

	/**
	 * Preserves stack frames to be used on the next suspend event. Iterates
	 * through all current stack frames, setting their state as invalid. This
	 * method should be called before this thread is resumed, when stack frames
	 * are to be re-used when it later suspends.
	 *
	 * @see #computeStackFrames()
	 */
	protected synchronized void preserveStackFrames() {
		fRefreshChildren = true;
		for(IJavaStackFrame frame : fStackFrames) {
			((JDIStackFrame)frame).setUnderlyingStackFrame(null);
		}
	}

	/**
	 * Disposes stack frames, to be completely re-computed on the next suspend
	 * event. This method should be called before this thread is resumed when
	 * stack frames are not to be re-used on the next suspend.
	 *
	 * @see #computeStackFrames()
	 */
	protected synchronized void disposeStackFrames() {
		fStackFrames.clear();
		fRefreshChildren = true;
	}

	/**
	 * This method is synchronized, such that the step request begins before a
	 * background evaluation can be performed.
	 *
	 * @see IStep#stepInto()
	 */
	@Override
	public void stepInto() throws DebugException {
		synchronized (this) {
			if (!canStepInto()) {
				return;
			}
		}
		StepHandler handler = createStepIntoHandler();
		handler.step();
	}

	/**
	 * This method is synchronized, such that the step request begins before a
	 * background evaluation can be performed.
	 *
	 * @see IStep#stepOver()
	 */
	@Override
	public void stepOver() throws DebugException {
		synchronized (this) {
			if (!canStepOver()) {
				return;
			}
		}
		StepHandler handler = createStepOverHandler();
		handler.step();
	}

	/**
	 * This method is synchronized, such that the step request begins before a
	 * background evaluation can be performed.
	 *
	 * @see IStep#stepReturn()
	 */
	@Override
	public void stepReturn() throws DebugException {
		synchronized (this) {
			if (!canStepReturn()) {
				return;
			}
		}
		StepHandler handler = createStepReturnHandler();
		handler.step();
	}

	protected void setOriginalStepKind(int stepKind) {
		fOriginalStepKind = stepKind;
	}

	protected int getOriginalStepKind() {
		return fOriginalStepKind;
	}

	protected void setOriginalStepLocation(Location location) {
		fOriginalStepLocation = location;
	}

	protected Location getOriginalStepLocation() {
		return fOriginalStepLocation;
	}

	protected void setOriginalStepStackDepth(int depth) {
		fOriginalStepStackDepth = depth;
	}

	protected int getOriginalStepStackDepth() {
		return fOriginalStepStackDepth;
	}

	/**
	 * In cases where a user-requested step into encounters nothing but filtered
	 * code (static initializers, synthetic methods, etc.), the default JDI
	 * behavior is to put the instruction pointer back where it was before the
	 * step into. This requires a second step to move forward. Since this is
	 * confusing to the user, we do an extra step into in such situations. This
	 * method determines when such an extra step into is necessary. It compares
	 * the current Location to the original Location when the user step into was
	 * initiated. It also makes sure the stack depth now is the same as when the
	 * step was initiated.
	 *
	 * @param location
	 *            the location to consider
	 * @return <code>true</code> if we should do an extra step,
	 *         <code>false</code> otherwise
	 * @throws DebugException
	 *             if an exception occurs
	 */
	protected boolean shouldDoExtraStepInto(Location location)
			throws DebugException {
		if (getOriginalStepKind() != StepRequest.STEP_INTO) {
			return false;
		}
		if (getOriginalStepStackDepth() != getUnderlyingFrameCount()) {
			return false;
		}
		Location origLocation = getOriginalStepLocation();
		if (origLocation == null) {
			return false;
		}
		// We cannot simply check if the two Locations are equal using the
		// equals()
		// method, since this checks the code index within the method. Even if
		// the
		// code indices are different, the line numbers may be the same, in
		// which case
		// we need to do the extra step into.
		Method origMethod = origLocation.method();
		Method currMethod = location.method();
		if (!origMethod.equals(currMethod)) {
			return false;
		}
		if (origLocation.lineNumber() != location.lineNumber()) {
			return false;
		}
		return true;
	}

	/**
	 * Determines if a user did a step into and stepped through filtered code.
	 * In this case, do a step return if the user has requested not to step thru
	 * to an unfiltered location.
	 *
	 * @return <code>true</code> if we should do a step return
	 * @throws DebugException
	 *             if an exception occurs
	 */
	protected boolean shouldDoStepReturn() throws DebugException {
		if (getOriginalStepKind() == StepRequest.STEP_INTO) {
			if ((getOriginalStepStackDepth() + 1) < getUnderlyingFrameCount()) {
				return true;
			}
		}
		return false;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.debug.core.model.ISuspendResume#suspend()
	 */
	@Override
	public void suspend() throws DebugException {
		// prepare for the suspend request
		prepareForClientSuspend();

		synchronized (this) {
			try {
				// Abort any pending step request
				abortStep();
				suspendUnderlyingThread();
			} catch (RuntimeException e) {
				fClientSuspendRequest = false;
				setRunning(true);
				targetRequestFailed(MessageFormat.format(
						JDIDebugModelMessages.JDIThread_exception_suspending,
						e.toString()), e);
			}
		}
	}

	/**
	 * Prepares to suspend this thread as requested by a client. Terminates any
	 * current evaluation (to stop after next instruction). Waits for any method
	 * invocations to complete.
	 *
	 * @throws DebugException
	 *             if thread does not suspend before timeout
	 */
	protected void prepareForClientSuspend() throws DebugException {
		// note that a suspend request has started
		synchronized (this) {
			// this will abort notification to pending breakpoint listeners
			fClientSuspendRequest = true;
		}

		synchronized (fEvaluationLock) {
			// terminate active evaluation, if any
			if (fEvaluationRunnable != null) {
				if (canTerminateEvaluation()) {
					fEvaluationInterrupted = true;
					((ITerminate) fEvaluationRunnable).terminate();
				}
				// wait for termination to complete
				int timeout = Platform.getPreferencesService().getInt(
						JDIDebugPlugin.getUniqueIdentifier(),
						JDIDebugModel.PREF_REQUEST_TIMEOUT,
						JDIDebugModel.DEF_REQUEST_TIMEOUT,
						null);
				try {
					fEvaluationLock.wait(timeout);
				} catch (InterruptedException e) {
				}
				if (fEvaluationRunnable != null) {
					fClientSuspendRequest = false;
					targetRequestFailed(JDIDebugModelMessages.JDIThread_1, null);
				}
			}
		}

		// first wait for any method invocation in progress to complete its
		// method invocation
		synchronized (fInvocationLock) {
			if (isInvokingMethod()) {
				int timeout = Platform.getPreferencesService().getInt(
						JDIDebugPlugin.getUniqueIdentifier(),
						JDIDebugModel.PREF_REQUEST_TIMEOUT,
						JDIDebugModel.DEF_REQUEST_TIMEOUT,
						null);
				try {
					fInvocationLock.wait(timeout);
				} catch (InterruptedException e) {
				}
				if (isInvokingMethod()) {
					// timeout waiting for invocation to complete, abort
					fClientSuspendRequest = false;
					targetRequestFailed(JDIDebugModelMessages.JDIThread_1, null);
				}
			}
		}
	}

	/**
	 * Suspends the underlying thread asynchronously and fires notification when
	 * the underlying thread is suspended.
	 */
	protected synchronized void suspendUnderlyingThread() {
		if (fIsSuspending) {
			return;
		}
		if (isSuspended()) {
			fireSuspendEvent(DebugEvent.CLIENT_REQUEST);
			return;
		}
		fIsSuspending = true;
		Thread thread = new Thread(new Runnable() {
			@Override
			public void run() {
				try {
					fThread.suspend();
					int timeout = Platform.getPreferencesService().getInt(
							JDIDebugPlugin.getUniqueIdentifier(),
							JDIDebugModel.PREF_REQUEST_TIMEOUT,
							JDIDebugModel.DEF_REQUEST_TIMEOUT,
							null);
					long stop = System.currentTimeMillis() + timeout;
					boolean suspended = isUnderlyingThreadSuspended();
					while (System.currentTimeMillis() < stop && !suspended) {
						try {
							Thread.sleep(50);
						} catch (InterruptedException e) {
						}
						suspended = isUnderlyingThreadSuspended();
						if (suspended) {
							break;
						}
					}
					if (!suspended) {
						IStatus status = new Status(
								IStatus.ERROR,
								JDIDebugPlugin.getUniqueIdentifier(),
								SUSPEND_TIMEOUT,
								MessageFormat.format(JDIDebugModelMessages.JDIThread_suspend_timeout, new Integer(timeout).toString()),
								null);
						IStatusHandler handler = DebugPlugin.getDefault()
								.getStatusHandler(status);
						if (handler != null) {
							try {
								handler.handleStatus(status, JDIThread.this);
							} catch (CoreException e) {
							}
						}
					}
					setRunning(false);
					fireSuspendEvent(DebugEvent.CLIENT_REQUEST);
				} catch (RuntimeException exception) {
				} finally {
					fIsSuspending = false;
				}
			}
		});
		thread.setDaemon(true);
		thread.start();
	}

	public boolean isUnderlyingThreadSuspended() {
		return fThread.isSuspended();
	}

	/**
	 * Notifies this thread that it has been suspended due to a VM suspend.
	 */
	protected synchronized void suspendedByVM() {
		setRunning(false);
	}

	/**
	 * Notifies this thread that is about to be resumed due to a VM resume.
	 *
	 * @throws DebugException
	 *             if an exception occurs
	 */
	protected synchronized void resumedByVM() throws DebugException {
		fClientSuspendRequest = false;
		setRunning(true);
		clearMethodResult();
		preserveStackFrames();
		// This method is called *before* the VM is actually resumed.
		// To ensure that all threads will fully resume when the VM
		// is resumed, make sure the suspend count of each thread
		// is no greater than 1. @see Bugs 23328 and 27622
		ThreadReference thread = fThread;
		try {
			while (thread.suspendCount() > 1) {
				thread.resume();
			}
		} catch (ObjectCollectedException e) {
		} catch (VMDisconnectedException e) {
			disconnected();
		} catch (RuntimeException e) {
			setRunning(false);
			fireSuspendEvent(DebugEvent.CLIENT_REQUEST);
			targetRequestFailed(MessageFormat.format(
					JDIDebugModelMessages.JDIThread_exception_resuming,
					e.toString()), e); //
		}
	}

	/**
	 * @see ITerminate#terminate()
	 */
	@Override
	public void terminate() throws DebugException {
		terminateEvaluation();
		getDebugTarget().terminate();
	}

	/**
	 * Drops to the given stack frame
	 *
	 * @param frame
	 *            the stack frame to try dropping to
	 *
	 * @exception DebugException
	 *                if this method fails. Reasons include:
	 *                <ul>
	 *                <li>Failure communicating with the VM. The
	 *                DebugException's status code contains the underlying
	 *                exception responsible for the failure.</li>
	 *                </ul>
	 */
	protected void dropToFrame(IStackFrame frame) throws DebugException {
		JDIDebugTarget target = (JDIDebugTarget) getDebugTarget();
		if (target.canPopFrames()) {
			// JDK 1.4 support
			try {
				// Pop the drop frame and all frames above it
				popFrame(frame);
				stepInto();
			} catch (RuntimeException exception) {
				targetRequestFailed(
						MessageFormat.format(
								JDIDebugModelMessages.JDIThread_exception_dropping_to_frame,
								exception.toString()),
						exception);
			}
		} else {
			// J9 support
			// This block is synchronized, such that the step request
			// begins before a background evaluation can be performed.
			synchronized (this) {
				StepHandler handler = createDropToFrameHandler(frame);
				handler.step();
			}
		}
	}

	protected void popFrame(IStackFrame frame) throws DebugException {
		JDIDebugTarget target = (JDIDebugTarget) getDebugTarget();
		if (target.canPopFrames()) {
			// JDK 1.4 support
			try {
				// Pop the frame and all frames above it
				StackFrame jdiFrame = null;
				int desiredSize = fStackFrames.size()
						- fStackFrames.indexOf(frame) - 1;
				int lastSize = fStackFrames.size() + 1; // Set up to pass the
														// first test
				int size = fStackFrames.size();
				while (size < lastSize && size > desiredSize) {
					// Keep popping frames until the stack stops getting smaller
					// or popFrame is gone.
					// see Bug 8054
					jdiFrame = ((JDIStackFrame) frame)
							.getUnderlyingStackFrame();
					preserveStackFrames();
					fThread.popFrames(jdiFrame);
					lastSize = size;
					size = computeStackFrames().size();
				}
			} catch (IncompatibleThreadStateException exception) {
				targetRequestFailed(MessageFormat.format(
						JDIDebugModelMessages.JDIThread_exception_popping,
						exception.toString()), exception);
			} catch (InvalidStackFrameException exception) {
				// InvalidStackFrameException can be thrown when all but the
				// deepest frame were popped. Fire a changed notification
				// in case this has occurred.
				fireChangeEvent(DebugEvent.CONTENT);
				targetRequestFailed(exception.toString(), exception);
			} catch (RuntimeException exception) {
				targetRequestFailed(MessageFormat.format(
						JDIDebugModelMessages.JDIThread_exception_popping,
						exception.toString()), exception);
			}
		}
	}

	/**
	 * Steps until the specified stack frame is the top frame. Provides ability
	 * to step over/return in the non-top stack frame. This method is
	 * synchronized, such that the step request begins before a background
	 * evaluation can be performed.
	 *
	 * @param frame
	 *            the stack frame to try and step to
	 * @exception DebugException
	 *                if this method fails. Reasons include:
	 *                <ul>
	 *                <li>Failure communicating with the VM. The
	 *                DebugException's status code contains the underlying
	 *                exception responsible for the failure.</li>
	 *                </ul>
	 */
	protected void stepToFrame(IStackFrame frame) throws DebugException {
		synchronized (this) {
			if (!canStepReturn()) {
				return;
			}
		}
		StepHandler handler = createStepToFrameHandler(frame);
		handler.step();
	}

	/**
	 * Aborts the current step, if any.
	 */
	protected void abortStep() {
		StepHandler handler = getPendingStepHandler();
		if (handler != null) {
			handler.abort();
		}
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see
	 * org.eclipse.jdt.debug.core.IJavaThread#findVariable(java.lang.String)
	 */
	@Override
	public IJavaVariable findVariable(String varName) throws DebugException {
		if (isSuspended()) {
			try {
				IStackFrame[] stackFrames = getStackFrames();
				for (IStackFrame stackFrame : stackFrames) {
					IJavaStackFrame sf = (IJavaStackFrame) stackFrame;
					IJavaVariable var = sf.findVariable(varName);
					if (var != null) {
						return var;
					}
				}
			} catch (DebugException e) {
				// if the thread has since resumed, return null (no need to
				// report error)
				if (e.getStatus().getCode() != IJavaThread.ERR_THREAD_NOT_SUSPENDED) {
					throw e;
				}
			}
		}
		return null;
	}

	/**
	 * Notification this thread has terminated - update state and fire a
	 * terminate event.
	 */
	protected void terminated() {
		setTerminated(true);
		setRunning(false);
		fireTerminateEvent();
	}

	/**
	 * Returns this thread on the underlying VM which this model thread is a
	 * proxy to.
	 *
	 * @return underlying thread
	 */
	public ThreadReference getUnderlyingThread() {
		return fThread;
	}

	/**
	 * Sets the underlying thread that this model object is a proxy to.
	 *
	 * @param thread
	 *            underlying thread on target VM
	 */
	protected void setUnderlyingThread(ThreadReference thread) {
		fThread = thread;
	}

	/**
	 * Returns this thread's underlying thread group.
	 *
	 * @return thread group
	 * @exception DebugException
	 *                if this method fails. Reasons include:
	 *                <ul>
	 *                <li>Failure communicating with the VM. The
	 *                DebugException's status code contains the underlying
	 *                exception responsible for the failure.</li>
	 *                <li>Retrieving the underlying thread group is not
	 *                supported on the underlying VM</li>
	 *                </ul>
	 */
	protected ThreadGroupReference getUnderlyingThreadGroup()
			throws DebugException {
		if (fThreadGroup == null) {
			try {
				fThreadGroup = fThread.threadGroup();
			} catch (UnsupportedOperationException e) {
				requestFailed(
						MessageFormat.format(
								JDIDebugModelMessages.JDIThread_exception_retrieving_thread_group,
								e.toString()), e);
				// execution will not reach this line, as
				// #requestFailed will throw an exception
				return null;
			} catch (VMDisconnectedException e) {
				// ignore disconnect
				return null;
			} catch (ObjectCollectedException e) {
				// ignore object collected
				return null;
			} catch (RuntimeException e) {
				targetRequestFailed(
						MessageFormat.format(
								JDIDebugModelMessages.JDIThread_exception_retrieving_thread_group,
								e.toString()), e);
				// execution will not reach this line, as
				// #targetRequestFailed will throw an exception
				return null;
			}
		}
		return fThreadGroup;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.jdt.debug.core.IJavaThread#isPerformingEvaluation()
	 */
	@Override
	public boolean isPerformingEvaluation() {
		return fEvaluationRunnable != null;
	}

	/**
	 * Returns whether this thread is currently performing a method invocation
	 *
	 * @return if the thread is currently invoking a method
	 */
	public boolean isInvokingMethod() {
		return fIsInvokingMethod;
	}

	/**
	 * Returns whether this thread is currently ignoring breakpoints.
	 *
	 * @return if the thread is currently ignoring breakpoints
	 */
	public boolean isIgnoringBreakpoints() {
		return !fHonorBreakpoints || fSuspendVoteInProgress
				|| hasClientRequestedSuspend();
	}

	/**
	 * Returns whether a client has requested the target/thread to suspend.
	 *
	 * @return whether a client has requested the target/thread to suspend
	 */
	public boolean hasClientRequestedSuspend() {
		return fClientSuspendRequest;
	}

	/**
	 * Sets whether this thread is currently invoking a method. Notifies any
	 * threads waiting for the method invocation lock
	 *
	 * @param invoking
	 *            whether this thread is currently invoking a method
	 */
	protected void setInvokingMethod(boolean invoking) {
		synchronized (fInvocationLock) {
			fIsInvokingMethod = invoking;
			if (!invoking) {
				fInvocationLock.notifyAll();
			}
		}
	}

	/**
	 * Sets the step handler currently handling a step request.
	 *
	 * @param handler
	 *            the current step handler, or <code>null</code> if none
	 */
	protected void setPendingStepHandler(StepHandler handler) {
		fStepHandler = handler;
	}

	/**
	 * Returns the step handler currently handling a step request, or
	 * <code>null</code> if none.
	 *
	 * @return step handler, or <code>null</code> if none
	 */
	protected StepHandler getPendingStepHandler() {
		return fStepHandler;
	}

	/**
	 * Helper class to perform stepping an a thread.
	 */
	abstract class StepHandler implements IJDIEventListener {
		/**
		 * Request for stepping in the underlying VM
		 */
		private StepRequest fStepRequest;

		/**
		 * Initiates a step in the underlying VM by creating a step request of
		 * the appropriate kind (over, into, return), and resuming this thread.
		 * When a step is initiated it is registered with its thread as a
		 * pending step. A pending step could be cancelled if a breakpoint
		 * suspends execution during the step.
		 * <p>
		 * This thread's state is set to running and stepping, and stack frames
		 * are invalidated (but preserved to be re-used when the step
		 * completes). A resume event with a step detail is fired for this
		 * thread.
		 * </p>
		 * Note this method does nothing if this thread has no stack frames.
		 *
		 * @exception DebugException
		 *                if this method fails. Reasons include:
		 *                <ul>
		 *                <li>Failure communicating with the VM. The
		 *                DebugException's status code contains the underlying
		 *                exception responsible for the failure.</li>
		 *                </ul>
		 */
		protected void step() throws DebugException {
			ISchedulingRule rule = getThreadRule();
			try {
				Job.getJobManager().beginRule(rule, null);
				JDIStackFrame top = (JDIStackFrame) getTopStackFrame();
				if (top == null) {
					return;
				}
				setOriginalStepKind(getStepKind());
				Location location = top.getUnderlyingStackFrame().location();
				setOriginalStepLocation(location);
				setOriginalStepStackDepth(computeStackFrames().size());
				setStepRequest(createStepRequest());
				setPendingStepHandler(this);
				addJDIEventListener(this, getStepRequest());
				setRunning(true);
				clearMethodResult();
				preserveStackFrames();
				fireResumeEvent(getStepDetail());
				invokeThread();
			} finally {
				Job.getJobManager().endRule(rule);
			}
		}

		/**
		 * Resumes the underlying thread to initiate the step. By default the
		 * thread is resumed. Step handlers that require other actions can
		 * override this method.
		 *
		 * @exception DebugException
		 *                if this method fails. Reasons include:
		 *                <ul>
		 *                <li>Failure communicating with the VM. The
		 *                DebugException's status code contains the underlying
		 *                exception responsible for the failure.</li>
		 *                </ul>
		 */
		protected void invokeThread() throws DebugException {
			try {
				synchronized (JDIThread.this) {
					fClientSuspendRequest = false;
				}
				fThread.resume();
			} catch (RuntimeException e) {
				stepEnd(null);
				fireSuspendEvent(DebugEvent.STEP_END);
				targetRequestFailed(MessageFormat.format(
						JDIDebugModelMessages.JDIThread_exception_stepping,
						e.toString()), e);
			}
		}

		/**
		 * Creates and returns a step request specific to this step handler.
		 * Subclasses must override <code>getStepKind()</code> to return the
		 * kind of step it implements.
		 *
		 * @return step request
		 * @exception DebugException
		 *                if this method fails. Reasons include:
		 *                <ul>
		 *                <li>Failure communicating with the VM. The
		 *                DebugException's status code contains the underlying
		 *                exception responsible for the failure.</li>
		 *                </ul>
		 */
		protected StepRequest createStepRequest() throws DebugException {
			return createStepRequest(getStepKind());
		}

		/**
		 * Creates and returns a step request of the specified kind.
		 *
		 * @param kind
		 *            of <code>StepRequest.STEP_INTO</code>,
		 *            <code>StepRequest.STEP_OVER</code>,
		 *            <code>StepRequest.STEP_OUT</code>
		 * @return step request
		 * @exception DebugException
		 *                if this method fails. Reasons include:
		 *                <ul>
		 *                <li>Failure communicating with the VM. The
		 *                DebugException's status code contains the underlying
		 *                exception responsible for the failure.</li>
		 *                </ul>
		 */
		protected StepRequest createStepRequest(int kind) throws DebugException {
			EventRequestManager manager = getEventRequestManager();
			if (manager == null) {
				requestFailed(
						JDIDebugModelMessages.JDIThread_Unable_to_create_step_request___VM_disconnected__1,
						null);
			}
			try {
				StepRequest request = manager.createStepRequest(fThread,
						StepRequest.STEP_LINE, kind);
				request.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD);
				request.addCountFilter(1);
				attachFiltersToStepRequest(request);
				request.enable();

				if (manager.virtualMachine().canGetMethodReturnValues() && showStepResultIsEnabled()) {
					if (fCurrentMethodExitRequest != null) {
						removeJDIEventListener(this, fCurrentMethodExitRequest);
						manager.deleteEventRequest(fCurrentMethodExitRequest);
						fCurrentMethodExitRequest = null;
					}
					if (fCurrentExceptionRequest != null) {
						removeJDIEventListener(this, fCurrentExceptionRequest);
						manager.deleteEventRequest(fCurrentExceptionRequest);
						fCurrentExceptionRequest = null;
					}
					if (fCurrentMethodEntryRequest != null) {
						removeJDIEventListener(this, fCurrentMethodEntryRequest);
						manager.deleteEventRequest(fCurrentMethodEntryRequest);
						fCurrentMethodEntryRequest = null;
					}
					fStepResultCandidate = null;
					List<IJavaStackFrame> frames = computeStackFrames();
					int frameCount = 0;
					StackFrame currentFrame = null;
					if (!frames.isEmpty()) {
						frameCount = frames.size();
						currentFrame = ((JDIStackFrame) frames.get(0)).getUnderlyingStackFrame();
					} else {
						// can happen, e.g. when step filters are active.
						if (fThread.isSuspended()) {
							try {
								// try to get the required info from the underlying object.
								frameCount = fThread.frameCount();
								currentFrame = fThread.frame(0);
							}
							catch (IncompatibleThreadStateException e) {
								// cannot not happen because of the enclosing isSuspended() check.
								logError(e);
							}
						}
					}
					if (currentFrame != null) {
						MethodExitRequest methodExitRequest = manager.createMethodExitRequest();
						methodExitRequest.addThreadFilter(fThread);
						methodExitRequest.addClassFilter(currentFrame.location().declaringType());

						if (manager.virtualMachine().canUseInstanceFilters()) {
							ObjectReference thisObject = null;
							try {
								thisObject = currentFrame.thisObject();
							} catch (Exception e) {
								// ignore errors here, continue without filtering
							}
							if (thisObject != null) {
								methodExitRequest.addInstanceFilter(thisObject);
							}
						}
						methodExitRequest.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD);
						methodExitRequest.enable();
						fCurrentMethodExitRequest = methodExitRequest;
						fStepResultMethod = currentFrame.location().method();
						fStepReturnTargetFrameCount = frameCount - 1; // depth of the frame that is returned to
						addJDIEventListener(this, methodExitRequest);

						ExceptionRequest exceptionRequest = manager.createExceptionRequest(null, true, false);
						exceptionRequest.addThreadFilter(fThread);
						exceptionRequest.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD);
						exceptionRequest.enable();
						fCurrentExceptionRequest = exceptionRequest;
						addJDIEventListener(this, exceptionRequest);

						if (kind == StepRequest.STEP_OVER) {
							MethodEntryRequest methodEntryRequest = manager.createMethodEntryRequest();
							methodEntryRequest.addThreadFilter(fThread);
							methodEntryRequest.enable();
							methodEntryRequest.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD);
							fCurrentMethodEntryRequest = methodEntryRequest;
							fStepOverLocation = currentFrame.location();
							fStepOverFrameCount = frameCount; // depth of the frame where the step-over is being done
							addJDIEventListener(this, methodEntryRequest);
						}
					}
				}
				return request;
			} catch (RuntimeException e) {
				targetRequestFailed(
						MessageFormat.format(
								JDIDebugModelMessages.JDIThread_exception_creating_step_request,
								e.toString()), e);
			}
			// this line will never be executed, as the try block
			// will either return, or the catch block will throw
			// an exception
			return null;

		}

		/**
		 * Returns the kind of step this handler implements.
		 *
		 * @return one of <code>StepRequest.STEP_INTO</code>,
		 *         <code>StepRequest.STEP_OVER</code>,
		 *         <code>StepRequest.STEP_OUT</code>
		 */
		protected abstract int getStepKind();

		/**
		 * Returns the detail for this step event.
		 *
		 * @return one of <code>DebugEvent.STEP_INTO</code>,
		 *         <code>DebugEvent.STEP_OVER</code>,
		 *         <code>DebugEvent.STEP_RETURN</code>
		 */
		protected abstract int getStepDetail();

		/**
		 * Sets the step request created by this handler in the underlying VM.
		 * Set to <code>null<code> when
		 * this handler deletes its request.
		 *
		 * @param request
		 *            step request
		 */
		protected void setStepRequest(StepRequest request) {
			fStepRequest = request;
		}

		/**
		 * Returns the step request created by this handler in the underlying
		 * VM.
		 *
		 * @return step request
		 */
		protected StepRequest getStepRequest() {
			return fStepRequest;
		}

		/**
		 * Deletes this handler's step request from the underlying VM and
		 * removes this handler as an event listener.
		 */
		protected void deleteStepRequest() {
			try {
				if (fCurrentMethodExitRequest != null) {
					removeJDIEventListener(this, fCurrentMethodExitRequest);
					EventRequestManager manager = getEventRequestManager();
					if (manager != null) {
						manager.deleteEventRequest(fCurrentMethodExitRequest);
					}
					fCurrentMethodExitRequest = null;
				}
				if (fCurrentExceptionRequest != null) {
					removeJDIEventListener(this, fCurrentExceptionRequest);
					EventRequestManager manager = getEventRequestManager();
					if (manager != null) {
						manager.deleteEventRequest(fCurrentExceptionRequest);
					}
					fCurrentExceptionRequest = null;
				}
				if (fCurrentMethodEntryRequest != null) {
					removeJDIEventListener(this, fCurrentMethodEntryRequest);
					EventRequestManager manager = getEventRequestManager();
					if (manager != null) {
						manager.deleteEventRequest(fCurrentMethodEntryRequest);
					}
					fCurrentMethodEntryRequest = null;
				}
				StepRequest req = getStepRequest();
				if (req != null) {
					removeJDIEventListener(this, req);
					EventRequestManager manager = getEventRequestManager();
					if (manager != null) {
						manager.deleteEventRequest(req);
					}
				}
			} catch (RuntimeException e) {
				logError(e);
			} finally {
				setStepRequest(null);
			}
		}

		/**
		 * If step filters are currently switched on and the current location is
		 * not a filtered location, set all active filters on the step request.
		 *
		 * @param request
		 *            the request to augment
		 */
		protected void attachFiltersToStepRequest(StepRequest request) {

			if (applyStepFilters() && isStepFiltersEnabled()) {
				Location currentLocation = getOriginalStepLocation();
				if (!isSupported(currentLocation)) {
					return;
				}
				// Removed the fix for bug 5587, to address bug 41510
				// //check if the user has already stopped in a filtered
				// location
				// //is so do not filter @see bug 5587
				// ReferenceType type= currentLocation.declaringType();
				// String typeName= type.name();
				String[] activeFilters = getJavaDebugTarget().getStepFilters();
				// for (int i = 0; i < activeFilters.length; i++) {
				// StringMatcher matcher = new StringMatcher(activeFilters[i],
				// false, false);
				// if (matcher.match(typeName)) {
				// return;
				// }
				// }
				if (activeFilters != null) {
					for (String activeFilter : activeFilters) {
						request.addClassExclusionFilter(activeFilter);
					}
				}
			}
		}

		/**
		 * Returns whether this step handler should use step filters when
		 * creating its step request. By default, step filters can be used by
		 * any step request. Subclasses must override if/when required.
		 *
		 * @return whether this step handler should use step filters when
		 *         creating its step request
		 */
		protected boolean applyStepFilters() {
			return true;
		}

		/**
		 * Notification the step request has completed. If the current location
		 * matches one of the user-specified step filter criteria (e.g.,
		 * synthetic methods, static initializers), then continue stepping.
		 *
		 * @see IJDIEventListener#handleEvent(Event, JDIDebugTarget, boolean,
		 *      EventSet)
		 */
		@Override
		public boolean handleEvent(Event event, JDIDebugTarget target,
				boolean suspendVote, EventSet eventSet) {
			try {
				if (event instanceof MethodExitEvent) {
					Method stepResultMethod = fStepResultMethod;
					if (stepResultMethod != null) {
						MethodExitEvent methodExitEvent = (MethodExitEvent) event;
						if (methodExitEvent.location().method().equals(stepResultMethod)) {
							fStepResultCandidate = new MethodResult(fStepResultMethod, fStepReturnTargetFrameCount, methodExitEvent.returnValue(), ResultType.returned);
						}
						return true;
					}
				}
				if (event instanceof ExceptionEvent) {
					ExceptionEvent exceptionEvent = (ExceptionEvent) event;
					fStepResultCandidate = new MethodResult(fStepResultMethod, fStepReturnTargetFrameCount, exceptionEvent.exception(), ResultType.threw);
					return true;
				}
				if (event instanceof MethodEntryEvent) {
					removeJDIEventListener(this, fCurrentMethodEntryRequest);
					EventRequestManager manager = getEventRequestManager();
					if (manager != null) {
						manager.deleteEventRequest(fCurrentMethodEntryRequest);
					}
					fCurrentMethodEntryRequest = null;
					deleteStepRequest();
					createSecondaryStepRequest(StepRequest.STEP_OUT);
					return true;
				}
				StepEvent stepEvent = (StepEvent) event;
				Location currentLocation = stepEvent.location();

				if (fStepResultCandidate != null) {
					setMethodResult(fStepResultCandidate);
					fStepResultMethod = null;
					fStepReturnTargetFrameCount = -1;
					fStepResultCandidate = null;
				}

				if (getStepKind() == StepRequest.STEP_OVER) {
					Location stepOverLocation2 = fStepOverLocation;
					if (stepOverLocation2 != null && fStepOverFrameCount >= 0) {
						int underlyingFrameCount = getUnderlyingFrameCount();
						if (underlyingFrameCount > fStepOverFrameCount) {
							// sometimes a MethodEntryEvent does not stop the thread but is delivered with another one grouped
							// in an event set. in this situation, multiple step-returns must be done.
							deleteStepRequest();
							createSecondaryStepRequest(StepRequest.STEP_OUT);
							return true;
						}
						if (underlyingFrameCount == fStepOverFrameCount && stepOverLocation2.method().equals(currentLocation.method())) {
							int lineNumber = stepOverLocation2.lineNumber();
							if (lineNumber != -1 && lineNumber == currentLocation.lineNumber()) {
								// line has not changed yet (probably returned from invocation with STEP_OUT)
								deleteStepRequest();
								createSecondaryStepRequest(StepRequest.STEP_OVER);
								return true;
							}
						}
						fStepOverLocation = null;
						fStepOverFrameCount = -1;
					}
				}

				if (!target.isStepThruFilters()) {
					if (shouldDoStepReturn()) {
						deleteStepRequest();
						createSecondaryStepRequest(StepRequest.STEP_OUT);
						return true;
					}
				}
				// if the ending step location is filtered and we did not start
				// from
				// a filtered location, or if we're back where
				// we started on a step into, do another step of the same kind
				if (locationShouldBeFiltered(currentLocation)
						|| shouldDoExtraStepInto(currentLocation)) {
					setRunning(true);
					deleteStepRequest();
					createSecondaryStepRequest();
					clearMethodResult();
					return true;
					// otherwise, we're done stepping
				}
				stepEnd(eventSet);
				return false;
			} catch (DebugException e) {
				logError(e);
				stepEnd(eventSet);
				return false;
			}
		}

		/*
		 * (non-Javadoc)
		 *
		 * @see
		 * org.eclipse.jdt.internal.debug.core.IJDIEventListener#eventSetComplete
		 * (com.sun.jdi.event.Event,
		 * org.eclipse.jdt.internal.debug.core.model.JDIDebugTarget, boolean)
		 */
		@Override
		public void eventSetComplete(Event event, JDIDebugTarget target,
				boolean suspend, EventSet eventSet) {
			// do nothing
		}

		/**
		 * Returns <code>true</code> if the StepEvent's Location is a Method
		 * that the user has indicated (via the step filter preferences) should
		 * be filtered and the step was not initiated from a filtered location.
		 * Returns <code>false</code> otherwise.
		 *
		 * @param location
		 *            the location to check
		 * @return if the given {@link Location} should be filtered
		 * @throws DebugException
		 *             if an exception occurs
		 */
		protected boolean locationShouldBeFiltered(Location location)
				throws DebugException {
			if (applyStepFilters()) {
				Location origLocation = getOriginalStepLocation();
				if (origLocation != null) {
					return !locationIsFiltered(origLocation.method(), true) && locationIsFiltered(location.method(), false);
				}
			}
			return false;
		}

		/**
		 * Returns <code>true</code> if the StepEvent's Location is a Method
		 * that the user has indicated (via the step filter preferences) should
		 * be filtered. Returns <code>false</code> otherwise.
		 *
		 * @param method
		 *            the {@link Method} location to check
		 * @param orig
		 *            <code>true</code> if the {@link Method} {@link Location} is the JDI Location
		 *         from which an original user-requested step began, <code>false</code> otherwise
		 * @return <code>true</code> if the {@link Method} {@link Location}
		 *         should be filtered, <code>false</code> otherwise
		 */
		protected boolean locationIsFiltered(Method method, boolean orig) {
			if (isStepFiltersEnabled()) {
				JDIDebugTarget target = getJavaDebugTarget();
				if ((target.isFilterStaticInitializers() && method.isStaticInitializer())
						|| (target.isFilterSynthetics() && method.isSynthetic())
						|| (target.isFilterConstructors() && method.isConstructor())
						|| (target.isFilterGetters() && JDIMethod.isGetterMethod(method))
						|| (target.isFilterSetters() && JDIMethod.isSetterMethod(method))) {
					return true;
				}
				if(!orig) {
					IStepFilter[] contributedFilters = DebugPlugin.getStepFilters(JDIDebugPlugin.getUniqueIdentifier());
					for (int i = 0; i < contributedFilters.length; i++) {
						if (contributedFilters[i].isFiltered(method)) {
							return true;
						}
					}
				}
			}
			return false;
		}

		/**
		 * Cleans up when a step completes.
		 * <ul>
		 * <li>Thread state is set to suspended.</li>
		 * <li>Stepping state is set to false</li>
		 * <li>Stack frames and variables are incrementally updated</li>
		 * <li>The step request is deleted and removed as and event listener</li>
		 * <li>A suspend event is fired</li>
		 * </ul>
		 *
		 * @param set
		 *            the remaining {@link EventSet} to queue
		 */
		protected void stepEnd(EventSet set) {
			setRunning(false);
			deleteStepRequest();
			setPendingStepHandler(null);
			if (set != null) {
				queueSuspendEvent(DebugEvent.STEP_END, set);
			}
		}

		/**
		 * Creates another step request in the underlying thread of the
		 * appropriate kind (over, into, return). This thread will be resumed by
		 * the event dispatcher as this event handler will vote to resume
		 * suspended threads. When a step is initiated it is registered with its
		 * thread as a pending step. A pending step could be cancelled if a
		 * breakpoint suspends execution during the step.
		 *
		 * @exception DebugException
		 *                if this method fails. Reasons include:
		 *                <ul>
		 *                <li>Failure communicating with the VM. The
		 *                DebugException's status code contains the underlying
		 *                exception responsible for the failure.</li>
		 *                </ul>
		 */
		protected void createSecondaryStepRequest() throws DebugException {
			createSecondaryStepRequest(getStepKind());
		}

		/**
		 * Creates another step request in the underlying thread of the
		 * specified kind (over, into, return). This thread will be resumed by
		 * the event dispatcher as this event handler will vote to resume
		 * suspended threads. When a step is initiated it is registered with its
		 * thread as a pending step. A pending step could be cancelled if a
		 * breakpoint suspends execution during the step.
		 *
		 * @param kind
		 *            of <code>StepRequest.STEP_INTO</code>,
		 *            <code>StepRequest.STEP_OVER</code>,
		 *            <code>StepRequest.STEP_OUT</code>
		 * @exception DebugException
		 *                if this method fails. Reasons include:
		 *                <ul>
		 *                <li>Failure communicating with the VM. The
		 *                DebugException's status code contains the underlying
		 *                exception responsible for the failure.</li>
		 *                </ul>
		 */
		protected void createSecondaryStepRequest(int kind)
				throws DebugException {
			setStepRequest(createStepRequest(kind));
			setPendingStepHandler(this);
			addJDIEventListener(this, getStepRequest());
		}

		/**
		 * Aborts this step request if active. The step event request is deleted
		 * from the underlying VM.
		 */
		protected void abort() {
			if (getStepRequest() != null) {
				deleteStepRequest();
				setPendingStepHandler(null);
				fStepOverLocation = null;
				fStepOverFrameCount =  -1;
			}
		}
	}

	/**
	 * Handler for step over requests.
	 */
	class StepOverHandler extends StepHandler {

		/*
		 * (non-Javadoc)
		 *
		 * @see org.eclipse.jdt.internal.debug.core.model.JDIThread.StepHandler#
		 * getStepKind()
		 */
		@Override
		protected int getStepKind() {
			return StepRequest.STEP_OVER;
		}

		/*
		 * (non-Javadoc)
		 *
		 * @see org.eclipse.jdt.internal.debug.core.model.JDIThread.StepHandler#
		 * getStepDetail()
		 */
		@Override
		protected int getStepDetail() {
			return DebugEvent.STEP_OVER;
		}
	}

	/**
	 * Handler for step into requests.
	 */
	protected class StepIntoHandler extends StepHandler {

		/*
		 * (non-Javadoc)
		 *
		 * @see org.eclipse.jdt.internal.debug.core.model.JDIThread.StepHandler#
		 * getStepKind()
		 */
		@Override
		protected int getStepKind() {
			return StepRequest.STEP_INTO;
		}

		/*
		 * (non-Javadoc)
		 *
		 * @see org.eclipse.jdt.internal.debug.core.model.JDIThread.StepHandler#
		 * getStepDetail()
		 */
		@Override
		protected int getStepDetail() {
			return DebugEvent.STEP_INTO;
		}

	}

	/**
	 * Handler for step return requests.
	 */
	protected class StepReturnHandler extends StepHandler {
		/*
		 * (non-Javadoc)
		 *
		 * @see org.eclipse.jdt.internal.debug.core.model.JDIThread.StepHandler#
		 * locationShouldBeFiltered(com.sun.jdi.Location)
		 */
		@Override
		protected boolean locationShouldBeFiltered(Location location)
				throws DebugException {
			// if still at the same depth, do another step return (see bug
			// 38744)
			if (getOriginalStepStackDepth() == getUnderlyingFrameCount()) {
				return true;
			}
			return super.locationShouldBeFiltered(location);
		}

		/*
		 * (non-Javadoc)
		 *
		 * @see org.eclipse.jdt.internal.debug.core.model.JDIThread.StepHandler#
		 * getStepKind()
		 */
		@Override
		protected int getStepKind() {
			return StepRequest.STEP_OUT;
		}

		/*
		 * (non-Javadoc)
		 *
		 * @see org.eclipse.jdt.internal.debug.core.model.JDIThread.StepHandler#
		 * getStepDetail()
		 */
		@Override
		protected int getStepDetail() {
			return DebugEvent.STEP_RETURN;
		}
	}

	/**
	 * Handler for stepping to a specific stack frame (stepping in the non-top
	 * stack frame). Step returns are performed until a specified stack frame is
	 * reached or the thread is suspended (explicitly, or by a breakpoint).
	 */
	protected class StepToFrameHandler extends StepReturnHandler {

		/**
		 * The number of frames that should be left on the stack
		 */
		private int fRemainingFrames;

		/**
		 * Constructs a step handler to step until the specified stack frame is
		 * reached.
		 *
		 * @param frame
		 *            the stack frame to step to
		 * @exception DebugException
		 *                if this method fails. Reasons include:
		 *                <ul>
		 *                <li>Failure communicating with the VM. The
		 *                DebugException's status code contains the underlying
		 *                exception responsible for the failure.</li>
		 *                </ul>
		 */
		protected StepToFrameHandler(IStackFrame frame) throws DebugException {
			List<IJavaStackFrame> frames = computeStackFrames();
			setRemainingFrames(frames.size() - frames.indexOf(frame));
		}

		/**
		 * Sets the number of frames that should be remaining on the stack when
		 * done.
		 *
		 * @param num
		 *            number of remaining frames
		 */
		protected void setRemainingFrames(int num) {
			fRemainingFrames = num;
		}

		/**
		 * Returns number of frames that should be remaining on the stack when
		 * done
		 *
		 * @return number of frames that should be left
		 */
		protected int getRemainingFrames() {
			return fRemainingFrames;
		}

		/**
		 * Notification the step request has completed. If in the desired frame,
		 * complete the step request normally. If not in the desired frame,
		 * another step request is created and this thread is resumed.
		 *
		 * @see IJDIEventListener#handleEvent(Event, JDIDebugTarget, boolean,
		 *      EventSet)
		 */
		@Override
		public boolean handleEvent(Event event, JDIDebugTarget target,
				boolean suspendVote, EventSet eventSet) {
			try {
				int numFrames = getUnderlyingFrameCount();
				// top of stack should not be null
				if (numFrames <= getRemainingFrames()) {
					stepEnd(eventSet);
					return false;
				}
				// reset running state and keep going
				setRunning(true);
				deleteStepRequest();
				createSecondaryStepRequest();
				clearMethodResult();
				return true;
			} catch (DebugException e) {
				logError(e);
				stepEnd(eventSet);
				return false;
			}
		}
	}

	/**
	 * Handles dropping to a specified frame.
	 */
	protected class DropToFrameHandler extends StepReturnHandler {

		/**
		 * The number of frames to drop off the stack.
		 */
		private int fFramesToDrop;

		/**
		 * Constructs a handler to drop to the specified stack frame.
		 *
		 * @param frame
		 *            the stack frame to drop to
		 * @exception DebugException
		 *                if this method fails. Reasons include:
		 *                <ul>
		 *                <li>Failure communicating with the VM. The
		 *                DebugException's status code contains the underlying
		 *                exception responsible for the failure.</li>
		 *                </ul>
		 */
		protected DropToFrameHandler(IStackFrame frame) throws DebugException {
			List<IJavaStackFrame> frames = computeStackFrames();
			setFramesToDrop(frames.indexOf(frame));
		}

		/**
		 * Sets the number of frames to pop off the stack.
		 *
		 * @param num
		 *            number of frames to pop
		 */
		protected void setFramesToDrop(int num) {
			fFramesToDrop = num;
		}

		/**
		 * Returns the number of frames to pop off the stack.
		 *
		 * @return remaining number of frames to pop
		 */
		protected int getFramesToDrop() {
			return fFramesToDrop;
		}

		/**
		 * To drop a frame or re-enter, the underlying thread is instructed to
		 * do a return. When the frame count is less than zero, the step being
		 * performed is a "step return", so a regular invocation is performed.
		 *
		 * @throws DebugException
		 *             if an exception occurs
		 */
		@Override
		protected void invokeThread() throws DebugException {
			if (getFramesToDrop() < 0) {
				super.invokeThread();
			} else {
				try {
					org.eclipse.jdi.hcr.ThreadReference hcrThread = (org.eclipse.jdi.hcr.ThreadReference) fThread;
					hcrThread.doReturn(null, true);
				} catch (RuntimeException e) {
					stepEnd(null);
					fireSuspendEvent(DebugEvent.STEP_END);
					targetRequestFailed(
							MessageFormat.format(
									JDIDebugModelMessages.JDIThread_exception_while_popping_stack_frame,
									e.toString()), e);
				}
			}
		}

		/**
		 * Notification that the pop has completed. If there are more frames to
		 * pop, keep going, otherwise re-enter the top frame. Returns false, as
		 * this handler will resume this thread with a special invocation (
		 * <code>doReturn</code>).
		 *
		 * @see IJDIEventListener#handleEvent(Event, JDIDebugTarget, boolean,
		 *      EventSet)
		 * @see #invokeThread()
		 */
		@Override
		public boolean handleEvent(Event event, JDIDebugTarget target,
				boolean suspendVote, EventSet eventSet) {
			// pop is complete, update number of frames to drop
			setFramesToDrop(getFramesToDrop() - 1);
			try {
				if (getFramesToDrop() >= -1) {
					deleteStepRequest();
					doSecondaryStep();
				} else {
					stepEnd(eventSet);
				}
			} catch (DebugException e) {
				stepEnd(eventSet);
				logError(e);
			}
			return false;
		}

		/**
		 * Pops a secondary frame off the stack, does a re-enter, or a
		 * step-into.
		 *
		 * @exception DebugException
		 *                if this method fails. Reasons include:
		 *                <ul>
		 *                <li>Failure communicating with the VM. The
		 *                DebugException's status code contains the underlying
		 *                exception responsible for the failure.</li>
		 *                </ul>
		 */
		protected void doSecondaryStep() throws DebugException {
			setStepRequest(createStepRequest());
			setPendingStepHandler(this);
			addJDIEventListener(this, getStepRequest());
			invokeThread();
		}

		/**
		 * Creates and returns a step request. If there are no more frames to
		 * drop, a re-enter request is made. If the re-enter is complete, a
		 * step-into request is created.
		 *
		 * @return step request
		 * @exception DebugException
		 *                if this method fails. Reasons include:
		 *                <ul>
		 *                <li>Failure communicating with the VM. The
		 *                DebugException's status code contains the underlying
		 *                exception responsible for the failure.</li>
		 *                </ul>
		 */
		@Override
		protected StepRequest createStepRequest() throws DebugException {
			EventRequestManager manager = getEventRequestManager();
			if (manager == null) {
				requestFailed(
						JDIDebugModelMessages.JDIThread_Unable_to_create_step_request___VM_disconnected__2,
						null);
			}
			int num = getFramesToDrop();
			if (num > 0) {
				return super.createStepRequest();
			} else if (num == 0) {
				try {
					StepRequest request = ((org.eclipse.jdi.hcr.EventRequestManager) manager).createReenterStepRequest(fThread);
					request.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD);
					request.addCountFilter(1);
					request.enable();
					return request;
				} catch (RuntimeException e) {
					targetRequestFailed(
							MessageFormat.format(
									JDIDebugModelMessages.JDIThread_exception_creating_step_request,
									e.toString()), e);
				}
			} else if (num == -1) {
				try {
					StepRequest request = manager.createStepRequest(fThread, StepRequest.STEP_LINE, StepRequest.STEP_INTO);
					request.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD);
					request.addCountFilter(1);
					request.enable();
					return request;
				} catch (RuntimeException e) {
					targetRequestFailed(
							MessageFormat.format(
									JDIDebugModelMessages.JDIThread_exception_creating_step_request,
									e.toString()), e);
				}
			}
			// this line will never be executed, as the try block
			// will either return, or the catch block with throw
			// an exception
			return null;
		}
	}

	/**
	 * @see IThread#hasStackFrames()
	 */
	@Override
	public boolean hasStackFrames() throws DebugException {
		return isSuspended();
	}

	/**
	 * @see IAdaptable#getAdapter(Class)
	 */
	@SuppressWarnings("unchecked")
	@Override
	public <T> T getAdapter(Class<T> adapter) {
		if (adapter == IJavaThread.class) {
			return (T) this;
		}
		if (adapter == IJavaStackFrame.class) {
			try {
				return (T) getTopStackFrame();
			} catch (DebugException e) {
				// do nothing if not able to get frame
			}
		}
		return super.getAdapter(adapter);
	}

	/**
	 * @see org.eclipse.jdt.debug.core.IJavaThread#hasOwnedMonitors()
	 */
	@Override
	public boolean hasOwnedMonitors() throws DebugException {
		return isSuspended() && getOwnedMonitors().length > 0;
	}

	/**
	 * @see org.eclipse.jdt.debug.core.IJavaThread#getOwnedMonitors()
	 */
	@Override
	public IJavaObject[] getOwnedMonitors() throws DebugException {
		try {
			JDIDebugTarget target = (JDIDebugTarget) getDebugTarget();
			List<ObjectReference> ownedMonitors = fThread.ownedMonitors();
			IJavaObject[] javaOwnedMonitors = new IJavaObject[ownedMonitors
					.size()];
			Iterator<ObjectReference> itr = ownedMonitors.iterator();
			int i = 0;
			while (itr.hasNext()) {
				ObjectReference element = itr.next();
				javaOwnedMonitors[i] = new JDIObjectValue(target, element);
				i++;
			}
			return javaOwnedMonitors;
		} catch (IncompatibleThreadStateException e) {
			targetRequestFailed(JDIDebugModelMessages.JDIThread_43, e);
		} catch (RuntimeException e) {
			targetRequestFailed(JDIDebugModelMessages.JDIThread_44, e);
		}
		return null;
	}

	/**
	 * @see org.eclipse.jdt.debug.core.IJavaThread#getContendedMonitor()
	 */
	@Override
	public IJavaObject getContendedMonitor() throws DebugException {
		try {
			ObjectReference monitor = fThread.currentContendedMonitor();
			if (monitor != null) {
				return new JDIObjectValue((JDIDebugTarget) getDebugTarget(),
						monitor);
			}
		} catch (IncompatibleThreadStateException e) {
			targetRequestFailed(JDIDebugModelMessages.JDIThread_45, e);
		} catch (RuntimeException e) {
			targetRequestFailed(JDIDebugModelMessages.JDIThread_46, e);
		}

		return null;
	}

	/**
	 * @see org.eclipse.debug.core.model.IFilteredStep#canStepWithFilters()
	 */
	@Override
	public boolean canStepWithFilters() {
		if (canStepInto()) {
			String[] filters = getJavaDebugTarget().getStepFilters();
			return filters != null && filters.length > 0;
		}
		return false;
	}

	/**
	 * @see org.eclipse.debug.core.model.IFilteredStep#stepWithFilters()
	 */
	@Override
	public void stepWithFilters() throws DebugException {
		if (!canStepWithFilters()) {
			return;
		}
		stepInto();
	}

	/**
	 * Class which managed the queue of runnable associated with this thread.
	 */
	static class ThreadJob extends Job {

		private Vector<Runnable> fRunnables;

		private JDIThread fJDIThread;

		public ThreadJob(JDIThread thread) {
			super(JDIDebugModelMessages.JDIThread_39);
			fJDIThread = thread;
			fRunnables = new Vector<>(5);
			setSystem(true);
		}

		public void addRunnable(Runnable runnable) {
			synchronized (fRunnables) {
				fRunnables.add(runnable);
			}
			schedule();
		}

		public boolean isEmpty() {
			return fRunnables.isEmpty();
		}

		/*
		 * @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.
		 * IProgressMonitor)
		 */
		@Override
		public IStatus run(IProgressMonitor monitor) {
			fJDIThread.fRunningAsyncJob = this;
			Object[] runnables;
			synchronized (fRunnables) {
				runnables = fRunnables.toArray();
				fRunnables.clear();
			}

			MultiStatus failed = null;
			monitor.beginTask(this.getName(), runnables.length);
			int i = 0;
			while (i < runnables.length && !fJDIThread.isTerminated()
					&& !monitor.isCanceled()) {
				try {
					((Runnable) runnables[i]).run();
				} catch (Exception e) {
					if (failed == null) {
						failed = new MultiStatus(
								JDIDebugPlugin.getUniqueIdentifier(),
								JDIDebugPlugin.ERROR,
								JDIDebugModelMessages.JDIThread_0, null);
					}
					failed.add(new Status(IStatus.ERROR, JDIDebugPlugin
							.getUniqueIdentifier(), JDIDebugPlugin.ERROR,
							JDIDebugModelMessages.JDIThread_0, e));
				}
				i++;
				monitor.worked(1);
			}
			fJDIThread.fRunningAsyncJob = null;
			monitor.done();
			if (failed == null) {
				return Status.OK_STATUS;
			}
			return failed;
		}

		/*
		 * @see org.eclipse.core.runtime.jobs.Job#shouldRun()
		 */
		@Override
		public boolean shouldRun() {
			return !fJDIThread.isTerminated() && !fRunnables.isEmpty();
		}

	}

	/*
	 * (non-Javadoc)
	 *
	 * @see
	 * org.eclipse.jdt.debug.core.IJavaThread#stop(org.eclipse.jdt.debug.core
	 * .IJavaObject)
	 */
	@Override
	public void stop(IJavaObject exception) throws DebugException {
		try {
			fThread.stop(((JDIObjectValue) exception).getUnderlyingObject());
		} catch (InvalidTypeException e) {
			targetRequestFailed(MessageFormat.format(
					JDIDebugModelMessages.JDIThread_exception_stoping_thread,
					e.toString()), e);
		}
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.jdt.debug.core.IJavaThread#getThreadGroup()
	 */
	@Override
	public IJavaThreadGroup getThreadGroup() throws DebugException {
		ThreadGroupReference group = getUnderlyingThreadGroup();
		if (group != null) {
			return getJavaDebugTarget().findThreadGroup(group);
		}
		return null;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.jdt.debug.core.IJavaThread#getFrameCount()
	 */
	@Override
	public int getFrameCount() throws DebugException {
		return getUnderlyingFrameCount();
	}

	protected void forceReturn(IJavaValue value) throws DebugException {
		if (!isSuspended()) {
			return;
		}
		try {
			fThread.forceEarlyReturn(((JDIValue) value).getUnderlyingValue());
			stepReturn();
		} catch (VMDisconnectedException e) {
			disconnected();
		} catch (InvalidTypeException e) {
			targetRequestFailed(JDIDebugModelMessages.JDIThread_48, e);
		} catch (ClassNotLoadedException e) {
			targetRequestFailed(JDIDebugModelMessages.JDIThread_48, e);
		} catch (IncompatibleThreadStateException e) {
			targetRequestFailed(JDIDebugModelMessages.JDIThread_48, e);
		} catch (UnsupportedOperationException e) {
			requestFailed(JDIDebugModelMessages.JDIThread_48, e);
		} catch (RuntimeException e) {
			targetRequestFailed(JDIDebugModelMessages.JDIThread_48, e);
		}
	}

	/**
	 * Implementation of a scheduling rule for this thread, which defines how it
	 * should behave when a request for content job tries to run while the
	 * thread is evaluating
	 *
	 * @since 3.3.0
	 */
	class SerialPerObjectRule implements ISchedulingRule {

		private Object fObject = null;

		public SerialPerObjectRule(Object lock) {
			fObject = lock;
		}

		/*
		 * (non-Javadoc)
		 *
		 * @see
		 * org.eclipse.core.runtime.jobs.ISchedulingRule#contains(org.eclipse
		 * .core.runtime.jobs.ISchedulingRule)
		 */
		@Override
		public boolean contains(ISchedulingRule rule) {
			return rule == this;
		}

		/*
		 * (non-Javadoc)
		 *
		 * @see
		 * org.eclipse.core.runtime.jobs.ISchedulingRule#isConflicting(org.eclipse
		 * .core.runtime.jobs.ISchedulingRule)
		 */
		@Override
		public boolean isConflicting(ISchedulingRule rule) {
			if (rule instanceof SerialPerObjectRule) {
				SerialPerObjectRule vup = (SerialPerObjectRule) rule;
				return fObject == vup.fObject;
			}
			return false;
		}

	}

	/**
	 * returns the scheduling rule for getting content while evaluations are
	 * running
	 *
	 * @return the <code>ISchedulingRule</code> for this thread
	 *
	 * @since 3.3.0
	 */
	public ISchedulingRule getThreadRule() {
		return new SerialPerObjectRule(this);
	}

	/**
	 * A class prepare has resumed this thread - if the thread was suspended at
	 * startup then fix up the state to running and fire an event to update UI.
	 */
	public synchronized void resumedFromClassPrepare() {
		if (isSuspended()) {
			setRunning(true);
			fireResumeEvent(DebugEvent.CLIENT_REQUEST);
		}
	}

	/**
	 * Returns whether a suspend vote is currently in progress.
	 *
	 * @return whether a suspend vote is currently in progress
	 */
	public synchronized boolean isSuspendVoteInProgress() {
		return fSuspendVoteInProgress;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.jdt.debug.core.IJavaThread#getThreadObject()
	 */
	@Override
	public IJavaObject getThreadObject() throws DebugException {
		return (IJavaObject) JDIValue
				.createValue(getJavaDebugTarget(), fThread);
	}

	protected StepIntoHandler createStepIntoHandler() {
        return new StepIntoHandler();
    }

    protected StepOverHandler createStepOverHandler() {
        return new StepOverHandler();
    }

    protected StepReturnHandler createStepReturnHandler() {
        return new StepReturnHandler();
    }

    protected StepToFrameHandler createStepToFrameHandler(IStackFrame stackFrame) throws DebugException {
        return new StepToFrameHandler(stackFrame);
    }

    protected DropToFrameHandler createDropToFrameHandler(IStackFrame stackFrame) throws DebugException {
        return new DropToFrameHandler(stackFrame);
    }
	public static boolean showStepResultIsEnabled() {
		return Platform.getPreferencesService().getBoolean(JDIDebugPlugin.getUniqueIdentifier(), JDIDebugModel.PREF_SHOW_STEP_RESULT, true, null);
	}

	protected boolean isSupported(Location currentLocation) {
		if (currentLocation == null) {
			return false;
		}
		return JAVA_STRATUM_CONSTANT.equals(currentLocation.declaringType().defaultStratum());
	}

	public MethodResult getMethodResult() {
		return fMethodResult;
	}

	public void setMethodResult(MethodResult fMethodResult) {
		this.fMethodResult = fMethodResult;
	}

}