/*******************************************************************************
 * 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
 *     Tim Tromey - update method signature syntax (bug 31507)
 *******************************************************************************/
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.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

import org.eclipse.jdi.internal.jdwp.JdwpCommandPacket;
import org.eclipse.jdi.internal.jdwp.JdwpMethodID;
import org.eclipse.jdi.internal.jdwp.JdwpReplyPacket;

import com.ibm.icu.text.MessageFormat;
import com.sun.jdi.AbsentInformationException;
import com.sun.jdi.ClassLoaderReference;
import com.sun.jdi.ClassNotLoadedException;
import com.sun.jdi.LocalVariable;
import com.sun.jdi.Locatable;
import com.sun.jdi.Location;
import com.sun.jdi.Method;
import com.sun.jdi.Type;

/**
 * Implementation of com.sun.jdi.Method.
 */
public class MethodImpl extends TypeComponentImpl implements Method, Locatable {
	/** InvokeOptions Constants. */
	public static final int INVOKE_SINGLE_THREADED_JDWP = 0x01;
	public static final int INVOKE_NONVIRTUAL_JDWP = 0x02;

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

	/** MethodTypeID that corresponds to this reference. */
	private JdwpMethodID fMethodID;

	/** The following are the stored results of JDWP calls. */
	private List<LocalVariable> fVariables = null;
	private long fLowestValidCodeIndex = -1;
	private long fHighestValidCodeIndex = -1;
	private Map<Long, Integer> fCodeIndexToLine = null;
	private Map<Integer, List<Long>> fLineToCodeIndexes = null;
	private Map<String, Map<String, List<Location>>> fStratumAllLineLocations = null;
	private int fArgumentSlotsCount = -1;
	private List<LocalVariable> fArguments = null;
	private List<Type> fArgumentTypes = null;
	private List<String> fArgumentTypeNames = null;
	private List<String> fArgumentTypeSignatures = null;
	private byte[] fByteCodes = null;
	private long[] fCodeIndexTable;
	private int[] fJavaStratumLineNumberTable;

	private String fReturnTypeName = null;

	/**
	 * Creates new MethodImpl.
	 */
	public MethodImpl(VirtualMachineImpl vmImpl,
			ReferenceTypeImpl declaringType, JdwpMethodID methodID,
			String name, String signature, String genericSignature,
			int modifierBits) {
		super(
				"Method", vmImpl, declaringType, name, signature, genericSignature, modifierBits); //$NON-NLS-1$
		fMethodID = methodID;
	}

	/**
	 * Flushes all stored Jdwp results.
	 */
	protected void flushStoredJdwpResults() {
		fVariables = null;
		fLowestValidCodeIndex = -1;
		fHighestValidCodeIndex = -1;
		fCodeIndexToLine = null;
		fLineToCodeIndexes = null;
		fStratumAllLineLocations = null;
		fCodeIndexTable = null;
		fJavaStratumLineNumberTable = null;
		fArgumentSlotsCount = -1;
		fArguments = null;
		fArgumentTypes = null;
		fArgumentTypeNames = null;
		fArgumentTypeSignatures = null;
		fByteCodes = null;
	}

	/**
	 * @return Returns methodID of method.
	 */
	protected JdwpMethodID getMethodID() {
		return fMethodID;
	}

	/**
	 * @return Returns map of location to line number.
	 */
	protected Map<Long, Integer> javaStratumCodeIndexToLine()
			throws AbsentInformationException {
		if (isAbstract()) {
			return Collections.EMPTY_MAP;
		}
		getLineTable();
		return fCodeIndexToLine;
	}

	/**
	 * @return Returns map of line number to locations.
	 */
	protected List<Long> javaStratumLineToCodeIndexes(int line) throws AbsentInformationException {
		if (isAbstract() || isNative()) {
			return null;
		}
		getLineTable();

		return fLineToCodeIndexes.get(new Integer(line));
	}

