/*******************************************************************************
 * Copyright (c) 2000, 2015 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.jdi.internal;

import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.eclipse.jdi.internal.jdwp.JdwpCommandPacket;
import org.eclipse.jdi.internal.jdwp.JdwpID;
import org.eclipse.jdi.internal.jdwp.JdwpReplyPacket;
import org.eclipse.jdi.internal.jdwp.JdwpThreadID;
import org.eclipse.osgi.util.NLS;

import com.sun.jdi.ClassNotLoadedException;
import com.sun.jdi.IncompatibleThreadStateException;
import com.sun.jdi.InternalException;
import com.sun.jdi.InvalidStackFrameException;
import com.sun.jdi.InvalidTypeException;
import com.sun.jdi.NativeMethodException;
import com.sun.jdi.ObjectCollectedException;
import com.sun.jdi.ObjectReference;
import com.sun.jdi.StackFrame;
import com.sun.jdi.ThreadGroupReference;
import com.sun.jdi.ThreadReference;
import com.sun.jdi.VMCannotBeModifiedException;
import com.sun.jdi.VMDisconnectedException;
import com.sun.jdi.Value;

/**
 * This class implements the corresponding interfaces declared by the JDI
 * specification. See the com.sun.jdi package for more information.
 *
 */
public class ThreadReferenceImpl extends ObjectReferenceImpl implements	ThreadReference, org.eclipse.jdi.hcr.ThreadReference {
	/** ThreadStatus Constants. */
	public static final int JDWP_THREAD_STATUS_ZOMBIE = 0;
	public static final int JDWP_THREAD_STATUS_RUNNING = 1;
	public static final int JDWP_THREAD_STATUS_SLEEPING = 2;
	public static final int JDWP_THREAD_STATUS_MONITOR = 3;
	public static final int JDWP_THREAD_STATUS_WAIT = 4;

	/** SuspendStatus Constants. */
	public static final int SUSPEND_STATUS_SUSPENDED = 0x01;

	/** Mapping of command codes to strings. */
	private static Map<Integer, String> fgThreadStatusMap = null;

	/** Map with Strings for flag bits. */
	private static String[] fgSuspendStatusStrings = null;

	/** JDWP Tag. */
	protected static final byte tag = JdwpID.THREAD_TAG;

	/** Is thread currently at a breakpoint? */
	private boolean fIsAtBreakpoint = false;

	/**
	 * The cached thread group. A thread's thread group cannot be changed.
	 */
	private ThreadGroupReferenceImpl fThreadGroup = null;

	/**
	 * Creates new ThreadReferenceImpl.
	 */
	public ThreadReferenceImpl(VirtualMachineImpl vmImpl, JdwpThreadID threadID) {
		super("ThreadReference", vmImpl, threadID); //$NON-NLS-1$
	}

	/**
	 * Sets at breakpoint flag.
	 */
	public void setIsAtBreakpoint() {
		fIsAtBreakpoint = true;
	}

	/**
	 * Reset flags that can be set when event occurs.
	 */
	public void resetEventFlags() {
		fIsAtBreakpoint = false;
	}

	/**
	 * @returns Value tag.
	 */
	@Override
	public byte getTag() {
		return tag;
	}

	/**
	 * @returns Returns an ObjectReference for the monitor, if any, for which
	 *          this thread is currently waiting.
	 */
	@Override
	public ObjectReference currentContendedMonitor()
			throws IncompatibleThreadStateException {
		if (!virtualMachine().canGetCurrentContendedMonitor()) {
			throw new UnsupportedOperationException();
		}
		// Note that this information should not be cached.
		initJdwpRequest();
		try {
			JdwpReplyPacket replyPacket = requestVM(
					JdwpCommandPacket.TR_CURRENT_CONTENDED_MONITOR, this);
			switch (replyPacket.errorCode()) {
			case JdwpReplyPacket.INVALID_THREAD:
				throw new ObjectCollectedException();
			case JdwpReplyPacket.THREAD_NOT_SUSPENDED:
				throw new IncompatibleThreadStateException(
						JDIMessages.ThreadReferenceImpl_Thread_was_not_suspended_1);
			}
			defaultReplyErrorHandler(replyPacket.errorCode());

			DataInputStream replyData = replyPacket.dataInStream();
			ObjectReference result = ObjectReferenceImpl.readObjectRefWithTag(
					this, replyData);
			return result;
		} catch (IOException e) {
			defaultIOExceptionHandler(e);
			return null;
		} finally {
			handledJdwpRequest();
		}
	}

