/*******************************************************************************
 * Copyright (c) 2000, 2013 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
 *     Stephan Herrmann <stephan@cs.tu-berlin.de> - Contributions for
 *     						Bug 320618 - inconsistent initialization of classpath container backed by external class folder
 *     						Bug 346010 - [model] strange initialization dependency in OptionTests
 *******************************************************************************/
package org.eclipse.jdt.internal.core;

import java.io.*;
import java.net.URI;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.eclipse.core.resources.ICommand;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.IProjectNature;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ProjectScope;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.QualifiedName;
import org.eclipse.core.runtime.content.IContentDescription;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.core.runtime.preferences.IScopeContext;
import org.eclipse.jdt.core.IClasspathAttribute;
import org.eclipse.jdt.core.IClasspathContainer;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaModelMarker;
import org.eclipse.jdt.core.IJavaModelStatus;
import org.eclipse.jdt.core.IJavaModelStatusConstants;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.IRegion;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.ITypeHierarchy;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.WorkingCopyOwner;
import org.eclipse.jdt.core.compiler.CategorizedProblem;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.core.eval.IEvaluationContext;
import org.eclipse.jdt.internal.compiler.util.ObjectVector;
import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
import org.eclipse.jdt.internal.core.JavaModelManager.PerProjectInfo;
import org.eclipse.jdt.internal.core.JavaProjectElementInfo.ProjectCache;
import org.eclipse.jdt.internal.core.builder.JavaBuilder;
import org.eclipse.jdt.internal.core.eval.EvaluationContextWrapper;
import org.eclipse.jdt.internal.core.util.JavaElementFinder;
import org.eclipse.jdt.internal.core.util.MementoTokenizer;
import org.eclipse.jdt.internal.core.util.Messages;
import org.eclipse.jdt.internal.core.util.Util;
import org.eclipse.jdt.internal.eval.EvaluationContext;
import org.osgi.service.prefs.BackingStoreException;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

/**
 * Handle for a Java Project.
 *
 * <p>A Java Project internally maintains a devpath that corresponds
 * to the project's classpath. The classpath may include source folders
 * from the current project; jars in the current project, other projects,
 * and the local file system; and binary folders (output location) of other
 * projects. The Java Model presents source elements corresponding to output
 * .class files in other projects, and thus uses the devpath rather than
 * the classpath (which is really a compilation path). The devpath mimics
 * the classpath, except has source folder entries in place of output
 * locations in external projects.
 *
 * <p>Each JavaProject has a NameLookup facility that locates elements
 * on by name, based on the devpath.
 *
 * @see IJavaProject
 */