	/**
	 * Gets line table from VM.
	 */
	private void getLineTable() throws AbsentInformationException {
		if (isObsolete()) {
			return;
		}
		if (fCodeIndexToLine != null) {
			if (fCodeIndexToLine.isEmpty()) {
				throw new AbsentInformationException(
						JDIMessages.MethodImpl_Got_empty_line_number_table_for_this_method_1);
			}
			return;
		}

		initJdwpRequest();
		try {
			ByteArrayOutputStream outBytes = new ByteArrayOutputStream();
			DataOutputStream outData = new DataOutputStream(outBytes);
			writeWithReferenceType(this, outData);

			JdwpReplyPacket replyPacket = requestVM(
					JdwpCommandPacket.M_LINE_TABLE, outBytes);
			switch (replyPacket.errorCode()) {
			case JdwpReplyPacket.ABSENT_INFORMATION:
				throw new AbsentInformationException(
						JDIMessages.MethodImpl_No_line_number_information_available_2);
			case JdwpReplyPacket.NATIVE_METHOD:
				throw new AbsentInformationException(
						JDIMessages.MethodImpl_No_line_number_information_available_2);
			}
			defaultReplyErrorHandler(replyPacket.errorCode());

			DataInputStream replyData = replyPacket.dataInStream();
			fLowestValidCodeIndex = readLong("lowest index", replyData); //$NON-NLS-1$
			fHighestValidCodeIndex = readLong("highest index", replyData); //$NON-NLS-1$
			int nrOfElements = readInt("elements", replyData); //$NON-NLS-1$
			fCodeIndexToLine = new HashMap<Long, Integer>();
			fLineToCodeIndexes = new HashMap<Integer, List<Long>>();
			if (nrOfElements == 0) {
				throw new AbsentInformationException(
						JDIMessages.MethodImpl_Got_empty_line_number_table_for_this_method_3);
			}
			fCodeIndexTable = new long[nrOfElements];
			fJavaStratumLineNumberTable = new int[nrOfElements];
			for (int i = 0; i < nrOfElements; i++) {
				long lineCodeIndex = readLong("code index", replyData); //$NON-NLS-1$
				Long lineCodeIndexLong = new Long(lineCodeIndex);
				int lineNr = readInt("line nr", replyData); //$NON-NLS-1$
				Integer lineNrInt = new Integer(lineNr);

				// Add entry to code-index to line mapping.
				fCodeIndexToLine.put(lineCodeIndexLong, lineNrInt);

				fCodeIndexTable[i] = lineCodeIndex;
				fJavaStratumLineNumberTable[i] = lineNr;

				List<Long> lineNrEntry = fLineToCodeIndexes.get(lineNrInt);
				if (lineNrEntry == null) {
					lineNrEntry = new ArrayList<Long>();
					fLineToCodeIndexes.put(lineNrInt, lineNrEntry);
				}
				lineNrEntry.add(lineCodeIndexLong);
			}
		} catch (IOException e) {
			fCodeIndexToLine = null;
			fLineToCodeIndexes = null;
			defaultIOExceptionHandler(e);
		} finally {
			handledJdwpRequest();
		}
	}

	/**
	 * @return Returns the line number that corresponds to the given
	 *         lineCodeIndex.
	 */
	protected int javaStratumLineNumber(long lineCodeIndex)
			throws AbsentInformationException {
		if (isAbstract() || isNative() || isObsolete()) {
			return -1;
		}
		getLineTable();
		if (lineCodeIndex > fHighestValidCodeIndex) {
			throw new AbsentInformationException(JDIMessages.MethodImpl_Invalid_code_index_of_a_location_given_4);
		}

		Long lineCodeIndexObj;
		Integer lineNrObj;
		long index = lineCodeIndex;
		// Search for the line where this code index is located.
		do {
			lineCodeIndexObj = new Long(index);
			lineNrObj = javaStratumCodeIndexToLine().get(lineCodeIndexObj);
		} while (lineNrObj == null && --index >= fLowestValidCodeIndex);
		if (lineNrObj == null) {
			if (lineCodeIndex >= fLowestValidCodeIndex) {
				index = lineCodeIndex;
				do {
					lineCodeIndexObj = new Long(index);
					lineNrObj = javaStratumCodeIndexToLine().get(lineCodeIndexObj);
				} while (lineNrObj == null && ++index <= fHighestValidCodeIndex);
				if (lineNrObj != null) {
					return lineNrObj.intValue();
				}
			}
			throw new AbsentInformationException(JDIMessages.MethodImpl_Invalid_code_index_of_a_location_given_4);
		}
		return lineNrObj.intValue();
	}

	/* (non-Javadoc)
	 * @see com.sun.jdi.Method#allLineLocations()
	 */
	@Override
	public List<Location> allLineLocations() throws AbsentInformationException {
		return allLineLocations(virtualMachine().getDefaultStratum(), null);
	}