	/**
	 * @see com.sun.jdi.ThreadReference#forceEarlyReturn(com.sun.jdi.Value)
	 * @since 3.3
	 */
	@Override
	public void forceEarlyReturn(Value value) throws InvalidTypeException,
			ClassNotLoadedException, IncompatibleThreadStateException {
		if (!virtualMachineImpl().canBeModified()) {
			throw new VMCannotBeModifiedException(
					JDIMessages.ThreadReferenceImpl_vm_read_only);
		}
		initJdwpRequest();
		ByteArrayOutputStream byteOutStream = new ByteArrayOutputStream();
		DataOutputStream dataOutStream = new DataOutputStream(byteOutStream);
		try {
			write(this, dataOutStream);
			if (value != null) {
				((ValueImpl) value).writeWithTag((ValueImpl) value,
						dataOutStream);
			} else {
				ValueImpl.writeNullWithTag(this, dataOutStream);
			}
			JdwpReplyPacket reply = requestVM(
					JdwpCommandPacket.TR_FORCE_EARLY_RETURN, byteOutStream);
			switch (reply.errorCode()) {
			case JdwpReplyPacket.INVALID_THREAD:
				throw new ObjectCollectedException(
						JDIMessages.ThreadReferenceImpl_thread_object_invalid);
			case JdwpReplyPacket.INVALID_OBJECT:
				throw new ClassNotLoadedException(
						JDIMessages.ThreadReferenceImpl_thread_or_value_unknown);
			case JdwpReplyPacket.THREAD_NOT_SUSPENDED:
			case JdwpReplyPacket.THREAD_NOT_ALIVE:
				throw new IncompatibleThreadStateException(
						JDIMessages.ThreadReferenceImpl_thread_not_suspended);
			case JdwpReplyPacket.NOT_IMPLEMENTED:
				throw new UnsupportedOperationException(
						JDIMessages.ThreadReferenceImpl_no_force_early_return_on_threads);
			case JdwpReplyPacket.OPAQUE_FRAME:
				throw new NativeMethodException(
						JDIMessages.ThreadReferenceImpl_thread_cannot_force_native_method);
			case JdwpReplyPacket.NO_MORE_FRAMES:
				throw new InvalidStackFrameException(
						JDIMessages.ThreadReferenceImpl_thread_no_stackframes);
			case JdwpReplyPacket.TYPE_MISMATCH:
				throw new InvalidTypeException(
						JDIMessages.ThreadReferenceImpl_incapatible_return_type);
			case JdwpReplyPacket.VM_DEAD:
				throw new VMDisconnectedException(JDIMessages.vm_dead);
			}
			defaultReplyErrorHandler(reply.errorCode());
		} catch (IOException e) {
			defaultIOExceptionHandler(e);
		} finally {
			handledJdwpRequest();
		}
	}

	/**
	 * @returns Returns the StackFrame at the given index in the thread's
	 *          current call stack.
	 */
	@Override
	public StackFrame frame(int index) throws IncompatibleThreadStateException {
		return frames(index, 1).get(0);
	}

	/**
	 * @see com.sun.jdi.ThreadReference#frameCount()
	 */
	@Override
	public int frameCount() throws IncompatibleThreadStateException {
		// Note that this information should not be cached.
		initJdwpRequest();
		try {
			JdwpReplyPacket replyPacket = requestVM(
					JdwpCommandPacket.TR_FRAME_COUNT, this);
			switch (replyPacket.errorCode()) {
			case JdwpReplyPacket.INVALID_THREAD:
				throw new ObjectCollectedException();
			case JdwpReplyPacket.THREAD_NOT_SUSPENDED:
				throw new IncompatibleThreadStateException(
						JDIMessages.ThreadReferenceImpl_Thread_was_not_suspended_1);
			}
			defaultReplyErrorHandler(replyPacket.errorCode());

			DataInputStream replyData = replyPacket.dataInStream();
			int result = readInt("frame count", replyData); //$NON-NLS-1$
			return result;
		} catch (IOException e) {
			defaultIOExceptionHandler(e);
			return 0;
		} finally {
			handledJdwpRequest();
		}
	}

