/*******************************************************************************
 * Copyright (c) 2000, 2004 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials 
 * are made available under the terms of the Common Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/cpl-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.Modifier;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.jdi.internal.jdwp.JdwpCommandPacket;
import org.eclipse.jdi.internal.jdwp.JdwpFieldID;
import org.eclipse.jdi.internal.jdwp.JdwpID;
import org.eclipse.jdi.internal.jdwp.JdwpMethodID;
import org.eclipse.jdi.internal.jdwp.JdwpReferenceTypeID;
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.ClassNotPreparedException;
import com.sun.jdi.ClassObjectReference;
import com.sun.jdi.ClassType;
import com.sun.jdi.Field;
import com.sun.jdi.InternalException;
import com.sun.jdi.NativeMethodException;
import com.sun.jdi.ReferenceType;
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 abstract class ReferenceTypeImpl extends TypeImpl implements ReferenceType, org.eclipse.jdi.hcr.ReferenceType {

	/** ClassStatus Constants. */
	public static final int JDWP_CLASS_STATUS_VERIFIED = 1;
	public static final int JDWP_CLASS_STATUS_PREPARED = 2;
	public static final int JDWP_CLASS_STATUS_INITIALIZED = 4;
	public static final int JDWP_CLASS_STATUS_ERROR = 8;

	/** Mapping of command codes to strings. */
	private static String[] fgClassStatusStrings = null;

	/**
	 * Represent the datat about one file info contained in one stratum in the Smap.
	 */	
	protected static class FileInfo {
		
		/**
		 * The id.
		 */
		protected int fFileId;

		/**
		 * The name of the source file.
		 */
		protected String fFileName;

		/**
		 * The path of the source file.
		 */
		protected String fAbsoluteFileName;
		
		/**
		 * Map line number in the input source file 
		 *   -> list of [start line in the output source file, range in the output source file].
		 * (Integer -> List of int[2]).
		 */
		private HashMap fLineInfo;

		/**
		 * FileInfo constructor.
		 * 
		 * @param fileId the id.
		 * @param fileName the name of the source file.
		 * @param absoluteFileName the path of the source file (can be <code>null</code>).
		 */
		public FileInfo(int fileId, String fileName, String absoluteFileName) {
			fFileId= fileId;
			fFileName= fileName;
			fAbsoluteFileName= absoluteFileName;
			fLineInfo= new HashMap();
		}
		
		/**
		 * Add information about the mapping of one line.
		 * Associate a line in the input source file to a snippet of code
		 * in the output source file.
		 * 
		 * @param inputLine the line number in the input source file.
		 * @param outputStartLine the number of the first line of the corresponding snippet in the output source file.
		 * @param outputLineRange the size of the corresponding snippet in the output source file.
		 */
		public void addLineInfo(int inputLine, int outputStartLine, int outputLineRange) {
			Integer key= new Integer(inputLine);
			List outputLines= (List)fLineInfo.get(key);
			if (outputLines == null) {
				outputLines= new ArrayList();
				fLineInfo.put(key, outputLines);
			}
			outputLines.add(new int[] {outputStartLine, outputLineRange});
		}

		/**
		 * Return a list of line information about the code in the output source file
		 * associated to the given line in the input source file.
		 * 
		 * @param lineNumber the line number in the input source file.
		 * @return a List of int[2].
		 */
		public List getOutputLinesForLine(int lineNumber) {
			List list= new ArrayList();
			List outputLines= (List)fLineInfo.get(new Integer(lineNumber));
			if (outputLines != null) {
				for (Iterator iter = outputLines.iterator(); iter.hasNext();) {
					int[] info = (int[])iter.next();
					int outputLineNumber= info[0];
					for (int i= 0, length= info[1]; i < length; i++) {
						list.add(new Integer(outputLineNumber++));
					}
				}
			}
			return list;
		}

		/**
		 * @see java.lang.Object#equals(java.lang.Object)
		 */
		public boolean equals(Object object) {
			if (!(object instanceof FileInfo)) {
				return false;
			}
			return fFileId == ((FileInfo)object).fFileId;
		}

	}
	
	/**
	 * Represent the information contains in the Smap about one stratum.
	 */
	protected static class Stratum {

		/**
		 * The id of this stratum.
		 */
		private String fId;
		
		/**
		 * The file info data associated to this stratum.
		 */
		private List fFileInfos;
	
		/**
		 * Id of the primary file for this stratum.
		 */		
		private int fPrimaryFileId;
		
		/**
		 * Map line number in the output source file -> list of line numbers in the intput source file.
		 * (Integer -> List of Integer)
		 */
		private HashMap fOutputLineToInputLine;
		
		/**
		 * Stratum constructor.
		 * @param id The id of this stratum.
		 */
		public Stratum(String id) {
			fId= id;
			fFileInfos= new ArrayList();
			fOutputLineToInputLine= new HashMap();
			fPrimaryFileId= -1;
		}
		
		/**
		 * Add a file info to this stratum.
		 * 
		 * @param fileId the id.
		 * @param fileName the name of the source file.
		 */
		public void addFileInfo(int fileId, String fileName) throws AbsentInformationException {
			addFileInfo(fileId, fileName, null);
		}
		
		/**
		 * Add a file info to this stratum.
		 * 
		 * @param fileId the id.
		 * @param fileName the name of the source file.
		 * @param absoluteFileName the path of the source file.
		 */
		public void addFileInfo(int fileId, String fileName, String absoluteFileName) throws AbsentInformationException {
			if (fPrimaryFileId == -1) {
				fPrimaryFileId= fileId;
			}
			FileInfo fileInfo= new FileInfo(fileId, fileName, absoluteFileName);
			if (fFileInfos.contains(fileInfo)) {
				throw new AbsentInformationException(MessageFormat.format(JDIMessages.getString("ReferenceTypeImpl.28"), new String[] {Integer.toString(fileId), fId})); //$NON-NLS-1$
			}
			fFileInfos.add(fileInfo);
		}

		/**
		 * Add line mapping information.
		 * 
		 * @param inputStartLine number of the first line in the input source file.
		 * @param lineFileId id of the input source file.
		 * @param repeatCount number of iterations.
		 * @param outputStartLine number of the first line in the output source file.
		 * @param outputLineIncrement number of line to increment at each iteration.
		 * @throws AbsentInformationException
		 */
		public void addLineInfo(int inputStartLine, int lineFileId, int repeatCount, int outputStartLine, int outputLineIncrement) throws AbsentInformationException {
			FileInfo fileInfo= null;
			// get the FileInfo object
			for (Iterator iter = fFileInfos.iterator(); iter.hasNext();) {
				FileInfo element = (FileInfo)iter.next();
				if (element.fFileId == lineFileId) {
					fileInfo= element;
				}
			}
			if (fileInfo == null) {
				throw new AbsentInformationException(MessageFormat.format(JDIMessages.getString("ReferenceTypeImpl.29"), new String[] {Integer.toString(lineFileId)})); //$NON-NLS-1$
			}
			// add the data to the different hash maps.
			for (int i= 0; i < repeatCount; i++, inputStartLine++) {
				fileInfo.addLineInfo(inputStartLine, outputStartLine, outputLineIncrement);
				if (outputLineIncrement == 0) {
					// see bug 40022
					addLineInfoToMap(inputStartLine, lineFileId, outputStartLine);
				} else {
					for (int j= 0; j < outputLineIncrement; j++, outputStartLine++) {
						addLineInfoToMap(inputStartLine, lineFileId, outputStartLine);
					}
				}
			}
		}

		/**
		 * Add the data to the map.
		 */
		private void addLineInfoToMap(int inputStartLine, int lineFileId, int outputStartLine) {
			Integer key= new Integer(outputStartLine);
			List inputLines= (List)fOutputLineToInputLine.get(key);
			if (inputLines == null) {
				inputLines= new ArrayList();
				fOutputLineToInputLine.put(key, inputLines);
			}
			inputLines.add(new int[] {lineFileId, inputStartLine});
		}

		/**
		 * Return the FileInfo object for the specified source name.
		 * Return <code>null</code> if the specified name is the source name of no file info.
		 * @param sourceName the source name to search.
		 */
		public FileInfo getFileInfo(String sourceName) {
			for (Iterator iter = fFileInfos.iterator(); iter.hasNext();) {
				FileInfo fileInfo = (FileInfo)iter.next();
				if (fileInfo.fFileName.equals(sourceName)) {
					return fileInfo;
				}
			}
			return null;
		}

		/**
		 * @param outputLineNumber
		 * @return
		 */
		public List getInputLineInfos(int outputLineNumber) {
			return (List)fOutputLineToInputLine.get(new Integer(outputLineNumber));
		}

	}
	


	/** ReferenceTypeID that corresponds to this reference. */
	private JdwpReferenceTypeID fReferenceTypeID;

	/** The following are the stored results of JDWP calls. */
	protected List fInterfaces = null;
	private List fMethods = null;
	private Hashtable fMethodTable= null;
	private List fFields = null;
	private List fAllMethods = null;
	private List fVisibleMethods = null;
	private List fAllFields = null;
	private List fVisibleFields = null;
	private List fAllInterfaces = null;
	private Map fStratumAllLineLocations = null;
	private String fSourceName = null;
	private int fModifierBits = -1;
	private ClassLoaderReferenceImpl fClassLoader = null;
	private ClassObjectReferenceImpl fClassObject = null;
	
	private String fGenericSignature; // 1.5 addition
	private boolean fGenericSignatureKnown; // 1.5 addition

	private boolean fGotClassFileVersion = false;	// HCR addition.
	private int fClassFileVersion;	// HCR addition.
	private boolean fIsHCREligible;	// HCR addition.
	private boolean fIsVersionKnown;	// HCR addition.
	
	private boolean fSourceDebugExtensionAvailable= true; // JSR-045 addition
	
	/**
	 * The default stratum id.
	 */
	private String fDefaultStratumId; // JSR-045 addition

	/**
	 * A map of the defined strata.
	 * Map stratum id -> Stratum object.
	 * (String -> Stratum).
	 */
	private Map fStrata; // JSR-045 addition

	/**
	 * The source map string returned by the VM.
	 */
	private String fSmap; // JSR-045 addition
	
	/**
	 * Creates new instance.
	 */
	protected ReferenceTypeImpl(String description, VirtualMachineImpl vmImpl, JdwpReferenceTypeID referenceTypeID) {
		super(description, vmImpl);
		fReferenceTypeID = referenceTypeID;
	}
	
	/**
	 * Creates new instance.
	 */
	protected ReferenceTypeImpl(String description, VirtualMachineImpl vmImpl, JdwpReferenceTypeID referenceTypeID, String signature, String genericSignature) {
		super(description, vmImpl);
		fReferenceTypeID = referenceTypeID;
		setSignature(signature);
		setGenericSignature(genericSignature);
	}
	
	/**
	 * @return Returns type tag.
	 */
	public abstract byte typeTag();
	
	/**
	 * Flushes all stored Jdwp results.
	 */
	public void flushStoredJdwpResults() {
		Iterator iter;
	
		// Flush Methods.
		if (fMethods != null) {
			iter = fMethods.iterator();
			while (iter.hasNext()) {
				MethodImpl method = (MethodImpl)iter.next();
				method.flushStoredJdwpResults();
			}
			fMethods = null;
			fMethodTable= null;
		}

		// Flush Fields.
		if (fFields != null) {
			iter = fFields.iterator();
			while (iter.hasNext()) {
				FieldImpl field = (FieldImpl)iter.next();
				field.flushStoredJdwpResults();
			}
			fFields = null;
		}

		fInterfaces = null;
		fAllMethods = null;
		fVisibleMethods = null;
		fAllFields = null;
		fVisibleFields = null;
		fAllInterfaces = null;
		fStratumAllLineLocations = null;
		fSourceName = null;
		fModifierBits = -1;
		fClassLoader = null;
		fClassObject = null;
		fGotClassFileVersion = false;
		// java 1.5
		fGenericSignature= null;
		fGenericSignatureKnown= false;
		
		// JSR-045
		fSourceDebugExtensionAvailable= true;
		fDefaultStratumId= null;
		fStrata= null;
		fSmap= null;
		
		// The following cached results are stored higher up in the class hierarchy.
		fSignature = null;
		fSourceName = null;
	}
	
	/** 
	 * @return Returns the interfaces declared as implemented by this class. Interfaces indirectly implemented (extended by the implemented interface or implemented by a superclass) are not included.
	 */
	public List allInterfaces() {
		if (fAllInterfaces != null) {
			return fAllInterfaces;
		}
	
		/* Recursion:
		 * The interfaces that it directly implements;
		 * All interfaces that are implemented by its interfaces;
		 * If it is a class, all interfaces that are implemented by its superclass.
		 */
		// The interfaces are maintained in a set, to avoid duplicates.
		// The interfaces of its own (own interfaces() command) are first inserted.
		HashSet allInterfacesSet = new HashSet(interfaces());
		
		// All interfaces of the interfaces it implements.
		Iterator interfaces = interfaces().iterator();
		InterfaceTypeImpl inter;
		while (interfaces.hasNext()) {
			inter = (InterfaceTypeImpl)interfaces.next();
			allInterfacesSet.addAll(inter.allInterfaces());
		}
		
		// If it is a class, all interfaces of it's superclass.
		if (this instanceof ClassType) {
			ClassType superclass = ((ClassType)this).superclass();
			if (superclass != null) {
				allInterfacesSet.addAll(superclass.allInterfaces());
			}
		}
				
		fAllInterfaces = new ArrayList(allInterfacesSet);
		return fAllInterfaces;
	}
	
	/**
	 * @return Returns Jdwp Reference ID.
	 */
	public JdwpReferenceTypeID getRefTypeID() {
		return fReferenceTypeID;
	}
	
	/**
	 * @return Returns modifier bits.
	 */
	public int modifiers() {
		if (fModifierBits != -1)
			return fModifierBits;
			
		initJdwpRequest();
		try {
			JdwpReplyPacket replyPacket = requestVM(JdwpCommandPacket.RT_MODIFIERS, this);
			defaultReplyErrorHandler(replyPacket.errorCode());
			DataInputStream replyData = replyPacket.dataInStream();
			fModifierBits = readInt("modifiers", AccessibleImpl.getModifierStrings(), replyData); //$NON-NLS-1$
			return fModifierBits;
		} catch (IOException e) {
			defaultIOExceptionHandler(e);
			return 0;
		} finally {
			handledJdwpRequest();
		}
	}
	
	/** 
	 * Add methods to a set of methods if they are not overriden, add new names+signature combinations to set of names+signature combinations.
	 */
	private void addVisibleMethods(List inheritedMethods, Set nameAndSignatures, List resultMethods) {
		Iterator iter = inheritedMethods.iterator();
		MethodImpl inheritedMethod;
		while (iter.hasNext()) {
			inheritedMethod = (MethodImpl)iter.next();
			if (!nameAndSignatures.contains(inheritedMethod.name() + inheritedMethod.signature())) {
				resultMethods.add(inheritedMethod);
			}
		}
	}
	
	/**
	 * @return Returns a list containing each unhidden and unambiguous Method in this type.
	 */
	public List visibleMethods() {
		if (fVisibleMethods != null)
			return fVisibleMethods;

		/* Recursion:
		 * The methods of its own (own methods() command);
		 * All methods of the interfaces it implements;
		 * If it is a class, all methods of it's superclass.
		 */
		// The name+signature combinations of methods are maintained in a set, to avoid including methods that have been overriden.
		Set namesAndSignatures = new HashSet();
		List visibleMethods= new ArrayList();
		
		// The methods of its own (own methods() command).
		for (Iterator iter= methods().iterator(); iter.hasNext();) {
			MethodImpl method= (MethodImpl) iter.next();
			namesAndSignatures.add(method.name() + method.signature());
			visibleMethods.add(method);
		}

		// All methods of the interfaces it implements.
		Iterator interfaces = interfaces().iterator();
		InterfaceTypeImpl inter;
		while (interfaces.hasNext()) {
			inter = (InterfaceTypeImpl)interfaces.next();
			addVisibleMethods(inter.visibleMethods(), namesAndSignatures, visibleMethods);
		}
		
		// If it is a class, all methods of it's superclass.
		if (this instanceof ClassType) {
			ClassType superclass = ((ClassType)this).superclass();
			if (superclass != null)
				addVisibleMethods(superclass.visibleMethods(), namesAndSignatures, visibleMethods);
		}
		
		fVisibleMethods= visibleMethods;
		return fVisibleMethods;
	}

	/**
	 * @return Returns a list containing each Method declared in this type, and its superclasses, implemented interfaces, and/or superinterfaces.
	 */
	public List allMethods() {
		if (fAllMethods != null)
			return fAllMethods;

		/* Recursion:
		 * The methods of its own (own methods() command);
		 * All methods of the interfaces it implements;
		 * If it is a class, all methods of it's superclass.
		 */
		// The name+signature combinations of methods are maintained in a set.
		HashSet resultSet = new HashSet();
		
		// The methods of its own (own methods() command).
		resultSet.addAll(methods());
		
		// All methods of the interfaces it implements.
		Iterator interfaces = interfaces().iterator();
		InterfaceTypeImpl inter;
		while (interfaces.hasNext()) {
			inter = (InterfaceTypeImpl)interfaces.next();
			resultSet.addAll(inter.allMethods());
		}
		
		// If it is a class, all methods of it's superclass.
		if (this instanceof ClassType) {
			ClassType superclass = ((ClassType)this).superclass();
			if (superclass != null)
				resultSet.addAll(superclass.allMethods());
		}
		
		fAllMethods  = new ArrayList(resultSet);
		return fAllMethods;
	}

	/** 
	 * @return Returns the interfaces declared as implemented by this class. Interfaces indirectly implemented (extended by the implemented interface or implemented by a superclass) are not included.
	 */
	public List interfaces() {
		if (fInterfaces != null) {
			return fInterfaces;
		}
			
		initJdwpRequest();
		try {
			JdwpReplyPacket replyPacket = requestVM(JdwpCommandPacket.RT_INTERFACES, this);
			switch (replyPacket.errorCode()) {
				case JdwpReplyPacket.NOT_FOUND:
					// Workaround for problem in J2ME WTK (wireless toolkit)
					// @see Bug 12966
					return Collections.EMPTY_LIST;
				default:
					defaultReplyErrorHandler(replyPacket.errorCode());
			}
			DataInputStream replyData = replyPacket.dataInStream();
			List elements = new ArrayList();
			int nrOfElements = readInt("elements", replyData); //$NON-NLS-1$
			for (int i = 0; i < nrOfElements; i++) {
				InterfaceTypeImpl ref = InterfaceTypeImpl.read(this, replyData);
				if (ref == null) {
					continue;
				}
				elements.add(ref);
			}
			fInterfaces = elements;
			return elements;
		} catch (IOException e) {
			defaultIOExceptionHandler(e);
			return null;
		} finally {
			handledJdwpRequest();
		}
	}
			
	/** 
	 * Add fields to a set of fields if they are not overriden, add new fieldnames to set of fieldnames.
	 */
	private void addVisibleFields(List newFields, Set names, List resultFields) {
		Iterator iter = newFields.iterator();
		FieldImpl field;
		while (iter.hasNext()) {
			field = (FieldImpl)iter.next();
			String name = field.name();
			if (!names.contains(name)) {
				resultFields.add(field);
				names.add(name);
			}
		}
	}
	
	/**
	 * @return Returns a list containing each unhidden and unambiguous Field in this type.
	 */
	public List visibleFields() {
		if (fVisibleFields != null)
			return fVisibleFields;

		/* Recursion:
		 * The fields of its own (own fields() command);
		 * All fields of the interfaces it implements;
		 * If it is a class, all fields of it's superclass.
		 */
		// The names of fields are maintained in a set, to avoid including fields that have been overriden.
		HashSet fieldNames = new HashSet();
		
		// The fields of its own (own fields() command).
		List visibleFields = new ArrayList();
		addVisibleFields(fields(), fieldNames, visibleFields);
		
		// All fields of the interfaces it implements.
		Iterator interfaces = interfaces().iterator();
		InterfaceTypeImpl inter;
		while (interfaces.hasNext()) {
			inter = (InterfaceTypeImpl)interfaces.next();
			addVisibleFields(inter.visibleFields(), fieldNames, visibleFields);
		}
		
		// If it is a class, all fields of it's superclass.
		if (this instanceof ClassType) {
			ClassType superclass = ((ClassType)this).superclass();
			if (superclass != null)
				addVisibleFields(superclass.visibleFields(), fieldNames, visibleFields);
		}
				
		fVisibleFields = visibleFields;
		return fVisibleFields;
	}

	/** 
	 * @return Returns a list containing each Field declared in this type, and its superclasses, implemented interfaces, and/or superinterfaces.
	 */
	public List allFields() {
		if (fAllFields != null)
			return fAllFields;

		/* Recursion:
		 * The fields of its own (own fields() command);
		 * All fields of the interfaces it implements;
		 * If it is a class, all fields of it's superclass.
		 */
		// The names of fields are maintained in a set, to avoid including fields that have been inherited double.
		HashSet resultSet = new HashSet();
		
		// The fields of its own (own fields() command).
		resultSet.addAll(fields());
		
		// All fields of the interfaces it implements.
		Iterator interfaces = interfaces().iterator();
		InterfaceTypeImpl inter;
		while (interfaces.hasNext()) {
			inter = (InterfaceTypeImpl)interfaces.next();
			resultSet.addAll(inter.allFields());
		}
		
		// If it is a class, all fields of it's superclass.
		if (this instanceof ClassType) {
			ClassType superclass = ((ClassType)this).superclass();
			if (superclass != null)
				resultSet.addAll(superclass.allFields());
		}
				
		fAllFields = new ArrayList(resultSet);
		return fAllFields;
	}
	
	/** 
	 * @return Returns the classloader object which loaded the class corresponding to this type.
	 */
	public ClassLoaderReference classLoader() {
		if (fClassLoader != null)
			return fClassLoader;

		initJdwpRequest();
		try {
	   		JdwpReplyPacket replyPacket = requestVM(JdwpCommandPacket.RT_CLASS_LOADER, this);
			defaultReplyErrorHandler(replyPacket.errorCode());
			DataInputStream replyData = replyPacket.dataInStream();
			fClassLoader = ClassLoaderReferenceImpl.read(this, replyData);
			return fClassLoader;
		} catch (IOException e) {
			defaultIOExceptionHandler(e);
	   		return null;
		} finally {
			handledJdwpRequest();
		}
	}
		
	/** 
	 * @return Returns the class object that corresponds to this type in the target VM. 
	 */
	public ClassObjectReference classObject() {
		if (fClassObject != null)
			return fClassObject;

		initJdwpRequest();
		try {
	   		JdwpReplyPacket replyPacket = requestVM(JdwpCommandPacket.RT_CLASS_OBJECT, this);
			defaultReplyErrorHandler(replyPacket.errorCode());
			DataInputStream replyData = replyPacket.dataInStream();
			fClassObject = ClassObjectReferenceImpl.read(this, replyData);
			return fClassObject;
		} catch (IOException e) {
			defaultIOExceptionHandler(e);
	   		return null;
		} finally {
			handledJdwpRequest();
		}
	}

	/** 
	 * @return Returns status of class/interface.
	 */
	protected int status() { 
		// Note that this information should not be cached.
		initJdwpRequest();
		try {
			JdwpReplyPacket replyPacket = requestVM(JdwpCommandPacket.RT_STATUS, this);
			defaultReplyErrorHandler(replyPacket.errorCode());
			DataInputStream replyData = replyPacket.dataInStream();
			int status = readInt("status", classStatusStrings(), replyData); //$NON-NLS-1$
			return status;
		} catch (IOException e) {
			defaultIOExceptionHandler(e);
			return 0;
		} finally {
			handledJdwpRequest();
		}
	}
	
	/** 
	 * @return Returns true if initialization failed for this class.
	 */
	public boolean failedToInitialize() {
		return (status() & JDWP_CLASS_STATUS_ERROR) != 0;
	}

	/** 
	 * @return Returns true if this type has been initialized.
	 */
	public boolean isInitialized() {
		return (status() & JDWP_CLASS_STATUS_INITIALIZED) != 0;
	}

	/** 
	 * @return Returns true if this type has been prepared.
	 */
	public boolean isPrepared() {
		return (status() & JDWP_CLASS_STATUS_PREPARED) != 0;
	}

	/** 
	 * @return Returns true if this type has been verified.
	 */
	public boolean isVerified() {
		return (status() & JDWP_CLASS_STATUS_VERIFIED) != 0;
	}

	/** 
	 * @return Returns the visible Field with the given non-ambiguous name. 
	 */
	public Field fieldByName(String name) {
		Iterator iter = visibleFields().iterator();
		while (iter.hasNext()) {
			FieldImpl field = (FieldImpl)iter.next();
			if (field.name().equals(name))
				return field;
		}
		return null;
	}
	
	/** 
	 * @return Returns a list containing each Field declared in this type. 
	 */
	public List fields() {
		if (fFields != null) {
			return fFields;
		}
		
		// Note: Fields are returned in the order they occur in the class file, therefore their
		// order in this list can be used for comparisons.
		initJdwpRequest();
		try {
			boolean withGenericSignature= virtualMachineImpl().isJdwpVersionGreaterOrEqual(1, 5);
			int jdwpCommand= withGenericSignature ? JdwpCommandPacket.RT_FIELDS_WITH_GENERIC : JdwpCommandPacket.RT_FIELDS;
			JdwpReplyPacket replyPacket = requestVM(jdwpCommand, this);
			defaultReplyErrorHandler(replyPacket.errorCode());
			DataInputStream replyData = replyPacket.dataInStream();
			List elements = new ArrayList();
			int nrOfElements = readInt("elements", replyData); //$NON-NLS-1$
			for (int i = 0; i < nrOfElements; i++) {
				FieldImpl elt = FieldImpl.readWithNameSignatureModifiers(this, this, withGenericSignature, replyData);
				if (elt == null) {
					continue;
				}
				elements.add(elt);
			}
			fFields = elements;
			return fFields;
		} catch (IOException e) {
			defaultIOExceptionHandler(e);
			return null;
		} finally {
			handledJdwpRequest();
		}
	}
	
	/** 
	 * @return Returns FieldImpl of a field in the reference specified by a given fieldID, or null if not found.
	 */
	public FieldImpl findField(JdwpFieldID fieldID) {
		Iterator iter = fields().iterator();
		while(iter.hasNext()) {
			FieldImpl field = (FieldImpl)iter.next();
			if (field.getFieldID().equals(fieldID))
				return field;
		}
		return null;
	}
	
	/** 
	 * @return Returns MethodImpl of a method in the reference specified by a given methodID, or null if not found.
	 */
	public MethodImpl findMethod(JdwpMethodID methodID) {
		if (methodID.value() == 0) {
			return new MethodImpl(virtualMachineImpl(), this, methodID, JDIMessages.getString("ReferenceTypeImpl.Obsolete_method_1"), "", null, -1); //$NON-NLS-1$ //$NON-NLS-2$
		}
		if (fMethodTable == null) {
			fMethodTable= new Hashtable();
			Iterator iter = methods().iterator();
			while(iter.hasNext()) {
				MethodImpl method = (MethodImpl)iter.next();
				fMethodTable.put(method.getMethodID(), method);
			}
		}
		return (MethodImpl)fMethodTable.get(methodID);
	}
	
	/** 
	 * @return Returns the Value of a given static Field in this type. 
	 */
	public Value getValue(Field field) {
		ArrayList list = new ArrayList(1);
		list.add(field);
		return (ValueImpl)getValues(list).get(field);
	}
		
	/** 
	 * @return a Map of the requested static Field objects with their Value.
	 */
	public Map getValues(List fields) {
		// if the field list is empty, nothing to do
		if (fields.isEmpty()) {
			return new HashMap();
		}
		// Note that this information should not be cached.
		initJdwpRequest();
		try {
			ByteArrayOutputStream outBytes = new ByteArrayOutputStream();
			DataOutputStream outData = new DataOutputStream(outBytes);
			int fieldsSize = fields.size();
			write(this, outData);
			writeInt(fieldsSize, "size", outData); //$NON-NLS-1$
			for (int i = 0; i < fieldsSize; i++) {
				FieldImpl field = (FieldImpl)fields.get(i);
				checkVM(field);
				field.getFieldID().write(outData);
			}
	
			JdwpReplyPacket replyPacket = requestVM(JdwpCommandPacket.RT_GET_VALUES, outBytes);
			defaultReplyErrorHandler(replyPacket.errorCode());
			
			DataInputStream replyData = replyPacket.dataInStream();
			HashMap map = new HashMap();
			int nrOfElements = readInt("elements", replyData); //$NON-NLS-1$
			if (nrOfElements != fieldsSize) 
				throw new InternalError(JDIMessages.getString("ReferenceTypeImpl.Retrieved_a_different_number_of_values_from_the_VM_than_requested_3")); //$NON-NLS-1$
				
			for (int i = 0; i < nrOfElements; i++) {
				map.put(fields.get(i), ValueImpl.readWithTag(this, replyData));
			}
			return map;
		} catch (IOException e) {
			defaultIOExceptionHandler(e);
			return null;
		} finally {
			handledJdwpRequest();
		}
	}
	
	/** 
	 * @return Returns the hash code value.
	 */
	public int hashCode() {
		return fReferenceTypeID.hashCode();
	}
	
	/**
	 * @return Returns true if two mirrors refer to the same entity in the target VM.
	 * @see java.lang.Object#equals(Object)
	 */
	public boolean equals(Object object) {
		return object != null
			&& object.getClass().equals(this.getClass())
			&& fReferenceTypeID.equals(((ReferenceTypeImpl)object).fReferenceTypeID)
			&& virtualMachine().equals(((MirrorImpl)object).virtualMachine());
	}
	
	/**
	 * @return Returns a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified object.
	 */
	public int compareTo(Object object) {
		if (object == null || !object.getClass().equals(this.getClass()))
			throw new ClassCastException(JDIMessages.getString("ReferenceTypeImpl.Can__t_compare_reference_type_to_given_object_4")); //$NON-NLS-1$
		return name().compareTo(((ReferenceType)object).name());
	}
	
	/** 
	 * @return Returns true if the type was declared abstract.
	 */
	public boolean isAbstract() {
		return (modifiers() & MODIFIER_ACC_ABSTRACT) != 0;
	}
	
	/** 
	 * @return Returns true if the type was declared final.
	 */
	public boolean isFinal() {
		return (modifiers() & MODIFIER_ACC_FINAL) != 0;
	}
	
	/** 
	 * @return Returns true if the type was declared static.
	 */
	public boolean isStatic() {
		return (modifiers() & MODIFIER_ACC_STATIC) != 0;
	}
	
	/**
	 * @return Returns a List filled with all Location objects that map to the given line number. 
	 */
	public List locationsOfLine(int line) throws AbsentInformationException {
		return locationsOfLine(virtualMachine().getDefaultStratum(), null, line);
	}
	
	/**
	 * @return Returns a list containing each Method declared directly in this type.
	 */
	public List methods() {
		// Note that ArrayReference overwrites this method by returning an empty list.
		if (fMethods != null)
			return fMethods;
		
		// Note: Methods are returned in the order they occur in the class file, therefore their
		// order in this list can be used for comparisons.
		initJdwpRequest();
		try {
			boolean withGenericSignature= virtualMachineImpl().isJdwpVersionGreaterOrEqual(1, 5);
			int jdwpCommand= withGenericSignature ? JdwpCommandPacket.RT_METHODS_WITH_GENERIC : JdwpCommandPacket.RT_METHODS;
			JdwpReplyPacket replyPacket = requestVM(jdwpCommand, this);
			defaultReplyErrorHandler(replyPacket.errorCode());
			DataInputStream replyData = replyPacket.dataInStream();
			List elements = new ArrayList();
			int nrOfElements = readInt("elements", replyData); //$NON-NLS-1$
			for (int i = 0; i < nrOfElements; i++) {
				MethodImpl elt = MethodImpl.readWithNameSignatureModifiers(this, this, withGenericSignature, replyData);
				if (elt == null) {
					continue;
				}
				elements.add(elt);
			}
			fMethods = elements;
			return fMethods;
		} catch (IOException e) {
			defaultIOExceptionHandler(e);
			return null;
		} finally {
			handledJdwpRequest();
		}
	}
	
	/**
	 * @return Returns a List containing each visible Method that has the given name.
	 */
	public List methodsByName(String name) {
		List elements = new ArrayList();
		Iterator iter = visibleMethods().iterator();
		while (iter.hasNext()) {
			MethodImpl method = (MethodImpl)iter.next();
			if (method.name().equals(name)){
				elements.add(method);
			}
		}
		return elements;
	}

	/**
	 * @return Returns a List containing each visible Method that has the given name and signature.
	 */
	public List methodsByName(String name, String signature) {
		List elements = new ArrayList();
		Iterator iter = visibleMethods().iterator();
		while (iter.hasNext()) {
			MethodImpl method = (MethodImpl)iter.next();
			if (method.name().equals(name) && method.signature().equals(signature)) {
				elements.add(method);
			}
		}
		return elements;
	}

	/** 
	 * @return Returns the fully qualified name of this type.
	 */
	public String name() {
		// Make sure that we know the signature, from which the name is derived.
		if (fName == null) {
			String genericSignature= genericSignature();
			StringBuffer name= new StringBuffer(GenericSignature.signatureToName(signature()));
			if (genericSignature != null) {
				List parameters= GenericSignature.getTypeParameters(genericSignature);
				Iterator iterator= parameters.iterator();
				if (iterator.hasNext()) {
					name.append('<').append(iterator.next());
					while (iterator.hasNext()) {
						name.append(',').append(iterator.next());
					}
					name.append('>');
				}
			}
			setName(name.toString());
		}
		return fName;
	}
	
	/** 
	 * @return Returns the JNI-style signature for this type. 
	 */
	public String signature() {
		if (fSignature != null) {
			return fSignature;
		}
		initJdwpRequest();
		try {
	   		JdwpReplyPacket replyPacket = requestVM(JdwpCommandPacket.RT_SIGNATURE, this);
			defaultReplyErrorHandler(replyPacket.errorCode());
			DataInputStream replyData = replyPacket.dataInStream();
			setSignature(readString("signature", replyData)); //$NON-NLS-1$
			return fSignature;
		} catch (IOException e) {
			defaultIOExceptionHandler(e);
	   		return null;
		} finally {
			handledJdwpRequest();
		}
	}

	/** 
	 * @return Returns a List containing each ReferenceType declared within this type. 
	 */
	public List nestedTypes() {
		// Note that the VM gives an empty reply on RT_NESTED_TYPES, therefore we search for the
		// nested types in the loaded types.
		List result = new ArrayList();
		Iterator itr = virtualMachineImpl().allRefTypes();
		while (itr.hasNext()) {
			try {
				ReferenceTypeImpl refType = (ReferenceTypeImpl)itr.next();
				String refName = refType.name();
				if (refName.length() > name().length() && refName.startsWith(name()) && refName.charAt(name().length()) == '$') {
					result.add(refType);
				}
			} catch (ClassNotPreparedException e) {
				continue;
			}
		}
		return result;
	}

	/** 
	 * @return Returns an identifing name for the source corresponding to the declaration of this type.
	 */
	public String sourceName() throws AbsentInformationException {
		// sourceNames list in never empty, an AbsentInformationException is thrown
		// if the source name is not known.
		return (String)sourceNames(virtualMachine().getDefaultStratum()).get(0);
	}

	/**
	 * @return Returns the CRC-32 of the given reference type, undefined if unknown.
	 */
	public int getClassFileVersion() {
		virtualMachineImpl().checkHCRSupported();
		if (fGotClassFileVersion)
			return fClassFileVersion;
		
		initJdwpRequest();
		try {
	   		JdwpReplyPacket replyPacket = requestVM(JdwpCommandPacket.HCR_GET_CLASS_VERSION, this);
			defaultReplyErrorHandler(replyPacket.errorCode());
			DataInputStream replyData = replyPacket.dataInStream();
			fIsHCREligible = readBoolean("HCR eligible", replyData); //$NON-NLS-1$
			fIsVersionKnown = readBoolean("version known", replyData); //$NON-NLS-1$
			fClassFileVersion = readInt("class file version", replyData); //$NON-NLS-1$
			fGotClassFileVersion = true;
			return fClassFileVersion;
		} catch (IOException e) {
			defaultIOExceptionHandler(e);
	   		return 0;
		} finally {
			handledJdwpRequest();
		}
	}
	
	/**
	 * @return Returns whether the CRC-32 of the given reference type is known.
	 */
	public boolean isVersionKnown() {
		getClassFileVersion();
		return fIsVersionKnown;
	}
	
	/**
	 * @return Returns whether the reference type is HCR-eligible.
	 */
	public boolean isHCREligible() {
		getClassFileVersion();
		return fIsHCREligible;
	}
	
	/**
	 * Writes JDWP representation.
	 */
	public void write(MirrorImpl target, DataOutputStream out) throws IOException {
		fReferenceTypeID.write(out);
		if (target.fVerboseWriter != null)
			target.fVerboseWriter.println("referenceType", fReferenceTypeID.value()); //$NON-NLS-1$
	}
	
	/**
	 * Writes representation of null referenceType.
	 */
	public static void writeNull(MirrorImpl target, DataOutputStream out) throws IOException {
		// create null id
		JdwpReferenceTypeID ID = new JdwpReferenceTypeID(target.virtualMachineImpl());
		ID.write(out);
		if (target.fVerboseWriter != null)
			target.fVerboseWriter.println("referenceType", ID.value()); //$NON-NLS-1$
	}
	
	/**
	 * Writes JDWP representation.
	 */
	public void writeWithTag(MirrorImpl target, DataOutputStream out) throws IOException {
		target.writeByte(typeTag(), "type tag", JdwpID.typeTagMap(), out); //$NON-NLS-1$
		write(target, out);
	}
	
	/**
	 * @return Reads JDWP representation and returns new or cached instance.
	 */
	public static ReferenceTypeImpl readWithTypeTag(MirrorImpl target, DataInputStream in) throws IOException {
		byte typeTag = target.readByte("type tag", JdwpID.typeTagMap(), in); //$NON-NLS-1$
		switch (typeTag) {
	   		case 0:
				return null;
			case ArrayTypeImpl.typeTag:
				return ArrayTypeImpl.read(target, in);
			case ClassTypeImpl.typeTag:
				return ClassTypeImpl.read(target, in);
			case InterfaceTypeImpl.typeTag:
				return InterfaceTypeImpl.read(target, in);
		}
		throw new InternalException(JDIMessages.getString("ReferenceTypeImpl.Invalid_ReferenceTypeID_tag_encountered___8") + typeTag); //$NON-NLS-1$
	}
	
	/**
	 * @return Returns the Location objects for each executable source line in this reference type.
	 */
	public List allLineLocations() throws AbsentInformationException {
		return allLineLocations(virtualMachine().getDefaultStratum(), null);
	}
	
	/**
	 * @return Reads JDWP representation and returns new or cached instance.
	 */
	public static ReferenceTypeImpl readWithTypeTagAndSignature(MirrorImpl target, boolean withGenericSignature, DataInputStream in) throws IOException {
		byte typeTag = target.readByte("type tag", JdwpID.typeTagMap(), in); //$NON-NLS-1$
		switch (typeTag) {
	   		case 0:
				return null;
			case ArrayTypeImpl.typeTag:
				return ArrayTypeImpl.readWithSignature(target, withGenericSignature, in);
			case ClassTypeImpl.typeTag:
				return ClassTypeImpl.readWithSignature(target, withGenericSignature, in);
			case InterfaceTypeImpl.typeTag:
				return InterfaceTypeImpl.readWithSignature(target, withGenericSignature, in);
		}
		throw new InternalException(JDIMessages.getString("ReferenceTypeImpl.Invalid_ReferenceTypeID_tag_encountered___8") + typeTag); //$NON-NLS-1$
	}
		
	/**
	 * @return Returns new instance based on signature and classLoader.
	 * @throws ClassNotLoadedException when the ReferenceType has not been loaded by the specified class loader.
	 */
	public static TypeImpl create(VirtualMachineImpl vmImpl, String signature, ClassLoaderReference classLoader) throws ClassNotLoadedException {
		ReferenceTypeImpl refTypeBootstrap = null;
		List classes= vmImpl.classesBySignature(signature);
		ReferenceTypeImpl type;
		Iterator iter= classes.iterator();		
		while (iter.hasNext()) {
			// First pass. Look for a class loaded by the given class loader
			type = (ReferenceTypeImpl)iter.next();
			if (type.classLoader() == null) {	// bootstrap classloader
				if (classLoader == null) {
					return type;
				} else {
					refTypeBootstrap = type;
				}
			}
			if (classLoader != null && classLoader.equals(type.classLoader())) {
				return type;
			}
		}
		// If no ReferenceType is found with the specified classloader, but there is one with the
		// bootstrap classloader, the latter is returned.
		if (refTypeBootstrap != null) {
			return refTypeBootstrap;
		}
		
		List visibleTypes;
		iter= classes.iterator();
		while (iter.hasNext()) {
			// Second pass. Look for a class that is visible to
			// the given class loader
			type = (ReferenceTypeImpl)iter.next();
			visibleTypes= classLoader.visibleClasses();
			Iterator visibleIter= visibleTypes.iterator();
			while (visibleIter.hasNext()) {
				if (type.equals(visibleIter.next())) {
					return type;
				}
			}
		}

		throw new ClassNotLoadedException(GenericSignature.signatureToName(signature), JDIMessages.getString("ReferenceTypeImpl.Type_has_not_been_loaded_10")); //$NON-NLS-1$
	}
	
	/**
	 * Retrieves constant mappings.
	 */
	public static void getConstantMaps() {
		if (fgClassStatusStrings != null) {
			return;
		}
		
		java.lang.reflect.Field[] fields = ReferenceTypeImpl.class.getDeclaredFields();
		fgClassStatusStrings = new String[32];
		
		for (int i = 0; i < fields.length; i++) {
			java.lang.reflect.Field field = fields[i];
			if ((field.getModifiers() & Modifier.PUBLIC) == 0 || (field.getModifiers() & Modifier.STATIC) == 0 || (field.getModifiers() & Modifier.FINAL) == 0) {
				continue;
			}
				
			String name = field.getName();
			if (!name.startsWith("JDWP_CLASS_STATUS_")) { //$NON-NLS-1$
				continue;
			}
				
			name = name.substring(18);
			
			try {
				int value = field.getInt(null);
				
				for (int j = 0; j < fgClassStatusStrings.length; j++) {
					if ((1 << j & value) != 0) {
						fgClassStatusStrings[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 String[] classStatusStrings() {
	 	getConstantMaps();
	 	return fgClassStatusStrings;
	 }
	 
	/**
	 * @see TypeImpl#createNullValue()
	 */
	public Value createNullValue() {
		return null;
	}

	/**
	 * @see ReferenceType#sourceNames(String)
	 */
	public List sourceNames(String stratumId) throws AbsentInformationException {
		List list= new ArrayList();
		Stratum stratum= getStratum(stratumId);
		if (stratum != null) {
			// return the source names defined for this stratum in the Smap.
			List fileInfos= stratum.fFileInfos;
			if (fileInfos.isEmpty()) {
				throw new AbsentInformationException(JDIMessages.getString("ReferenceTypeImpl.30")); //$NON-NLS-1$
			}
			for (Iterator iter = stratum.fFileInfos.iterator(); iter.hasNext();) {
				list.add(((FileInfo) iter.next()).fFileName);
			}
			return list;
		}
		// Java stratum
		if (fSourceName == null) {
			getSourceName();
		}
		list.add(fSourceName);
		return list;
	}

	/**
	 * @see ReferenceType#sourcePaths(String)
	 */
	public List sourcePaths(String stratumId) throws AbsentInformationException {
		List list= new ArrayList();
		Stratum stratum= getStratum(stratumId);
		if (stratum != null) {
			// return the source paths defined for this stratum in the Smap.
			for (Iterator iter = stratum.fFileInfos.iterator(); iter.hasNext();) {
				FileInfo fileInfo= (FileInfo) iter.next();
				String path= fileInfo.fAbsoluteFileName;
				if (path == null) {
					path= getPath(fileInfo.fFileName);
				}
				list.add(path);
			}
			return list;
		}
		// Java stratum
		if (fSourceName == null) {
			getSourceName();
		}
		list.add(getPath(fSourceName));
		return list;
	}
	
	/**
	 * @see ReferenceType#sourceDebugExtension()
	 */
	public String sourceDebugExtension() throws AbsentInformationException {
		if (isSourceDebugExtensionAvailable()) {
			return fSmap;
		}
		if (!virtualMachine().canGetSourceDebugExtension()) {
			throw new UnsupportedOperationException();
		}
		throw new AbsentInformationException();
	}

	/**
	 * @see ReferenceType#allLineLocations(String, String)
	 */
	public List allLineLocations(String stratum, String sourceName) throws AbsentInformationException {
		Iterator allMethods = methods().iterator();
		if (stratum == null) { // if stratum not defined use the default stratum
			stratum= defaultStratum();
		}
		List allLineLocations= null;
		Map sourceNameAllLineLocations= null;
		if (fStratumAllLineLocations == null) { // the stratum map doesn't exist, create it
			fStratumAllLineLocations= new HashMap();
		} else {
			// get the source name map
			sourceNameAllLineLocations= (Map)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= (List)sourceNameAllLineLocations.get(sourceName);
		}
		if (allLineLocations == null) { // the line locations are not know, compute and store them
			allLineLocations = new ArrayList();
			while (allMethods.hasNext()) {
				MethodImpl method = (MethodImpl)allMethods.next();
				if (method.isAbstract() || method.isNative()) {
					continue;
				}
				allLineLocations.addAll(method.allLineLocations(stratum, sourceName));
			}
			sourceNameAllLineLocations.put(sourceName, allLineLocations);
		}
		return allLineLocations;
	}

	/**
	 * @see ReferenceType#locationsOfLine(String, String, int)
	 */
	public List locationsOfLine(String stratum, String sourceName, int lineNumber) throws AbsentInformationException {
		Iterator allMethods = methods().iterator();
		List locations= new ArrayList();
		boolean hasLineInformation= false;
		AbsentInformationException exception= null;
		while (allMethods.hasNext()) {
			MethodImpl method = (MethodImpl)allMethods.next();
			if (method.isAbstract() || method.isNative()) {
					continue;
			}
			// one line in the input source can be translate in multiple lines in different
			// methods in the output source. We need all these locations.
			try {
				locations.addAll(locationsOfLine(stratum, sourceName, lineNumber, method));
				hasLineInformation= true;
			} catch (AbsentInformationException e) {
				exception= e;
			}
		}
		if (!hasLineInformation && exception != null) {
			throw exception;
		}
		return locations;
	}

	/**
	 * @see ReferenceType#availableStrata()
	 */
	public List availableStrata() {
		List list= new ArrayList();
		// The strata defined in the Smap.
		if (isSourceDebugExtensionAvailable()) {
			list.add(fStrata.keySet());
		}
		// plus the Java stratum
		list.add(VirtualMachineImpl.JAVA_STRATUM_NAME);
		return list;
	}

	/**
	 * @see ReferenceType#defaultStratum()
	 */
	public String defaultStratum() {
		if (isSourceDebugExtensionAvailable()) {
			return fDefaultStratumId;
		}
		// if not defined, return Java.
		return VirtualMachineImpl.JAVA_STRATUM_NAME;
	}

	/**
	 * Generate a source path from the given source name.
	 * The returned string is the package name of this type converted to a platform dependent path
	 * followed by the given source name.
	 * For example, on a Unix platform, the type org.my.TestJsp with the source name test.jsp would
	 * return "org/my/test.jsp".
	 */
	private String getPath(String sourceName) {
		String name= name();
		int lastDotOffset= name.lastIndexOf('.');
		if (lastDotOffset == -1) {
			return sourceName;
		}
		char fileSeparator= System.getProperty("file.separator").charAt(0); //$NON-NLS-1$
		return name.substring(0, lastDotOffset).replace('.', fileSeparator) + fileSeparator + sourceName;
	}

	/**
	 * Return the stratum object for this stratum Id.
	 * If the the specified stratum id is not defined for this reference type,
	 * return the stratum object for the default stratum.
	 * If the specified stratum id (or the default stratum id, if the specified
	 * stratum id is not defined) is <code>Java</code>, return <code>null</code>.
	 */
	private Stratum getStratum(String stratumId) {
		if (!VirtualMachineImpl.JAVA_STRATUM_NAME.equals(stratumId) && isSourceDebugExtensionAvailable()) {
			if (stratumId == null || !fStrata.keySet().contains(stratumId)) {
				stratumId= fDefaultStratumId;
			}
			if (!VirtualMachineImpl.JAVA_STRATUM_NAME.equals(stratumId)) {
				return (Stratum)fStrata.get(stratumId);
			}
		}
		return null;
	}

	/**
	 * Get the source debug extension from the VM.
	 * @throws AbsentInformationException
	 */	
	private void getSourceDebugExtension() throws AbsentInformationException {
		initJdwpRequest();
		try {
			JdwpReplyPacket replyPacket = requestVM(JdwpCommandPacket.RT_SOURCE_DEBUG_EXTENSION, this);
			if (replyPacket.errorCode() == JdwpReplyPacket.ABSENT_INFORMATION) {
				throw new AbsentInformationException(JDIMessages.getString("ReferenceTypeImpl.31")); //$NON-NLS-1$
			}
			defaultReplyErrorHandler(replyPacket.errorCode());
			DataInputStream replyData = replyPacket.dataInStream();
			fSmap= readString(JDIMessages.getString("ReferenceTypeImpl.32"), replyData); //$NON-NLS-1$
		} catch (IOException e) {
			defaultIOExceptionHandler(e);
		} finally {
			handledJdwpRequest();
		}
		// TODO: remove the workaround when the J9SC20030415 bug is fixed (see bug 96485 of the vendor bug system).
		// Workaround to a J9SC bug. It returns an empty string instead of a ABSENT_INFORMATION
		// error if the source debug extension is not available.
		if ("".equals(fSmap)) { //$NON-NLS-1$
			throw new AbsentInformationException(JDIMessages.getString("ReferenceTypeImpl.33")); //$NON-NLS-1$
		}
		// parse the source map.
		fStrata= new HashMap();
		SourceDebugExtensionParser.parse(fSmap, this);
	}
	
	/**
	 * Get the name of the Java source file from the VM.
	 * @throws AbsentInformationException
	 */
	private void getSourceName() throws AbsentInformationException {
		if (fSourceName != null || isSourceDebugExtensionAvailable()) {
			return;
		}
		initJdwpRequest();
		try {
			JdwpReplyPacket replyPacket = requestVM(JdwpCommandPacket.RT_SOURCE_FILE, this);
			if (replyPacket.errorCode() == JdwpReplyPacket.ABSENT_INFORMATION)
				throw new AbsentInformationException(JDIMessages.getString("ReferenceTypeImpl.Source_name_is_not_known_7")); //$NON-NLS-1$
			else
				defaultReplyErrorHandler(replyPacket.errorCode());
		
			DataInputStream replyData = replyPacket.dataInStream();
			fSourceName = readString("source name", replyData); //$NON-NLS-1$
		} catch (IOException e) {
			defaultIOExceptionHandler(e);
		} finally {
			handledJdwpRequest();
		}
	}

	/**
	 * Check in the source debug extension is available.
	 * To call before doing operations which need data from the Smap.
	 * Return <code>false</code> if the source debug extension is not available
	 * for any reason. <code>true</code> indicates that the source debug extension
	 * is available and the information has been parsed and stored in the 
	 * maps and lists.
	 */
	private synchronized boolean isSourceDebugExtensionAvailable() {
		if (!fSourceDebugExtensionAvailable) {
			return false;
		}
		if (!virtualMachine().canGetSourceDebugExtension()) {
			fSourceDebugExtensionAvailable= false;
			return false;
		}
		if (fSmap == null) {
			try {
				 getSourceDebugExtension();
			} catch (AbsentInformationException e) {
				fSourceDebugExtensionAvailable= false;
				return false;
			}
		}
		return true;
	}

	/**
	 * Set the output file name, i.e. the .java file used to generate
	 * the bytecode.
	 */
	protected void setOutputFileName(String outputFileName) {
		fSourceName= outputFileName;
	}
	
	/**
	 * Set the default stratum. This stratum will be used for the method
	 * on strata related data, but with no stratum parameter.
	 */
	protected void setDefaultStratumId(String defaultStratumId) {
		fDefaultStratumId= defaultStratumId;
	}
	
	/**
	 * Add a new stratum to this type.
	 */
	protected void addStratum(Stratum stratum) {
		fStrata.put(stratum.fId, stratum);
	}

	/**
	 * Return the name of the input source file of which the given code index
	 * is part of the translation, for this stratum.
	 * If the code at the given index is not a part of the translation of
	 * the given stratum code, return the name of the primary input source file.
	 * 
	 * @param codeIndex the index of the code.
	 * @param method the method where is the code.
	 * @param stratumId
	 */
	protected String sourceName(long codeIndex, MethodImpl method, String stratumId) throws AbsentInformationException {
		Stratum stratum= getStratum(stratumId);
		if (stratum != null) {
			FileInfo fileInfo= fileInfo(codeIndex, method, stratum);
			if (fileInfo != null) {
				return fileInfo.fFileName;
			}
		}
		// Java stratum
		if (fSourceName == null) {
			getSourceName();
		}
		return fSourceName;
	}
	
	/**
	 * Return the FileInfo object of the input source file of which the given code index
	 * is part of the translation, for this stratum.
	 * If the code at the given index is not a part of the translation of
	 * the given stratum code, return the FileInfo of the primary input source file.
	 * 
	 * @param codeIndex the index of the code.
	 * @param method the method where is the code.
	 * @param stratum
	 */
	private FileInfo fileInfo(long codeIndex, MethodImpl method, Stratum stratum) {
		int fileId= stratum.fPrimaryFileId;
		if (stratum.fFileInfos.size() > 1) {
			List lineInfos= null;
			try {
				lineInfos = lineInfos(codeIndex, method, stratum);
			} catch (AbsentInformationException e) {
				// nothing to do, use the primary file id.
			}
			if (lineInfos != null) {
				fileId= ((int[])lineInfos.get(0))[0];
			}
		}
		for (Iterator iter = stratum.fFileInfos.iterator(); iter.hasNext();) {
			FileInfo fileInfo = (FileInfo)iter.next();
			if (fileInfo.fFileId == fileId) {
				return fileInfo;
			}
		}
		// should never return null
		return null;
	}

	/**
	 * Return the list of line number in the input files of the stratum associated
	 * with the code at the given address.
	 * 
	 * @param codeIndex the index of the code.
	 * @param method the method where is the code.
	 * @param stratum
	 * @return List of int[2]: [fileId, inputLineNumber]
	 */
	private List lineInfos(long codeIndex, MethodImpl method, Stratum stratum) throws AbsentInformationException {
		int outputLineNumber= -1;
		try {
			outputLineNumber = method.javaStratumLineNumber(codeIndex);
		} catch (NativeMethodException e) { // Occurs in SUN VM.
			return null;
		}
		if (outputLineNumber != -1) {
			return stratum.getInputLineInfos(outputLineNumber);
		}
		return null;
	}

	/**
	 * Return the path of the input source file of which the given code index
	 * is part of the translation, for this stratum.
	 * If the code at the given index is not a part of the translation of
	 * the given stratum code, return the path of the primary input source file.
	 * 
	 * @param codeIndex the index of the code.
	 * @param method the method where is the code.
	 * @param stratumId
	 */
	protected String sourcePath(long codeIndex, MethodImpl method, String stratumId) throws AbsentInformationException {
		Stratum stratum= getStratum(stratumId);
		if (stratum != null) {
			FileInfo fileInfo= fileInfo(codeIndex, method, stratum);
			if (fileInfo != null) {
				String path= fileInfo.fAbsoluteFileName;
				if (path == null) {
					return getPath(fileInfo.fFileName);
				}
				return path;
			}
		}
		// Java stratum
		if (fSourceName == null) {
			getSourceName();
		}
		return getPath(fSourceName);
	}

	/**
	 * Return the number of the line of which the given code index
	 * is part of the translation, for this stratum.
	 * 
	 * @param codeIndex the index of the code.
	 * @param method the method where is the code.
	 * @param stratumId
	 */
	protected int lineNumber(long codeIndex, MethodImpl method, String stratumId) {
		Stratum stratum= getStratum(stratumId);
		try {
			if (stratum != null) {
				List lineInfos = lineInfos(codeIndex, method, stratum);
				if (lineInfos != null) {
					return ((int[])lineInfos.get(0))[1];
				}
				return LocationImpl.LINE_NR_NOT_AVAILABLE;
			}
			// Java stratum
			try {
				return method.javaStratumLineNumber(codeIndex);
			} catch (NativeMethodException e) { // Occurs in SUN VM.
				return LocationImpl.LINE_NR_NOT_AVAILABLE;
			}
		} catch (AbsentInformationException e) {
			return LocationImpl.LINE_NR_NOT_AVAILABLE;
		}
	}

	/**
	 * Return the location which are part of the translation of the given line,
	 * in the given stratum in the source file with the given source name.
	 * If sourceName is <code>null</code>, return the locations for all source file
	 * in the given stratum.
	 * The returned location are in the given method.
	 * 
	 * @param stratumId the stratum id.
	 * @param sourceName the name of the source file.
	 * @param lineNumber  the number of the line.
	 * @param method
	 * @throws AbsentInformationException if the specified sourceName is not valid.
	 */
	public List locationsOfLine(String stratumId, String sourceName, int lineNumber, MethodImpl method) throws AbsentInformationException {
		Stratum stratum= getStratum(stratumId);
		List javaLines= new ArrayList();
		if (stratum != null) {
			boolean found= false;
			for (Iterator iter = stratum.fFileInfos.iterator(); iter.hasNext() && !found;) {
				FileInfo fileInfo = (FileInfo)iter.next();
				if (sourceName == null || (found= sourceName.equals(fileInfo.fFileName))) {
					javaLines.addAll(fileInfo.getOutputLinesForLine(lineNumber));
				}
			}
			if (sourceName != null && !found) {
				throw new AbsentInformationException(JDIMessages.getString("ReferenceTypeImpl.34")); //$NON-NLS-1$
			}
		} else {   // Java stratum
			javaLines.add(new Integer(lineNumber));
		}
		return method.javaStratumLocationsOfLines(javaLines);
	}

	/**
	 * Return the locations of all lines in the given source file of the given stratum which
	 * are included in the given method.
	 * If sourceName is <code>null</code>, return the locations for all source file
	 * in the given stratum.
	 * 
	 * @param stratumId the stratum id
	 * @param sourceName the name of the source file
	 * @param method 
	 * @param codeIndexTable the list of code indexes for the method, as get from the VM/JDWP
	 * @param javaStratumLineNumberTable the list of line numbers in the java stratum for the method, as get from the VM/JDWP
	 * @return
	 */
	public List allLineLocations(String stratumId, String sourceName, MethodImpl method, long[] codeIndexTable, int[] javaStratumLineNumberTable) throws AbsentInformationException {
		Stratum stratum= getStratum(stratumId);
		if (stratum != null) {
			int[][] lineInfoTable= new int[codeIndexTable.length][];
			if (sourceName == null) {
				int lastIndex=0;
				for (int i = 0, length= javaStratumLineNumberTable.length; i < length; i++) {
					// for each executable line in the java source, get the associated lines in the stratum source
					List lineInfos= stratum.getInputLineInfos(javaStratumLineNumberTable[i]);
					if (lineInfos != null) {
						int[] lineInfo= (int[])lineInfos.get(0);
						if (!lineInfo.equals(lineInfoTable[lastIndex])) {
							lineInfoTable[i]= lineInfo;
							lastIndex= i;
						}
					}
				}
			} else { // sourceName != null
				FileInfo fileInfo= stratum.getFileInfo(sourceName);
				if (fileInfo == null) {
					throw new AbsentInformationException(JDIMessages.getString("ReferenceTypeImpl.35")); //$NON-NLS-1$
				}
				int fileId= fileInfo.fFileId;
				int lastIndex= 0;
				for (int i = 0, length= javaStratumLineNumberTable.length; i < length; i++) {
					List lineInfos= stratum.getInputLineInfos(javaStratumLineNumberTable[i]);
					if (lineInfos != null) {
						for (Iterator iter = lineInfos.iterator(); iter.hasNext();) {
							int[] lineInfo= (int[])iter.next();
							if (lineInfo[0] == fileId) {
								if (!lineInfo.equals(lineInfoTable[lastIndex])) {
									lineInfoTable[i]= lineInfo;
									lastIndex= i;
								}
								break;
							}
						}
					}
				}
			}
			List locations= new ArrayList();
			for (int i = 0, length= lineInfoTable.length; i < length; i++) {
				if (lineInfoTable[i] != null) {
					locations.add(new LocationImpl(virtualMachineImpl(), method, codeIndexTable[i]));
				}
			}
			return locations;
		}
		// Java stratum
		List result = new ArrayList();
		for (int i = 0; i < codeIndexTable.length; i++) {
			result.add(new LocationImpl(virtualMachineImpl(), method, codeIndexTable[i]));
		}
		return result;
	}
	
	/*
	 * @since 3.0
	 * @since java 1.5
	 */
	public String genericSignature() {
		if (fGenericSignatureKnown) {
			return fGenericSignature;
		}
		if (virtualMachineImpl().isJdwpVersionGreaterOrEqual(1, 5)) {
			initJdwpRequest();
			try {
		   		JdwpReplyPacket replyPacket = requestVM(JdwpCommandPacket.RT_SIGNATURE_WITH_GENERIC, this);
				defaultReplyErrorHandler(replyPacket.errorCode());
				DataInputStream replyData = replyPacket.dataInStream();
				setSignature(readString("signature", replyData)); //$NON-NLS-1$
				fGenericSignature= readString("generic signature", replyData); //$NON-NLS-1$
				if (fGenericSignature.length() == 0) {
					fGenericSignature= null;
				}
				fGenericSignatureKnown= true;
			} catch (IOException e) {
				defaultIOExceptionHandler(e);
		   		return null;
			} finally {
				handledJdwpRequest();
			}
		} else {
			fGenericSignatureKnown= true;
		}
		return fGenericSignature;
	}
	
	/**
	 * if genericSignature is <code>null</code>, the generic signature is set to not-known
	 * (genericSignature() will ask the VM for the generic signature)
	 * if genericSignature is an empty String, the generic signature is set to no-generic-signature
	 * (genericSignature() will return null)
	 * if genericSignature is an non-empty String, the generic signature is set to the specified value
	 * (genericSignature() will return the specified value)
	 * @since 3.0
	 */
	public void setGenericSignature(String genericSignature) {
		if (genericSignature == null) {
			fGenericSignature= null;
			fGenericSignatureKnown= false;
		} else {
			if (genericSignature.length() == 0) {
				fGenericSignature= null;
			} else {
				fGenericSignature= genericSignature;
			}
			fGenericSignatureKnown= true;
		}
	}

}