	/* (non-Javadoc)
	 * @see com.sun.jdi.Method#arguments()
	 */
	@Override
	public List<LocalVariable> arguments() throws AbsentInformationException {
		if (isNative() || isAbstract()) {
			throw new AbsentInformationException(JDIMessages.MethodImpl_No_local_variable_information_available_9);
		}
		if (fArguments != null) {
			return fArguments;
		}

		List<LocalVariable> result = new ArrayList<LocalVariable>();
		Iterator<LocalVariable> iter = variables().iterator();
		while (iter.hasNext()) {
			LocalVariable var = iter.next();
			if (var.isArgument())
				result.add(var);
		}
		fArguments = result;
		return fArguments;
	}

	/**
	 * @return Returns a text representation of all declared argument types of
	 *         this method.
	 */
	@Override
	public List<String> argumentTypeNames() {
		if (fArgumentTypeNames != null) {
			return fArgumentTypeNames;
		}
		List<String> argumentTypeSignatures = argumentTypeSignatures();
		List<String> result = new ArrayList<String>();
		for (Iterator<String> iter = argumentTypeSignatures.iterator(); iter.hasNext();) {
			result.add(TypeImpl.signatureToName(iter.next()));
		}

		fArgumentTypeNames = result;
		return fArgumentTypeNames;
	}

	/**
	 * @return Returns a signatures of all declared argument types of this
	 *         method.
	 */
	private List<String> argumentTypeSignatures() {
		if (fArgumentTypeSignatures != null) {
			return fArgumentTypeSignatures;
		}

		fArgumentTypeSignatures = GenericSignature.getParameterTypes(signature());
		return fArgumentTypeSignatures;
	}

	/**
	 * @return Returns the list containing the type of each argument.
	 */
	@Override
	public List<Type> argumentTypes() throws ClassNotLoadedException {
		if (fArgumentTypes != null) {
			return fArgumentTypes;
		}
		List<Type> result = new ArrayList<Type>();
		Iterator<String> iter = argumentTypeSignatures().iterator();
		ClassLoaderReference classLoaderRef = declaringType().classLoader();
		VirtualMachineImpl vm = virtualMachineImpl();
		while (iter.hasNext()) {
			String argumentTypeSignature = iter.next();
			result.add(TypeImpl.create(vm, argumentTypeSignature, classLoaderRef));
		}
		fArgumentTypes = result;
		return fArgumentTypes;
	}

	/**
	 * @return Returns an array containing the bytecodes for this method.
	 */
	@Override
	public byte[] bytecodes() {
		if (fByteCodes != null) {
			return fByteCodes;
		}

		initJdwpRequest();
		try {
			ByteArrayOutputStream outBytes = new ByteArrayOutputStream();
			DataOutputStream outData = new DataOutputStream(outBytes);
			writeWithReferenceType(this, outData);

			JdwpReplyPacket replyPacket = requestVM(
					JdwpCommandPacket.M_BYTECODES, outBytes);
			defaultReplyErrorHandler(replyPacket.errorCode());

			DataInputStream replyData = replyPacket.dataInStream();
			int length = readInt("length", replyData); //$NON-NLS-1$
			fByteCodes = readByteArray(length, "bytecodes", replyData); //$NON-NLS-1$
			return fByteCodes;
		} catch (IOException e) {
			fByteCodes = null;
			defaultIOExceptionHandler(e);
			return null;
		} finally {
			handledJdwpRequest();
		}
	}

	/**
	 * @return Returns the hash code value.
	 */
	@Override
	public int hashCode() {
		return fMethodID.hashCode();
	}

	/**
	 * @return Returns true if two mirrors refer to the same entity in the
	 *         target VM.
	 * @see java.lang.Object#equals(Object)
	 */
	@Override
	public boolean equals(Object object) {
		return object != null
				&& object.getClass().equals(this.getClass())
				&& fMethodID.equals(((MethodImpl) object).fMethodID)
				&& referenceTypeImpl().equals(
						((MethodImpl) object).referenceTypeImpl());
	}