	/* (non-Javadoc)
	 * @see com.sun.jdi.ThreadReference#frames()
	 */
	@Override
	public List<StackFrame> frames() throws IncompatibleThreadStateException {
		return frames(0, -1);
	}

	/* (non-Javadoc)
	 * @see com.sun.jdi.ThreadReference#frames(int, int)
	 */
	@Override
	public List<StackFrame> frames(int start, int length) throws IndexOutOfBoundsException,
			IncompatibleThreadStateException {
		// Note that this information should not be cached.
		initJdwpRequest();
		try {
			ByteArrayOutputStream outBytes = new ByteArrayOutputStream();
			DataOutputStream outData = new DataOutputStream(outBytes);
			write(this, outData);
			writeInt(start, "start", outData); //$NON-NLS-1$
			writeInt(length, "length", outData); //$NON-NLS-1$

			JdwpReplyPacket replyPacket = requestVM(
					JdwpCommandPacket.TR_FRAMES, outBytes);
			switch (replyPacket.errorCode()) {
			case JdwpReplyPacket.INVALID_THREAD:
				throw new ObjectCollectedException();
			case JdwpReplyPacket.THREAD_NOT_SUSPENDED:
				throw new IncompatibleThreadStateException(
						JDIMessages.ThreadReferenceImpl_Thread_was_not_suspended_1);
			case JdwpReplyPacket.INVALID_INDEX:
				throw new IndexOutOfBoundsException(
						JDIMessages.ThreadReferenceImpl_Invalid_index_of_stack_frames_given_4);
			}
			defaultReplyErrorHandler(replyPacket.errorCode());

			DataInputStream replyData = replyPacket.dataInStream();
			int nrOfElements = readInt("elements", replyData); //$NON-NLS-1$
			List<StackFrame> frames = new ArrayList<>(nrOfElements);
			for (int i = 0; i < nrOfElements; i++) {
				StackFrameImpl frame = StackFrameImpl.readWithLocation(this,
						this, replyData);
				if (frame == null) {
					continue;
				}
				frames.add(frame);
			}
			return frames;
		} catch (IOException e) {
			defaultIOExceptionHandler(e);
			return null;
		} finally {
			handledJdwpRequest();
		}
	}

	/* (non-Javadoc)
	 * @see com.sun.jdi.ThreadReference#interrupt()
	 */
	@Override
	public void interrupt() {
		// Note that this information should not be cached.
		initJdwpRequest();
		try {
			requestVM(JdwpCommandPacket.TR_INTERRUPT, this);
		} finally {
			handledJdwpRequest();
		}
	}

	/* (non-Javadoc)
	 * @see com.sun.jdi.ThreadReference#isAtBreakpoint()
	 */
	@Override
	public boolean isAtBreakpoint() {
		return isSuspended() && fIsAtBreakpoint;
	}

	/* (non-Javadoc)
	 * @see com.sun.jdi.ThreadReference#isSuspended()
	 */
	@Override
	public boolean isSuspended() {
		// Note that this information should not be cached.
		initJdwpRequest();
		try {
			JdwpReplyPacket replyPacket = requestVM(
					JdwpCommandPacket.TR_STATUS, this);
			switch (replyPacket.errorCode()) {
			case JdwpReplyPacket.INVALID_THREAD:
				throw new ObjectCollectedException();
			}
			defaultReplyErrorHandler(replyPacket.errorCode());
			DataInputStream replyData = replyPacket.dataInStream();
			// remove the thread status reply
			readInt("thread status", threadStatusMap(), replyData); //$NON-NLS-1$
			int suspendStatus = readInt(
					"suspend status", suspendStatusStrings(), replyData); //$NON-NLS-1$
			boolean result = suspendStatus == SUSPEND_STATUS_SUSPENDED;
			return result;
		} catch (IOException e) {
			defaultIOExceptionHandler(e);
			return false;
		} finally {
			handledJdwpRequest();
		}
	}

	/* (non-Javadoc)
	 * @see com.sun.jdi.ThreadReference#name()
	 */
	@Override
	public String name() {
		initJdwpRequest();
		try {
			JdwpReplyPacket replyPacket = requestVM(JdwpCommandPacket.TR_NAME,
					this);
			switch (replyPacket.errorCode()) {
			case JdwpReplyPacket.INVALID_THREAD:
				throw new ObjectCollectedException();
			}
			defaultReplyErrorHandler(replyPacket.errorCode());
			DataInputStream replyData = replyPacket.dataInStream();
			return readString("name", replyData); //$NON-NLS-1$
		} catch (IOException e) {
			defaultIOExceptionHandler(e);
			return null;
		} finally {
			handledJdwpRequest();
		}
	}

