/*******************************************************************************
 * Copyright (c) 2000, 2015 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.jdi.internal;

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

}