	/**
	 * @return Returns a negative integer, zero, or a positive integer as this
	 *         {@link Method} is less than, equal to, or greater than the specified
	 *         {@link Method}.
	 */
	@Override
	public int compareTo(Method method) {
		if (method == null || !method.getClass().equals(this.getClass()))
			throw new ClassCastException(
					JDIMessages.MethodImpl_Can__t_compare_method_to_given_object_6);

		// See if declaring types are the same, if not return comparison between
		// declaring types.
		Method type2 = method;
		if (!declaringType().equals(type2.declaringType()))
			return declaringType().compareTo(type2.declaringType());

		// Return comparison of position within declaring type.
		int index1 = declaringType().methods().indexOf(this);
		int index2 = type2.declaringType().methods().indexOf(type2);
		if (index1 < index2) {
			return -1;
		} else if (index1 > index2) {
			return 1;
		} else {
			return 0;
		}
	}

	/* (non-Javadoc)
	 * @see com.sun.jdi.Method#isAbstract()
	 */
	@Override
	public boolean isAbstract() {
		return (fModifierBits & MODIFIER_ACC_ABSTRACT) != 0;
	}

	/* (non-Javadoc)
	 * @see com.sun.jdi.Method#isConstructor()
	 */
	@Override
	public boolean isConstructor() {
		return name().equals("<init>"); //$NON-NLS-1$
	}

	/* (non-Javadoc)
	 * @see com.sun.jdi.Method#isNative()
	 */
	@Override
	public boolean isNative() {
		return (fModifierBits & MODIFIER_ACC_NATIVE) != 0;
	}

	/* (non-Javadoc)
	 * @see com.sun.jdi.Method#isStaticInitializer()
	 */
	@Override
	public boolean isStaticInitializer() {
		return name().equals("<clinit>"); //$NON-NLS-1$
	}

	/* (non-Javadoc)
	 * @see com.sun.jdi.Method#isSynchronized()
	 */
	@Override
	public boolean isSynchronized() {
		return (fModifierBits & MODIFIER_ACC_SYNCHRONIZED) != 0;
	}

	/* (non-Javadoc)
	 * @see com.sun.jdi.Method#locationOfCodeIndex(long)
	 */
	@Override
	public Location locationOfCodeIndex(long index) {
		if (isAbstract() || isNative()) {
			return null;
		}
		try {
			Integer lineNrInt = javaStratumCodeIndexToLine().get(new Long(index));
			if (lineNrInt == null) {
				throw new AbsentInformationException(MessageFormat.format(JDIMessages.MethodImpl_No_valid_location_at_the_specified_code_index__0__2, new Object[] { Long.toString(index) }));
			}
		} catch (AbsentInformationException e) {
		}
		return new LocationImpl(virtualMachineImpl(), this, index);
	}

	/* (non-Javadoc)
	 * @see com.sun.jdi.Method#locationsOfLine(int)
	 */
	@Override
	public List<Location> locationsOfLine(int line) throws AbsentInformationException {
		return locationsOfLine(virtualMachine().getDefaultStratum(), null, line);
	}

	/* (non-Javadoc)
	 * @see com.sun.jdi.Method#returnType()
	 */
	@Override
	public Type returnType() throws ClassNotLoadedException {
		int startIndex = signature().lastIndexOf(')') + 1; // Signature position
															// is just after
															// ending brace.
		return TypeImpl.create(virtualMachineImpl(),
				signature().substring(startIndex), declaringType()
						.classLoader());
	}

	/* (non-Javadoc)
	 * @see com.sun.jdi.Method#returnTypeName()
	 */
	@Override
	public String returnTypeName() {
		if (fReturnTypeName != null) {
			return fReturnTypeName;
		}
		int startIndex = signature().lastIndexOf(')') + 1; // Signature position
															// is just after
															// ending brace.
		fReturnTypeName = TypeImpl.signatureToName(signature().substring(
				startIndex));
		return fReturnTypeName;
	}