	/* (non-Javadoc)
	 * @see com.sun.jdi.ThreadReference#ownedMonitors()
	 */
	@Override
	public List<ObjectReference> ownedMonitors() throws IncompatibleThreadStateException {
		if (!virtualMachine().canGetOwnedMonitorInfo()) {
			throw new UnsupportedOperationException();
		}
		// Note that this information should not be cached.
		initJdwpRequest();
		try {
			JdwpReplyPacket replyPacket = requestVM(
					JdwpCommandPacket.TR_OWNED_MONITORS, this);
			switch (replyPacket.errorCode()) {
			case JdwpReplyPacket.INVALID_THREAD:
				throw new ObjectCollectedException();
			case JdwpReplyPacket.THREAD_NOT_SUSPENDED:
				throw new IncompatibleThreadStateException(
						JDIMessages.ThreadReferenceImpl_Thread_was_not_suspended_5);
			}
			defaultReplyErrorHandler(replyPacket.errorCode());
			DataInputStream replyData = replyPacket.dataInStream();

			int nrOfMonitors = readInt("nr of monitors", replyData); //$NON-NLS-1$
			List<ObjectReference> result = new ArrayList<>(nrOfMonitors);
			for (int i = 0; i < nrOfMonitors; i++) {
				result.add(ObjectReferenceImpl.readObjectRefWithTag(this,
						replyData));
			}
			return result;
		} catch (IOException e) {
			defaultIOExceptionHandler(e);
			return null;
		} finally {
			handledJdwpRequest();
		}
	}

	/* (non-Javadoc)
	 * @see com.sun.jdi.ThreadReference#ownedMonitorsAndFrames()
	 */
	@Override
	public List<com.sun.jdi.MonitorInfo> ownedMonitorsAndFrames()
			throws IncompatibleThreadStateException {
		initJdwpRequest();
		try {
			JdwpReplyPacket replyPacket = requestVM(
					JdwpCommandPacket.TR_OWNED_MONITOR_STACK_DEPTH, this);
			switch (replyPacket.errorCode()) {
			case JdwpReplyPacket.INVALID_THREAD:
			case JdwpReplyPacket.INVALID_OBJECT:
				throw new ObjectCollectedException(
						JDIMessages.ThreadReferenceImpl_thread_object_invalid);
			case JdwpReplyPacket.THREAD_NOT_SUSPENDED:
				throw new IncompatibleThreadStateException(
						JDIMessages.ThreadReferenceImpl_Thread_was_not_suspended_5);
			case JdwpReplyPacket.NOT_IMPLEMENTED:
				throw new UnsupportedOperationException(
						JDIMessages.ThreadReferenceImpl_no_force_early_return_on_threads);
			case JdwpReplyPacket.VM_DEAD:
				throw new VMDisconnectedException(JDIMessages.vm_dead);
			}
			defaultReplyErrorHandler(replyPacket.errorCode());
			DataInputStream replyData = replyPacket.dataInStream();

			int owned = readInt("owned monitors", replyData); //$NON-NLS-1$
			List<com.sun.jdi.MonitorInfo> result = new ArrayList<>(owned);
			ObjectReference monitor = null;
			int depth = -1;
			for (int i = 0; i < owned; i++) {
				monitor = ObjectReferenceImpl.readObjectRefWithTag(this,
						replyData);
				depth = readInt("stack depth", replyData); //$NON-NLS-1$
				result.add(new MonitorInfoImpl(this, depth, monitor, virtualMachineImpl()));
			}
			return result;
		} catch (IOException e) {
			defaultIOExceptionHandler(e);
			return null;
		} finally {
			handledJdwpRequest();
		}
	}

	/**
	 * Resumes this thread.
	 *
	 * @see com.sun.jdi.ThreadReference#resume()
	 */
	@Override
	public void resume() {
		initJdwpRequest();
		try {
			JdwpReplyPacket replyPacket = requestVM(
					JdwpCommandPacket.TR_RESUME, this);
			switch (replyPacket.errorCode()) {
			case JdwpReplyPacket.INVALID_THREAD:
				throw new ObjectCollectedException();
			}
			defaultReplyErrorHandler(replyPacket.errorCode());
			resetEventFlags();
		} finally {
			handledJdwpRequest();
		}
	}

