/*******************************************************************************
 * 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
 *     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.text.MessageFormat;
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.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(Integer.valueOf(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<>();
			fLineToCodeIndexes = new HashMap<>();
			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 = Long.valueOf(lineCodeIndex);
				int lineNr = readInt("line nr", replyData); //$NON-NLS-1$
				Integer lineNrInt = Integer.valueOf(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<>();
					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 = Long.valueOf(index);
			lineNrObj = javaStratumCodeIndexToLine().get(lineCodeIndexObj);
		} while (lineNrObj == null && --index >= fLowestValidCodeIndex);
		if (lineNrObj == null) {
			if (lineCodeIndex >= fLowestValidCodeIndex) {
				index = lineCodeIndex;
				do {
					lineCodeIndexObj = Long.valueOf(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<>();
		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> result = new ArrayList<>();
		for (String signature : argumentTypeSignatures()) {
			result.add(TypeImpl.signatureToName(signature));
		}

		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<>();
		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(Long.valueOf(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<>(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<>(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<>();
		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<>();
		} 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<>();
			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<>();
		for (Integer key : javaLines) {
			List<Long> indexes = javaStratumLineToCodeIndexes(key.intValue());
			if (indexes != null) {
				tmpLocations.addAll(indexes);
			}
		}
		List<Location> locations = new ArrayList<>();
		for (Long location : tmpLocations) {
			long index = location.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(Long.valueOf(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$
	}
}