	/* (non-Javadoc)
	 * @see com.sun.jdi.Method#variables()
	 */
	@Override
	public List<LocalVariable> variables() throws AbsentInformationException {
		if (isNative() || isAbstract()) {
			throw new AbsentInformationException(JDIMessages.MethodImpl_No_local_variable_information_available_9);
		}
		if (fVariables != null) {
			return fVariables;
		}
		initJdwpRequest();
		try {
			ByteArrayOutputStream outBytes = new ByteArrayOutputStream();
			DataOutputStream outData = new DataOutputStream(outBytes);
			writeWithReferenceType(this, outData);

			boolean withGenericSignature = virtualMachineImpl()
					.isJdwpVersionGreaterOrEqual(1, 5);
			int jdwpCommand = withGenericSignature ? JdwpCommandPacket.M_VARIABLE_TABLE_WITH_GENERIC
					: JdwpCommandPacket.M_VARIABLE_TABLE;
			JdwpReplyPacket replyPacket = requestVM(jdwpCommand, outBytes);
			switch (replyPacket.errorCode()) {
			case JdwpReplyPacket.ABSENT_INFORMATION:
				return inferArguments();
			}

			defaultReplyErrorHandler(replyPacket.errorCode());

			DataInputStream replyData = replyPacket.dataInStream();
			fArgumentSlotsCount = readInt("arg count", replyData); //$NON-NLS-1$
			int nrOfElements = readInt("elements", replyData); //$NON-NLS-1$
			List<LocalVariable> variables = new ArrayList<LocalVariable>(nrOfElements);
			for (int i = 0; i < nrOfElements; i++) {
				long codeIndex = readLong("code index", replyData); //$NON-NLS-1$
				String name = readString("name", replyData); //$NON-NLS-1$
				String signature = readString("signature", replyData); //$NON-NLS-1$
				String genericSignature = null;
				if (withGenericSignature) {
					genericSignature = readString("generic signature", replyData); //$NON-NLS-1$
					if ("".equals(genericSignature)) { //$NON-NLS-1$
						genericSignature = null;
					}
				}
				int length = readInt("length", replyData); //$NON-NLS-1$
				int slot = readInt("slot", replyData); //$NON-NLS-1$
				boolean isArgument = slot < fArgumentSlotsCount;

				// Note that for instance methods, the first slot contains the
				// this reference.
				if (isStatic() || slot > 0) {
					LocalVariableImpl localVar = new LocalVariableImpl(
							virtualMachineImpl(), this, codeIndex, name,
							signature, genericSignature, length, slot,
							isArgument);
					variables.add(localVar);
				}
			}
			fVariables = variables;
			return fVariables;
		} catch (IOException e) {
			fArgumentSlotsCount = -1;
			fVariables = null;
			defaultIOExceptionHandler(e);
			return null;
		} finally {
			handledJdwpRequest();
		}
	}

	/**
	 * @throws AbsentInformationException
	 */
	private List<LocalVariable> inferArguments() throws AbsentInformationException {
		// infer arguments, if possible

		// try to generate the right generic signature for each argument
		String genericSignature = genericSignature();
		String[] signatures = argumentTypeSignatures().toArray(new String[0]);
		String[] genericSignatures;
		if (genericSignature == null) {
			genericSignatures = new String[signatures.length];
		} else {
			genericSignatures = GenericSignature.getParameterTypes(genericSignature).toArray(new String[0]);
			for (int i = 0; i < genericSignatures.length; i++) {
				if (genericSignatures[i].equals(signatures[i])) {
					genericSignatures[i] = null;
				}
			}
		}

		int slot = 0;
		if (!isStatic()) {
			slot++;
		}
		if (signatures.length > 0) {
			fArgumentSlotsCount = signatures.length;
			fVariables = new ArrayList<LocalVariable>(fArgumentSlotsCount);
			for (int i = 0; i < signatures.length; i++) {
				String name = "arg" + i; //$NON-NLS-1$
				LocalVariableImpl localVar = new LocalVariableImpl(virtualMachineImpl(), this, 0, name, signatures[i], genericSignatures[i], -1, slot, true);
				fVariables.add(localVar);
				slot++;
			}
			return fVariables;
		}
		throw new AbsentInformationException(
				JDIMessages.MethodImpl_No_local_variable_information_available_9);

	}

	/* (non-Javadoc)
	 * @see com.sun.jdi.Method#variablesByName(java.lang.String)
	 */
	@Override
	public List<LocalVariable> variablesByName(String name) throws AbsentInformationException {
		Iterator<LocalVariable> iter = variables().iterator();
		List<LocalVariable> result = new ArrayList<LocalVariable>();
		while (iter.hasNext()) {
			LocalVariable var = iter.next();
			if (var.name().equals(name)) {
				result.add(var);
			}
		}
		return result;
	}

	/**
	 * @see com.sun.jdi.Locatable#location()
	 */
	@Override
	public Location location() {
		if (isAbstract()) {
			return null;
		}
		if (isNative()) {
			return new LocationImpl(virtualMachineImpl(), this, -1);
		}
		// First retrieve line code table.
		try {
			getLineTable();
		} catch (AbsentInformationException e) {
			return new LocationImpl(virtualMachineImpl(), this, -1);
		}

		// Return location with Lowest Valid Code Index.
		return new LocationImpl(virtualMachineImpl(), this,
				fLowestValidCodeIndex);
	}