	/**
	 * @return Returns the thread's status.
	 */
	@Override
	public int status() {
		// Note that this information should not be cached.
		initJdwpRequest();
		try {
			JdwpReplyPacket replyPacket = requestVM(
					JdwpCommandPacket.TR_STATUS, this);
			switch (replyPacket.errorCode()) {
			case JdwpReplyPacket.ABSENT_INFORMATION:
				return THREAD_STATUS_UNKNOWN;
			case JdwpReplyPacket.INVALID_THREAD:
				return THREAD_STATUS_NOT_STARTED;
			}
			defaultReplyErrorHandler(replyPacket.errorCode());
			DataInputStream replyData = replyPacket.dataInStream();
			int threadStatus = readInt(
					"thread status", threadStatusMap(), replyData); //$NON-NLS-1$
			readInt("suspend status", suspendStatusStrings(), replyData); //$NON-NLS-1$
			switch (threadStatus) {
			case JDWP_THREAD_STATUS_ZOMBIE:
				return THREAD_STATUS_ZOMBIE;
			case JDWP_THREAD_STATUS_RUNNING:
				return THREAD_STATUS_RUNNING;
			case JDWP_THREAD_STATUS_SLEEPING:
				return THREAD_STATUS_SLEEPING;
			case JDWP_THREAD_STATUS_MONITOR:
				return THREAD_STATUS_MONITOR;
			case JDWP_THREAD_STATUS_WAIT:
				return THREAD_STATUS_WAIT;
			case -1: // see bug 30816
				return THREAD_STATUS_UNKNOWN;
			}
			throw new InternalException(
					JDIMessages.ThreadReferenceImpl_Unknown_thread_status_received___6
							+ threadStatus);
		} catch (IOException e) {
			defaultIOExceptionHandler(e);
			return 0;
		} finally {
			handledJdwpRequest();
		}
	}

	/**
	 * Stops this thread with an asynchronous exception.
	 *
	 * @see com.sun.jdi.ThreadReference#stop(com.sun.jdi.ObjectReference)
	 */
	@Override
	public void stop(ObjectReference throwable) throws InvalidTypeException {
		checkVM(throwable);
		ObjectReferenceImpl throwableImpl = (ObjectReferenceImpl) throwable;

		initJdwpRequest();
		try {
			ByteArrayOutputStream outBytes = new ByteArrayOutputStream();
			DataOutputStream outData = new DataOutputStream(outBytes);
			write(this, outData);
			throwableImpl.write(this, outData);

			JdwpReplyPacket replyPacket = requestVM(JdwpCommandPacket.TR_STOP,
					outBytes);
			switch (replyPacket.errorCode()) {
			case JdwpReplyPacket.INVALID_THREAD:
				throw new ObjectCollectedException();
			case JdwpReplyPacket.INVALID_CLASS:
				throw new InvalidTypeException(
						JDIMessages.ThreadReferenceImpl_Stop_argument_not_an_instance_of_java_lang_Throwable_in_the_target_VM_7);
			}
			defaultReplyErrorHandler(replyPacket.errorCode());
		} catch (IOException e) {
			defaultIOExceptionHandler(e);
		} finally {
			handledJdwpRequest();
		}
	}

	/**
	 * Suspends this thread.
	 *
	 * @see com.sun.jdi.ThreadReference#suspend()
	 */
	@Override
	public void suspend() {
		initJdwpRequest();
		try {
			JdwpReplyPacket replyPacket = requestVM(
					JdwpCommandPacket.TR_SUSPEND, this);
			switch (replyPacket.errorCode()) {
			case JdwpReplyPacket.INVALID_THREAD:
				throw new ObjectCollectedException();
			}
			defaultReplyErrorHandler(replyPacket.errorCode());
		} finally {
			handledJdwpRequest();
		}
	}

	/**
	 * @return Returns the number of pending suspends for this thread.
	 */
	@Override
	public int suspendCount() {
		// Note that this information should not be cached.
		initJdwpRequest();
		try {
			JdwpReplyPacket replyPacket = requestVM(
					JdwpCommandPacket.TR_SUSPEND_COUNT, this);
			defaultReplyErrorHandler(replyPacket.errorCode());
			DataInputStream replyData = replyPacket.dataInStream();
			int result = readInt("suspend count", replyData); //$NON-NLS-1$
			return result;
		} catch (IOException e) {
			defaultIOExceptionHandler(e);
			return 0;
		} finally {
			handledJdwpRequest();
		}
	}