public class JavaProject
	extends Openable
	implements IJavaProject, IProjectNature, SuffixConstants {

	/**
	 * Name of file containing project classpath
	 */
	public static final String CLASSPATH_FILENAME = IJavaProject.CLASSPATH_FILE_NAME;

	/**
	 * Value of the project's raw classpath if the .classpath file contains invalid entries.
	 */
	public static final IClasspathEntry[] INVALID_CLASSPATH = new IClasspathEntry[0];

	/**
	 * Whether the underlying file system is case sensitive.
	 */
	protected static final boolean IS_CASE_SENSITIVE = !new File("Temp").equals(new File("temp")); //$NON-NLS-1$ //$NON-NLS-2$

	/**
	 * An empty array of strings indicating that a project doesn't have any prerequesite projects.
	 */
	protected static final String[] NO_PREREQUISITES = CharOperation.NO_STRINGS;

	/**
	 * Name of file containing custom project preferences
	 * @see <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=59258">bug 59258</a>
	 */
	private static final String PREF_FILENAME = ".jprefs";  //$NON-NLS-1$

	/**
	 * Name of directory containing preferences file
	 */
	public static final String DEFAULT_PREFERENCES_DIRNAME = ".settings"; //$NON-NLS-1$

	/**
	 * Extension for file containing custom project preferences
	 */
	public static final String JAVA_CORE_PREFS_FILE = JavaCore.PLUGIN_ID+".prefs"; //$NON-NLS-1$

	/*
	 * Value of project's resolved classpath while it is being resolved
	 */
	private static final IClasspathEntry[] RESOLUTION_IN_PROGRESS = new IClasspathEntry[0];

	/*
	 * For testing purpose only
	 */
	private static ArrayList CP_RESOLUTION_BP_LISTENERS;
	public static class ClasspathResolutionBreakpointListener {
		public void breakpoint(int bp) {
			// override in listener implementation
		}
	}

	/**
	 * The platform project this <code>IJavaProject</code> is based on
	 */
	protected IProject project;

	/**
	 * Preferences listeners
	 */
	private IEclipsePreferences.INodeChangeListener preferencesNodeListener;
	private IEclipsePreferences.IPreferenceChangeListener preferencesChangeListener;

	/**
	 * Constructor needed for <code>IProject.getNature()</code> and <code>IProject.addNature()</code>.
	 *
	 * @see #setProject(IProject)
	 */
	public JavaProject() {
		super(null);
	}

	public JavaProject(IProject project, JavaElement parent) {
		super(parent);
		this.project = project;
	}

	/*
	 * For testing purpose only
	 */
	public static synchronized void addCPResolutionBPListener(ClasspathResolutionBreakpointListener listener) {
		if (CP_RESOLUTION_BP_LISTENERS == null)
			CP_RESOLUTION_BP_LISTENERS = new ArrayList();
		CP_RESOLUTION_BP_LISTENERS.add(listener);
	}

	/*
	 * For testing purpose only
	 */
	public static synchronized void removeCPResolutionBPListener(ClasspathResolutionBreakpointListener listener) {
		if (CP_RESOLUTION_BP_LISTENERS == null)
			return;
		CP_RESOLUTION_BP_LISTENERS.remove(listener);
		if (CP_RESOLUTION_BP_LISTENERS.size() == 0)
			CP_RESOLUTION_BP_LISTENERS = null;
	}

	private static synchronized ClasspathResolutionBreakpointListener[] getBPListeners() {
		if (CP_RESOLUTION_BP_LISTENERS == null)
			return null;
		return (ClasspathResolutionBreakpointListener[]) CP_RESOLUTION_BP_LISTENERS.toArray(new ClasspathResolutionBreakpointListener[CP_RESOLUTION_BP_LISTENERS.size()]);
	}

	private static void breakpoint(int bp, JavaProject project) {
		ClasspathResolutionBreakpointListener[] listeners = getBPListeners();
		if (listeners == null)
			return;
		for (int j = 0, length = listeners.length; j < length; j++) {
			listeners[j].breakpoint(bp);
		}
	}

	public static boolean areClasspathsEqual(
			IClasspathEntry[] firstClasspath, IClasspathEntry[] secondClasspath,
			IPath firstOutputLocation, IPath secondOutputLocation) {
		int length = firstClasspath.length;
		if (length != secondClasspath.length) return false;
		for (int i = 0; i < length; i++) {
			if (!firstClasspath[i].equals(secondClasspath[i]))
				return false;
		}
		if (firstOutputLocation == null)
			return secondOutputLocation == null;
		return firstOutputLocation.equals(secondOutputLocation);
	}

	/**
	 * Compare current classpath with given one to see if any different.
	 * Note that the argument classpath contains its binary output.
	 * @param newClasspath IClasspathEntry[]
	 * @param newOutputLocation IPath
	 * @param otherClasspathWithOutput IClasspathEntry[]
	 * @return boolean
	 */
	private static boolean areClasspathsEqual(IClasspathEntry[] newClasspath, IPath newOutputLocation, IClasspathEntry[] otherClasspathWithOutput) {

		if (otherClasspathWithOutput == null || otherClasspathWithOutput.length == 0)
			return false;

		int length = otherClasspathWithOutput.length;
		if (length != newClasspath.length + 1)
				// output is amongst file entries (last one)
				return false;


		// compare classpath entries
		for (int i = 0; i < length - 1; i++) {
			if (!otherClasspathWithOutput[i].equals(newClasspath[i]))
				return false;
		}
		// compare binary outputs
		IClasspathEntry output = otherClasspathWithOutput[length - 1];
		if (output.getContentKind() != ClasspathEntry.K_OUTPUT
				|| !output.getPath().equals(newOutputLocation))
			return false;
		return true;
	}
	
	private static boolean areClasspathsEqual(IClasspathEntry[] first, IClasspathEntry[] second) {
		if (first != second){
		    if (first == null) return false;
			int length = first.length;
			if (second == null || second.length != length)
				return false;
			for (int i = 0; i < length; i++) {
				if (!first[i].equals(second[i]))
					return false;
			}
		}
		return true;
	}

	/**
	 * Returns a canonicalized path from the given external path.
	 * Note that the return path contains the same number of segments
	 * and it contains a device only if the given path contained one.
	 * @param externalPath IPath
	 * @see java.io.File for the definition of a canonicalized path
	 * @return IPath
	 */
	public static IPath canonicalizedPath(IPath externalPath) {

		if (externalPath == null)
			return null;

		if (IS_CASE_SENSITIVE) {
			return externalPath;
		}
		
		// if not external path, return original path
		IWorkspace workspace = ResourcesPlugin.getWorkspace();
		if (workspace == null) return externalPath; // protection during shutdown (30487)
		if (workspace.getRoot().findMember(externalPath) != null) {
			return externalPath;
		}

		IPath canonicalPath = null;
		try {
			canonicalPath =
				new Path(new File(externalPath.toOSString()).getCanonicalPath());
		} catch (IOException e) {
			// default to original path
			return externalPath;
		}

		IPath result;
		int canonicalLength = canonicalPath.segmentCount();
		if (canonicalLength == 0) {
			// the java.io.File canonicalization failed
			return externalPath;
		} else if (externalPath.isAbsolute()) {
			result = canonicalPath;
		} else {
			// if path is relative, remove the first segments that were added by the java.io.File canonicalization
			// e.g. 'lib/classes.zip' was converted to 'd:/myfolder/lib/classes.zip'
			int externalLength = externalPath.segmentCount();
			if (canonicalLength >= externalLength) {
				result = canonicalPath.removeFirstSegments(canonicalLength - externalLength);
			} else {
				return externalPath;
			}
		}

		// keep device only if it was specified (this is because File.getCanonicalPath() converts '/lib/classes.zip' to 'd:/lib/classes/zip')
		if (externalPath.getDevice() == null) {
			result = result.setDevice(null);
		}
		// keep trailing separator only if it was specified (this is because File.getCanonicalPath() converts 'd:/lib/classes/' to 'd:/lib/classes')
		if (externalPath.hasTrailingSeparator()) {
			result = result.addTrailingSeparator();
		}
		return result;
	}

	/**
	 * Returns true if the given project is accessible and it has
	 * a java nature, otherwise false.
	 * @param project IProject
	 * @return boolean
	 */
	public static boolean hasJavaNature(IProject project) {
		try {
			return project.hasNature(JavaCore.NATURE_ID);
		} catch (CoreException e) {
			if (ExternalJavaProject.EXTERNAL_PROJECT_NAME.equals(project.getName()))
				return true;
			// project does not exist or is not open
		}
		return false;
	}

	/*
	 * Detect cycles in the classpath of the workspace's projects
	 * and create markers if necessary.
	 * @param preferredClasspaths Map
	 * @throws JavaModelException
	 */
	public static void validateCycles(Map preferredClasspaths) throws JavaModelException {

		//long start = System.currentTimeMillis();

		IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
		IProject[] rscProjects = workspaceRoot.getProjects();
		int length = rscProjects.length;
		JavaProject[] projects = new JavaProject[length];

		LinkedHashSet cycleParticipants = new LinkedHashSet();
		HashSet traversed = new HashSet();

		// compute cycle participants
		ArrayList prereqChain = new ArrayList();
		for (int i = 0; i < length; i++){
			if (hasJavaNature(rscProjects[i])) {
				JavaProject project = (projects[i] = (JavaProject)JavaCore.create(rscProjects[i]));
				if (!traversed.contains(project.getPath())){
					prereqChain.clear();
					project.updateCycleParticipants(prereqChain, cycleParticipants, workspaceRoot, traversed, preferredClasspaths);
				}
			}
		}
		//System.out.println("updateAllCycleMarkers: " + (System.currentTimeMillis() - start) + " ms");

		for (int i = 0; i < length; i++){
			JavaProject project = projects[i];
			if (project != null) {
				if (cycleParticipants.contains(project.getPath())){
					IMarker cycleMarker = project.getCycleMarker();
					String circularCPOption = project.getOption(JavaCore.CORE_CIRCULAR_CLASSPATH, true);
					int circularCPSeverity = JavaCore.ERROR.equals(circularCPOption) ? IMarker.SEVERITY_ERROR : IMarker.SEVERITY_WARNING;
					if (cycleMarker != null) {
						// update existing cycle marker if needed
						try {
							int existingSeverity = ((Integer)cycleMarker.getAttribute(IMarker.SEVERITY)).intValue();
							if (existingSeverity != circularCPSeverity) {
								cycleMarker.setAttribute(IMarker.SEVERITY, circularCPSeverity);
							}
						} catch (CoreException e) {
							throw new JavaModelException(e);
						}
					} else {
						IJavaProject[] projectsInCycle;
						String cycleString = "";	 //$NON-NLS-1$
						if (cycleParticipants.isEmpty()) {
							projectsInCycle = null;
						} else {
							projectsInCycle = new IJavaProject[cycleParticipants.size()];
							Iterator it = cycleParticipants.iterator();
							int k = 0;
							while (it.hasNext()) {
								//projectsInCycle[i++] = (IPath) it.next();
								IResource member = workspaceRoot.findMember((IPath) it.next());
								if (member != null && member.getType() == IResource.PROJECT){
									projectsInCycle[k] = JavaCore.create((IProject)member);
									if (projectsInCycle[k] != null) {
										if (k != 0) cycleString += ", "; //$NON-NLS-1$
										cycleString += projectsInCycle[k++].getElementName();
									}
								}
							}
						}
						// create new marker
						project.createClasspathProblemMarker(
							new JavaModelStatus(IJavaModelStatusConstants.CLASSPATH_CYCLE, project, cycleString));
					}
				} else {
					project.flushClasspathProblemMarkers(true, false, false);
				}
			}
		}
	}

	/**
	 * Adds a builder to the build spec for the given project.
	 */
	protected void addToBuildSpec(String builderID) throws CoreException {

		IProjectDescription description = this.project.getDescription();
		int javaCommandIndex = getJavaCommandIndex(description.getBuildSpec());

		if (javaCommandIndex == -1) {

			// Add a Java command to the build spec
			ICommand command = description.newCommand();
			command.setBuilderName(builderID);
			setJavaCommand(description, command);
		}
	}
	/**
	 * @see Openable
	 */
	protected boolean buildStructure(OpenableElementInfo info, IProgressMonitor pm, Map newElements, IResource underlyingResource) throws JavaModelException {
		// cannot refresh cp markers on opening (emulate cp check on startup) since can create deadlocks (see bug 37274)
		IClasspathEntry[] resolvedClasspath = getResolvedClasspath();

		// compute the pkg fragment roots
		info.setChildren(computePackageFragmentRoots(resolvedClasspath, false, null /*no reverse map*/));

		return true;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.jdt.internal.core.JavaElement#close()
	 */
	public void close() throws JavaModelException {
		if (JavaProject.hasJavaNature(this.project)) {
			// Get cached preferences if exist
			JavaModelManager.PerProjectInfo perProjectInfo = JavaModelManager.getJavaModelManager().getPerProjectInfo(this.project, false);
			if (perProjectInfo != null && perProjectInfo.preferences != null) {
				IEclipsePreferences eclipseParentPreferences = (IEclipsePreferences) perProjectInfo.preferences.parent();
				if (this.preferencesNodeListener != null) {
					eclipseParentPreferences.removeNodeChangeListener(this.preferencesNodeListener);
					this.preferencesNodeListener = null;
				}
				if (this.preferencesChangeListener != null) {
					perProjectInfo.preferences.removePreferenceChangeListener(this.preferencesChangeListener);
					this.preferencesChangeListener = null;
				}
			}
		}
		super.close();
	}

	/**
	 * Internal computation of an expanded classpath. It will eliminate duplicates, and produce copies
	 * of exported or restricted classpath entries to avoid possible side-effects ever after.
	 */
	private void computeExpandedClasspath(
		ClasspathEntry referringEntry,
		HashSet rootIDs,
		ObjectVector accumulatedEntries) throws JavaModelException {

		String projectRootId = rootID();
		if (rootIDs.contains(projectRootId)){
			return; // break cycles if any
		}
		rootIDs.add(projectRootId);

		IClasspathEntry[] resolvedClasspath = getResolvedClasspath();

		IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
		boolean isInitialProject = referringEntry == null;
		for (int i = 0, length = resolvedClasspath.length; i < length; i++){
			ClasspathEntry entry = (ClasspathEntry) resolvedClasspath[i];
			if (isInitialProject || entry.isExported()){
				String rootID = entry.rootID();
				if (rootIDs.contains(rootID)) {
					continue;
				}
				// combine restrictions along the project chain
				ClasspathEntry combinedEntry = entry.combineWith(referringEntry);
				accumulatedEntries.add(combinedEntry);

				// recurse in project to get all its indirect exports (only consider exported entries from there on)
				if (entry.getEntryKind() == IClasspathEntry.CPE_PROJECT) {
					IResource member = workspaceRoot.findMember(entry.getPath());
					if (member != null && member.getType() == IResource.PROJECT){ // double check if bound to project (23977)
						IProject projRsc = (IProject) member;
						if (JavaProject.hasJavaNature(projRsc)) {
							JavaProject javaProject = (JavaProject) JavaCore.create(projRsc);
							javaProject.computeExpandedClasspath(
								combinedEntry,
								rootIDs,
								accumulatedEntries);
						}
					}
				} else {
					rootIDs.add(rootID);
				}
			}
		}
	}

	/**
	 * Computes the package fragment roots identified by the given entry.
	 * Only works with resolved entry
	 * @param resolvedEntry IClasspathEntry
	 * @return IPackageFragmentRoot[]
	 */
	public IPackageFragmentRoot[] computePackageFragmentRoots(IClasspathEntry resolvedEntry) {
		try {
			return
				computePackageFragmentRoots(
					new IClasspathEntry[]{ resolvedEntry },
					false, // don't retrieve exported roots
					null /* no reverse map */
				);
		} catch (JavaModelException e) {
			return new IPackageFragmentRoot[] {};
		}
	}

	/**
	 * Returns the package fragment roots identified by the given entry. In case it refers to
	 * a project, it will follow its classpath so as to find exported roots as well.
	 * Only works with resolved entry
	 * @param resolvedEntry IClasspathEntry
	 * @param accumulatedRoots ObjectVector
	 * @param rootIDs HashSet
	 * @param referringEntry the CP entry (project) referring to this entry, or null if initial project
	 * @param retrieveExportedRoots boolean
	 * @throws JavaModelException
	 */
	public void computePackageFragmentRoots(
		IClasspathEntry resolvedEntry,
		ObjectVector accumulatedRoots,
		HashSet rootIDs,
		IClasspathEntry referringEntry,
		boolean retrieveExportedRoots,
		Map rootToResolvedEntries) throws JavaModelException {

		String rootID = ((ClasspathEntry)resolvedEntry).rootID();
		if (rootIDs.contains(rootID)) return;

		IPath projectPath = this.project.getFullPath();
		IPath entryPath = resolvedEntry.getPath();
		IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
		IPackageFragmentRoot root = null;

		switch(resolvedEntry.getEntryKind()){

			// source folder
			case IClasspathEntry.CPE_SOURCE :

				if (projectPath.isPrefixOf(entryPath)){
					Object target = JavaModel.getTarget(entryPath, true/*check existency*/);
					if (target == null) return;

					if (target instanceof IFolder || target instanceof IProject){
						root = getPackageFragmentRoot((IResource)target);
					}
				}
				break;

			// internal/external JAR or folder
			case IClasspathEntry.CPE_LIBRARY :
				if (referringEntry != null  && !resolvedEntry.isExported())
					return;
				Object target = JavaModel.getTarget(entryPath, true/*check existency*/);
				if (target == null)
					return;

				if (target instanceof IResource){
					// internal target
					root = getPackageFragmentRoot((IResource) target, entryPath);
				} else if (target instanceof File) {
					// external target
					if (JavaModel.isFile(target)) {
						root = new JarPackageFragmentRoot(entryPath, this);
					} else if (((File) target).isDirectory()) {
						root = new ExternalPackageFragmentRoot(entryPath, this);
					}
				}
				break;

			// recurse into required project
			case IClasspathEntry.CPE_PROJECT :

				if (!retrieveExportedRoots) return;
				if (referringEntry != null && !resolvedEntry.isExported()) return;

				IResource member = workspaceRoot.findMember(entryPath);
				if (member != null && member.getType() == IResource.PROJECT){// double check if bound to project (23977)
					IProject requiredProjectRsc = (IProject) member;
					if (JavaProject.hasJavaNature(requiredProjectRsc)){ // special builder binary output
						rootIDs.add(rootID);
						JavaProject requiredProject = (JavaProject)JavaCore.create(requiredProjectRsc);
						requiredProject.computePackageFragmentRoots(
							requiredProject.getResolvedClasspath(),
							accumulatedRoots,
							rootIDs,
							rootToResolvedEntries == null ? resolvedEntry : ((ClasspathEntry)resolvedEntry).combineWith((ClasspathEntry) referringEntry), // only combine if need to build the reverse map
							retrieveExportedRoots,
							rootToResolvedEntries);
					}
				break;
			}
		}
		if (root != null) {
			accumulatedRoots.add(root);
			rootIDs.add(rootID);
			if (rootToResolvedEntries != null) rootToResolvedEntries.put(root, ((ClasspathEntry)resolvedEntry).combineWith((ClasspathEntry) referringEntry));
		}
	}

	/**
	 * Returns (local/all) the package fragment roots identified by the given project's classpath.
	 * Note: this follows project classpath references to find required project contributions,
	 * eliminating duplicates silently.
	 * Only works with resolved entries
	 * @param resolvedClasspath IClasspathEntry[]
	 * @param retrieveExportedRoots boolean
	 * @return IPackageFragmentRoot[]
	 * @throws JavaModelException
	 */
	public IPackageFragmentRoot[] computePackageFragmentRoots(
					IClasspathEntry[] resolvedClasspath,
					boolean retrieveExportedRoots,
					Map rootToResolvedEntries) throws JavaModelException {

		ObjectVector accumulatedRoots = new ObjectVector();
		computePackageFragmentRoots(
			resolvedClasspath,
			accumulatedRoots,
			new HashSet(5), // rootIDs
			null, // inside original project
			retrieveExportedRoots,
			rootToResolvedEntries);
		IPackageFragmentRoot[] rootArray = new IPackageFragmentRoot[accumulatedRoots.size()];
		accumulatedRoots.copyInto(rootArray);
		return rootArray;
	}

	/**
	 * Returns (local/all) the package fragment roots identified by the given project's classpath.
	 * Note: this follows project classpath references to find required project contributions,
	 * eliminating duplicates silently.
	 * Only works with resolved entries
	 * @param resolvedClasspath IClasspathEntry[]
	 * @param accumulatedRoots ObjectVector
	 * @param rootIDs HashSet
	 * @param referringEntry project entry referring to this CP or null if initial project
	 * @param retrieveExportedRoots boolean
	 * @throws JavaModelException
	 */
	public void computePackageFragmentRoots(
		IClasspathEntry[] resolvedClasspath,
		ObjectVector accumulatedRoots,
		HashSet rootIDs,
		IClasspathEntry referringEntry,
		boolean retrieveExportedRoots,
		Map rootToResolvedEntries) throws JavaModelException {

		if (referringEntry == null){
			rootIDs.add(rootID());
		}
		for (int i = 0, length = resolvedClasspath.length; i < length; i++){
			computePackageFragmentRoots(
				resolvedClasspath[i],
				accumulatedRoots,
				rootIDs,
				referringEntry,
				retrieveExportedRoots,
				rootToResolvedEntries);
		}
	}
	/**
	 * Compute the file name to use for a given shared property
	 * @param qName QualifiedName
	 * @return String
	 */
	public String computeSharedPropertyFileName(QualifiedName qName) {

		return '.' + qName.getLocalName();
	}

	/**
	 * Configure the project with Java nature.
	 */
	public void configure() throws CoreException {

		// register Java builder
		addToBuildSpec(JavaCore.BUILDER_ID);
	}

	/*
	 * Returns whether the given resource is accessible through the children or the non-Java resources of this project.
	 * Returns true if the resource is not in the project.
	 * Assumes that the resource is a folder or a file.
	 */
	public boolean contains(IResource resource) {

		IClasspathEntry[] classpath;
		IPath output;
		try {
			classpath = getResolvedClasspath();
			output = getOutputLocation();
		} catch (JavaModelException e) {
			return false;
		}

		IPath fullPath = resource.getFullPath();
		IPath innerMostOutput = output.isPrefixOf(fullPath) ? output : null;
		IClasspathEntry innerMostEntry = null;
		ExternalFoldersManager foldersManager = JavaModelManager.getExternalManager();
		for (int j = 0, cpLength = classpath.length; j < cpLength; j++) {
			IClasspathEntry entry = classpath[j];

			IPath entryPath = entry.getPath();
			if (entry.getEntryKind() == IClasspathEntry.CPE_LIBRARY) {
				IResource linkedFolder = foldersManager.getFolder(entryPath);
				if (linkedFolder != null)
					entryPath = linkedFolder.getFullPath();
			}
			if ((innerMostEntry == null || innerMostEntry.getPath().isPrefixOf(entryPath))
					&& entryPath.isPrefixOf(fullPath)) {
				innerMostEntry = entry;
			}
			IPath entryOutput = classpath[j].getOutputLocation();
			if (entryOutput != null && entryOutput.isPrefixOf(fullPath)) {
				innerMostOutput = entryOutput;
			}
		}
		if (innerMostEntry != null) {
			// special case prj==src and nested output location
			if (innerMostOutput != null && innerMostOutput.segmentCount() > 1 // output isn't project
					&& innerMostEntry.getPath().segmentCount() == 1) { // 1 segment must be project name
				return false;
			}
			if  (resource instanceof IFolder) {
				 // folders are always included in src/lib entries
				 return true;
			}
			switch (innerMostEntry.getEntryKind()) {
				case IClasspathEntry.CPE_SOURCE:
					// .class files are not visible in source folders
					return !org.eclipse.jdt.internal.compiler.util.Util.isClassFileName(fullPath.lastSegment());
				case IClasspathEntry.CPE_LIBRARY:
					// .java files are not visible in library folders
					return !org.eclipse.jdt.internal.core.util.Util.isJavaLikeFileName(fullPath.lastSegment());
			}
		}
		if (innerMostOutput != null) {
			return false;
		}
		return true;
	}

	/**
	 * Record a new marker denoting a classpath problem
	 */
	public void createClasspathProblemMarker(IJavaModelStatus status) {

		IMarker marker = null;
		int severity;
		String[] arguments = CharOperation.NO_STRINGS;
		boolean isCycleProblem = false, isClasspathFileFormatProblem = false, isOutputOverlapping = false;
		switch (status.getCode()) {

			case  IJavaModelStatusConstants.CLASSPATH_CYCLE :
				isCycleProblem = true;
				if (JavaCore.ERROR.equals(getOption(JavaCore.CORE_CIRCULAR_CLASSPATH, true))) {
					severity = IMarker.SEVERITY_ERROR;
				} else {
					severity = IMarker.SEVERITY_WARNING;
				}
				break;

			case  IJavaModelStatusConstants.INVALID_CLASSPATH_FILE_FORMAT :
				isClasspathFileFormatProblem = true;
				severity = IMarker.SEVERITY_ERROR;
				break;

			case  IJavaModelStatusConstants.INCOMPATIBLE_JDK_LEVEL :
				String setting = getOption(JavaCore.CORE_INCOMPATIBLE_JDK_LEVEL, true);
				if (JavaCore.ERROR.equals(setting)) {
					severity = IMarker.SEVERITY_ERROR;
				} else if (JavaCore.WARNING.equals(setting)) {
					severity = IMarker.SEVERITY_WARNING;
				} else {
					return; // setting == IGNORE
				}
				break;
			case IJavaModelStatusConstants.OUTPUT_LOCATION_OVERLAPPING_ANOTHER_SOURCE :
				isOutputOverlapping = true;
				setting = getOption(JavaCore.CORE_OUTPUT_LOCATION_OVERLAPPING_ANOTHER_SOURCE, true);
				if (JavaCore.ERROR.equals(setting)) {
					severity = IMarker.SEVERITY_ERROR;
				} else if (JavaCore.WARNING.equals(setting)) {
					severity = IMarker.SEVERITY_WARNING;
				} else {
					return; // setting == IGNORE
				}
				break;
			default:
				IPath path = status.getPath();
				if (path != null) arguments = new String[] { path.toString() };
				if (JavaCore.ERROR.equals(getOption(JavaCore.CORE_INCOMPLETE_CLASSPATH, true)) &&
					status.getSeverity() != IStatus.WARNING) {
					severity = IMarker.SEVERITY_ERROR;
				} else {
					severity = IMarker.SEVERITY_WARNING;
				}
				break;
		}

		try {
			marker = this.project.createMarker(IJavaModelMarker.BUILDPATH_PROBLEM_MARKER);
			marker.setAttributes(
				new String[] {
					IMarker.MESSAGE,
					IMarker.SEVERITY,
					IMarker.LOCATION,
					IJavaModelMarker.CYCLE_DETECTED,
					IJavaModelMarker.CLASSPATH_FILE_FORMAT,
					IJavaModelMarker.OUTPUT_OVERLAPPING_SOURCE,
					IJavaModelMarker.ID,
					IJavaModelMarker.ARGUMENTS ,
					IJavaModelMarker.CATEGORY_ID,
					IMarker.SOURCE_ID,
				},
				new Object[] {
					status.getMessage(),
					new Integer(severity),
					Messages.classpath_buildPath,
					isCycleProblem ? "true" : "false",//$NON-NLS-1$ //$NON-NLS-2$
					isClasspathFileFormatProblem ? "true" : "false",//$NON-NLS-1$ //$NON-NLS-2$
					isOutputOverlapping ? "true" : "false", //$NON-NLS-1$ //$NON-NLS-2$
					new Integer(status.getCode()),
					Util.getProblemArgumentsForMarker(arguments) ,
					new Integer(CategorizedProblem.CAT_BUILDPATH),
					JavaBuilder.SOURCE_ID,
				}
			);
		} catch (CoreException e) {
			// could not create marker: cannot do much
			if (JavaModelManager.VERBOSE) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * Returns a new element info for this element.
	 */
	protected Object createElementInfo() {
		return new JavaProjectElementInfo();
	}

	/**
	 * Reads and decode an XML classpath string. Returns a two-dimensional array, where the number of elements in the row is fixed to 2.
	 * The first element is an array of raw classpath entries and the second element is an array of referenced entries that may have been stored
	 * by the client earlier. See {@link IJavaProject#getReferencedClasspathEntries()} for more details. 
	 * 
	 */
	public IClasspathEntry[][] decodeClasspath(String xmlClasspath, Map unknownElements) throws IOException, ClasspathEntry.AssertionFailedException {

		ArrayList paths = new ArrayList();
		IClasspathEntry defaultOutput = null;
		StringReader reader = new StringReader(xmlClasspath);
		Element cpElement;
		try {
			DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder();
			cpElement = parser.parse(new InputSource(reader)).getDocumentElement();
		} catch (SAXException e) {
			throw new IOException(Messages.file_badFormat);
		} catch (ParserConfigurationException e) {
			throw new IOException(Messages.file_badFormat);
		} finally {
			reader.close();
		}

		if (!cpElement.getNodeName().equalsIgnoreCase("classpath")) { //$NON-NLS-1$
			throw new IOException(Messages.file_badFormat);
		}
		NodeList list = cpElement.getElementsByTagName(ClasspathEntry.TAG_CLASSPATHENTRY);
		int length = list.getLength();

		for (int i = 0; i < length; ++i) {
			Node node = list.item(i);
			if (node.getNodeType() == Node.ELEMENT_NODE) {
				IClasspathEntry entry = ClasspathEntry.elementDecode((Element)node, this, unknownElements);
				if (entry != null){
					if (entry.getContentKind() == ClasspathEntry.K_OUTPUT) {
						defaultOutput = entry; // separate output
					} else {
						paths.add(entry);
					}
				}
			}
		}
		int pathSize = paths.size();
		IClasspathEntry[][] entries = new IClasspathEntry[2][];
		entries[0] = new IClasspathEntry[pathSize + (defaultOutput == null ? 0 : 1)];
		paths.toArray(entries[0]);
		if (defaultOutput != null) entries[0][pathSize] = defaultOutput; // ensure output is last item
		
		paths.clear();
		list = cpElement.getElementsByTagName(ClasspathEntry.TAG_REFERENCED_ENTRY);
		length = list.getLength();

		for (int i = 0; i < length; ++i) {
			Node node = list.item(i);
			if (node.getNodeType() == Node.ELEMENT_NODE) {
				IClasspathEntry entry = ClasspathEntry.elementDecode((Element)node, this, unknownElements);
				if (entry != null){
					paths.add(entry);
				}
			}
		}
		entries[1] = new IClasspathEntry[paths.size()];
		paths.toArray(entries[1]);

		return entries;
	}

	public IClasspathEntry decodeClasspathEntry(String encodedEntry) {

		try {
			if (encodedEntry == null) return null;
			StringReader reader = new StringReader(encodedEntry);
			Element node;

			try {
				DocumentBuilder parser =
					DocumentBuilderFactory.newInstance().newDocumentBuilder();
				node = parser.parse(new InputSource(reader)).getDocumentElement();
			} catch (SAXException e) {
				return null;
			} catch (ParserConfigurationException e) {
				return null;
			} finally {
				reader.close();
			}

			if (!node.getNodeName().equalsIgnoreCase(ClasspathEntry.TAG_CLASSPATHENTRY)
					|| node.getNodeType() != Node.ELEMENT_NODE) {
				return null;
			}
			return ClasspathEntry.elementDecode(node, this, null/*not interested in unknown elements*/);
		} catch (IOException e) {
			// bad format
			return null;
		}
	}

	/**
	/**
	 * Removes the Java nature from the project.
	 */
	public void deconfigure() throws CoreException {

		// deregister Java builder
		removeFromBuildSpec(JavaCore.BUILDER_ID);

		// remove .classpath file
//		getProject().getFile(ClasspathHelper.CLASSPATH_FILENAME).delete(false, null);
	}

	/**
	 * Returns a default class path.
	 * This is the root of the project
	 */
	protected IClasspathEntry[] defaultClasspath() {

		return new IClasspathEntry[] {
			 JavaCore.newSourceEntry(this.project.getFullPath())};
	}

	/**
	 * Returns a default output location.
	 * This is the project bin folder
	 */
	protected IPath defaultOutputLocation() {
		return this.project.getFullPath().append("bin"); //$NON-NLS-1$
	}

	/**
	 * Returns the XML String encoding of the class path.
	 */
	protected String encodeClasspath(IClasspathEntry[] classpath, IClasspathEntry[] referencedEntries, IPath outputLocation, boolean indent, Map unknownElements) throws JavaModelException {
		try {
			ByteArrayOutputStream s = new ByteArrayOutputStream();
			OutputStreamWriter writer = new OutputStreamWriter(s, "UTF8"); //$NON-NLS-1$
			XMLWriter xmlWriter = new XMLWriter(writer, this, true/*print XML version*/);

			xmlWriter.startTag(ClasspathEntry.TAG_CLASSPATH, indent);
			for (int i = 0; i < classpath.length; ++i) {
				((ClasspathEntry)classpath[i]).elementEncode(xmlWriter, this.project.getFullPath(), indent, true, unknownElements, false);
			}

			if (outputLocation != null) {
				outputLocation = outputLocation.removeFirstSegments(1);
				outputLocation = outputLocation.makeRelative();
				HashMap parameters = new HashMap();
				parameters.put(ClasspathEntry.TAG_KIND, ClasspathEntry.kindToString(ClasspathEntry.K_OUTPUT));
				parameters.put(ClasspathEntry.TAG_PATH, String.valueOf(outputLocation));
				xmlWriter.printTag(ClasspathEntry.TAG_CLASSPATHENTRY, parameters, indent, true, true);
			}

			if (referencedEntries != null) {
				for (int i = 0; i < referencedEntries.length; ++i) {
					((ClasspathEntry) referencedEntries[i]).elementEncode(xmlWriter, this.project.getFullPath(), indent, true, unknownElements, true);
				}
			}
			
			xmlWriter.endTag(ClasspathEntry.TAG_CLASSPATH, indent, true/*insert new line*/);
			writer.flush();
			writer.close();
			return s.toString("UTF8");//$NON-NLS-1$
		} catch (IOException e) {
			throw new JavaModelException(e, IJavaModelStatusConstants.IO_EXCEPTION);
		}
	}

	public String encodeClasspathEntry(IClasspathEntry classpathEntry) {
		try {
			ByteArrayOutputStream s = new ByteArrayOutputStream();
			OutputStreamWriter writer = new OutputStreamWriter(s, "UTF8"); //$NON-NLS-1$
			XMLWriter xmlWriter = new XMLWriter(writer, this, false/*don't print XML version*/);

			((ClasspathEntry)classpathEntry).elementEncode(xmlWriter, this.project.getFullPath(), true/*indent*/, true/*insert new line*/, null/*not interested in unknown elements*/, (classpathEntry.getReferencingEntry() != null));

			writer.flush();
			writer.close();
			return s.toString("UTF8");//$NON-NLS-1$
		} catch (IOException e) {
			return null; // never happens since all is done in memory
		}
	}

	/**
	 * Returns true if this handle represents the same Java project
	 * as the given handle. Two handles represent the same
	 * project if they are identical or if they represent a project with
	 * the same underlying resource and occurrence counts.
	 *
	 * @see JavaElement#equals(Object)
	 */
	public boolean equals(Object o) {

		if (this == o)
			return true;

		if (!(o instanceof JavaProject))
			return false;

		JavaProject other = (JavaProject) o;
		return this.project.equals(other.getProject());
	}

	/**
	 * @see IJavaProject#findElement(IPath)
	 */
	public IJavaElement findElement(IPath path) throws JavaModelException {
		return findElement(path, DefaultWorkingCopyOwner.PRIMARY);
	}

	/**
	 * @see IJavaProject#findElement(IPath, WorkingCopyOwner)
	 */
	public IJavaElement findElement(IPath path, WorkingCopyOwner owner) throws JavaModelException {

		if (path == null || path.isAbsolute()) {
			throw new JavaModelException(
				new JavaModelStatus(IJavaModelStatusConstants.INVALID_PATH, path));
		}
		try {

			String extension = path.getFileExtension();
			if (extension == null) {
				String packageName = path.toString().replace(IPath.SEPARATOR, '.');
				return findPackageFragment(packageName);
			} else if (Util.isJavaLikeFileName(path.lastSegment())
					|| extension.equalsIgnoreCase(EXTENSION_class)) {
				IPath packagePath = path.removeLastSegments(1);
				String packageName = packagePath.toString().replace(IPath.SEPARATOR, '.');
				String typeName = path.lastSegment();
				typeName = typeName.substring(0, typeName.length() - extension.length() - 1);
				String qualifiedName = null;
				if (packageName.length() > 0) {
					qualifiedName = packageName + "." + typeName; //$NON-NLS-1$
				} else {
					qualifiedName = typeName;
				}

				// lookup type
				NameLookup lookup = newNameLookup(owner);
				NameLookup.Answer answer = lookup.findType(
					qualifiedName,
					false,
					NameLookup.ACCEPT_ALL,
					true/* consider secondary types */,
					false/* do NOT wait for indexes */,
					false/*don't check restrictions*/,
					null);

				if (answer != null) {
					return answer.type.getParent();
				} else {
					return null;
				}
			} else {
				// unsupported extension
				return null;
			}
		} catch (JavaModelException e) {
			if (e.getStatus().getCode()
				== IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST) {
				return null;
			} else {
				throw e;
			}
		}
	}

	public IJavaElement findPackageFragment(String packageName)
			throws JavaModelException {
		NameLookup lookup = newNameLookup((WorkingCopyOwner)null/*no need to look at working copies for pkgs*/);
		IPackageFragment[] pkgFragments = lookup.findPackageFragments(packageName, false);
		if (pkgFragments == null) {
			return null;

		} else {
			// try to return one that is a child of this project
			for (int i = 0, length = pkgFragments.length; i < length; i++) {

				IPackageFragment pkgFragment = pkgFragments[i];
				if (equals(pkgFragment.getParent().getParent())) {
					return pkgFragment;
				}
			}
			// default to the first one
			return pkgFragments[0];
		}
	}

	public IJavaElement findElement(String bindingKey, WorkingCopyOwner owner) throws JavaModelException {
		JavaElementFinder elementFinder = new JavaElementFinder(bindingKey, this, owner);
		elementFinder.parse();
		if (elementFinder.exception != null)
			throw elementFinder.exception;
		return elementFinder.element;
	}

	/**
	 * @see IJavaProject
	 */
	public IPackageFragment findPackageFragment(IPath path)
		throws JavaModelException {

		return findPackageFragment0(JavaProject.canonicalizedPath(path));
	}
	/*
	 * non path canonicalizing version
	 */
	private IPackageFragment findPackageFragment0(IPath path)
		throws JavaModelException {

		NameLookup lookup = newNameLookup((WorkingCopyOwner)null/*no need to look at working copies for pkgs*/);
		return lookup.findPackageFragment(path);
	}

	/**
	 * @see IJavaProject
	 */
	public IPackageFragmentRoot findPackageFragmentRoot(IPath path)
		throws JavaModelException {

		return findPackageFragmentRoot0(JavaProject.canonicalizedPath(path));
	}
	/*
	 * no path canonicalization
	 */
	public IPackageFragmentRoot findPackageFragmentRoot0(IPath path)
		throws JavaModelException {

		IPackageFragmentRoot[] allRoots = this.getAllPackageFragmentRoots();
		if (!path.isAbsolute()) {
			throw new IllegalArgumentException(Messages.path_mustBeAbsolute);
		}
		for (int i= 0; i < allRoots.length; i++) {
			IPackageFragmentRoot classpathRoot= allRoots[i];
			if (classpathRoot.getPath().equals(path)) {
				return classpathRoot;
			}
		}
		return null;
	}
	/**
	 * @see IJavaProject
	 */
	public IPackageFragmentRoot[] findPackageFragmentRoots(IClasspathEntry entry) {
		try {
			IClasspathEntry[] classpath = getRawClasspath();
			for (int i = 0, length = classpath.length; i < length; i++) {
				if (classpath[i].equals(entry)) { // entry may need to be resolved
					return
						computePackageFragmentRoots(
							resolveClasspath(new IClasspathEntry[] {entry}),
							false, // don't retrieve exported roots
							null); /*no reverse map*/
				}
			}
		} catch (JavaModelException e) {
			// project doesn't exist: return an empty array
		}
		return new IPackageFragmentRoot[] {};
	}
	/**
	 * @see IJavaProject#findType(String)
	 */
	public IType findType(String fullyQualifiedName) throws JavaModelException {
		return findType(fullyQualifiedName, DefaultWorkingCopyOwner.PRIMARY);
	}
	/**
	 * @see IJavaProject#findType(String, IProgressMonitor)
	 */
	public IType findType(String fullyQualifiedName, IProgressMonitor progressMonitor) throws JavaModelException {
		return findType(fullyQualifiedName, DefaultWorkingCopyOwner.PRIMARY, progressMonitor);
	}

	/*
	 * Internal findType with instanciated name lookup
	 */
	IType findType(String fullyQualifiedName, NameLookup lookup, boolean considerSecondaryTypes, IProgressMonitor progressMonitor) throws JavaModelException {
		NameLookup.Answer answer = lookup.findType(
			fullyQualifiedName,
			false,
			NameLookup.ACCEPT_ALL,
			considerSecondaryTypes,
			true, /* wait for indexes (only if consider secondary types)*/
			false/*don't check restrictions*/,
			progressMonitor);
		if (answer == null) {
			// try to find enclosing type
			int lastDot = fullyQualifiedName.lastIndexOf('.');
			if (lastDot == -1) return null;
			IType type = findType(fullyQualifiedName.substring(0, lastDot), lookup, considerSecondaryTypes, progressMonitor);
			if (type != null) {
				type = type.getType(fullyQualifiedName.substring(lastDot+1));
				if (!type.exists()) {
					return null;
				}
			}
			return type;
		}
		return answer.type;
	}
	/**
	 * @see IJavaProject#findType(String, String)
	 */
	public IType findType(String packageName, String typeQualifiedName) throws JavaModelException {
		return findType(packageName, typeQualifiedName, DefaultWorkingCopyOwner.PRIMARY);
	}
	/**
	 * @see IJavaProject#findType(String, String, IProgressMonitor)
	 */
	public IType findType(String packageName, String typeQualifiedName, IProgressMonitor progressMonitor) throws JavaModelException {
		return findType(packageName, typeQualifiedName, DefaultWorkingCopyOwner.PRIMARY, progressMonitor);
	}
	/*
	 * Internal findType with instanciated name lookup
	 */
	IType findType(String packageName, String typeQualifiedName, NameLookup lookup, boolean considerSecondaryTypes, IProgressMonitor progressMonitor) throws JavaModelException {
		NameLookup.Answer answer = lookup.findType(
			typeQualifiedName,
			packageName,
			false,
			NameLookup.ACCEPT_ALL,
			considerSecondaryTypes,
			true, // wait for indexes (in case we need to consider secondary types)
			false/*don't check restrictions*/,
			progressMonitor);
		return answer == null ? null : answer.type;
	}
	/**
	 * @see IJavaProject#findType(String, String, WorkingCopyOwner)
	 */
	public IType findType(String packageName, String typeQualifiedName, WorkingCopyOwner owner) throws JavaModelException {
		NameLookup lookup = newNameLookup(owner);
		return findType(
			packageName,
			typeQualifiedName,
			lookup,
			false, // do not consider secondary types
			null);
	}

	/**
	 * @see IJavaProject#findType(String, String, WorkingCopyOwner, IProgressMonitor)
	 */
	public IType findType(String packageName, String typeQualifiedName, WorkingCopyOwner owner, IProgressMonitor progressMonitor) throws JavaModelException {
		NameLookup lookup = newNameLookup(owner);
		return findType(
			packageName,
			typeQualifiedName,
			lookup,
			true, // consider secondary types
			progressMonitor);
	}

	/**
	 * @see IJavaProject#findType(String, WorkingCopyOwner)
	 */
	public IType findType(String fullyQualifiedName, WorkingCopyOwner owner) throws JavaModelException {
		NameLookup lookup = newNameLookup(owner);
		return findType(fullyQualifiedName, lookup, false, null);
	}

	/**
	 * @see IJavaProject#findType(String, WorkingCopyOwner, IProgressMonitor)
	 */
	public IType findType(String fullyQualifiedName, WorkingCopyOwner owner, IProgressMonitor progressMonitor) throws JavaModelException {
		NameLookup lookup = newNameLookup(owner);
		return findType(fullyQualifiedName, lookup, true, progressMonitor);
	}

	/**
	 * Remove all markers denoting classpath problems
	 */ //TODO (philippe) should improve to use a bitmask instead of booleans (CYCLE, FORMAT, VALID)
	protected void flushClasspathProblemMarkers(boolean flushCycleMarkers, boolean flushClasspathFormatMarkers, boolean flushOverlappingOutputMarkers) {
		try {
			if (this.project.isAccessible()) {
				IMarker[] markers = this.project.findMarkers(IJavaModelMarker.BUILDPATH_PROBLEM_MARKER, false, IResource.DEPTH_ZERO);
				for (int i = 0, length = markers.length; i < length; i++) {
					IMarker marker = markers[i];
					if (flushCycleMarkers && flushClasspathFormatMarkers && flushOverlappingOutputMarkers) {
						marker.delete();
					} else {
						String cycleAttr = (String)marker.getAttribute(IJavaModelMarker.CYCLE_DETECTED);
						String classpathFileFormatAttr =  (String)marker.getAttribute(IJavaModelMarker.CLASSPATH_FILE_FORMAT);
						String overlappingOutputAttr = (String) marker.getAttribute(IJavaModelMarker.OUTPUT_OVERLAPPING_SOURCE);
						if ((flushCycleMarkers == (cycleAttr != null && cycleAttr.equals("true"))) //$NON-NLS-1$
							&& (flushOverlappingOutputMarkers == (overlappingOutputAttr != null && overlappingOutputAttr.equals("true"))) //$NON-NLS-1$
							&& (flushClasspathFormatMarkers == (classpathFileFormatAttr != null && classpathFileFormatAttr.equals("true")))){ //$NON-NLS-1$
							marker.delete();
						}
					}
				}
			}
		} catch (CoreException e) {
			// could not flush markers: not much we can do
			if (JavaModelManager.VERBOSE) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * Returns the set of patterns corresponding to this project visibility given rules
	 * @return an array of IPath or null if none
	 */
	public IPath[] getAccessRestrictions(String optionName) {
		String sequence = getOption(optionName, true); // inherit from workspace
		if (sequence == null || sequence.length() == 0) return null;
		IPath[] rules = null;
		char[][] patterns = CharOperation.splitOn('|', sequence.toCharArray());
		int patternCount;
		if ((patternCount  = patterns.length) > 0) {
			rules = new IPath[patternCount];
			for (int j = 0; j < patterns.length; j++){
				rules[j] = new Path(new String(patterns[j]));
			}
		}
		return rules;
	}

	/**
	 * @see IJavaProject
	 */
	public IPackageFragmentRoot[] getAllPackageFragmentRoots()
		throws JavaModelException {

		return getAllPackageFragmentRoots(null /*no reverse map*/);
	}

	public IPackageFragmentRoot[] getAllPackageFragmentRoots(Map rootToResolvedEntries) throws JavaModelException {

		return computePackageFragmentRoots(getResolvedClasspath(), true/*retrieveExportedRoots*/, rootToResolvedEntries);
	}

	/**
	 * Returns the classpath entry that refers to the given path
	 * or <code>null</code> if there is no reference to the path.
	 * @param path IPath
	 * @return IClasspathEntry
	 * @throws JavaModelException
	 */
	public IClasspathEntry getClasspathEntryFor(IPath path) throws JavaModelException {
		getResolvedClasspath(); // force resolution
		PerProjectInfo perProjectInfo = getPerProjectInfo();
		if (perProjectInfo == null)
			return null;
		Map rootPathToResolvedEntries = perProjectInfo.rootPathToResolvedEntries;
		if (rootPathToResolvedEntries == null)
			return null;
		IClasspathEntry classpathEntry = (IClasspathEntry) rootPathToResolvedEntries.get(path);
		if (classpathEntry == null) {
			path = getProject().getWorkspace().getRoot().getLocation().append(path);
			classpathEntry = (IClasspathEntry) rootPathToResolvedEntries.get(path);
		}
		return classpathEntry;
	}

	/*
	 * Returns the cycle marker associated with this project or null if none.
	 */
	public IMarker getCycleMarker(){
		try {
			if (this.project.isAccessible()) {
				IMarker[] markers = this.project.findMarkers(IJavaModelMarker.BUILDPATH_PROBLEM_MARKER, false, IResource.DEPTH_ZERO);
				for (int i = 0, length = markers.length; i < length; i++) {
					IMarker marker = markers[i];
					String cycleAttr = (String)marker.getAttribute(IJavaModelMarker.CYCLE_DETECTED);
					if (cycleAttr != null && cycleAttr.equals("true")){ //$NON-NLS-1$
						return marker;
					}
				}
			}
		} catch (CoreException e) {
			// could not get markers: return null
		}
		return null;
	}

	/**
	 * Returns the project custom preference pool.
	 * Project preferences may include custom encoding.
	 * @return IEclipsePreferences or <code>null</code> if the project
	 * 	does not have a java nature.
	 */
	public IEclipsePreferences getEclipsePreferences() {
		if (!JavaProject.hasJavaNature(this.project)) return null;
		// Get cached preferences if exist
		JavaModelManager.PerProjectInfo perProjectInfo = JavaModelManager.getJavaModelManager().getPerProjectInfo(this.project, true);
		if (perProjectInfo.preferences != null) return perProjectInfo.preferences;
		// Init project preferences
		IScopeContext context = new ProjectScope(getProject());
		final IEclipsePreferences eclipsePreferences = context.getNode(JavaCore.PLUGIN_ID);
		updatePreferences(eclipsePreferences);
		perProjectInfo.preferences = eclipsePreferences;

		// Listen to new preferences node
		final IEclipsePreferences eclipseParentPreferences = (IEclipsePreferences) eclipsePreferences.parent();
		if (eclipseParentPreferences != null) {
			if (this.preferencesNodeListener != null) {
				eclipseParentPreferences.removeNodeChangeListener(this.preferencesNodeListener);
			}
			this.preferencesNodeListener = new IEclipsePreferences.INodeChangeListener() {
				public void added(IEclipsePreferences.NodeChangeEvent event) {
					// do nothing
				}
				public void removed(IEclipsePreferences.NodeChangeEvent event) {
					if (event.getChild() == eclipsePreferences) {
						JavaModelManager.getJavaModelManager().resetProjectPreferences(JavaProject.this);
					}
				}
			};
			eclipseParentPreferences.addNodeChangeListener(this.preferencesNodeListener);
		}

		// Listen to preferences changes
		if (this.preferencesChangeListener != null) {
			eclipsePreferences.removePreferenceChangeListener(this.preferencesChangeListener);
		}
		this.preferencesChangeListener = new IEclipsePreferences.IPreferenceChangeListener() {
			public void preferenceChange(IEclipsePreferences.PreferenceChangeEvent event) {
				String propertyName = event.getKey();
				JavaModelManager manager = JavaModelManager.getJavaModelManager();
				if (propertyName.startsWith(JavaCore.PLUGIN_ID)) {
					if (propertyName.equals(JavaCore.CORE_JAVA_BUILD_CLEAN_OUTPUT_FOLDER) ||
						propertyName.equals(JavaCore.CORE_JAVA_BUILD_RESOURCE_COPY_FILTER) ||
						propertyName.equals(JavaCore.CORE_JAVA_BUILD_DUPLICATE_RESOURCE) ||
						propertyName.equals(JavaCore.CORE_JAVA_BUILD_RECREATE_MODIFIED_CLASS_FILES_IN_OUTPUT_FOLDER) ||
						propertyName.equals(JavaCore.CORE_JAVA_BUILD_INVALID_CLASSPATH) ||
						propertyName.equals(JavaCore.CORE_ENABLE_CLASSPATH_EXCLUSION_PATTERNS) ||
						propertyName.equals(JavaCore.CORE_ENABLE_CLASSPATH_MULTIPLE_OUTPUT_LOCATIONS) ||
						propertyName.equals(JavaCore.CORE_INCOMPLETE_CLASSPATH) ||
						propertyName.equals(JavaCore.CORE_CIRCULAR_CLASSPATH) ||
						propertyName.equals(JavaCore.CORE_OUTPUT_LOCATION_OVERLAPPING_ANOTHER_SOURCE) ||
						propertyName.equals(JavaCore.CORE_INCOMPATIBLE_JDK_LEVEL) ||
						propertyName.equals(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM))
					{
						manager.deltaState.addClasspathValidation(JavaProject.this);
					}
					manager.resetProjectOptions(JavaProject.this);
					JavaProject.this.resetCaches(); // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=233568
				}
			}
		};
		eclipsePreferences.addPreferenceChangeListener(this.preferencesChangeListener);
		return eclipsePreferences;
	}

	public String getElementName() {
		return this.project.getName();
	}

	/**
	 * @see IJavaElement
	 */
	public int getElementType() {
		return JAVA_PROJECT;
	}

	/**
	 * This is a helper method returning the expanded classpath for the project, as a list of classpath entries,
	 * where all classpath variable entries have been resolved and substituted with their final target entries.
	 * All project exports have been appended to project entries.
	 * @return IClasspathEntry[]
	 * @throws JavaModelException
	 */
	public IClasspathEntry[] getExpandedClasspath()	throws JavaModelException {

			ObjectVector accumulatedEntries = new ObjectVector();
			computeExpandedClasspath(null, new HashSet(5), accumulatedEntries);

			IClasspathEntry[] expandedPath = new IClasspathEntry[accumulatedEntries.size()];
			accumulatedEntries.copyInto(expandedPath);

			return expandedPath;
	}

	/**
	 * The path is known to match a source/library folder entry.
	 * @param path IPath
	 * @return IPackageFragmentRoot
	 */
	public IPackageFragmentRoot getFolderPackageFragmentRoot(IPath path) {
		if (path.segmentCount() == 1) { // default project root
			return getPackageFragmentRoot(this.project);
		}
		return getPackageFragmentRoot(this.project.getWorkspace().getRoot().getFolder(path));
	}

	/*
	 * @see JavaElement
	 */
	public IJavaElement getHandleFromMemento(String token, MementoTokenizer memento, WorkingCopyOwner owner) {
		switch (token.charAt(0)) {
			case JEM_PACKAGEFRAGMENTROOT:
				String rootPath = IPackageFragmentRoot.DEFAULT_PACKAGEROOT_PATH;
				token = null;
				while (memento.hasMoreTokens()) {
					token = memento.nextToken();
					// https://bugs.eclipse.org/bugs/show_bug.cgi?id=331821
					if (token == MementoTokenizer.PACKAGEFRAGMENT || token == MementoTokenizer.COUNT) {
						break;
					}
					rootPath += token;
				}
				JavaElement root = (JavaElement)getPackageFragmentRoot(new Path(rootPath));
				if (token != null && token.charAt(0) == JEM_PACKAGEFRAGMENT) {
					return root.getHandleFromMemento(token, memento, owner);
				} else {
					return root.getHandleFromMemento(memento, owner);
				}
		}
		return null;
	}

	/**
	 * Returns the <code>char</code> that marks the start of this handles
	 * contribution to a memento.
	 */
	protected char getHandleMementoDelimiter() {

		return JEM_JAVAPROJECT;
	}

	/**
	 * Find the specific Java command amongst the given build spec
	 * and return its index or -1 if not found.
	 */
	private int getJavaCommandIndex(ICommand[] buildSpec) {

		for (int i = 0; i < buildSpec.length; ++i) {
			if (buildSpec[i].getBuilderName().equals(JavaCore.BUILDER_ID)) {
				return i;
			}
		}
		return -1;
	}

	/**
	 * Convenience method that returns the specific type of info for a Java project.
	 */
	protected JavaProjectElementInfo getJavaProjectElementInfo()
		throws JavaModelException {

		return (JavaProjectElementInfo) getElementInfo();
	}

	/**
	 * Returns an array of non-java resources contained in the receiver.
	 */
	public Object[] getNonJavaResources() throws JavaModelException {

		return ((JavaProjectElementInfo) getElementInfo()).getNonJavaResources(this);
	}

	/**
	 * @see org.eclipse.jdt.core.IJavaProject#getOption(String, boolean)
	 */
	public String getOption(String optionName, boolean inheritJavaCoreOptions) {
		return JavaModelManager.getJavaModelManager().getOption(optionName, inheritJavaCoreOptions, getEclipsePreferences());
	}

	/**
	 * @see org.eclipse.jdt.core.IJavaProject#getOptions(boolean)
	 */
	public Map getOptions(boolean inheritJavaCoreOptions) {

		// initialize to the defaults from JavaCore options pool
		Map options = inheritJavaCoreOptions ? JavaCore.getOptions() : new Hashtable(5);

		// Get project specific options
		JavaModelManager.PerProjectInfo perProjectInfo = null;
		Hashtable projectOptions = null;
		JavaModelManager javaModelManager = JavaModelManager.getJavaModelManager();
		HashSet optionNames = javaModelManager.optionNames;
		try {
			perProjectInfo = getPerProjectInfo();
			projectOptions = perProjectInfo.options;
			if (projectOptions == null) {
				// get eclipse preferences
				IEclipsePreferences projectPreferences= getEclipsePreferences();
				if (projectPreferences == null) return options; // cannot do better (non-Java project)
				// create project options
				String[] propertyNames = projectPreferences.keys();
				projectOptions = new Hashtable(propertyNames.length);
				for (int i = 0; i < propertyNames.length; i++){
					String propertyName = propertyNames[i];
					String value = projectPreferences.get(propertyName, null);
					if (value != null) {
						value = value.trim();
						// Keep the option value, even if it's deprecated
						// see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=324987
						projectOptions.put(propertyName, value);
						if (!optionNames.contains(propertyName)) {
							// try to migrate deprecated options
							String[] compatibleOptions = (String[]) javaModelManager.deprecatedOptions.get(propertyName);
							if (compatibleOptions != null) {
								for (int co=0, length=compatibleOptions.length; co < length; co++) {
									String compatibleOption = compatibleOptions[co];
									if (!projectOptions.containsKey(compatibleOption))
										projectOptions.put(compatibleOption, value);
								}
							}
						}
					}
				}
				// cache project options
				perProjectInfo.options = projectOptions;
			}
		} catch (JavaModelException jme) {
			projectOptions = new Hashtable();
		} catch (BackingStoreException e) {
			projectOptions = new Hashtable();
		}

		// Inherit from JavaCore options if specified
		if (inheritJavaCoreOptions) {
			Iterator propertyNames = projectOptions.entrySet().iterator();
			while (propertyNames.hasNext()) {
				Map.Entry entry = (Map.Entry) propertyNames.next();
				String propertyName = (String) entry.getKey();
				String propertyValue = (String) entry.getValue();
				if (propertyValue != null && javaModelManager.knowsOption(propertyName)){
					options.put(propertyName, propertyValue.trim());
				}
			}
			Util.fixTaskTags(options);
			return options;
		}
		Util.fixTaskTags(projectOptions);
		return projectOptions;
	}

	/**
	 * @see IJavaProject
	 */
	public IPath getOutputLocation() throws JavaModelException {
		// Do not create marker while getting output location
		JavaModelManager.PerProjectInfo perProjectInfo = getPerProjectInfo();
		IPath outputLocation = perProjectInfo.outputLocation;
		if (outputLocation != null) return outputLocation;

		// force to read classpath - will position output location as well
		getRawClasspath();

		outputLocation = perProjectInfo.outputLocation;
		if (outputLocation == null) {
			return defaultOutputLocation();
		}
		return outputLocation;
	}

	/**
	 * @param path IPath
	 * @return A handle to the package fragment root identified by the given path.
	 * This method is handle-only and the element may or may not exist. Returns
	 * <code>null</code> if unable to generate a handle from the path (for example,
	 * an absolute path that has less than 1 segment. The path may be relative or
	 * absolute.
	 */
	public IPackageFragmentRoot getPackageFragmentRoot(IPath path) {
		if (!path.isAbsolute()) {
			path = getPath().append(path);
		}
		int segmentCount = path.segmentCount();
		if (segmentCount == 0) {
			return null;
		}
		if (path.getDevice() != null || JavaModel.getExternalTarget(path, true/*check existence*/) != null) {
			// external path
			return getPackageFragmentRoot0(path);
		}
		IWorkspaceRoot workspaceRoot = this.project.getWorkspace().getRoot();
		IResource resource = workspaceRoot.findMember(path);
		if (resource == null) {
			// resource doesn't exist in workspace
			if (path.getFileExtension() != null) {
				if (!workspaceRoot.getProject(path.segment(0)).exists()) {
					// assume it is an external ZIP archive
					return getPackageFragmentRoot0(path);
				} else {
					// assume it is an internal ZIP archive
					resource = workspaceRoot.getFile(path);
				}
			} else if (segmentCount == 1) {
				// assume it is a project
				String projectName = path.segment(0);
				if (getElementName().equals(projectName)) { // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=75814
					// default root
					resource = this.project;
				} else {
					// lib being another project
					resource = workspaceRoot.getProject(projectName);
				}
			} else {
				// assume it is an internal folder
				resource = workspaceRoot.getFolder(path);
			}
		}
		return getPackageFragmentRoot(resource);
	}

	/**
	 * @see IJavaProject
	 */
	public IPackageFragmentRoot getPackageFragmentRoot(IResource resource) {
		return getPackageFragmentRoot(resource, null/*no entry path*/);
	}

	private IPackageFragmentRoot getPackageFragmentRoot(IResource resource, IPath entryPath) {
		switch (resource.getType()) {
			case IResource.FILE:
				return new JarPackageFragmentRoot(resource, this);
			case IResource.FOLDER:
				if (ExternalFoldersManager.isInternalPathForExternalFolder(resource.getFullPath()))
					return new ExternalPackageFragmentRoot(resource, entryPath, this);
				return new PackageFragmentRoot(resource, this);
			case IResource.PROJECT:
				return new PackageFragmentRoot(resource, this);
			default:
				return null;
		}
	}

	/**
	 * @see IJavaProject
	 */
	public IPackageFragmentRoot getPackageFragmentRoot(String externalLibraryPath) {
		return getPackageFragmentRoot0(JavaProject.canonicalizedPath(new Path(externalLibraryPath)));
	}

	/*
	 * no path canonicalization
	 */
	public IPackageFragmentRoot getPackageFragmentRoot0(IPath externalLibraryPath) {
		IFolder linkedFolder = JavaModelManager.getExternalManager().getFolder(externalLibraryPath);
		if (linkedFolder != null)
			return new ExternalPackageFragmentRoot(linkedFolder, externalLibraryPath, this);
		return new JarPackageFragmentRoot(externalLibraryPath, this);
	}

	/**
	 * @see IJavaProject
	 */
	public IPackageFragmentRoot[] getPackageFragmentRoots()
		throws JavaModelException {

		Object[] children;
		int length;
		IPackageFragmentRoot[] roots;

		System.arraycopy(
			children = getChildren(),
			0,
			roots = new IPackageFragmentRoot[length = children.length],
			0,
			length);

		return roots;
	}

	/**
	 * @see IJavaProject
	 * @deprecated
	 */
	public IPackageFragmentRoot[] getPackageFragmentRoots(IClasspathEntry entry) {
		return findPackageFragmentRoots(entry);
	}

	/**
	 * @see IJavaProject
	 */
	public IPackageFragment[] getPackageFragments() throws JavaModelException {

		IPackageFragmentRoot[] roots = getPackageFragmentRoots();
		return getPackageFragmentsInRoots(roots);
	}

	/**
	 * Returns all the package fragments found in the specified
	 * package fragment roots.
	 * @param roots IPackageFragmentRoot[]
	 * @return IPackageFragment[]
	 */
	public IPackageFragment[] getPackageFragmentsInRoots(IPackageFragmentRoot[] roots) {

		ArrayList frags = new ArrayList();
		for (int i = 0; i < roots.length; i++) {
			IPackageFragmentRoot root = roots[i];
			try {
				IJavaElement[] rootFragments = root.getChildren();
				for (int j = 0; j < rootFragments.length; j++) {
					frags.add(rootFragments[j]);
				}
			} catch (JavaModelException e) {
				// do nothing
			}
		}
		IPackageFragment[] fragments = new IPackageFragment[frags.size()];
		frags.toArray(fragments);
		return fragments;
	}

	/**
	 * @see IJavaElement
	 */
	public IPath getPath() {
		return this.project.getFullPath();
	}

	public JavaModelManager.PerProjectInfo getPerProjectInfo() throws JavaModelException {
		return JavaModelManager.getJavaModelManager().getPerProjectInfoCheckExistence(this.project);
	}

	private IPath getPluginWorkingLocation() {
		return this.project.getWorkingLocation(JavaCore.PLUGIN_ID);
	}

	/**
	 * @see IJavaProject#getProject()
	 */
	public IProject getProject() {
		return this.project;
	}

	public ProjectCache getProjectCache() throws JavaModelException {
		return ((JavaProjectElementInfo) getElementInfo()).getProjectCache(this);
	}

	/**
	 * @see IJavaProject
	 */
	public IClasspathEntry[] getRawClasspath() throws JavaModelException {
		JavaModelManager.PerProjectInfo perProjectInfo = getPerProjectInfo();
		IClasspathEntry[] classpath = perProjectInfo.rawClasspath;
		if (classpath != null) return classpath;

		classpath = perProjectInfo.readAndCacheClasspath(this)[0];

		if (classpath == JavaProject.INVALID_CLASSPATH)
			return defaultClasspath();

		return classpath;
	}

	/**
	 * @see IJavaProject
	 */
	public IClasspathEntry[] getReferencedClasspathEntries() throws JavaModelException {
		return getPerProjectInfo().referencedEntries;
	}
	
	/**
	 * @see IJavaProject#getRequiredProjectNames()
	 */
	public String[] getRequiredProjectNames() throws JavaModelException {

		return projectPrerequisites(getResolvedClasspath());
	}

	public IClasspathEntry[] getResolvedClasspath() throws JavaModelException {
		PerProjectInfo perProjectInfo = getPerProjectInfo();
		IClasspathEntry[] resolvedClasspath = perProjectInfo.getResolvedClasspath();
		if (resolvedClasspath == null) {
			resolveClasspath(perProjectInfo, false/*don't use previous session values*/, true/*add classpath change*/);
			resolvedClasspath = perProjectInfo.getResolvedClasspath();
			if (resolvedClasspath == null) {
				// another thread reset the resolved classpath, use a temporary PerProjectInfo
				PerProjectInfo temporaryInfo = newTemporaryInfo();
				resolveClasspath(temporaryInfo, false/*don't use previous session values*/, true/*add classpath change*/);
				resolvedClasspath = temporaryInfo.getResolvedClasspath();
			}
		}
		return resolvedClasspath;
	}

	/**
	 * @see IJavaProject
	 */
	public IClasspathEntry[] getResolvedClasspath(boolean ignoreUnresolvedEntry) throws JavaModelException {
		if  (JavaModelManager.getJavaModelManager().isClasspathBeingResolved(this)) {
			if (JavaModelManager.CP_RESOLVE_VERBOSE_ADVANCED)
				verbose_reentering_classpath_resolution();
		    return RESOLUTION_IN_PROGRESS;
		}
		PerProjectInfo perProjectInfo = getPerProjectInfo();

		// use synchronized block to ensure consistency
		IClasspathEntry[] resolvedClasspath;
		IJavaModelStatus unresolvedEntryStatus;
		synchronized (perProjectInfo) {
			resolvedClasspath = perProjectInfo.getResolvedClasspath();
			unresolvedEntryStatus = perProjectInfo.unresolvedEntryStatus;
		}

		if (resolvedClasspath == null
				|| (unresolvedEntryStatus != null && !unresolvedEntryStatus.isOK())) { // force resolution to ensure initializers are run again
			resolveClasspath(perProjectInfo, false/*don't use previous session values*/, true/*add classpath change*/);
			synchronized (perProjectInfo) {
				resolvedClasspath = perProjectInfo.getResolvedClasspath();
				unresolvedEntryStatus = perProjectInfo.unresolvedEntryStatus;
			}
			if (resolvedClasspath == null) {
				// another thread reset the resolved classpath, use a temporary PerProjectInfo
				PerProjectInfo temporaryInfo = newTemporaryInfo();
				resolveClasspath(temporaryInfo, false/*don't use previous session values*/, true/*add classpath change*/);
				resolvedClasspath = temporaryInfo.getResolvedClasspath();
				unresolvedEntryStatus = temporaryInfo.unresolvedEntryStatus;
			}
		}
		if (!ignoreUnresolvedEntry && unresolvedEntryStatus != null && !unresolvedEntryStatus.isOK())
			throw new JavaModelException(unresolvedEntryStatus);
		return resolvedClasspath;
	}

	private void verbose_reentering_classpath_resolution() {
		Util.verbose(
			"CPResolution: reentering raw classpath resolution, will use empty classpath instead" + //$NON-NLS-1$
			"	project: " + getElementName() + '\n' + //$NON-NLS-1$
			"	invocation stack trace:"); //$NON-NLS-1$
		new Exception("<Fake exception>").printStackTrace(System.out); //$NON-NLS-1$
	}

	/**
	 * @see IJavaElement
	 */
	public IResource resource(PackageFragmentRoot root) {
		return this.project;
	}

	/**
	 * Retrieve a shared property on a project. If the property is not defined, answers null.
	 * Note that it is orthogonal to IResource persistent properties, and client code has to decide
	 * which form of storage to use appropriately. Shared properties produce real resource files which
	 * can be shared through a VCM onto a server. Persistent properties are not shareable.
	 *
	 * @param key String
	 * @see JavaProject#setSharedProperty(String, String)
	 * @return String
	 * @throws CoreException
	 */
	public String getSharedProperty(String key) throws CoreException {

		String property = null;
		IFile rscFile = this.project.getFile(key);
		if (rscFile.exists()) {
			byte[] bytes = Util.getResourceContentsAsByteArray(rscFile);
			try {
				property = new String(bytes, org.eclipse.jdt.internal.compiler.util.Util.UTF_8); // .classpath always encoded with UTF-8
			} catch (UnsupportedEncodingException e) {
				Util.log(e, "Could not read .classpath with UTF-8 encoding"); //$NON-NLS-1$
				// fallback to default
				property = new String(bytes);
			}
		} else {
			// when a project is imported, we get a first delta for the addition of the .project, but the .classpath is not accessible
			// so default to using java.io.File
			// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=96258
			URI location = rscFile.getLocationURI();
			if (location != null) {
				File file = Util.toLocalFile(location, null/*no progress monitor available*/);
				if (file != null && file.exists()) {
					byte[] bytes;
					try {
						bytes = org.eclipse.jdt.internal.compiler.util.Util.getFileByteContent(file);
					} catch (IOException e) {
						return null;
					}
					try {
						property = new String(bytes, org.eclipse.jdt.internal.compiler.util.Util.UTF_8); // .classpath always encoded with UTF-8
					} catch (UnsupportedEncodingException e) {
						Util.log(e, "Could not read .classpath with UTF-8 encoding"); //$NON-NLS-1$
						// fallback to default
						property = new String(bytes);
					}
				}
			}
		}
		return property;
	}

	/**
	 * @see JavaElement
	 */
	public SourceMapper getSourceMapper() {

		return null;
	}

	/**
	 * @see IJavaElement
	 */
	public IResource getUnderlyingResource() throws JavaModelException {
		if (!exists()) throw newNotPresentException();
		return this.project;
	}

	/**
	 * @see IJavaProject
	 */
	public boolean hasBuildState() {

		return JavaModelManager.getJavaModelManager().getLastBuiltState(this.project, null) != null;
	}

	/**
	 * @see IJavaProject
	 */
	public boolean hasClasspathCycle(IClasspathEntry[] preferredClasspath) {
		LinkedHashSet cycleParticipants = new LinkedHashSet();
		HashMap preferredClasspaths = new HashMap(1);
		preferredClasspaths.put(this, preferredClasspath);
		updateCycleParticipants(new ArrayList(2), cycleParticipants, ResourcesPlugin.getWorkspace().getRoot(), new HashSet(2), preferredClasspaths);
		return !cycleParticipants.isEmpty();
	}

	public boolean hasCycleMarker(){
		return getCycleMarker() != null;
	}

	public int hashCode() {
		return this.project.hashCode();
	}
	
	private boolean hasUTF8BOM(byte[] bytes) {
		if (bytes.length > IContentDescription.BOM_UTF_8.length) {
			for (int i = 0, length = IContentDescription.BOM_UTF_8.length; i < length; i++) {
				if (IContentDescription.BOM_UTF_8[i] != bytes[i])
					return false;
			}
			return true;
		}
		return false;
	}

	/**
	 * Answers true if the project potentially contains any source. A project which has no source is immutable.
	 * @return boolean
	 */
	public boolean hasSource() {

		// look if any source folder on the classpath
		// no need for resolved path given source folder cannot be abstracted
		IClasspathEntry[] entries;
		try {
			entries = getRawClasspath();
		} catch (JavaModelException e) {
			return true; // unsure
		}
		for (int i = 0, max = entries.length; i < max; i++) {
			if (entries[i].getEntryKind() == IClasspathEntry.CPE_SOURCE) {
				return true;
			}
		}
		return false;
	}



	/*
	 * @see IJavaProject
	 */
	public boolean isOnClasspath(IJavaElement element) {
		IClasspathEntry[] rawClasspath;
		try {
			rawClasspath = getRawClasspath();
		} catch(JavaModelException e){
			return false; // not a Java project
		}
		int elementType = element.getElementType();
		boolean isPackageFragmentRoot = false;
		boolean isFolderPath = false;
		boolean isSource = false;
		switch (elementType) {
			case IJavaElement.JAVA_MODEL:
				return false;
			case IJavaElement.JAVA_PROJECT:
				break;
			case IJavaElement.PACKAGE_FRAGMENT_ROOT:
				isPackageFragmentRoot = true;
				break;
			case IJavaElement.PACKAGE_FRAGMENT:
				isFolderPath = !((IPackageFragmentRoot)element.getParent()).isArchive();
				break;
			case IJavaElement.COMPILATION_UNIT:
				isSource = true;
				break;
			default:
				isSource = element.getAncestor(IJavaElement.COMPILATION_UNIT) != null;
				break;
		}
		IPath elementPath = element.getPath();

		// first look at unresolved entries
		int length = rawClasspath.length;
		for (int i = 0; i < length; i++) {
			IClasspathEntry entry = rawClasspath[i];
			switch (entry.getEntryKind()) {
				case IClasspathEntry.CPE_LIBRARY:
				case IClasspathEntry.CPE_PROJECT:
				case IClasspathEntry.CPE_SOURCE:
					if (isOnClasspathEntry(elementPath, isFolderPath, isPackageFragmentRoot, entry))
						return true;
					break;
			}
		}

		// no need to go further for compilation units and elements inside a compilation unit
		// it can only be in a source folder, thus on the raw classpath
		if (isSource)
			return false;

		// https://bugs.eclipse.org/bugs/show_bug.cgi?id=304081
		// All the resolved classpath entries need to be considered, including the referenced classpath entries
		IClasspathEntry[] resolvedClasspath = null;
		try {
			resolvedClasspath = getResolvedClasspath();
		} catch (JavaModelException e) {
			return false; // Perhaps, not a Java project
		}

		for (int index = 0; index < resolvedClasspath.length; index++) {
			if (isOnClasspathEntry(elementPath, isFolderPath, isPackageFragmentRoot, resolvedClasspath[index]))
				return true;
		}
		
		return false;
	}

	/*
	 * @see IJavaProject
	 */
	public boolean isOnClasspath(IResource resource) {
		IPath exactPath = resource.getFullPath();
		IPath path = exactPath;

		// ensure that folders are only excluded if all of their children are excluded
		int resourceType = resource.getType();
		boolean isFolderPath = resourceType == IResource.FOLDER || resourceType == IResource.PROJECT;

		IClasspathEntry[] classpath;
		try {
			classpath = this.getResolvedClasspath();
		} catch(JavaModelException e){
			return false; // not a Java project
		}
		for (int i = 0; i < classpath.length; i++) {
			IClasspathEntry entry = classpath[i];
			IPath entryPath = entry.getPath();
			if (entryPath.equals(exactPath)) { // package fragment roots must match exactly entry pathes (no exclusion there)
				return true;
			}
			// https://bugs.eclipse.org/bugs/show_bug.cgi?id=276373
			// When a classpath entry is absolute, convert the resource's relative path to a file system path and compare
			// e.g - /P/lib/variableLib.jar and /home/P/lib/variableLib.jar when compared should return true
			if (entryPath.isAbsolute()
					&& entryPath.equals(ResourcesPlugin.getWorkspace().getRoot().getLocation().append(exactPath))) {
				return true;
			}
			if (entryPath.isPrefixOf(path)
					&& !Util.isExcluded(path, ((ClasspathEntry)entry).fullInclusionPatternChars(), ((ClasspathEntry)entry).fullExclusionPatternChars(), isFolderPath)) {
				return true;
			}
		}
		return false;
	}

	private boolean isOnClasspathEntry(IPath elementPath, boolean isFolderPath, boolean isPackageFragmentRoot, IClasspathEntry entry) {
		IPath entryPath = entry.getPath();
		if (isPackageFragmentRoot) {
			// package fragment roots must match exactly entry pathes (no exclusion there)
			if (entryPath.equals(elementPath))
				return true;
		} else {
			if (entryPath.isPrefixOf(elementPath)
					&& !Util.isExcluded(elementPath, ((ClasspathEntry)entry).fullInclusionPatternChars(), ((ClasspathEntry)entry).fullExclusionPatternChars(), isFolderPath))
				return true;
		}
		// https://bugs.eclipse.org/bugs/show_bug.cgi?id=276373
		if (entryPath.isAbsolute()
				&& entryPath.equals(ResourcesPlugin.getWorkspace().getRoot().getLocation().append(elementPath))) {
			return true;
		}
		return false;
	}

	/**
	 * load preferences from a shareable format (VCM-wise)
	 */
	 private IEclipsePreferences loadPreferences() {

	 	IEclipsePreferences preferences = null;
	 	IPath projectMetaLocation = getPluginWorkingLocation();
		if (projectMetaLocation != null) {
			File prefFile = projectMetaLocation.append(PREF_FILENAME).toFile();
			if (prefFile.exists()) { // load preferences from file
				InputStream in = null;
				try {
					in = new BufferedInputStream(new FileInputStream(prefFile));
					preferences = Platform.getPreferencesService().readPreferences(in);
				} catch (CoreException e) { // problems loading preference store - quietly ignore
				} catch (IOException e) { // problems loading preference store - quietly ignore
				} finally {
					if (in != null) {
						try {
							in.close();
						} catch (IOException e) { // ignore problems with close
						}
					}
				}
				// one shot read, delete old preferences
				prefFile.delete();
				return preferences;
			}
		}
		return null;
	 }

	/**
	 * @see IJavaProject#newEvaluationContext()
	 */
	public IEvaluationContext newEvaluationContext() {
		EvaluationContext context = new EvaluationContext();
		context.setLineSeparator(Util.getLineSeparator(null/*no existing source*/, this));
		return new EvaluationContextWrapper(context, this);
	}

	/*
	 * Returns a new name lookup. This name lookup first looks in the given working copies.
	 */
	public NameLookup newNameLookup(ICompilationUnit[] workingCopies) throws JavaModelException {
		return getJavaProjectElementInfo().newNameLookup(this, workingCopies);
	}

	/*
	 * Returns a new name lookup. This name lookup first looks in the working copies of the given owner.
	 */
	public NameLookup newNameLookup(WorkingCopyOwner owner) throws JavaModelException {

		JavaModelManager manager = JavaModelManager.getJavaModelManager();
		ICompilationUnit[] workingCopies = owner == null ? null : manager.getWorkingCopies(owner, true/*add primary WCs*/);
		return newNameLookup(workingCopies);
	}

	/*
	 * Returns a new search name environment for this project. This name environment first looks in the given working copies.
	 */
	public SearchableEnvironment newSearchableNameEnvironment(ICompilationUnit[] workingCopies) throws JavaModelException {
		return new SearchableEnvironment(this, workingCopies);
	}

	/*
	 * Returns a new search name environment for this project. This name environment first looks in the working copies
	 * of the given owner.
	 */
	public SearchableEnvironment newSearchableNameEnvironment(WorkingCopyOwner owner) throws JavaModelException {
		return new SearchableEnvironment(this, owner);
	}

	/*
	 * Returns a PerProjectInfo that doesn't register classpath change
	 * and that should be used as a temporary info.
	 */
	public PerProjectInfo newTemporaryInfo() {
		return 
			new PerProjectInfo(this.project.getProject()) {
				protected ClasspathChange addClasspathChange() {
					return null;
				}
		};
	}

	/**
	 * @see IJavaProject
	 */
	public ITypeHierarchy newTypeHierarchy(
		IRegion region,
		IProgressMonitor monitor)
		throws JavaModelException {

		return newTypeHierarchy(region, DefaultWorkingCopyOwner.PRIMARY, monitor);
	}

	/**
	 * @see IJavaProject
	 */
	public ITypeHierarchy newTypeHierarchy(
		IRegion region,
		WorkingCopyOwner owner,
		IProgressMonitor monitor)
		throws JavaModelException {

		if (region == null) {
			throw new IllegalArgumentException(Messages.hierarchy_nullRegion);
		}
		ICompilationUnit[] workingCopies = JavaModelManager.getJavaModelManager().getWorkingCopies(owner, true/*add primary working copies*/);
		CreateTypeHierarchyOperation op =
			new CreateTypeHierarchyOperation(region, workingCopies, null, true);
		op.runOperation(monitor);
		return op.getResult();
	}

	/**
	 * @see IJavaProject
	 */
	public ITypeHierarchy newTypeHierarchy(
		IType type,
		IRegion region,
		IProgressMonitor monitor)
		throws JavaModelException {

		return newTypeHierarchy(type, region, DefaultWorkingCopyOwner.PRIMARY, monitor);
	}

	/**
	 * @see IJavaProject
	 */
	public ITypeHierarchy newTypeHierarchy(
		IType type,
		IRegion region,
		WorkingCopyOwner owner,
		IProgressMonitor monitor)
		throws JavaModelException {

		if (type == null) {
			throw new IllegalArgumentException(Messages.hierarchy_nullFocusType);
		}
		if (region == null) {
			throw new IllegalArgumentException(Messages.hierarchy_nullRegion);
		}
		ICompilationUnit[] workingCopies = JavaModelManager.getJavaModelManager().getWorkingCopies(owner, true/*add primary working copies*/);
		CreateTypeHierarchyOperation op =
			new CreateTypeHierarchyOperation(region, workingCopies, type, true/*compute subtypes*/);
		op.runOperation(monitor);
		return op.getResult();
	}
	public String[] projectPrerequisites(IClasspathEntry[] resolvedClasspath)
		throws JavaModelException {

		ArrayList prerequisites = new ArrayList();
		for (int i = 0, length = resolvedClasspath.length; i < length; i++) {
			IClasspathEntry entry = resolvedClasspath[i];
			if (entry.getEntryKind() == IClasspathEntry.CPE_PROJECT) {
				prerequisites.add(entry.getPath().lastSegment());
			}
		}
		int size = prerequisites.size();
		if (size == 0) {
			return NO_PREREQUISITES;
		} else {
			String[] result = new String[size];
			prerequisites.toArray(result);
			return result;
		}
	}
	/**
	 * Reads the classpath file entries of this project's .classpath file.
	 * Returns a two-dimensional array, where the number of elements in the row is fixed to 2.
	 * The first element is an array of raw classpath entries, which includes the output entry,
	 * and the second element is an array of referenced entries that may have been stored 
	 * by the client earlier. 
	 * See {@link IJavaProject#getReferencedClasspathEntries()} for more details.
	 * As a side effect, unknown elements are stored in the given map (if not null)
	 * Throws exceptions if the file cannot be accessed or is malformed.
	 */
	public IClasspathEntry[][] readFileEntriesWithException(Map unknownElements) throws CoreException, IOException, ClasspathEntry.AssertionFailedException {
		IFile rscFile = this.project.getFile(JavaProject.CLASSPATH_FILENAME);
		byte[] bytes;
		if (rscFile.exists()) {
			bytes = Util.getResourceContentsAsByteArray(rscFile);
		} else {
			// when a project is imported, we get a first delta for the addition of the .project, but the .classpath is not accessible
			// so default to using java.io.File
			// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=96258
			URI location = rscFile.getLocationURI();
			if (location == null)
				throw new IOException("Cannot obtain a location URI for " + rscFile); //$NON-NLS-1$
			File file = Util.toLocalFile(location, null/*no progress monitor available*/);
			if (file == null)
				throw new IOException("Unable to fetch file from " + location); //$NON-NLS-1$
			try {
				bytes = org.eclipse.jdt.internal.compiler.util.Util.getFileByteContent(file);
			} catch (IOException e) {
				if (!file.exists())
					return new IClasspathEntry[][]{defaultClasspath(), ClasspathEntry.NO_ENTRIES};
				throw e;
			}
		}
		if (hasUTF8BOM(bytes)) { // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=240034
			int length = bytes.length-IContentDescription.BOM_UTF_8.length;
			System.arraycopy(bytes, IContentDescription.BOM_UTF_8.length, bytes = new byte[length], 0, length);
		}
		String xmlClasspath;
		try {
			xmlClasspath = new String(bytes, org.eclipse.jdt.internal.compiler.util.Util.UTF_8); // .classpath always encoded with UTF-8
		} catch (UnsupportedEncodingException e) {
			Util.log(e, "Could not read .classpath with UTF-8 encoding"); //$NON-NLS-1$
			// fallback to default
			xmlClasspath = new String(bytes);
		}
		return decodeClasspath(xmlClasspath, unknownElements);
	}

	/*
	 * Reads the classpath file entries of this project's .classpath file.
	 * This includes the output entry.
	 * As a side effect, unknown elements are stored in the given map (if not null)
	 */
	private IClasspathEntry[][] readFileEntries(Map unkwownElements) {
		try {
			return readFileEntriesWithException(unkwownElements);
		} catch (CoreException e) {
			Util.log(e, "Exception while reading " + getPath().append(JavaProject.CLASSPATH_FILENAME)); //$NON-NLS-1$
			return new IClasspathEntry[][]{JavaProject.INVALID_CLASSPATH, ClasspathEntry.NO_ENTRIES};
		} catch (IOException e) {
			Util.log(e, "Exception while reading " + getPath().append(JavaProject.CLASSPATH_FILENAME)); //$NON-NLS-1$
			return new IClasspathEntry[][]{JavaProject.INVALID_CLASSPATH, ClasspathEntry.NO_ENTRIES};
		} catch (ClasspathEntry.AssertionFailedException e) {
			Util.log(e, "Exception while reading " + getPath().append(JavaProject.CLASSPATH_FILENAME)); //$NON-NLS-1$
			return new IClasspathEntry[][]{JavaProject.INVALID_CLASSPATH, ClasspathEntry.NO_ENTRIES};
		}
	}

	/**
	 * @see IJavaProject
	 */
	public IPath readOutputLocation() {
		// Read classpath file without creating markers nor logging problems
		IClasspathEntry[][] classpath = readFileEntries(null/*not interested in unknown elements*/);
		if (classpath[0] == JavaProject.INVALID_CLASSPATH)
			return defaultOutputLocation();

		// extract the output location
		IPath outputLocation = null;
		if (classpath[0].length > 0) {
			IClasspathEntry entry = classpath[0][classpath[0].length - 1];
			if (entry.getContentKind() == ClasspathEntry.K_OUTPUT) {
				outputLocation = entry.getPath();
			}
		}
		return outputLocation;
	}

	/**
	 * @see IJavaProject
	 */
	public IClasspathEntry[] readRawClasspath() {
		// Read classpath file without creating markers nor logging problems
		IClasspathEntry[][] classpath = readFileEntries(null/*not interested in unknown elements*/);
		if (classpath[0] == JavaProject.INVALID_CLASSPATH)
			return defaultClasspath();

		// discard the output location
		if (classpath[0].length > 0) {
			IClasspathEntry entry = classpath[0][classpath[0].length - 1];
			if (entry.getContentKind() == ClasspathEntry.K_OUTPUT) {
				IClasspathEntry[] copy = new IClasspathEntry[classpath[0].length - 1];
				System.arraycopy(classpath[0], 0, copy, 0, copy.length);
				classpath[0] = copy;
			}
		}
		return classpath[0];
	}

	/**
	 * Removes the given builder from the build spec for the given project.
	 */
	protected void removeFromBuildSpec(String builderID) throws CoreException {

		IProjectDescription description = this.project.getDescription();
		ICommand[] commands = description.getBuildSpec();
		for (int i = 0; i < commands.length; ++i) {
			if (commands[i].getBuilderName().equals(builderID)) {
				ICommand[] newCommands = new ICommand[commands.length - 1];
				System.arraycopy(commands, 0, newCommands, 0, i);
				System.arraycopy(commands, i + 1, newCommands, i, commands.length - i - 1);
				description.setBuildSpec(newCommands);
				this.project.setDescription(description, null);
				return;
			}
		}
	}

	/*
	 * Resets this project's caches
	 */
	public void resetCaches() {
		JavaProjectElementInfo info = (JavaProjectElementInfo) JavaModelManager.getJavaModelManager().peekAtInfo(this);
		if (info != null){
			info.resetCaches();
		}
	}

	public ClasspathChange resetResolvedClasspath() {
		try {
			return getPerProjectInfo().resetResolvedClasspath();
		} catch (JavaModelException e) {
			// project doesn't exist
			return null;
		}
	}		
	
	/*
	 * Resolve the given raw classpath.
	 */
	public IClasspathEntry[] resolveClasspath(IClasspathEntry[] rawClasspath) throws JavaModelException {
		return resolveClasspath(rawClasspath, false/*don't use previous session*/, true/*resolve chained libraries*/).resolvedClasspath;
	}
	
	static class ResolvedClasspath {
		IClasspathEntry[] resolvedClasspath;
		IJavaModelStatus unresolvedEntryStatus = JavaModelStatus.VERIFIED_OK;
		HashMap rawReverseMap = new HashMap();
		Map rootPathToResolvedEntries = new HashMap();
		IClasspathEntry[] referencedEntries = null;
	}
	
	public ResolvedClasspath resolveClasspath(IClasspathEntry[] rawClasspath, boolean usePreviousSession, boolean resolveChainedLibraries) throws JavaModelException {
		return resolveClasspath(rawClasspath, null, usePreviousSession, resolveChainedLibraries);
	}

	public ResolvedClasspath resolveClasspath(IClasspathEntry[] rawClasspath, IClasspathEntry[] referencedEntries, boolean usePreviousSession, boolean resolveChainedLibraries) throws JavaModelException {
		JavaModelManager manager = JavaModelManager.getJavaModelManager();
		ExternalFoldersManager externalFoldersManager = JavaModelManager.getExternalManager();
		ResolvedClasspath result = new ResolvedClasspath();
		Map knownDrives = new HashMap();

		Map referencedEntriesMap = new HashMap();
		List rawLibrariesPath = new ArrayList();
		LinkedHashSet resolvedEntries = new LinkedHashSet();
		
		if(resolveChainedLibraries) {
			for (int index = 0; index < rawClasspath.length; index++) {
				IClasspathEntry currentEntry = rawClasspath[index]; 
				if (currentEntry.getEntryKind() == IClasspathEntry.CPE_LIBRARY) {
					rawLibrariesPath.add(ClasspathEntry.resolveDotDot(getProject().getLocation(), currentEntry.getPath()));
				}
			}
			if (referencedEntries != null) {
				// The Set is required to keep the order intact while the referencedEntriesMap (Map)
				// is used to map the referenced entries with path
				LinkedHashSet referencedEntriesSet = new LinkedHashSet();
				for (int index = 0; index < referencedEntries.length; index++) {
					IPath path = referencedEntries[index].getPath();
					if (!rawLibrariesPath.contains(path) && referencedEntriesMap.get(path) == null) {
						referencedEntriesMap.put(path, referencedEntries[index]);
						referencedEntriesSet.add(referencedEntries[index]);
					}
				}
				if (referencedEntriesSet.size() > 0) {
					result.referencedEntries = new IClasspathEntry[referencedEntriesSet.size()];
					referencedEntriesSet.toArray(result.referencedEntries);
				}
			}
		}
		
		int length = rawClasspath.length;
		for (int i = 0; i < length; i++) {

			IClasspathEntry rawEntry = rawClasspath[i];
			IClasspathEntry resolvedEntry = rawEntry;

			switch (rawEntry.getEntryKind()){

				case IClasspathEntry.CPE_VARIABLE :
					try {
						resolvedEntry = manager.resolveVariableEntry(rawEntry, usePreviousSession);
					} catch (ClasspathEntry.AssertionFailedException e) {
						// Catch the assertion failure and set status instead
						// see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=55992
						result.unresolvedEntryStatus = new JavaModelStatus(IJavaModelStatusConstants.INVALID_PATH, e.getMessage());
						break;
					}
					if (resolvedEntry == null) {
						result.unresolvedEntryStatus = new JavaModelStatus(IJavaModelStatusConstants.CP_VARIABLE_PATH_UNBOUND, this, rawEntry.getPath());
					} else {
						// If the entry is already present in the rawReversetMap, it means the entry and the chained libraries
						// have already been processed. So, skip it.
						if (resolveChainedLibraries && resolvedEntry.getEntryKind() == IClasspathEntry.CPE_LIBRARY
													&& result.rawReverseMap.get(resolvedEntry.getPath()) == null) {
							// resolve Class-Path: in manifest
							ClasspathEntry[] extraEntries = ((ClasspathEntry) resolvedEntry).resolvedChainedLibraries();
							for (int j = 0, length2 = extraEntries.length; j < length2; j++) {
								if (!rawLibrariesPath.contains(extraEntries[j].getPath())) {
									// https://bugs.eclipse.org/bugs/show_bug.cgi?id=305037
									// referenced entries for variable entries could also be persisted with extra attributes, so addAsChainedEntry = true
									addToResult(rawEntry, extraEntries[j], result, resolvedEntries, externalFoldersManager, referencedEntriesMap, true, knownDrives);
								}
							}
						}
						addToResult(rawEntry, resolvedEntry, result, resolvedEntries, externalFoldersManager, referencedEntriesMap, false, knownDrives);
					}
					break;

				case IClasspathEntry.CPE_CONTAINER :
					IClasspathContainer container = usePreviousSession ? manager.getPreviousSessionContainer(rawEntry.getPath(), this) : JavaCore.getClasspathContainer(rawEntry.getPath(), this);
					if (container == null){
						result.unresolvedEntryStatus = new JavaModelStatus(IJavaModelStatusConstants.CP_CONTAINER_PATH_UNBOUND, this, rawEntry.getPath());
						break;
					}

					IClasspathEntry[] containerEntries = container.getClasspathEntries();
					if (containerEntries == null) {
						if (JavaModelManager.CP_RESOLVE_VERBOSE || JavaModelManager.CP_RESOLVE_VERBOSE_FAILURE) {
							JavaModelManager.getJavaModelManager().verbose_missbehaving_container_null_entries(this, rawEntry.getPath());
						}
						break;
					}

					// container was bound
					for (int j = 0, containerLength = containerEntries.length; j < containerLength; j++){
						ClasspathEntry cEntry = (ClasspathEntry) containerEntries[j];
						if (cEntry == null) {
							if (JavaModelManager.CP_RESOLVE_VERBOSE || JavaModelManager.CP_RESOLVE_VERBOSE_FAILURE) {
								JavaModelManager.getJavaModelManager().verbose_missbehaving_container(this, rawEntry.getPath(), containerEntries);
							}
							break;
						}
						// if container is exported or restricted, then its nested entries must in turn be exported  (21749) and/or propagate restrictions
						cEntry = cEntry.combineWith((ClasspathEntry) rawEntry);
						
						if (cEntry.getEntryKind() == IClasspathEntry.CPE_LIBRARY) {
							// resolve ".." in library path
							cEntry = cEntry.resolvedDotDot(getProject().getLocation());
							// https://bugs.eclipse.org/bugs/show_bug.cgi?id=313965
							// Do not resolve if the system attribute is set to false	
							if (resolveChainedLibraries
									&& JavaModelManager.getJavaModelManager().resolveReferencedLibrariesForContainers
									&& result.rawReverseMap.get(cEntry.getPath()) == null) {
								// resolve Class-Path: in manifest
								ClasspathEntry[] extraEntries = cEntry.resolvedChainedLibraries();
								for (int k = 0, length2 = extraEntries.length; k < length2; k++) {
									if (!rawLibrariesPath.contains(extraEntries[k].getPath())) {
										addToResult(rawEntry, extraEntries[k], result, resolvedEntries, externalFoldersManager, referencedEntriesMap, false, knownDrives);
									}
								}
							}
						}
						addToResult(rawEntry, cEntry, result, resolvedEntries, externalFoldersManager, referencedEntriesMap, false, knownDrives);
					}
					break;

				case IClasspathEntry.CPE_LIBRARY:
					// resolve ".." in library path
					resolvedEntry = ((ClasspathEntry) rawEntry).resolvedDotDot(getProject().getLocation());
					
					if (resolveChainedLibraries && result.rawReverseMap.get(resolvedEntry.getPath()) == null) {
						// resolve Class-Path: in manifest
						ClasspathEntry[] extraEntries = ((ClasspathEntry) resolvedEntry).resolvedChainedLibraries();
						for (int k = 0, length2 = extraEntries.length; k < length2; k++) {
							if (!rawLibrariesPath.contains(extraEntries[k].getPath())) {
								addToResult(rawEntry, extraEntries[k], result, resolvedEntries, externalFoldersManager, referencedEntriesMap, true, knownDrives);
							}
						}
					}

					addToResult(rawEntry, resolvedEntry, result, resolvedEntries, externalFoldersManager, referencedEntriesMap, false, knownDrives);
					break;
				default :
					addToResult(rawEntry, resolvedEntry, result, resolvedEntries, externalFoldersManager, referencedEntriesMap, false, knownDrives);
					break;
			}
		}
		result.resolvedClasspath = new IClasspathEntry[resolvedEntries.size()];
		resolvedEntries.toArray(result.resolvedClasspath);
		return result;
	}

	private void addToResult(IClasspathEntry rawEntry, IClasspathEntry resolvedEntry, ResolvedClasspath result,
			LinkedHashSet resolvedEntries, ExternalFoldersManager externalFoldersManager,
			Map oldChainedEntriesMap, boolean addAsChainedEntry, Map knownDrives) {

		IPath resolvedPath;
		// If it's already been resolved, do not add to resolvedEntries
		if (result.rawReverseMap.get(resolvedPath = resolvedEntry.getPath()) == null) {
			result.rawReverseMap.put(resolvedPath, rawEntry);
			result.rootPathToResolvedEntries.put(resolvedPath, resolvedEntry);
			resolvedEntries.add(resolvedEntry);
			if (addAsChainedEntry) {
				IClasspathEntry chainedEntry = null;
				chainedEntry = (ClasspathEntry) oldChainedEntriesMap.get(resolvedPath);
				if (chainedEntry != null) {
					// This is required to keep the attributes if any added by the user in
					// the previous session such as source attachment path etc.
					copyFromOldChainedEntry((ClasspathEntry) resolvedEntry, (ClasspathEntry) chainedEntry);
				}
			}
		}
		if (resolvedEntry.getEntryKind() == IClasspathEntry.CPE_LIBRARY && ExternalFoldersManager.isExternalFolderPath(resolvedPath)) {
			externalFoldersManager.addFolder(resolvedPath, true/*scheduleForCreation*/); // no-op if not an external folder or if already registered
		}
		// https://bugs.eclipse.org/bugs/show_bug.cgi?id=336046
		// The source attachment path could be external too and in which case, must be added.
		IPath sourcePath = resolvedEntry.getSourceAttachmentPath();
		if (sourcePath != null && driveExists(sourcePath, knownDrives) && ExternalFoldersManager.isExternalFolderPath(sourcePath)) {
			externalFoldersManager.addFolder(sourcePath, true);
		}
	}

	private void copyFromOldChainedEntry(ClasspathEntry resolvedEntry, ClasspathEntry chainedEntry) {
		IPath path = chainedEntry.getSourceAttachmentPath();
		if ( path != null) {
			resolvedEntry.sourceAttachmentPath = path;
		}
		path = chainedEntry.getSourceAttachmentRootPath();
		if (path != null) {
			resolvedEntry.sourceAttachmentRootPath = path;
		}
		IClasspathAttribute[] attributes = chainedEntry.getExtraAttributes();
		if (attributes != null) {
			resolvedEntry.extraAttributes = attributes;
		}
	}
	
	/*
	 * File#exists() takes lot of time for an unmapped drive. Hence, cache the info.
	 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=338649
	 */
	private boolean driveExists(IPath sourcePath, Map knownDrives) {	
		String drive = sourcePath.getDevice();
		if (drive == null) return true;
		Boolean good = (Boolean)knownDrives.get(drive);
		if (good == null) {
			if (new File(drive).exists()) {
				knownDrives.put(drive, Boolean.TRUE);
				return true;
			} else {
				knownDrives.put(drive, Boolean.FALSE);
				return false;
			}
		}
		return good.booleanValue();
	}
	
	/*
	 * Resolve the given perProjectInfo's raw classpath and store the resolved classpath in the perProjectInfo.
	 */
	public void resolveClasspath(PerProjectInfo perProjectInfo, boolean usePreviousSession, boolean addClasspathChange) throws JavaModelException {
		if (CP_RESOLUTION_BP_LISTENERS != null)
			breakpoint(1, this);
		JavaModelManager manager = JavaModelManager.getJavaModelManager();
		boolean isClasspathBeingResolved = manager.isClasspathBeingResolved(this);
		try {
			if (!isClasspathBeingResolved) {
				manager.setClasspathBeingResolved(this, true);
			}

			// get raw info inside a synchronized block to ensure that it is consistent
			IClasspathEntry[][] classpath = new IClasspathEntry[2][];
			int timeStamp;
			synchronized (perProjectInfo) {
				classpath[0] = perProjectInfo.rawClasspath;
				classpath[1] = perProjectInfo.referencedEntries;
				// Checking null only for rawClasspath enough
				if (classpath[0] == null)
					classpath = perProjectInfo.readAndCacheClasspath(this);
				timeStamp = perProjectInfo.rawTimeStamp;
			}

			ResolvedClasspath result = resolveClasspath(classpath[0], classpath[1], usePreviousSession, true/*resolve chained libraries*/);
			
			if (CP_RESOLUTION_BP_LISTENERS != null)
				breakpoint(2, this);

			// store resolved info along with the raw info to ensure consistency
			perProjectInfo.setResolvedClasspath(result.resolvedClasspath, result.referencedEntries, result.rawReverseMap, result.rootPathToResolvedEntries, usePreviousSession ? PerProjectInfo.NEED_RESOLUTION : result.unresolvedEntryStatus, timeStamp, addClasspathChange);
		} finally {
			if (!isClasspathBeingResolved) {
				manager.setClasspathBeingResolved(this, false);
			}
			if (CP_RESOLUTION_BP_LISTENERS != null)
				breakpoint(3, this);
		}
	}
	
	/**
	 * Answers an ID which is used to distinguish project/entries during package
	 * fragment root computations
	 * @return String
	 */
	public String rootID(){
		return "[PRJ]"+this.project.getFullPath(); //$NON-NLS-1$
	}

	/**
	 * Writes the classpath in a sharable format (VCM-wise) only when necessary, that is, if  it is semantically different
	 * from the existing one in file. Will never write an identical one.
	 *
	 * @param newClasspath IClasspathEntry[]
	 * @param newOutputLocation IPath
	 * @return boolean Return whether the .classpath file was modified.
	 * @throws JavaModelException
	 */
	public boolean writeFileEntries(IClasspathEntry[] newClasspath, IClasspathEntry[] referencedEntries, IPath newOutputLocation) throws JavaModelException {

		if (!this.project.isAccessible()) return false;

		Map unknownElements = new HashMap();
		IClasspathEntry[][] fileEntries = readFileEntries(unknownElements);
		if (fileEntries[0] != JavaProject.INVALID_CLASSPATH && 
				areClasspathsEqual(newClasspath, newOutputLocation, fileEntries[0])
				&& (referencedEntries == null || areClasspathsEqual(referencedEntries, fileEntries[1])) ) {
			// no need to save it, it is the same
			return false;
		}

		// actual file saving
		try {
			setSharedProperty(JavaProject.CLASSPATH_FILENAME, encodeClasspath(newClasspath, referencedEntries, newOutputLocation, true, unknownElements));
			return true;
		} catch (CoreException e) {
			throw new JavaModelException(e);
		}
	}
	public boolean writeFileEntries(IClasspathEntry[] newClasspath, IPath newOutputLocation) throws JavaModelException {
		return writeFileEntries(newClasspath, ClasspathEntry.NO_ENTRIES, newOutputLocation);
	}

	/**
	 * Update the Java command in the build spec (replace existing one if present,
	 * add one first if none).
	 */
	private void setJavaCommand(
		IProjectDescription description,
		ICommand newCommand)
		throws CoreException {

		ICommand[] oldBuildSpec = description.getBuildSpec();
		int oldJavaCommandIndex = getJavaCommandIndex(oldBuildSpec);
		ICommand[] newCommands;

		if (oldJavaCommandIndex == -1) {
			// Add a Java build spec before other builders (1FWJK7I)
			newCommands = new ICommand[oldBuildSpec.length + 1];
			System.arraycopy(oldBuildSpec, 0, newCommands, 1, oldBuildSpec.length);
			newCommands[0] = newCommand;
		} else {
		    oldBuildSpec[oldJavaCommandIndex] = newCommand;
			newCommands = oldBuildSpec;
		}

		// Commit the spec change into the project
		description.setBuildSpec(newCommands);
		this.project.setDescription(description, null);
	}

	/**
	 * @see org.eclipse.jdt.core.IJavaProject#setOption(java.lang.String, java.lang.String)
	 */
	public void setOption(String optionName, String optionValue) {
		// Store option value
		IEclipsePreferences projectPreferences = getEclipsePreferences();
		boolean modified = JavaModelManager.getJavaModelManager().storePreference(optionName, optionValue, projectPreferences, null);

		// Write changes
		if (modified) {
			try {
				projectPreferences.flush();
			} catch (BackingStoreException e) {
				// problem with pref store - quietly ignore
			}
		}
	}

	/**
	 * @see org.eclipse.jdt.core.IJavaProject#setOptions(Map)
	 */
	public void setOptions(Map newOptions) {

		IEclipsePreferences projectPreferences = getEclipsePreferences();
		if (projectPreferences == null) return;
		try {
			if (newOptions == null){
				projectPreferences.clear();
			} else {
				Iterator entries = newOptions.entrySet().iterator();
				JavaModelManager javaModelManager = JavaModelManager.getJavaModelManager();
				while (entries.hasNext()){
					Map.Entry entry = (Map.Entry) entries.next();
					String key = (String) entry.getKey();
					String value = (String) entry.getValue();
					javaModelManager.storePreference(key, value, projectPreferences, newOptions);
				}

				// reset to default all options not in new map
				// @see https://bugs.eclipse.org/bugs/show_bug.cgi?id=26255
				// @see https://bugs.eclipse.org/bugs/show_bug.cgi?id=49691
				String[] pNames = projectPreferences.keys();
				int ln = pNames.length;
				for (int i=0; i<ln; i++) {
					String key = pNames[i];
					if (!newOptions.containsKey(key)) {
						projectPreferences.remove(key); // old preferences => remove from preferences table
					}
				}
			}

			// persist options
			projectPreferences.flush();

			// flush cache immediately
			try {
				getPerProjectInfo().options = null;
			} catch (JavaModelException e) {
				// do nothing
			}
		} catch (BackingStoreException e) {
			// problem with pref store - quietly ignore
		}
	}
	/**
	 * @see IJavaProject
	 */
	public void setOutputLocation(IPath path, IProgressMonitor monitor) throws JavaModelException {
		if (path == null) {
			throw new IllegalArgumentException(Messages.path_nullPath);
		}
		if (path.equals(getOutputLocation())) {
			return;
		}
		setRawClasspath(getRawClasspath(), path, monitor);
	}

	/**
	 * Sets the underlying kernel project of this Java project,
	 * and fills in its parent and name.
	 * Called by IProject.getNature().
	 *
	 * @see IProjectNature#setProject(IProject)
	 */
	public void setProject(IProject project) {

		this.project = project;
		this.parent = JavaModelManager.getJavaModelManager().getJavaModel();
	}

	/**
	 * @see IJavaProject#setRawClasspath(IClasspathEntry[],boolean,IProgressMonitor)
	 */
	public void setRawClasspath(
		IClasspathEntry[] entries,
		boolean canModifyResources,
		IProgressMonitor monitor)
		throws JavaModelException {

		setRawClasspath(
			entries,
			getOutputLocation()/*don't change output*/,
			canModifyResources,
			monitor);
	}

	/**
	 * @see IJavaProject#setRawClasspath(IClasspathEntry[],IPath,boolean,IProgressMonitor)
	 */
	public void setRawClasspath(
			IClasspathEntry[] newRawClasspath,
			IPath newOutputLocation,
			boolean canModifyResources,
			IProgressMonitor monitor)
			throws JavaModelException {
		setRawClasspath(newRawClasspath, null, newOutputLocation, canModifyResources, monitor);
	}

	/**
	 * @see IJavaProject#setRawClasspath(IClasspathEntry[],IPath,IProgressMonitor)
	 */
	public void setRawClasspath(
		IClasspathEntry[] entries,
		IPath outputLocation,
		IProgressMonitor monitor)
		throws JavaModelException {

		setRawClasspath(
			entries,
			outputLocation,
			true/*can change resource (as per API contract)*/,
			monitor);
	}
	
	public void setRawClasspath(IClasspathEntry[] entries, IClasspathEntry[] referencedEntries, IPath outputLocation,
			IProgressMonitor monitor) throws JavaModelException {
		setRawClasspath(entries, referencedEntries, outputLocation, true, monitor);
	}
	
	protected void setRawClasspath(IClasspathEntry[] newRawClasspath, IClasspathEntry[] referencedEntries, IPath newOutputLocation,
			boolean canModifyResources,	IProgressMonitor monitor) throws JavaModelException {

		try {
			if (newRawClasspath == null) //are we already with the default classpath
				newRawClasspath = defaultClasspath();

			SetClasspathOperation op =
				new SetClasspathOperation(
					this,
					newRawClasspath,
					referencedEntries,
					newOutputLocation,
					canModifyResources);
			op.runOperation(monitor);
		} catch (JavaModelException e) {
			JavaModelManager.getJavaModelManager().getDeltaProcessor().flush();
			throw e;
		}
	}

	/**
	 * @see IJavaProject
	 */
	public void setRawClasspath(
		IClasspathEntry[] entries,
		IProgressMonitor monitor)
		throws JavaModelException {

		setRawClasspath(
			entries,
			getOutputLocation()/*don't change output*/,
			true/*can change resource (as per API contract)*/,
			monitor);
	}

	/**
	 * Record a shared persistent property onto a project.
	 * Note that it is orthogonal to IResource persistent properties, and client code has to decide
	 * which form of storage to use appropriately. Shared properties produce real resource files which
	 * can be shared through a VCM onto a server. Persistent properties are not shareable.
	 * <p>
	 * Shared properties end up in resource files, and thus cannot be modified during
	 * delta notifications (a CoreException would then be thrown).
	 *
	 * @param key String
	 * @param value String
	 * @see JavaProject#getSharedProperty(String key)
	 * @throws CoreException
	 */
	public void setSharedProperty(String key, String value) throws CoreException {

		IFile rscFile = this.project.getFile(key);
		byte[] bytes = null;
		try {
			bytes = value.getBytes(org.eclipse.jdt.internal.compiler.util.Util.UTF_8); // .classpath always encoded with UTF-8
		} catch (UnsupportedEncodingException e) {
			Util.log(e, "Could not write .classpath with UTF-8 encoding "); //$NON-NLS-1$
			// fallback to default
			bytes = value.getBytes();
		}
		InputStream inputStream = new ByteArrayInputStream(bytes);
		// update the resource content
		if (rscFile.exists()) {
			if (rscFile.isReadOnly()) {
				// provide opportunity to checkout read-only .classpath file (23984)
				ResourcesPlugin.getWorkspace().validateEdit(new IFile[]{rscFile}, IWorkspace.VALIDATE_PROMPT);
			}
			rscFile.setContents(inputStream, IResource.FORCE, null);
		} else {
			rscFile.create(inputStream, IResource.FORCE, null);
		}
	}

	/**
	 * If a cycle is detected, then cycleParticipants contains all the paths of projects involved in this cycle (directly and indirectly),
	 * no cycle if the set is empty (and started empty)
	 * @param prereqChain ArrayList
	 * @param cycleParticipants HashSet
	 * @param workspaceRoot IWorkspaceRoot
	 * @param traversed HashSet
	 * @param preferredClasspaths Map
	 */
	public void updateCycleParticipants(
			ArrayList prereqChain,
			LinkedHashSet cycleParticipants,
			IWorkspaceRoot workspaceRoot,
			HashSet traversed,
			Map preferredClasspaths){

		IPath path = getPath();
		prereqChain.add(path);
		traversed.add(path);
		try {
			IClasspathEntry[] classpath = null;
			if (preferredClasspaths != null) classpath = (IClasspathEntry[])preferredClasspaths.get(this);
			if (classpath == null) classpath = getResolvedClasspath();
			for (int i = 0, length = classpath.length; i < length; i++) {
				IClasspathEntry entry = classpath[i];

				if (entry.getEntryKind() == IClasspathEntry.CPE_PROJECT){
					IPath prereqProjectPath = entry.getPath();
					int index = cycleParticipants.contains(prereqProjectPath) ? 0 : prereqChain.indexOf(prereqProjectPath);
					if (index >= 0) { // refer to cycle, or in cycle itself
						for (int size = prereqChain.size(); index < size; index++) {
							cycleParticipants.add(prereqChain.get(index));
						}
					} else {
						if (!traversed.contains(prereqProjectPath)) {
							IResource member = workspaceRoot.findMember(prereqProjectPath);
							if (member != null && member.getType() == IResource.PROJECT){
								JavaProject javaProject = (JavaProject)JavaCore.create((IProject)member);
								javaProject.updateCycleParticipants(prereqChain, cycleParticipants, workspaceRoot, traversed, preferredClasspaths);
							}
						}
					}
				}
			}
		} catch(JavaModelException e){
			// project doesn't exist: ignore
		}
		prereqChain.remove(path);
	}

	/*
	 * Update eclipse preferences from old preferences.
	 */
	 private void updatePreferences(IEclipsePreferences preferences) {

	 	IEclipsePreferences oldPreferences = loadPreferences();
	 	if (oldPreferences != null) {
			try {
		 		String[] propertyNames = oldPreferences.childrenNames();
				for (int i = 0; i < propertyNames.length; i++){
					String propertyName = propertyNames[i];
				    String propertyValue = oldPreferences.get(propertyName, ""); //$NON-NLS-1$
				    if (!"".equals(propertyValue)) { //$NON-NLS-1$
					    preferences.put(propertyName, propertyValue);
				    }
				}
				// save immediately new preferences
				preferences.flush();
			} catch (BackingStoreException e) {
				// fails silently
			}
		}
	 }

	protected IStatus validateExistence(IResource underlyingResource) {
		// check whether the java project can be opened
		try {
			if (!((IProject) underlyingResource).hasNature(JavaCore.NATURE_ID))
				return newDoesNotExistStatus();
		} catch (CoreException e) {
			return newDoesNotExistStatus();
		}
		return JavaModelStatus.VERIFIED_OK;
	}
}