	/**
	 * Writes JDWP representation.
	 */
	public void write(MirrorImpl target, DataOutputStream out)
			throws IOException {
		fMethodID.write(out);
		if (target.fVerboseWriter != null) {
			target.fVerboseWriter.println("method", fMethodID.value()); //$NON-NLS-1$
		}
	}

	/**
	 * Writes JDWP representation, including ReferenceType.
	 */
	protected void writeWithReferenceType(MirrorImpl target,
			DataOutputStream out) throws IOException {
		referenceTypeImpl().write(target, out);
		write(target, out);
	}

	/**
	 * Writes JDWP representation, including ReferenceType with Tag.
	 */
	protected void writeWithReferenceTypeWithTag(MirrorImpl target,
			DataOutputStream out) throws IOException {
		referenceTypeImpl().writeWithTag(target, out);
		write(target, out);
	}

	/**
	 * @return Reads JDWP representation and returns new instance.
	 */
	protected static MethodImpl readWithReferenceTypeWithTag(MirrorImpl target,
			DataInputStream in) throws IOException {
		VirtualMachineImpl vmImpl = target.virtualMachineImpl();
		// See Location.
		ReferenceTypeImpl referenceType = ReferenceTypeImpl.readWithTypeTag(
				target, in);
		if (referenceType == null)
			return null;

		JdwpMethodID ID = new JdwpMethodID(vmImpl);
		if (target.fVerboseWriter != null) {
			target.fVerboseWriter.println("method", ID.value()); //$NON-NLS-1$
		}

		ID.read(in);
		if (ID.isNull()) {
			return null;
		}

		// The method must be part of a known reference type.
		Method method = referenceType.findMethod(ID);
		if (method == null) {
			throw new InternalError(
					JDIMessages.MethodImpl_Got_MethodID_of_ReferenceType_that_is_not_a_member_of_the_ReferenceType_10);
		}
		return (MethodImpl) method;
	}

	/**
	 * @return Reads JDWP representation and returns new instance.
	 */
	protected static MethodImpl readWithNameSignatureModifiers(
			ReferenceTypeImpl target, ReferenceTypeImpl referenceType,
			boolean withGenericSignature, DataInputStream in)
			throws IOException {
		VirtualMachineImpl vmImpl = target.virtualMachineImpl();
		JdwpMethodID ID = new JdwpMethodID(vmImpl);
		ID.read(in);
		if (target.fVerboseWriter != null) {
			target.fVerboseWriter.println("method", ID.value()); //$NON-NLS-1$
		}

		if (ID.isNull()) {
			return null;
		}
		String name = target.readString("name", in); //$NON-NLS-1$
		String signature = target.readString("signature", in); //$NON-NLS-1$
		String genericSignature = null;
		if (withGenericSignature) {
			genericSignature = target.readString("generic signature", in); //$NON-NLS-1$
			if ("".equals(genericSignature)) { //$NON-NLS-1$
				genericSignature = null;
			}
		}
		int modifierBits = target.readInt(
				"modifiers", AccessibleImpl.getModifierStrings(), in); //$NON-NLS-1$

		MethodImpl mirror = new MethodImpl(vmImpl, referenceType, ID, name,
				signature, genericSignature, modifierBits);
		return mirror;
	}

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

		Field[] fields = MethodImpl.class.getDeclaredFields();
		fgInvokeOptions = new String[32];

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