	/**
	 * @return Returns this thread's thread group.
	 */
	@Override
	public ThreadGroupReference threadGroup() {
		if (fThreadGroup != null) {
			return fThreadGroup;
		}
		initJdwpRequest();
		try {
			JdwpReplyPacket replyPacket = requestVM(
					JdwpCommandPacket.TR_THREAD_GROUP, this);
			switch (replyPacket.errorCode()) {
			case JdwpReplyPacket.INVALID_THREAD:
				throw new ObjectCollectedException();
			}
			defaultReplyErrorHandler(replyPacket.errorCode());
			DataInputStream replyData = replyPacket.dataInStream();
			fThreadGroup = ThreadGroupReferenceImpl.read(this, replyData);
			return fThreadGroup;
		} catch (IOException e) {
			defaultIOExceptionHandler(e);
			return null;
		} finally {
			handledJdwpRequest();
		}
	}

	/**
	 * Simulate the execution of a return instruction instead of executing the
	 * next byte code in a method.
	 *
	 * @return Returns whether any finally or synchronized blocks are enclosing
	 *         the current instruction.
	 */
	@Override
	public boolean doReturn(Value returnValue,
			boolean triggerFinallyAndSynchronized)
			throws org.eclipse.jdi.hcr.OperationRefusedException {
		virtualMachineImpl().checkHCRSupported();
		ValueImpl valueImpl;
		if (returnValue != null) { // null is used if no value is returned.
			checkVM(returnValue);
			valueImpl = (ValueImpl) returnValue;
		} else {
			try {
				TypeImpl returnType = (TypeImpl) frame(0).location().method()
						.returnType();
				valueImpl = (ValueImpl) returnType.createNullValue();
			} catch (IncompatibleThreadStateException e) {
				throw new org.eclipse.jdi.hcr.OperationRefusedException(
						e.toString());
			} catch (ClassNotLoadedException e) {
				throw new org.eclipse.jdi.hcr.OperationRefusedException(
						e.toString());
			}
		}

		// Note that this information should not be cached.
		initJdwpRequest();
		try {
			ByteArrayOutputStream outBytes = new ByteArrayOutputStream();
			DataOutputStream outData = new DataOutputStream(outBytes);
			write(this, outData);
			valueImpl.writeWithTag(this, outData);
			writeBoolean(triggerFinallyAndSynchronized,
					"trigger finaly+sync", outData); //$NON-NLS-1$

			JdwpReplyPacket replyPacket = requestVM(
					JdwpCommandPacket.HCR_DO_RETURN, outBytes);
			switch (replyPacket.errorCode()) {
			case JdwpReplyPacket.INVALID_THREAD:
				throw new ObjectCollectedException();
			}
			defaultReplyErrorHandler(replyPacket.errorCode());

			DataInputStream replyData = replyPacket.dataInStream();
			boolean result = readBoolean("is enclosed", replyData); //$NON-NLS-1$
			return result;
		} catch (IOException e) {
			defaultIOExceptionHandler(e);
			return false;
		} finally {
			handledJdwpRequest();
		}
	}

	/**
	 * @return Returns description of Mirror object.
	 */
	@Override
	public String toString() {
		try {
			return NLS.bind(JDIMessages.ThreadReferenceImpl_8,
					new String[] { type().toString(), name(),
							getObjectID().toString() });
		} catch (ObjectCollectedException e) {
			return JDIMessages.ThreadReferenceImpl__Garbage_Collected__ThreadReference__9
					+ idString();
		} catch (Exception e) {
			return fDescription;
		}
	}

	/**
	 * @return Reads JDWP representation and returns new instance.
	 */
	public static ThreadReferenceImpl read(MirrorImpl target, DataInputStream in)
			throws IOException {
		VirtualMachineImpl vmImpl = target.virtualMachineImpl();
		JdwpThreadID ID = new JdwpThreadID(vmImpl);
		ID.read(in);
		if (target.fVerboseWriter != null)
			target.fVerboseWriter.println("threadReference", ID.value()); //$NON-NLS-1$

		if (ID.isNull())
			return null;

		ThreadReferenceImpl mirror = (ThreadReferenceImpl) vmImpl
				.getCachedMirror(ID);
		if (mirror == null) {
			mirror = new ThreadReferenceImpl(vmImpl, ID);
			vmImpl.addCachedMirror(mirror);
		}
		return mirror;
	}