			try {
				String name = field.getName();

				if (name.startsWith("INVOKE_")) { //$NON-NLS-1$
					int value = field.getInt(null);
					for (int j = 0; j < fgInvokeOptions.length; j++) {
						if ((1 << j & value) != 0) {
							fgInvokeOptions[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.
	 */
	protected static String[] getInvokeOptions() {
		getConstantMaps();
		return fgInvokeOptions;
	}

	/**
	 * @see Method#isObsolete()
	 *
	 *      The JDK 1.4.0 specification states that obsolete methods are given
	 *      an ID of zero. It also states that when a method is redefined, the
	 *      new method gets the ID of the old method. Thus, the JDWP query for
	 *      isObsolete on JDK 1.4 will never return true for a non-zero method
	 *      ID. The query is therefore not needed
	 */
	@Override
	public boolean isObsolete() {
		if (virtualMachineImpl().isJdwpVersionGreaterOrEqual(1, 4)) {
			return fMethodID.value() == 0;
		}
		return false;
	}

	/* (non-Javadoc)
	 * @see com.sun.jdi.Method#allLineLocations(java.lang.String, java.lang.String)
	 */
	@Override
	public List<Location> allLineLocations(String stratum, String sourceName)	throws AbsentInformationException {
		if (isAbstract() || isNative()) {
			return Collections.EMPTY_LIST;
		}
		if (stratum == null) { // if stratum not defined use the default stratum for the declaring type
			stratum = declaringType().defaultStratum();
		}
		List<Location> allLineLocations = null;
		Map<String, List<Location>> sourceNameAllLineLocations = null;
		if (fStratumAllLineLocations == null) { // the stratum map doesn't
												// exist, create it
			fStratumAllLineLocations = new HashMap<String, Map<String, List<Location>>>();
		} else {
			// get the source name map
			sourceNameAllLineLocations = fStratumAllLineLocations.get(stratum);
		}
		if (sourceNameAllLineLocations == null) { // the source name map doesn't
													// exist, create it
			sourceNameAllLineLocations = new HashMap<String, List<Location>>();
			fStratumAllLineLocations.put(stratum, sourceNameAllLineLocations);
		} else {
			// get the line locations
			allLineLocations = sourceNameAllLineLocations.get(sourceName);
		}
		if (allLineLocations == null) { // the line locations are not know,
										// compute and store them
			getLineTable();
			allLineLocations = referenceTypeImpl().allLineLocations(stratum, sourceName, this, fCodeIndexTable, fJavaStratumLineNumberTable);
			sourceNameAllLineLocations.put(sourceName, allLineLocations);
		}
		return allLineLocations;
	}

	/* (non-Javadoc)
	 * @see com.sun.jdi.Method#locationsOfLine(java.lang.String, java.lang.String, int)
	 */
	@Override
	public List<Location> locationsOfLine(String stratum, String sourceName,
			int lineNumber) throws AbsentInformationException {
		if (isAbstract() || isNative()) {
			return Collections.EMPTY_LIST;
		}
		return referenceTypeImpl().locationsOfLine(stratum, sourceName, lineNumber, this);
	}

	/**
	 * Return a list which contains a location for the each disjoint range of
	 * code indices that have bean assigned to the given lines (by the compiler
	 * or/and the VM). Return an empty list if there is not executable code at
	 * the specified lines.
	 */
	protected List<Location> javaStratumLocationsOfLines(List<Integer> javaLines)	throws AbsentInformationException {
		Set<Long> tmpLocations = new TreeSet<Long>();
		for (Iterator<Integer> iter = javaLines.iterator(); iter.hasNext();) {
			Integer key = iter.next();
			List<Long> indexes = javaStratumLineToCodeIndexes(key.intValue());
			if (indexes != null) {
				tmpLocations.addAll(indexes);
			}
		}
		List<Location> locations = new ArrayList<Location>();
		for (Iterator<Long> iter = tmpLocations.iterator(); iter.hasNext();) {
			long index = iter.next().longValue();
			int position = Arrays.binarySearch(fCodeIndexTable, index);
			if(position < 0) {
				//https://bugs.eclipse.org/bugs/show_bug.cgi?id=388172
				//the key is not in the code index, we should not insert it as the line table is supposed to be
				//constant unless the parent class is redefined.
				//See http://docs.oracle.com/javase/6/docs/platform/jpda/jdwp/jdwp-protocol.html#JDWP_Method_LineTable for more information
				continue;
			}
			if (position == 0 || !tmpLocations.contains(new Long(fCodeIndexTable[position - 1]))) {
				locations.add(new LocationImpl(virtualMachineImpl(), this, index));
			}
		}
		return locations;
	}

	/* (non-Javadoc)
	 * @see com.sun.jdi.Method#isBridge()
	 */
	@Override
	public boolean isBridge() {
		return (fModifierBits & MODIFIER_ACC_BRIDGE) != 0;
	}

	/* (non-Javadoc)
	 * @see com.sun.jdi.Method#isVarArgs()
	 */
	@Override
	public boolean isVarArgs() {
		// TODO: remove this test when j9 solve its problem
		// it returns invalid 1.5 flags for 1.4 classes.
		// see bug 53870
		return !virtualMachine().name().equals("j9") && (fModifierBits & MODIFIER_ACC_VARARGS) != 0; //$NON-NLS-1$
	}
}