	/**
	 * Retrieves constant mappings.
	 */
	public static void getConstantMaps() {
		if (fgThreadStatusMap != null) {
			return;
		}

		Field[] fields = ThreadReferenceImpl.class.getDeclaredFields();
		fgThreadStatusMap = new HashMap<>();
		fgSuspendStatusStrings = new String[32]; // Int

		for (Field field : fields) {
			if ((field.getModifiers() & Modifier.PUBLIC) == 0
					|| (field.getModifiers() & Modifier.STATIC) == 0
					|| (field.getModifiers() & Modifier.FINAL) == 0)
				continue;

			try {
				String name = field.getName();
				int value = field.getInt(null);
				Integer intValue = new Integer(value);

				if (name.startsWith("JDWP_THREAD_STATUS_")) { //$NON-NLS-1$
					name = name.substring(19);
					fgThreadStatusMap.put(intValue, name);
				} else if (name.startsWith("SUSPEND_STATUS_")) { //$NON-NLS-1$
					name = name.substring(15);
					for (int j = 0; j < fgSuspendStatusStrings.length; j++) {
						if ((1 << j & value) != 0) {
							fgSuspendStatusStrings[j] = name;
							break;
						}
					}
				}
			} catch (IllegalAccessException e) {
				// Will not occur for own class.
			} catch (IllegalArgumentException e) {
				// Should not occur.
				// We should take care that all public static final constants
				// in this class are numbers that are convertible to int.
			}
		}
	}

	/**
	 * @return Returns a map with string representations of tags.
	 */
	public static Map<Integer, String> threadStatusMap() {
		getConstantMaps();
		return fgThreadStatusMap;
	}

	/**
	 * @return Returns a map with string representations of tags.
	 */
	public static String[] suspendStatusStrings() {
		getConstantMaps();
		return fgSuspendStatusStrings;
	}

	/**
	 * @see ThreadReference#popFrames(StackFrame)
	 */
	@Override
	public void popFrames(StackFrame frameToPop)
			throws IncompatibleThreadStateException {
		if (!isSuspended()) {
			throw new IncompatibleThreadStateException();
		}
		if (!virtualMachineImpl().canPopFrames()) {
			throw new UnsupportedOperationException();
		}

		StackFrameImpl frame = (StackFrameImpl) frameToPop;

		initJdwpRequest();
		try {
			ByteArrayOutputStream outBytes = new ByteArrayOutputStream();
			DataOutputStream outData = new DataOutputStream(outBytes);
			frame.writeWithThread(frame, outData);

			JdwpReplyPacket replyPacket = requestVM(
					JdwpCommandPacket.SF_POP_FRAME, outBytes);
			switch (replyPacket.errorCode()) {
			case JdwpReplyPacket.INVALID_THREAD:
				throw new InvalidStackFrameException();
			case JdwpReplyPacket.INVALID_FRAMEID:
				throw new InvalidStackFrameException(
						JDIMessages.ThreadReferenceImpl_Unable_to_pop_the_requested_stack_frame_from_the_call_stack__Reasons_include__The_frame_id_was_invalid__The_thread_was_resumed__10);
			case JdwpReplyPacket.THREAD_NOT_SUSPENDED:
				throw new IncompatibleThreadStateException(
						JDIMessages.ThreadReferenceImpl_Unable_to_pop_the_requested_stack_frame__The_requested_stack_frame_is_not_suspended_11);
			case JdwpReplyPacket.NO_MORE_FRAMES:
				throw new InvalidStackFrameException(
						JDIMessages.ThreadReferenceImpl_Unable_to_pop_the_requested_stack_frame_from_the_call_stack__Reasons_include__The_requested_frame_was_the_last_frame_on_the_call_stack__The_requested_frame_was_the_last_frame_above_a_native_frame__12);
			default:
				defaultReplyErrorHandler(replyPacket.errorCode());
			}
		} catch (IOException ioe) {
			defaultIOExceptionHandler(ioe);
		} finally {
			handledJdwpRequest();
		}
	}

}
