/*******************************************************************************
 * Copyright (c) 2000, 2012 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
 *     Theodora Yeung (tyeung@bea.com) - ensure that JarPackageFragmentRoot make it into cache
 *                                                           before its contents
 *                                                           (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=102422)
 *     Stephan Herrmann - Contribution for Bug 346010 - [model] strange initialization dependency in OptionTests
 *     Terry Parker <tparker@google.com> - DeltaProcessor misses state changes in archive files, see https://bugs.eclipse.org/bugs/show_bug.cgi?id=357425
 *******************************************************************************/
package org.eclipse.jdt.internal.core;

import java.io.*;
import java.net.URI;
import java.text.MessageFormat;
import java.util.*;
import java.util.Map.Entry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.content.IContentTypeManager.ContentTypeChangeEvent;
import org.eclipse.core.runtime.content.IContentTypeManager.IContentTypeChangeListener;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.runtime.preferences.DefaultScope;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.core.runtime.preferences.IPreferencesService;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.core.runtime.preferences.IEclipsePreferences.PreferenceChangeEvent;
import org.eclipse.jdt.core.*;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.core.compiler.CompilationParticipant;
import org.eclipse.jdt.core.compiler.IProblem;
import org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants;
import org.eclipse.jdt.internal.codeassist.CompletionEngine;
import org.eclipse.jdt.internal.codeassist.SelectionEngine;
import org.eclipse.jdt.internal.compiler.AbstractAnnotationProcessorManager;
import org.eclipse.jdt.internal.compiler.Compiler;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.util.HashtableOfObjectToInt;
import org.eclipse.jdt.internal.core.JavaProjectElementInfo.ProjectCache;
import org.eclipse.jdt.internal.core.builder.JavaBuilder;
import org.eclipse.jdt.internal.core.hierarchy.TypeHierarchy;
import org.eclipse.jdt.internal.core.search.AbstractSearchScope;
import org.eclipse.jdt.internal.core.search.BasicSearchEngine;
import org.eclipse.jdt.internal.core.search.IRestrictedAccessTypeRequestor;
import org.eclipse.jdt.internal.core.search.JavaWorkspaceScope;
import org.eclipse.jdt.internal.core.search.indexing.IndexManager;
import org.eclipse.jdt.internal.core.search.processing.JobManager;
import org.eclipse.jdt.internal.core.util.HashtableOfArrayToObject;
import org.eclipse.jdt.internal.core.util.LRUCache;
import org.eclipse.jdt.internal.core.util.Messages;
import org.eclipse.jdt.internal.core.util.Util;
import org.eclipse.jdt.internal.core.util.WeakHashSet;
import org.eclipse.jdt.internal.core.util.WeakHashSetOfCharArray;
import org.eclipse.jdt.internal.core.util.LRUCache.Stats;
import org.eclipse.jdt.internal.formatter.DefaultCodeFormatter;
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;

/**
 * The <code>JavaModelManager</code> manages instances of <code>IJavaModel</code>.
 * <code>IElementChangedListener</code>s register with the <code>JavaModelManager</code>,
 * and receive <code>ElementChangedEvent</code>s for all <code>IJavaModel</code>s.
 * <p>
 * The single instance of <code>JavaModelManager</code> is available from
 * the static method <code>JavaModelManager.getJavaModelManager()</code>.
 */
public class JavaModelManager implements ISaveParticipant, IContentTypeChangeListener {

	private static final String NON_CHAINING_JARS_CACHE = "nonChainingJarsCache"; //$NON-NLS-1$
	private static final String INVALID_ARCHIVES_CACHE = "invalidArchivesCache";  //$NON-NLS-1$

	/**
	 * Define a zip cache object.
	 */
	static class ZipCache {
		private Map map;
		Object owner;

		ZipCache(Object owner) {
			this.map = new HashMap();
			this.owner = owner;
		}

		public void flush() {
			Thread currentThread = Thread.currentThread();
			Iterator iterator = this.map.values().iterator();
			while (iterator.hasNext()) {
				try {
					ZipFile zipFile = (ZipFile)iterator.next();
					if (JavaModelManager.ZIP_ACCESS_VERBOSE) {
						System.out.println("(" + currentThread + ") [JavaModelManager.flushZipFiles()] Closing ZipFile on " +zipFile.getName()); //$NON-NLS-1$//$NON-NLS-2$
					}
					zipFile.close();
				} catch (IOException e) {
					// problem occured closing zip file: cannot do much more
				}
			}
		}

		public ZipFile getCache(IPath path) {
			return (ZipFile) this.map.get(path);
		}

		public void setCache(IPath path, ZipFile zipFile) {
			this.map.put(path, zipFile);
		}
	}
	/**
	 * Unique handle onto the JavaModel
	 */
	final JavaModel javaModel = new JavaModel();

	/**
	 * Classpath variables pool
	 */
	public HashMap variables = new HashMap(5);
	public HashSet variablesWithInitializer = new HashSet(5);
	public HashMap deprecatedVariables = new HashMap(5);
	public HashSet readOnlyVariables = new HashSet(5);
	public HashMap previousSessionVariables = new HashMap(5);
	private ThreadLocal variableInitializationInProgress = new ThreadLocal();

	/**
	 * Classpath containers pool
	 */
	public HashMap containers = new HashMap(5);
	public HashMap previousSessionContainers = new HashMap(5);
	private ThreadLocal containerInitializationInProgress = new ThreadLocal();
	ThreadLocal containersBeingInitialized = new ThreadLocal();
	
	public static final int NO_BATCH_INITIALIZATION = 0;
	public static final int NEED_BATCH_INITIALIZATION = 1;
	public static final int BATCH_INITIALIZATION_IN_PROGRESS = 2;
	public static final int BATCH_INITIALIZATION_FINISHED = 3;
	public int batchContainerInitializations = NO_BATCH_INITIALIZATION;

	public BatchInitializationMonitor batchContainerInitializationsProgress = new BatchInitializationMonitor();
	public Hashtable containerInitializersCache = new Hashtable(5);

	/*
	 * A HashSet that contains the IJavaProject whose classpath is being resolved.
	 */
	private ThreadLocal classpathsBeingResolved = new ThreadLocal();

	/*
	 * The unique workspace scope
	 */
	public JavaWorkspaceScope workspaceScope;

	/*
	 * Pools of symbols used in the Java model.
	 * Used as a replacement for String#intern() that could prevent garbage collection of strings on some VMs.
	 */
	private WeakHashSet stringSymbols = new WeakHashSet(5);
	private WeakHashSetOfCharArray charArraySymbols = new WeakHashSetOfCharArray(5);

	/*
	 * Extension used to construct Java 6 annotation processor managers
	 */
	private IConfigurationElement annotationProcessorManagerFactory = null;

	/*
	 * Map from a package fragment root's path to a source attachment property (source path + ATTACHMENT_PROPERTY_DELIMITER + source root path)
	 */
	public Map rootPathToAttachments = new Hashtable();

	public final static String CP_VARIABLE_PREFERENCES_PREFIX = JavaCore.PLUGIN_ID+".classpathVariable."; //$NON-NLS-1$
	public final static String CP_CONTAINER_PREFERENCES_PREFIX = JavaCore.PLUGIN_ID+".classpathContainer."; //$NON-NLS-1$
	public final static String CP_USERLIBRARY_PREFERENCES_PREFIX = JavaCore.PLUGIN_ID+".userLibrary."; //$NON-NLS-1$
	public final static String CP_ENTRY_IGNORE = "##<cp entry ignore>##"; //$NON-NLS-1$
	public final static IPath CP_ENTRY_IGNORE_PATH = new Path(CP_ENTRY_IGNORE);
	public final static String TRUE = "true"; //$NON-NLS-1$

	private final static int VARIABLES_AND_CONTAINERS_FILE_VERSION = 2;

	/**
	 * Name of the extension point for contributing classpath variable initializers
	 */
	public static final String CPVARIABLE_INITIALIZER_EXTPOINT_ID = "classpathVariableInitializer" ; //$NON-NLS-1$

	/**
	 * Name of the extension point for contributing classpath container initializers
	 */
	public static final String CPCONTAINER_INITIALIZER_EXTPOINT_ID = "classpathContainerInitializer" ; //$NON-NLS-1$

	/**
	 * Name of the extension point for contributing a source code formatter
	 */
	public static final String FORMATTER_EXTPOINT_ID = "codeFormatter" ; //$NON-NLS-1$

	/**
	 * Name of the extension point for contributing a compilation participant
	 */
	public static final String COMPILATION_PARTICIPANT_EXTPOINT_ID = "compilationParticipant" ; //$NON-NLS-1$

	/**
	 * Name of the extension point for contributing the Java 6 annotation processor manager
	 */
	public static final String ANNOTATION_PROCESSOR_MANAGER_EXTPOINT_ID = "annotationProcessorManager" ;  //$NON-NLS-1$

	/**
	 * Name of the JVM parameter to specify whether or not referenced JAR should be resolved for container libraries.
	 */
	private static final String RESOLVE_REFERENCED_LIBRARIES_FOR_CONTAINERS = "resolveReferencedLibrariesForContainers"; //$NON-NLS-1$
	
	/**
	 * Special value used for recognizing ongoing initialization and breaking initialization cycles
	 */
	public final static IPath VARIABLE_INITIALIZATION_IN_PROGRESS = new Path("Variable Initialization In Progress"); //$NON-NLS-1$
	public final static IClasspathContainer CONTAINER_INITIALIZATION_IN_PROGRESS = new IClasspathContainer() {
		public IClasspathEntry[] getClasspathEntries() { return null; }
		public String getDescription() { return "Container Initialization In Progress"; } //$NON-NLS-1$
		public int getKind() { return 0; }
		public IPath getPath() { return null; }
		public String toString() { return getDescription(); }
	};

	private static final String BUFFER_MANAGER_DEBUG = JavaCore.PLUGIN_ID + "/debug/buffermanager" ; //$NON-NLS-1$
	private static final String INDEX_MANAGER_DEBUG = JavaCore.PLUGIN_ID + "/debug/indexmanager" ; //$NON-NLS-1$
	private static final String INDEX_MANAGER_ADVANCED_DEBUG = JavaCore.PLUGIN_ID + "/debug/indexmanager/advanced" ; //$NON-NLS-1$
	private static final String COMPILER_DEBUG = JavaCore.PLUGIN_ID + "/debug/compiler" ; //$NON-NLS-1$
	private static final String JAVAMODEL_DEBUG = JavaCore.PLUGIN_ID + "/debug/javamodel" ; //$NON-NLS-1$
	private static final String JAVAMODELCACHE_DEBUG = JavaCore.PLUGIN_ID + "/debug/javamodel/cache" ; //$NON-NLS-1$
	private static final String CP_RESOLVE_DEBUG = JavaCore.PLUGIN_ID + "/debug/cpresolution" ; //$NON-NLS-1$
	private static final String CP_RESOLVE_ADVANCED_DEBUG = JavaCore.PLUGIN_ID + "/debug/cpresolution/advanced" ; //$NON-NLS-1$
	private static final String CP_RESOLVE_FAILURE_DEBUG = JavaCore.PLUGIN_ID + "/debug/cpresolution/failure" ; //$NON-NLS-1$
	private static final String ZIP_ACCESS_DEBUG = JavaCore.PLUGIN_ID + "/debug/zipaccess" ; //$NON-NLS-1$
	private static final String DELTA_DEBUG =JavaCore.PLUGIN_ID + "/debug/javadelta" ; //$NON-NLS-1$
	private static final String DELTA_DEBUG_VERBOSE =JavaCore.PLUGIN_ID + "/debug/javadelta/verbose" ; //$NON-NLS-1$
	private static final String HIERARCHY_DEBUG = JavaCore.PLUGIN_ID + "/debug/hierarchy" ; //$NON-NLS-1$
	private static final String POST_ACTION_DEBUG = JavaCore.PLUGIN_ID + "/debug/postaction" ; //$NON-NLS-1$
	private static final String BUILDER_DEBUG = JavaCore.PLUGIN_ID + "/debug/builder" ; //$NON-NLS-1$
	private static final String BUILDER_STATS_DEBUG = JavaCore.PLUGIN_ID + "/debug/builder/stats" ; //$NON-NLS-1$
	private static final String COMPLETION_DEBUG = JavaCore.PLUGIN_ID + "/debug/completion" ; //$NON-NLS-1$
	private static final String RESOLUTION_DEBUG = JavaCore.PLUGIN_ID + "/debug/resolution" ; //$NON-NLS-1$
	private static final String SELECTION_DEBUG = JavaCore.PLUGIN_ID + "/debug/selection" ; //$NON-NLS-1$
	private static final String SEARCH_DEBUG = JavaCore.PLUGIN_ID + "/debug/search" ; //$NON-NLS-1$
	private static final String SOURCE_MAPPER_DEBUG_VERBOSE = JavaCore.PLUGIN_ID + "/debug/sourcemapper" ; //$NON-NLS-1$
	private static final String FORMATTER_DEBUG = JavaCore.PLUGIN_ID + "/debug/formatter" ; //$NON-NLS-1$

	public static final String COMPLETION_PERF = JavaCore.PLUGIN_ID + "/perf/completion" ; //$NON-NLS-1$
	public static final String SELECTION_PERF = JavaCore.PLUGIN_ID + "/perf/selection" ; //$NON-NLS-1$
	public static final String DELTA_LISTENER_PERF = JavaCore.PLUGIN_ID + "/perf/javadeltalistener" ; //$NON-NLS-1$
	public static final String VARIABLE_INITIALIZER_PERF = JavaCore.PLUGIN_ID + "/perf/variableinitializer" ; //$NON-NLS-1$
	public static final String CONTAINER_INITIALIZER_PERF = JavaCore.PLUGIN_ID + "/perf/containerinitializer" ; //$NON-NLS-1$
	public static final String RECONCILE_PERF = JavaCore.PLUGIN_ID + "/perf/reconcile" ; //$NON-NLS-1$

	private final static String INDEXED_SECONDARY_TYPES = "#@*_indexing secondary cache_*@#"; //$NON-NLS-1$

	public static boolean PERF_VARIABLE_INITIALIZER = false;
	public static boolean PERF_CONTAINER_INITIALIZER = false;
	// Non-static, which will give it a chance to retain the default when and if JavaModelManager is restarted.
	boolean resolveReferencedLibrariesForContainers = false;

	public final static ICompilationUnit[] NO_WORKING_COPY = new ICompilationUnit[0];

	// Options
	private final static int UNKNOWN_OPTION = 0;
	private final static int DEPRECATED_OPTION = 1;
	private final static int VALID_OPTION = 2;
	HashSet optionNames = new HashSet(20);
	Map deprecatedOptions = new HashMap();
	Hashtable optionsCache;

	// Preferences
	public final IEclipsePreferences[] preferencesLookup = new IEclipsePreferences[2];
	static final int PREF_INSTANCE = 0;
	static final int PREF_DEFAULT = 1;

	static final Object[][] NO_PARTICIPANTS = new Object[0][];

	public static class CompilationParticipants {

		private final static int MAX_SOURCE_LEVEL = 7; // 1.1 to 1.7

		/*
		 * The registered compilation participants (a table from int (source level) to Object[])
		 * The Object array contains first IConfigurationElements when not resolved yet, then
		 * it contains CompilationParticipants.
		 */
		private Object[][] registeredParticipants = null;
		private HashSet managedMarkerTypes;

		public CompilationParticipant[] getCompilationParticipants(IJavaProject project) {
			final Object[][] participantsPerSource = getRegisteredParticipants();
			if (participantsPerSource == NO_PARTICIPANTS)
				return null;
			String sourceLevel = project.getOption(JavaCore.COMPILER_SOURCE, true/*inherit options*/);
			final int sourceLevelIndex = indexForSourceLevel(sourceLevel);
			final Object[] participants = participantsPerSource[sourceLevelIndex];
			int length = participants.length;
			CompilationParticipant[] result = new CompilationParticipant[length];
			int index = 0;
			for (int i = 0; i < length; i++) {
				if (participants[i] instanceof IConfigurationElement) {
					final IConfigurationElement configElement = (IConfigurationElement) participants[i];
					final int participantIndex = i;
					SafeRunner.run(new ISafeRunnable() {
						public void handleException(Throwable exception) {
							Util.log(exception, "Exception occurred while creating compilation participant"); //$NON-NLS-1$
						}
						public void run() throws Exception {
							Object executableExtension = configElement.createExecutableExtension("class"); //$NON-NLS-1$
							for (int j = sourceLevelIndex; j < MAX_SOURCE_LEVEL; j++)
								participantsPerSource[j][participantIndex] = executableExtension;
						}
					});
				}
				CompilationParticipant participant;
				if ((participants[i] instanceof CompilationParticipant) && (participant = (CompilationParticipant) participants[i]).isActive(project))
					result[index++] = participant;
			}
			if (index == 0)
				return null;
			if (index < length)
				System.arraycopy(result, 0, result = new CompilationParticipant[index], 0, index);
			return result;
		}

		public HashSet managedMarkerTypes() {
			if (this.managedMarkerTypes == null) {
				// force extension points to be read
				getRegisteredParticipants();
			}
			return this.managedMarkerTypes;
		}

		private synchronized Object[][] getRegisteredParticipants() {
			if (this.registeredParticipants != null) {
				return this.registeredParticipants;
			}
			this.managedMarkerTypes = new HashSet();
			IExtensionPoint extension = Platform.getExtensionRegistry().getExtensionPoint(JavaCore.PLUGIN_ID, COMPILATION_PARTICIPANT_EXTPOINT_ID);
			if (extension == null)
				return this.registeredParticipants = NO_PARTICIPANTS;
			final ArrayList modifyingEnv = new ArrayList();
			final ArrayList creatingProblems = new ArrayList();
			final ArrayList others = new ArrayList();
			IExtension[] extensions = extension.getExtensions();
			// for all extensions of this point...
			for(int i = 0; i < extensions.length; i++) {
				IConfigurationElement[] configElements = extensions[i].getConfigurationElements();
				// for all config elements named "compilationParticipant"
				for(int j = 0; j < configElements.length; j++) {
					final IConfigurationElement configElement = configElements[j];
					String elementName =configElement.getName();
					if (!("compilationParticipant".equals(elementName))) { //$NON-NLS-1$
						continue;
					}
					// add config element in the group it belongs to
					if (TRUE.equals(configElement.getAttribute("modifiesEnvironment"))) //$NON-NLS-1$
						modifyingEnv.add(configElement);
					else if (TRUE.equals(configElement.getAttribute("createsProblems"))) //$NON-NLS-1$
						creatingProblems.add(configElement);
					else
						others.add(configElement);
					// add managed marker types
					IConfigurationElement[] managedMarkers = configElement.getChildren("managedMarker"); //$NON-NLS-1$
					for (int k = 0, length = managedMarkers.length; k < length; k++) {
						IConfigurationElement element = managedMarkers[k];
						String markerType = element.getAttribute("markerType"); //$NON-NLS-1$
						if (markerType != null)
							this.managedMarkerTypes.add(markerType);
					}
				}
			}
			int size = modifyingEnv.size() + creatingProblems.size() + others.size();
			if (size == 0)
				return this.registeredParticipants = NO_PARTICIPANTS;

			// sort config elements in each group
			IConfigurationElement[] configElements = new IConfigurationElement[size];
			int index = 0;
			index = sortParticipants(modifyingEnv, configElements, index);
			index = sortParticipants(creatingProblems, configElements, index);
			index = sortParticipants(others, configElements, index);

			// create result table
			Object[][] result = new Object[MAX_SOURCE_LEVEL][];
			int length = configElements.length;
			for (int i = 0; i < MAX_SOURCE_LEVEL; i++) {
				result[i] = new Object[length];
			}
			for (int i = 0; i < length; i++) {
				String sourceLevel = configElements[i].getAttribute("requiredSourceLevel"); //$NON-NLS-1$
				int sourceLevelIndex = indexForSourceLevel(sourceLevel);
				for (int j = sourceLevelIndex; j < MAX_SOURCE_LEVEL; j++) {
					result[j][i] = configElements[i];
				}
			}
			return this.registeredParticipants = result;
		}

		/*
		 * 1.1 -> 0
		 * 1.2 -> 1
		 * ...
		 * 1.6 -> 5
		 * 1.7 -> 6
		 * null -> 0
		 */
		private int indexForSourceLevel(String sourceLevel) {
			if (sourceLevel == null) return 0;
			int majVersion = (int) (CompilerOptions.versionToJdkLevel(sourceLevel) >>> 16);
			switch (majVersion) {
				case ClassFileConstants.MAJOR_VERSION_1_2:
					return 1;
				case ClassFileConstants.MAJOR_VERSION_1_3:
					return 2;
				case ClassFileConstants.MAJOR_VERSION_1_4:
					return 3;
				case ClassFileConstants.MAJOR_VERSION_1_5:
					return 4;
				case ClassFileConstants.MAJOR_VERSION_1_6:
					return 5;
				case ClassFileConstants.MAJOR_VERSION_1_7:
					return 6;
				default:
					// all other cases including ClassFileConstants.MAJOR_VERSION_1_1
					return 0;
			}
		}

		private int sortParticipants(ArrayList group, IConfigurationElement[] configElements, int index) {
			int size = group.size();
			if (size == 0) return index;
			Object[] elements = group.toArray();
			Util.sort(elements, new Util.Comparer() {
				public int compare(Object a, Object b) {
					if (a == b) return 0;
					String id = ((IConfigurationElement) a).getAttribute("id"); //$NON-NLS-1$
					if (id == null) return -1;
					IConfigurationElement[] requiredElements = ((IConfigurationElement) b).getChildren("requires"); //$NON-NLS-1$
					for (int i = 0, length = requiredElements.length; i < length; i++) {
						IConfigurationElement required = requiredElements[i];
						if (id.equals(required.getAttribute("id"))) //$NON-NLS-1$
							return 1;
					}
					return -1;
				}
			});
			for (int i = 0; i < size; i++)
				configElements[index+i] = (IConfigurationElement) elements[i];
			return index + size;
		}
	}

	public final CompilationParticipants compilationParticipants = new CompilationParticipants();

	/* whether an AbortCompilationUnit should be thrown when the source of a compilation unit cannot be retrieved */
	public ThreadLocal abortOnMissingSource = new ThreadLocal();

	private ExternalFoldersManager externalFoldersManager = ExternalFoldersManager.getExternalFoldersManager();

	/**
	 * Returns whether the given full path (for a package) conflicts with the output location
	 * of the given project.
	 */
	public static boolean conflictsWithOutputLocation(IPath folderPath, JavaProject project) {
		try {
			IPath outputLocation = project.getOutputLocation();
			if (outputLocation == null) {
				// in doubt, there is a conflict
				return true;
			}
			if (outputLocation.isPrefixOf(folderPath)) {
				// only allow nesting in project's output if there is a corresponding source folder
				// or if the project's output is not used (in other words, if all source folders have their custom output)
				IClasspathEntry[] classpath = project.getResolvedClasspath();
				boolean isOutputUsed = false;
				for (int i = 0, length = classpath.length; i < length; i++) {
					IClasspathEntry entry = classpath[i];
					if (entry.getEntryKind() == IClasspathEntry.CPE_SOURCE) {
						if (entry.getPath().equals(outputLocation)) {
							return false;
						}
						if (entry.getOutputLocation() == null) {
							isOutputUsed = true;
						}
					}
				}
				return isOutputUsed;
			}
			return false;
		} catch (JavaModelException e) {
			// in doubt, there is a conflict
			return true;
		}
	}

	public synchronized IClasspathContainer containerGet(IJavaProject project, IPath containerPath) {
		// check initialization in progress first
		if (containerIsInitializationInProgress(project, containerPath)) {
			return CONTAINER_INITIALIZATION_IN_PROGRESS;
		}

		Map projectContainers = (Map)this.containers.get(project);
		if (projectContainers == null){
			return null;
		}
		IClasspathContainer container = (IClasspathContainer)projectContainers.get(containerPath);
		return container;
	}

	public synchronized IClasspathContainer containerGetDefaultToPreviousSession(IJavaProject project, IPath containerPath) {
		Map projectContainers = (Map)this.containers.get(project);
		if (projectContainers == null)
			return getPreviousSessionContainer(containerPath, project);
		IClasspathContainer container = (IClasspathContainer)projectContainers.get(containerPath);
		if (container == null)
			return getPreviousSessionContainer(containerPath, project);
		return container;
	}

	private boolean containerIsInitializationInProgress(IJavaProject project, IPath containerPath) {
		Map initializations = (Map)this.containerInitializationInProgress.get();
		if (initializations == null)
			return false;
		HashSet projectInitializations = (HashSet) initializations.get(project);
		if (projectInitializations == null)
			return false;
		return projectInitializations.contains(containerPath);
	}

	private void containerAddInitializationInProgress(IJavaProject project, IPath containerPath) {
		Map initializations = (Map)this.containerInitializationInProgress.get();
		if (initializations == null)
			this.containerInitializationInProgress.set(initializations = new HashMap());
		HashSet projectInitializations = (HashSet) initializations.get(project);
		if (projectInitializations == null)
			initializations.put(project, projectInitializations = new HashSet());
		projectInitializations.add(containerPath);
	}
	
	public void containerBeingInitializedPut(IJavaProject project, IPath containerPath, IClasspathContainer container) {
		Map perProjectContainers = (Map)this.containersBeingInitialized.get();
		if (perProjectContainers == null)
			this.containersBeingInitialized.set(perProjectContainers = new HashMap());
		HashMap perPathContainers = (HashMap) perProjectContainers.get(project);
		if (perPathContainers == null)
			perProjectContainers.put(project, perPathContainers = new HashMap());
		perPathContainers.put(containerPath, container);
	}

	public IClasspathContainer containerBeingInitializedGet(IJavaProject project, IPath containerPath) {
		Map perProjectContainers = (Map)this.containersBeingInitialized.get();
		if (perProjectContainers == null)
			return null;
		HashMap perPathContainers = (HashMap) perProjectContainers.get(project);
		if (perPathContainers == null)
			return null;
		return (IClasspathContainer) perPathContainers.get(containerPath);
	}

	public IClasspathContainer containerBeingInitializedRemove(IJavaProject project, IPath containerPath) {
		Map perProjectContainers = (Map)this.containersBeingInitialized.get();
		if (perProjectContainers == null)
			return null;
		HashMap perPathContainers = (HashMap) perProjectContainers.get(project);
		if (perPathContainers == null)
			return null;
		IClasspathContainer container = (IClasspathContainer) perPathContainers.remove(containerPath);
		if (perPathContainers.size() == 0)
			perPathContainers.remove(project);
		if (perProjectContainers.size() == 0)
			this.containersBeingInitialized.set(null);
		return container;
	}

	public synchronized void containerPut(IJavaProject project, IPath containerPath, IClasspathContainer container){

		// set/unset the initialization in progress
		if (container == CONTAINER_INITIALIZATION_IN_PROGRESS) {
			containerAddInitializationInProgress(project, containerPath);

			// do not write out intermediate initialization value
			return;
		} else {
			containerRemoveInitializationInProgress(project, containerPath);

			Map projectContainers = (Map)this.containers.get(project);
 			if (projectContainers == null){
				projectContainers = new HashMap(1);
				this.containers.put(project, projectContainers);
			}

			if (container == null) {
				projectContainers.remove(containerPath);
			} else {
  				projectContainers.put(containerPath, container);
			}
			// discard obsoleted information about previous session
			Map previousContainers = (Map)this.previousSessionContainers.get(project);
			if (previousContainers != null){
				previousContainers.remove(containerPath);
			}
		}
		// container values are persisted in preferences during save operations, see #saving(ISaveContext)
	}

	/*
	 * The given project is being removed. Remove all containers for this project from the cache.
	 */
	public synchronized void containerRemove(IJavaProject project) {
		Map initializations = (Map) this.containerInitializationInProgress.get();
		if (initializations != null) {
			initializations.remove(project);
		}
		this.containers.remove(project);
	}

	public boolean containerPutIfInitializingWithSameEntries(IPath containerPath, IJavaProject[] projects, IClasspathContainer[] respectiveContainers) {
		int projectLength = projects.length;
		if (projectLength != 1)
			return false;
		final IClasspathContainer container = respectiveContainers[0];
		IJavaProject project = projects[0];
		// optimize only if initializing, otherwise we are in a regular setContainer(...) call
		if (!containerIsInitializationInProgress(project, containerPath))
			return false;
		IClasspathContainer previousContainer = containerGetDefaultToPreviousSession(project, containerPath);
		if (container == null) {
			if (previousContainer == null) {
				containerPut(project, containerPath, null);
				return true;
			}
			return false;
		}
		final IClasspathEntry[] newEntries = container.getClasspathEntries();
		if (previousContainer == null)
			if (newEntries.length == 0) {
				containerPut(project, containerPath, container);
				return true;
			} else {
				if (CP_RESOLVE_VERBOSE || CP_RESOLVE_VERBOSE_FAILURE)
					verbose_missbehaving_container(containerPath, projects, respectiveContainers, container, newEntries, null/*no old entries*/);
				return false;
			}
		final IClasspathEntry[] oldEntries = previousContainer.getClasspathEntries();
		if (oldEntries.length != newEntries.length) {
			if (CP_RESOLVE_VERBOSE || CP_RESOLVE_VERBOSE_FAILURE)
				verbose_missbehaving_container(containerPath, projects, respectiveContainers, container, newEntries, oldEntries);
			return false;
		}
		for (int i = 0, length = newEntries.length; i < length; i++) {
			if (newEntries[i] == null) {
				if (CP_RESOLVE_VERBOSE || CP_RESOLVE_VERBOSE_FAILURE)
					verbose_missbehaving_container(project, containerPath, newEntries);
				return false;
			}
			if (!newEntries[i].equals(oldEntries[i])) {
				if (CP_RESOLVE_VERBOSE || CP_RESOLVE_VERBOSE_FAILURE)
					verbose_missbehaving_container(containerPath, projects, respectiveContainers, container, newEntries, oldEntries);
				return false;
			}
		}
		containerPut(project, containerPath, container);
		return true;
	}

	private void verbose_missbehaving_container(
			IPath containerPath,
			IJavaProject[] projects,
			IClasspathContainer[] respectiveContainers,
			final IClasspathContainer container,
			final IClasspathEntry[] newEntries,
			final IClasspathEntry[] oldEntries) {
		Util.verbose(
			"CPContainer SET  - missbehaving container\n" + //$NON-NLS-1$
			"	container path: " + containerPath + '\n' + //$NON-NLS-1$
			"	projects: {" +//$NON-NLS-1$
			org.eclipse.jdt.internal.compiler.util.Util.toString(
				projects,
				new org.eclipse.jdt.internal.compiler.util.Util.Displayable(){
					public String displayString(Object o) { return ((IJavaProject) o).getElementName(); }
				}) +
			"}\n	values on previous session: {\n"  +//$NON-NLS-1$
			org.eclipse.jdt.internal.compiler.util.Util.toString(
				respectiveContainers,
				new org.eclipse.jdt.internal.compiler.util.Util.Displayable(){
					public String displayString(Object o) {
						StringBuffer buffer = new StringBuffer("		"); //$NON-NLS-1$
						if (o == null) {
							buffer.append("<null>"); //$NON-NLS-1$
							return buffer.toString();
						}
						buffer.append(container.getDescription());
						buffer.append(" {\n"); //$NON-NLS-1$
						if (oldEntries == null) {
							buffer.append(" 			"); //$NON-NLS-1$
							buffer.append("<null>\n"); //$NON-NLS-1$
						} else {
							for (int j = 0; j < oldEntries.length; j++){
								buffer.append(" 			"); //$NON-NLS-1$
								buffer.append(oldEntries[j]);
								buffer.append('\n');
							}
						}
						buffer.append(" 		}"); //$NON-NLS-1$
						return buffer.toString();
					}
				}) +
			"}\n	new values: {\n"  +//$NON-NLS-1$
			org.eclipse.jdt.internal.compiler.util.Util.toString(
				respectiveContainers,
				new org.eclipse.jdt.internal.compiler.util.Util.Displayable(){
					public String displayString(Object o) {
						StringBuffer buffer = new StringBuffer("		"); //$NON-NLS-1$
						if (o == null) {
							buffer.append("<null>"); //$NON-NLS-1$
							return buffer.toString();
						}
						buffer.append(container.getDescription());
						buffer.append(" {\n"); //$NON-NLS-1$
						for (int j = 0; j < newEntries.length; j++){
							buffer.append(" 			"); //$NON-NLS-1$
							buffer.append(newEntries[j]);
							buffer.append('\n');
						}
						buffer.append(" 		}"); //$NON-NLS-1$
						return buffer.toString();
					}
				}) +
			"\n	}"); //$NON-NLS-1$
	}

	void verbose_missbehaving_container(IJavaProject project, IPath containerPath, IClasspathEntry[] classpathEntries) {
		Util.verbose(
			"CPContainer GET - missbehaving container (returning null classpath entry)\n" + //$NON-NLS-1$
			"	project: " + project.getElementName() + '\n' + //$NON-NLS-1$
			"	container path: " + containerPath + '\n' + //$NON-NLS-1$
			"	classpath entries: {\n" + //$NON-NLS-1$
			org.eclipse.jdt.internal.compiler.util.Util.toString(
				classpathEntries,
				new org.eclipse.jdt.internal.compiler.util.Util.Displayable(){
					public String displayString(Object o) {
						StringBuffer buffer = new StringBuffer("		"); //$NON-NLS-1$
						if (o == null) {
							buffer.append("<null>"); //$NON-NLS-1$
							return buffer.toString();
						}
						buffer.append(o);
						return buffer.toString();
					}
				}) +
			"\n	}" //$NON-NLS-1$
		);
	}

	void verbose_missbehaving_container_null_entries(IJavaProject project, IPath containerPath) {
		Util.verbose(
			"CPContainer GET - missbehaving container (returning null as classpath entries)\n" + //$NON-NLS-1$
			"	project: " + project.getElementName() + '\n' + //$NON-NLS-1$
			"	container path: " + containerPath + '\n' + //$NON-NLS-1$
			"	classpath entries: <null>" //$NON-NLS-1$
		);
	}

	private void containerRemoveInitializationInProgress(IJavaProject project, IPath containerPath) {
		Map initializations = (Map)this.containerInitializationInProgress.get();
		if (initializations == null)
			return;
		HashSet projectInitializations = (HashSet) initializations.get(project);
		if (projectInitializations == null)
			return;
		projectInitializations.remove(containerPath);
		if (projectInitializations.size() == 0)
			initializations.remove(project);
		if (initializations.size() == 0)
			this.containerInitializationInProgress.set(null);
	}

	private synchronized void containersReset(String[] containerIDs) {
		for (int i = 0; i < containerIDs.length; i++) {
			String containerID = containerIDs[i];
			Iterator projectIterator = this.containers.values().iterator();
			while (projectIterator.hasNext()){
				Map projectContainers = (Map) projectIterator.next();
				if (projectContainers != null){
					Iterator containerIterator = projectContainers.keySet().iterator();
					while (containerIterator.hasNext()){
						IPath containerPath = (IPath)containerIterator.next();
						if (containerID.equals(containerPath.segment(0))) { // registered container
							projectContainers.put(containerPath, null); // reset container value, but leave entry in Map
						}
					}
				}
			}
		}
	}

	/**
	 * Returns the Java element corresponding to the given resource, or
	 * <code>null</code> if unable to associate the given resource
	 * with a Java element.
	 * <p>
	 * The resource must be one of:<ul>
	 *	<li>a project - the element returned is the corresponding <code>IJavaProject</code></li>
	 *	<li>a <code>.java</code> file - the element returned is the corresponding <code>ICompilationUnit</code></li>
	 *	<li>a <code>.class</code> file - the element returned is the corresponding <code>IClassFile</code></li>
	 *	<li>a ZIP archive (e.g. a <code>.jar</code>, a <code>.zip</code> file, etc.) - the element returned is the corresponding <code>IPackageFragmentRoot</code></li>
	 *  <li>a folder - the element returned is the corresponding <code>IPackageFragmentRoot</code>
	 *			or <code>IPackageFragment</code></li>
	 *  <li>the workspace root resource - the element returned is the <code>IJavaModel</code></li>
	 *	</ul>
	 * <p>
	 * Creating a Java element has the side effect of creating and opening all of the
	 * element's parents if they are not yet open.
	 */
	public static IJavaElement create(IResource resource, IJavaProject project) {
		if (resource == null) {
			return null;
		}
		int type = resource.getType();
		switch (type) {
			case IResource.PROJECT :
				return JavaCore.create((IProject) resource);
			case IResource.FILE :
				return create((IFile) resource, project);
			case IResource.FOLDER :
				return create((IFolder) resource, project);
			case IResource.ROOT :
				return JavaCore.create((IWorkspaceRoot) resource);
			default :
				return null;
		}
	}

	/**
	 * Returns the Java element corresponding to the given file, its project being the given
	 * project.
	 * Returns <code>null</code> if unable to associate the given file
	 * with a Java element.
	 *
	 * <p>The file must be one of:<ul>
	 *	<li>a <code>.java</code> file - the element returned is the corresponding <code>ICompilationUnit</code></li>
	 *	<li>a <code>.class</code> file - the element returned is the corresponding <code>IClassFile</code></li>
	 *	<li>a ZIP archive (e.g. a <code>.jar</code>, a <code>.zip</code> file, etc.) - the element returned is the corresponding <code>IPackageFragmentRoot</code></li>
	 *	</ul>
	 * <p>
	 * Creating a Java element has the side effect of creating and opening all of the
	 * element's parents if they are not yet open.
	 */
	public static IJavaElement create(IFile file, IJavaProject project) {
		if (file == null) {
			return null;
		}
		if (project == null) {
			project = JavaCore.create(file.getProject());
		}

		if (file.getFileExtension() != null) {
			String name = file.getName();
			if (org.eclipse.jdt.internal.core.util.Util.isJavaLikeFileName(name))
				return createCompilationUnitFrom(file, project);
			if (org.eclipse.jdt.internal.compiler.util.Util.isClassFileName(name))
				return createClassFileFrom(file, project);
			return createJarPackageFragmentRootFrom(file, project);
		}
		return null;
	}

	/**
	 * Returns the package fragment or package fragment root corresponding to the given folder,
	 * its parent or great parent being the given project.
	 * or <code>null</code> if unable to associate the given folder with a Java element.
	 * <p>
	 * Note that a package fragment root is returned rather than a default package.
	 * <p>
	 * Creating a Java element has the side effect of creating and opening all of the
	 * element's parents if they are not yet open.
	 */
	public static IJavaElement create(IFolder folder, IJavaProject project) {
		if (folder == null) {
			return null;
		}
		IJavaElement element;
		if (project == null) {
			project = JavaCore.create(folder.getProject());
			element = determineIfOnClasspath(folder, project);
			if (element == null) {
				// walk all projects and find one that have the given folder on its classpath
				IJavaProject[] projects;
				try {
					projects = JavaModelManager.getJavaModelManager().getJavaModel().getJavaProjects();
				} catch (JavaModelException e) {
					return null;
				}
				for (int i = 0, length = projects.length; i < length; i++) {
					project = projects[i];
					element = determineIfOnClasspath(folder, project);
					if (element != null)
						break;
				}
			}
		} else {
			element = determineIfOnClasspath(folder, project);
		}
		return element;
	}

	/**
	 * Creates and returns a class file element for the given <code>.class</code> file,
	 * its project being the given project. Returns <code>null</code> if unable
	 * to recognize the class file.
	 */
	public static IClassFile createClassFileFrom(IFile file, IJavaProject project ) {
		if (file == null) {
			return null;
		}
		if (project == null) {
			project = JavaCore.create(file.getProject());
		}
		IPackageFragment pkg = (IPackageFragment) determineIfOnClasspath(file, project);
		if (pkg == null) {
			// fix for 1FVS7WE
			// not on classpath - make the root its folder, and a default package
			PackageFragmentRoot root = (PackageFragmentRoot) project.getPackageFragmentRoot(file.getParent());
			pkg = root.getPackageFragment(CharOperation.NO_STRINGS);
		}
		return pkg.getClassFile(file.getName());
	}

	/**
	 * Creates and returns a compilation unit element for the given <code>.java</code>
	 * file, its project being the given project. Returns <code>null</code> if unable
	 * to recognize the compilation unit.
	 */
	public static ICompilationUnit createCompilationUnitFrom(IFile file, IJavaProject project) {

		if (file == null) return null;

		if (project == null) {
			project = JavaCore.create(file.getProject());
		}
		IPackageFragment pkg = (IPackageFragment) determineIfOnClasspath(file, project);
		if (pkg == null) {
			// not on classpath - make the root its folder, and a default package
			PackageFragmentRoot root = (PackageFragmentRoot) project.getPackageFragmentRoot(file.getParent());
			pkg = root.getPackageFragment(CharOperation.NO_STRINGS);

			if (VERBOSE){
				System.out.println("WARNING : creating unit element outside classpath ("+ Thread.currentThread()+"): " + file.getFullPath()); //$NON-NLS-1$//$NON-NLS-2$
			}
		}
		return pkg.getCompilationUnit(file.getName());
	}

	/**
	 * Creates and returns a handle for the given JAR file, its project being the given project.
	 * The Java model associated with the JAR's project may be
	 * created as a side effect.
	 * Returns <code>null</code> if unable to create a JAR package fragment root.
	 * (for example, if the JAR file represents a non-Java resource)
	 */
	public static IPackageFragmentRoot createJarPackageFragmentRootFrom(IFile file, IJavaProject project) {
		if (file == null) {
			return null;
		}
		if (project == null) {
			project = JavaCore.create(file.getProject());
		}

		// Create a jar package fragment root only if on the classpath
		IPath resourcePath = file.getFullPath();
		try {
			IClasspathEntry entry = ((JavaProject)project).getClasspathEntryFor(resourcePath);
			if (entry != null) {
				return project.getPackageFragmentRoot(file);
			}
		} catch (JavaModelException e) {
			// project doesn't exist: return null
		}
		return null;
	}

	/**
	 * Returns the package fragment root represented by the resource, or
	 * the package fragment the given resource is located in, or <code>null</code>
	 * if the given resource is not on the classpath of the given project.
	 */
	public static IJavaElement determineIfOnClasspath(IResource resource, IJavaProject project) {
		IPath resourcePath = resource.getFullPath();
		boolean isExternal = ExternalFoldersManager.isInternalPathForExternalFolder(resourcePath);
		if (isExternal)
			resourcePath = resource.getLocation();

		try {
			JavaProjectElementInfo projectInfo = (JavaProjectElementInfo) getJavaModelManager().getInfo(project);
			ProjectCache projectCache = projectInfo == null ? null : projectInfo.projectCache;
			HashtableOfArrayToObject allPkgFragmentsCache = projectCache == null ? null : projectCache.allPkgFragmentsCache;
			boolean isJavaLike = org.eclipse.jdt.internal.core.util.Util.isJavaLikeFileName(resourcePath.lastSegment());
			IClasspathEntry[] entries = isJavaLike ? project.getRawClasspath() // JAVA file can only live inside SRC folder (on the raw path)
					: ((JavaProject)project).getResolvedClasspath();

			int length	= entries.length;
			if (length > 0) {
				String sourceLevel = project.getOption(JavaCore.COMPILER_SOURCE, true);
				String complianceLevel = project.getOption(JavaCore.COMPILER_COMPLIANCE, true);
				for (int i = 0; i < length; i++) {
					IClasspathEntry entry = entries[i];
					if (entry.getEntryKind() == IClasspathEntry.CPE_PROJECT) continue;
					IPath rootPath = entry.getPath();
					if (rootPath.equals(resourcePath)) {
						if (isJavaLike) 
							return null;
						return project.getPackageFragmentRoot(resource);
					} else if (rootPath.isPrefixOf(resourcePath)) {
						// allow creation of package fragment if it contains a .java file that is included
						if (!Util.isExcluded(resource, ((ClasspathEntry)entry).fullInclusionPatternChars(), ((ClasspathEntry)entry).fullExclusionPatternChars())) {
							// given we have a resource child of the root, it cannot be a JAR pkg root
							PackageFragmentRoot root =
								isExternal ?
									new ExternalPackageFragmentRoot(rootPath, (JavaProject) project) :
									(PackageFragmentRoot) ((JavaProject) project).getFolderPackageFragmentRoot(rootPath);
							if (root == null) return null;
							IPath pkgPath = resourcePath.removeFirstSegments(rootPath.segmentCount());

							if (resource.getType() == IResource.FILE) {
								// if the resource is a file, then remove the last segment which
								// is the file name in the package
								pkgPath = pkgPath.removeLastSegments(1);
							}
							String[] pkgName = pkgPath.segments();

							// if package name is in the cache, then it has already been validated
							// (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=133141)
							if (allPkgFragmentsCache != null && allPkgFragmentsCache.containsKey(pkgName))
								return root.getPackageFragment(pkgName);

							if (pkgName.length != 0 && JavaConventions.validatePackageName(Util.packageName(pkgPath, sourceLevel, complianceLevel), sourceLevel, complianceLevel).getSeverity() == IStatus.ERROR) {
								return null;
							}
							return root.getPackageFragment(pkgName);
						}
					}
				}
			}
		} catch (JavaModelException npe) {
			return null;
		}
		return null;
	}

	/**
	 * The singleton manager
	 */
	private static JavaModelManager MANAGER= new JavaModelManager();

	/**
	 * Infos cache.
	 */
	private JavaModelCache cache;

	/*
	 * Temporary cache of newly opened elements
	 */
	private ThreadLocal temporaryCache = new ThreadLocal();

	/**
	 * Set of elements which are out of sync with their buffers.
	 */
	protected HashSet elementsOutOfSynchWithBuffers = new HashSet(11);

	/**
	 * Holds the state used for delta processing.
	 */
	public DeltaProcessingState deltaState = new DeltaProcessingState();

	public IndexManager indexManager = null;

	/**
	 * Table from IProject to PerProjectInfo.
	 * NOTE: this object itself is used as a lock to synchronize creation/removal of per project infos
	 */
	protected Map perProjectInfos = new HashMap(5);

	/**
	 * Table from WorkingCopyOwner to a table of ICompilationUnit (working copy handle) to PerWorkingCopyInfo.
	 * NOTE: this object itself is used as a lock to synchronize creation/removal of per working copy infos
	 */
	protected Map perWorkingCopyInfos = new HashMap(5);

	/**
	 * A weak set of the known search scopes.
	 */
	protected WeakHashMap searchScopes = new WeakHashMap();

	public static class PerProjectInfo {
		private static final int JAVADOC_CACHE_INITIAL_SIZE = 10;

		static final IJavaModelStatus NEED_RESOLUTION = new JavaModelStatus();

		public IProject project;
		public Object savedState;
		public boolean triedRead;
		public IClasspathEntry[] rawClasspath;
		public IClasspathEntry[] referencedEntries;
		public IJavaModelStatus rawClasspathStatus;
		public int rawTimeStamp = 0;
		public boolean writtingRawClasspath = false;
		public IClasspathEntry[] resolvedClasspath;
		public IJavaModelStatus unresolvedEntryStatus;
		public Map rootPathToRawEntries; // reverse map from a package fragment root's path to the raw entry
		public Map rootPathToResolvedEntries; // map from a package fragment root's path to the resolved entry
		public IPath outputLocation;

		public IEclipsePreferences preferences;
		public Hashtable options;
		public Hashtable secondaryTypes;
		public LRUCache javadocCache;

		public PerProjectInfo(IProject project) {

			this.triedRead = false;
			this.savedState = null;
			this.project = project;
			this.javadocCache = new LRUCache(JAVADOC_CACHE_INITIAL_SIZE);
		}

		public synchronized IClasspathEntry[] getResolvedClasspath() {
			if (this.unresolvedEntryStatus == NEED_RESOLUTION)
				return null;
			return this.resolvedClasspath;
		}
		
		public void forgetExternalTimestampsAndIndexes() {
			IClasspathEntry[] classpath = this.resolvedClasspath;
			if (classpath == null) return;
			JavaModelManager manager = JavaModelManager.getJavaModelManager();
			IndexManager indexManager = manager.indexManager;
			Map externalTimeStamps = manager.deltaState.getExternalLibTimeStamps();
			HashMap rootInfos = JavaModelManager.getDeltaState().otherRoots;
			for (int i = 0, length = classpath.length; i < length; i++) {
				IClasspathEntry entry = classpath[i];
				if (entry.getEntryKind() == IClasspathEntry.CPE_LIBRARY) {
					IPath path = entry.getPath();
					if (rootInfos.get(path) == null) {
						externalTimeStamps.remove(path);
						indexManager.removeIndex(path); // force reindexing on next reference (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=250083 )
					}
				}
			}
		}

		public void rememberExternalLibTimestamps() {
			IClasspathEntry[] classpath = this.resolvedClasspath;
			if (classpath == null) return;
			Map externalTimeStamps = JavaModelManager.getJavaModelManager().deltaState.getExternalLibTimeStamps();
			for (int i = 0, length = classpath.length; i < length; i++) {
				IClasspathEntry entry = classpath[i];
				if (entry.getEntryKind() == IClasspathEntry.CPE_LIBRARY) {
					IPath path = entry.getPath();
					if (externalTimeStamps.get(path) == null) {
						Object target = JavaModel.getExternalTarget(path, true);
						if (target instanceof File) {
							long timestamp = DeltaProcessor.getTimeStamp((java.io.File)target);
							externalTimeStamps.put(path, new Long(timestamp));
						}
					}
				}
			}
		}

		public synchronized ClasspathChange resetResolvedClasspath() {
			// clear non-chaining jars cache and invalid jars cache
			JavaModelManager.getJavaModelManager().resetClasspathListCache();
			
			// null out resolved information
			return setResolvedClasspath(null, null, null, null, this.rawTimeStamp, true/*add classpath change*/);
		}

		private ClasspathChange setClasspath(IClasspathEntry[] newRawClasspath, IClasspathEntry[] referencedEntries, IPath newOutputLocation, IJavaModelStatus newRawClasspathStatus, IClasspathEntry[] newResolvedClasspath, Map newRootPathToRawEntries, Map newRootPathToResolvedEntries, IJavaModelStatus newUnresolvedEntryStatus, boolean addClasspathChange) {
			ClasspathChange classpathChange = addClasspathChange ? addClasspathChange() : null;

			if (referencedEntries != null)	this.referencedEntries = referencedEntries;
			if (this.referencedEntries == null) this.referencedEntries = ClasspathEntry.NO_ENTRIES;
			this.rawClasspath = newRawClasspath;
			this.outputLocation = newOutputLocation;
			this.rawClasspathStatus = newRawClasspathStatus;
			this.resolvedClasspath = newResolvedClasspath;
			this.rootPathToRawEntries = newRootPathToRawEntries;
			this.rootPathToResolvedEntries = newRootPathToResolvedEntries;
			this.unresolvedEntryStatus = newUnresolvedEntryStatus;
			this.javadocCache = new LRUCache(JAVADOC_CACHE_INITIAL_SIZE);

			return classpathChange;
		}

		protected ClasspathChange addClasspathChange() {
			// remember old info
			JavaModelManager manager = JavaModelManager.getJavaModelManager();
			ClasspathChange classpathChange = manager.deltaState.addClasspathChange(this.project, this.rawClasspath, this.outputLocation, this.resolvedClasspath);
			return classpathChange;
		}

		public ClasspathChange setRawClasspath(IClasspathEntry[] newRawClasspath, IPath newOutputLocation, IJavaModelStatus newRawClasspathStatus) {
			return setRawClasspath(newRawClasspath, null, newOutputLocation, newRawClasspathStatus);
		}

		public synchronized ClasspathChange setRawClasspath(IClasspathEntry[] newRawClasspath, IClasspathEntry[] referencedEntries, IPath newOutputLocation, IJavaModelStatus newRawClasspathStatus) {
			this.rawTimeStamp++;
			return setClasspath(newRawClasspath, referencedEntries, newOutputLocation, newRawClasspathStatus, null/*resolved classpath*/, null/*root to raw map*/, null/*root to resolved map*/, null/*unresolved status*/, true/*add classpath change*/);
		}

		public ClasspathChange setResolvedClasspath(IClasspathEntry[] newResolvedClasspath, Map newRootPathToRawEntries, Map newRootPathToResolvedEntries, IJavaModelStatus newUnresolvedEntryStatus, int timeStamp, boolean addClasspathChange) {
			return setResolvedClasspath(newResolvedClasspath, null, newRootPathToRawEntries, newRootPathToResolvedEntries, newUnresolvedEntryStatus, timeStamp, addClasspathChange);
		}
		
		public synchronized ClasspathChange setResolvedClasspath(IClasspathEntry[] newResolvedClasspath, IClasspathEntry[] referencedEntries, Map newRootPathToRawEntries, Map newRootPathToResolvedEntries, IJavaModelStatus newUnresolvedEntryStatus, int timeStamp, boolean addClasspathChange) {
			if (this.rawTimeStamp != timeStamp)
				return null;
			return setClasspath(this.rawClasspath, referencedEntries, this.outputLocation, this.rawClasspathStatus, newResolvedClasspath, newRootPathToRawEntries, newRootPathToResolvedEntries, newUnresolvedEntryStatus, addClasspathChange);
		}

		/**
		 * Reads the classpath and caches the entries. 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 synchronized IClasspathEntry[][] readAndCacheClasspath(JavaProject javaProject) {
			// read file entries and update status
			IClasspathEntry[][] classpath;
			IJavaModelStatus status;
			try {
				classpath = javaProject.readFileEntriesWithException(null/*not interested in unknown elements*/);
				status = JavaModelStatus.VERIFIED_OK;
			} catch (CoreException e) {
				classpath = new IClasspathEntry[][]{JavaProject.INVALID_CLASSPATH, ClasspathEntry.NO_ENTRIES};
				status =
					new JavaModelStatus(
						IJavaModelStatusConstants.INVALID_CLASSPATH_FILE_FORMAT,
						Messages.bind(Messages.classpath_cannotReadClasspathFile, javaProject.getElementName()));
			} catch (IOException e) {
				classpath = new IClasspathEntry[][]{JavaProject.INVALID_CLASSPATH, ClasspathEntry.NO_ENTRIES};
				if (Messages.file_badFormat.equals(e.getMessage()))
					status =
						new JavaModelStatus(
							IJavaModelStatusConstants.INVALID_CLASSPATH_FILE_FORMAT,
							Messages.bind(Messages.classpath_xmlFormatError, javaProject.getElementName(), Messages.file_badFormat));
				else
					status =
						new JavaModelStatus(
							IJavaModelStatusConstants.INVALID_CLASSPATH_FILE_FORMAT,
							Messages.bind(Messages.classpath_cannotReadClasspathFile, javaProject.getElementName()));
			} catch (ClasspathEntry.AssertionFailedException e) {
				classpath = new IClasspathEntry[][]{JavaProject.INVALID_CLASSPATH, ClasspathEntry.NO_ENTRIES};
				status =
					new JavaModelStatus(
						IJavaModelStatusConstants.INVALID_CLASSPATH_FILE_FORMAT,
						Messages.bind(Messages.classpath_illegalEntryInClasspathFile, new String[] {javaProject.getElementName(), e.getMessage()}));
			}

			// extract out the output location
			int rawClasspathLength = classpath[0].length;
			IPath output = null;
			if (rawClasspathLength > 0) {
				IClasspathEntry entry = classpath[0][rawClasspathLength - 1];
				if (entry.getContentKind() == ClasspathEntry.K_OUTPUT) {
					output = entry.getPath();
					IClasspathEntry[] copy = new IClasspathEntry[rawClasspathLength - 1];
					System.arraycopy(classpath[0], 0, copy, 0, copy.length);
					classpath[0] = copy;
				}
			}

			// store new raw classpath, new output and new status, and null out resolved info
			setRawClasspath(classpath[0], classpath[1], output, status);

			return classpath;
		}

		public String toString() {
			StringBuffer buffer = new StringBuffer();
			buffer.append("Info for "); //$NON-NLS-1$
			buffer.append(this.project.getFullPath());
			buffer.append("\nRaw classpath:\n"); //$NON-NLS-1$
			if (this.rawClasspath == null) {
				buffer.append("  <null>\n"); //$NON-NLS-1$
			} else {
				for (int i = 0, length = this.rawClasspath.length; i < length; i++) {
					buffer.append("  "); //$NON-NLS-1$
					buffer.append(this.rawClasspath[i]);
					buffer.append('\n');
				}
			}
			buffer.append("Resolved classpath:\n"); //$NON-NLS-1$
			IClasspathEntry[] resolvedCP = this.resolvedClasspath;
			if (resolvedCP == null) {
				buffer.append("  <null>\n"); //$NON-NLS-1$
			} else {
				for (int i = 0, length = resolvedCP.length; i < length; i++) {
					buffer.append("  "); //$NON-NLS-1$
					buffer.append(resolvedCP[i]);
					buffer.append('\n');
				}
			}
			buffer.append("Resolved classpath status: "); //$NON-NLS-1$
			if (this.unresolvedEntryStatus == NEED_RESOLUTION)
				buffer.append("NEED RESOLUTION"); //$NON-NLS-1$
			else
				buffer.append(this.unresolvedEntryStatus == null ? "<null>\n" : this.unresolvedEntryStatus.toString()); //$NON-NLS-1$
			buffer.append("Output location:\n  "); //$NON-NLS-1$
			if (this.outputLocation == null) {
				buffer.append("<null>"); //$NON-NLS-1$
			} else {
				buffer.append(this.outputLocation);
			}
			return buffer.toString();
		}

		public boolean writeAndCacheClasspath(
				JavaProject javaProject, 
				final IClasspathEntry[] newRawClasspath, 
				IClasspathEntry[] newReferencedEntries,
				final IPath newOutputLocation) throws JavaModelException {
			try {
				this.writtingRawClasspath = true;
				if (newReferencedEntries == null) newReferencedEntries = this.referencedEntries;
				
				// write .classpath
				if (!javaProject.writeFileEntries(newRawClasspath, newReferencedEntries,  newOutputLocation)) {
					return false;
				}
				// store new raw classpath, new output and new status, and null out resolved info
				setRawClasspath(newRawClasspath, newReferencedEntries, newOutputLocation, JavaModelStatus.VERIFIED_OK);
			} finally {
				this.writtingRawClasspath = false;
			}
			return true;
		}
		
		public boolean writeAndCacheClasspath(JavaProject javaProject, final IClasspathEntry[] newRawClasspath, final IPath newOutputLocation) throws JavaModelException {
			return writeAndCacheClasspath(javaProject, newRawClasspath, null, newOutputLocation);
		}

	}

	public static class PerWorkingCopyInfo implements IProblemRequestor {
		int useCount = 0;
		IProblemRequestor problemRequestor;
		CompilationUnit workingCopy;
		public PerWorkingCopyInfo(CompilationUnit workingCopy, IProblemRequestor problemRequestor) {
			this.workingCopy = workingCopy;
			this.problemRequestor = problemRequestor;
		}
		public void acceptProblem(IProblem problem) {
			IProblemRequestor requestor = getProblemRequestor();
			if (requestor == null) return;
			requestor.acceptProblem(problem);
		}
		public void beginReporting() {
			IProblemRequestor requestor = getProblemRequestor();
			if (requestor == null) return;
			requestor.beginReporting();
		}
		public void endReporting() {
			IProblemRequestor requestor = getProblemRequestor();
			if (requestor == null) return;
			requestor.endReporting();
		}
		public IProblemRequestor getProblemRequestor() {
			if (this.problemRequestor == null && this.workingCopy.owner != null) {
				return this.workingCopy.owner.getProblemRequestor(this.workingCopy);
			}
			return this.problemRequestor;
		}
		public ICompilationUnit getWorkingCopy() {
			return this.workingCopy;
		}
		public boolean isActive() {
			IProblemRequestor requestor = getProblemRequestor();
			return requestor != null && requestor.isActive();
		}
		public String toString() {
			StringBuffer buffer = new StringBuffer();
			buffer.append("Info for "); //$NON-NLS-1$
			buffer.append(((JavaElement)this.workingCopy).toStringWithAncestors());
			buffer.append("\nUse count = "); //$NON-NLS-1$
			buffer.append(this.useCount);
			buffer.append("\nProblem requestor:\n  "); //$NON-NLS-1$
			buffer.append(this.problemRequestor);
			if (this.problemRequestor == null) {
				IProblemRequestor requestor = getProblemRequestor();
				buffer.append("\nOwner problem requestor:\n  "); //$NON-NLS-1$
				buffer.append(requestor);
			}
			return buffer.toString();
		}
	}

	public static boolean VERBOSE = false;
	public static boolean CP_RESOLVE_VERBOSE = false;
	public static boolean CP_RESOLVE_VERBOSE_ADVANCED = false;
	public static boolean CP_RESOLVE_VERBOSE_FAILURE = false;
	public static boolean ZIP_ACCESS_VERBOSE = false;
	
	/**
	 * A cache of opened zip files per thread.
	 * (for a given thread, the object value is a HashMap from IPath to java.io.ZipFile)
	 */
	private ThreadLocal zipFiles = new ThreadLocal();

	private UserLibraryManager userLibraryManager;
	
	/*
	 * List of IPath of jars that are known to not contain a chaining (through MANIFEST.MF) to another library
	 */
	private Set nonChainingJars;
	
	/*
	 * List of IPath of jars that are known to be invalid - such as not being a valid/known format
	 */
	private Set invalidArchives;

	/**
	 * Update the classpath variable cache
	 */
	public static class EclipsePreferencesListener implements IEclipsePreferences.IPreferenceChangeListener {
		/**
         * @see org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener#preferenceChange(org.eclipse.core.runtime.preferences.IEclipsePreferences.PreferenceChangeEvent)
         */
        public void preferenceChange(IEclipsePreferences.PreferenceChangeEvent event) {
        	String propertyName = event.getKey();
        	if (propertyName.startsWith(JavaCore.PLUGIN_ID)) {
	        	if (propertyName.startsWith(CP_VARIABLE_PREFERENCES_PREFIX)) {
	        		String varName = propertyName.substring(CP_VARIABLE_PREFERENCES_PREFIX.length());
	        		JavaModelManager manager = getJavaModelManager();
	        		if (manager.variablesWithInitializer.contains(varName)) {
	        			// revert preference value as we will not apply it to JavaCore classpath variable
	        			String oldValue = (String) event.getOldValue();
	        			if (oldValue == null) {
	        				// unexpected old value => remove variable from set
	        				manager.variablesWithInitializer.remove(varName);
	        			} else {
	        				manager.getInstancePreferences().put(varName, oldValue);
	        			}
	        		} else {
	        			String newValue = (String)event.getNewValue();
	        			IPath newPath;
	        			if (newValue != null && !(newValue = newValue.trim()).equals(CP_ENTRY_IGNORE)) {
	        				newPath = new Path(newValue);
	        			} else {
	        				newPath = null;
	        			}
	        			try {
	        				SetVariablesOperation operation = new SetVariablesOperation(new String[] {varName}, new IPath[] {newPath}, false/*don't update preferences*/);
	        				operation.runOperation(null/*no progress available*/);
	        			} catch (JavaModelException e) {
	        				Util.log(e, "Could not set classpath variable " + varName + " to " + newPath); //$NON-NLS-1$ //$NON-NLS-2$
	        			}
	        		}
	        	} else if (propertyName.startsWith(CP_CONTAINER_PREFERENCES_PREFIX)) {
	        		recreatePersistedContainer(propertyName, (String)event.getNewValue(), false);
	        	} else 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_INCOMPATIBLE_JDK_LEVEL) ||
					propertyName.equals(JavaCore.CORE_OUTPUT_LOCATION_OVERLAPPING_ANOTHER_SOURCE)) {
					JavaModelManager manager = JavaModelManager.getJavaModelManager();
					IJavaModel model = manager.getJavaModel();
					IJavaProject[] projects;
					try {
						projects = model.getJavaProjects();
						for (int i = 0, pl = projects.length; i < pl; i++) {
							JavaProject javaProject = (JavaProject) projects[i];
							manager.deltaState.addClasspathValidation(javaProject);
							try {
								// need to touch the project to force validation by DeltaProcessor
					            javaProject.getProject().touch(null);
					        } catch (CoreException e) {
					            // skip
					        }
						}
					} catch (JavaModelException e) {
						// skip
					}
	        	} else if (propertyName.startsWith(CP_USERLIBRARY_PREFERENCES_PREFIX)) {
					String libName = propertyName.substring(CP_USERLIBRARY_PREFERENCES_PREFIX.length());
					UserLibraryManager manager = JavaModelManager.getUserLibraryManager();
	        		manager.updateUserLibrary(libName, (String)event.getNewValue());
	        	}
	        }
        	// Reset all project caches (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=233568 )
        	try {
        		IJavaProject[] projects = JavaModelManager.getJavaModelManager().getJavaModel().getJavaProjects();
	        	for (int i = 0, length = projects.length; i < length; i++) {
					((JavaProject) projects[i]).resetCaches();
				}
        	} catch (JavaModelException e) {
        		// cannot retrieve Java projects
        	}
        }
	}
	/**
	 * Listener on eclipse preferences changes.
	 */
	EclipsePreferencesListener instancePreferencesListener = new EclipsePreferencesListener();
	/**
	 * Listener on eclipse preferences default/instance node changes.
	 */
	IEclipsePreferences.INodeChangeListener instanceNodeListener = new IEclipsePreferences.INodeChangeListener() {
		public void added(IEclipsePreferences.NodeChangeEvent event) {
			// do nothing
		}
		public void removed(IEclipsePreferences.NodeChangeEvent event) {
			if (event.getChild() == JavaModelManager.this.preferencesLookup[PREF_INSTANCE]) {
				JavaModelManager.this.preferencesLookup[PREF_INSTANCE] = InstanceScope.INSTANCE.getNode(JavaCore.PLUGIN_ID);
				JavaModelManager.this.preferencesLookup[PREF_INSTANCE].addPreferenceChangeListener(new EclipsePreferencesListener());
			}
		}
	};
	IEclipsePreferences.INodeChangeListener defaultNodeListener = new IEclipsePreferences.INodeChangeListener() {
		public void added(IEclipsePreferences.NodeChangeEvent event) {
			// do nothing
		}
		public void removed(IEclipsePreferences.NodeChangeEvent event) {
			if (event.getChild() == JavaModelManager.this.preferencesLookup[PREF_DEFAULT]) {
				JavaModelManager.this.preferencesLookup[PREF_DEFAULT] = DefaultScope.INSTANCE.getNode(JavaCore.PLUGIN_ID);
			}
		}
	};
	/**
	 * Listener on properties changes.
	 */
	IEclipsePreferences.IPreferenceChangeListener propertyListener;
	IEclipsePreferences.IPreferenceChangeListener resourcesPropertyListener;

	/**
	 * Constructs a new JavaModelManager
	 */
	private JavaModelManager() {
		// singleton: prevent others from creating a new instance
		/*
		 * It is required to initialize all fields that depends on a headless environment
		 * only if the platform is running. Otherwise this breaks the ability to use
		 * ASTParser in a non-headless environment.
		 */
		if (Platform.isRunning()) {
			this.indexManager = new IndexManager();
			this.nonChainingJars = loadClasspathListCache(NON_CHAINING_JARS_CACHE);
			this.invalidArchives = loadClasspathListCache(INVALID_ARCHIVES_CACHE);
			String includeContainerReferencedLib = System.getProperty(RESOLVE_REFERENCED_LIBRARIES_FOR_CONTAINERS);
			this.resolveReferencedLibrariesForContainers = TRUE.equalsIgnoreCase(includeContainerReferencedLib);
		}
	}

	/**
	 * @deprecated
	 */
	private void addDeprecatedOptions(Hashtable options) {
		options.put(JavaCore.COMPILER_PB_INVALID_IMPORT, JavaCore.ERROR);
		options.put(JavaCore.COMPILER_PB_UNREACHABLE_CODE, JavaCore.ERROR);
	}
	
	public void addNonChainingJar(IPath path) {
		if (this.nonChainingJars != null)
			this.nonChainingJars.add(path);
	}
	
	public void addInvalidArchive(IPath path) {
		// unlikely to be null
		if (this.invalidArchives == null) {
			this.invalidArchives = Collections.synchronizedSet(new HashSet());
		}
		if(this.invalidArchives != null) {
			this.invalidArchives.add(path);
		}
	}

	/**
	 * Starts caching ZipFiles.
	 * Ignores if there are already clients.
	 */
	public void cacheZipFiles(Object owner) {
		ZipCache zipCache = (ZipCache) this.zipFiles.get();
		if (zipCache != null) {
			return;
		}
		// the owner will be responsible for flushing the cache
		this.zipFiles.set(new ZipCache(owner));
	}

	public void closeZipFile(ZipFile zipFile) {
		if (zipFile == null) return;
		if (this.zipFiles.get() != null) {
			return; // zip file will be closed by call to flushZipFiles
		}
		try {
			if (JavaModelManager.ZIP_ACCESS_VERBOSE) {
				System.out.println("(" + Thread.currentThread() + ") [JavaModelManager.closeZipFile(ZipFile)] Closing ZipFile on " +zipFile.getName()); //$NON-NLS-1$	//$NON-NLS-2$
			}
			zipFile.close();
		} catch (IOException e) {
			// problem occured closing zip file: cannot do much more
		}
	}

	/**
	 * Configure the plugin with respect to option settings defined in ".options" file
	 */
	public void configurePluginDebugOptions(){
		if(JavaCore.getPlugin().isDebugging()){
			String option = Platform.getDebugOption(BUFFER_MANAGER_DEBUG);
			if(option != null) BufferManager.VERBOSE = option.equalsIgnoreCase(TRUE) ;

			option = Platform.getDebugOption(BUILDER_DEBUG);
			if(option != null) JavaBuilder.DEBUG = option.equalsIgnoreCase(TRUE) ;

			option = Platform.getDebugOption(COMPILER_DEBUG);
			if(option != null) Compiler.DEBUG = option.equalsIgnoreCase(TRUE) ;

			option = Platform.getDebugOption(BUILDER_STATS_DEBUG);
			if(option != null) JavaBuilder.SHOW_STATS = option.equalsIgnoreCase(TRUE) ;

			option = Platform.getDebugOption(COMPLETION_DEBUG);
			if(option != null) CompletionEngine.DEBUG = option.equalsIgnoreCase(TRUE) ;

			option = Platform.getDebugOption(CP_RESOLVE_DEBUG);
			if(option != null) JavaModelManager.CP_RESOLVE_VERBOSE = option.equalsIgnoreCase(TRUE) ;

			option = Platform.getDebugOption(CP_RESOLVE_ADVANCED_DEBUG);
			if(option != null) JavaModelManager.CP_RESOLVE_VERBOSE_ADVANCED = option.equalsIgnoreCase(TRUE) ;

			option = Platform.getDebugOption(CP_RESOLVE_FAILURE_DEBUG);
			if(option != null) JavaModelManager.CP_RESOLVE_VERBOSE_FAILURE = option.equalsIgnoreCase(TRUE) ;

			option = Platform.getDebugOption(DELTA_DEBUG);
			if(option != null) DeltaProcessor.DEBUG = option.equalsIgnoreCase(TRUE) ;

			option = Platform.getDebugOption(DELTA_DEBUG_VERBOSE);
			if(option != null) DeltaProcessor.VERBOSE = option.equalsIgnoreCase(TRUE) ;

			option = Platform.getDebugOption(HIERARCHY_DEBUG);
			if(option != null) TypeHierarchy.DEBUG = option.equalsIgnoreCase(TRUE) ;

			option = Platform.getDebugOption(INDEX_MANAGER_DEBUG);
			if(option != null) JobManager.VERBOSE = option.equalsIgnoreCase(TRUE) ;

			option = Platform.getDebugOption(INDEX_MANAGER_ADVANCED_DEBUG);
			if(option != null) IndexManager.DEBUG = option.equalsIgnoreCase(TRUE) ;

			option = Platform.getDebugOption(JAVAMODEL_DEBUG);
			if(option != null) JavaModelManager.VERBOSE = option.equalsIgnoreCase(TRUE) ;

			option = Platform.getDebugOption(JAVAMODELCACHE_DEBUG);
			if(option != null) JavaModelCache.VERBOSE = option.equalsIgnoreCase(TRUE) ;

			option = Platform.getDebugOption(POST_ACTION_DEBUG);
			if(option != null) JavaModelOperation.POST_ACTION_VERBOSE = option.equalsIgnoreCase(TRUE) ;

			option = Platform.getDebugOption(RESOLUTION_DEBUG);
			if(option != null) NameLookup.VERBOSE = option.equalsIgnoreCase(TRUE) ;

			option = Platform.getDebugOption(SEARCH_DEBUG);
			if(option != null) BasicSearchEngine.VERBOSE = option.equalsIgnoreCase(TRUE) ;

			option = Platform.getDebugOption(SELECTION_DEBUG);
			if(option != null) SelectionEngine.DEBUG = option.equalsIgnoreCase(TRUE) ;

			option = Platform.getDebugOption(ZIP_ACCESS_DEBUG);
			if(option != null) JavaModelManager.ZIP_ACCESS_VERBOSE = option.equalsIgnoreCase(TRUE) ;

			option = Platform.getDebugOption(SOURCE_MAPPER_DEBUG_VERBOSE);
			if(option != null) SourceMapper.VERBOSE = option.equalsIgnoreCase(TRUE) ;

			option = Platform.getDebugOption(FORMATTER_DEBUG);
			if(option != null) DefaultCodeFormatter.DEBUG = option.equalsIgnoreCase(TRUE) ;
		}

		// configure performance options
		if(PerformanceStats.ENABLED) {
			CompletionEngine.PERF = PerformanceStats.isEnabled(COMPLETION_PERF);
			SelectionEngine.PERF = PerformanceStats.isEnabled(SELECTION_PERF);
			DeltaProcessor.PERF = PerformanceStats.isEnabled(DELTA_LISTENER_PERF);
			JavaModelManager.PERF_VARIABLE_INITIALIZER = PerformanceStats.isEnabled(VARIABLE_INITIALIZER_PERF);
			JavaModelManager.PERF_CONTAINER_INITIALIZER = PerformanceStats.isEnabled(CONTAINER_INITIALIZER_PERF);
			ReconcileWorkingCopyOperation.PERF = PerformanceStats.isEnabled(RECONCILE_PERF);
		}
	}

	/*
	 * Return a new Java 6 annotation processor manager.  The manager will need to
	 * be configured before it can be used.  Returns null if a manager cannot be
	 * created, i.e. if the current VM does not support Java 6 annotation processing.
	 */
	public AbstractAnnotationProcessorManager createAnnotationProcessorManager() {
		synchronized(this) {
			if (this.annotationProcessorManagerFactory == null) {
				IExtensionPoint extension = Platform.getExtensionRegistry().getExtensionPoint(JavaCore.PLUGIN_ID, ANNOTATION_PROCESSOR_MANAGER_EXTPOINT_ID);
				if (extension == null)
					return null;
				IExtension[] extensions = extension.getExtensions();
				for(int i = 0; i < extensions.length; i++) {
					if (i > 0) {
						Util.log(null, "An annotation processor manager is already registered: ignoring " + extensions[i].getUniqueIdentifier()); //$NON-NLS-1$
						break;
					}
					IConfigurationElement[] configElements = extensions[i].getConfigurationElements();
					for(int j = 0; j < configElements.length; j++) {
						final IConfigurationElement configElement = configElements[j];
						if ("annotationProcessorManager".equals(configElement.getName())) { //$NON-NLS-1$
							this.annotationProcessorManagerFactory = configElement;
							break;
						}
					}
				}
			}
		}

		if (this.annotationProcessorManagerFactory == null) {
			return null;
		}
		final AbstractAnnotationProcessorManager[] apm = new AbstractAnnotationProcessorManager[1];
		apm[0] = null;
		final IConfigurationElement factory = this.annotationProcessorManagerFactory;
		SafeRunner.run(new ISafeRunnable() {
			public void handleException(Throwable exception) {
				Util.log(exception, "Exception occurred while loading annotation processor manager"); //$NON-NLS-1$
			}
			public void run() throws Exception {
				Object executableExtension = factory.createExecutableExtension("class"); //$NON-NLS-1$
				if (executableExtension instanceof AbstractAnnotationProcessorManager) {
					apm[0] = (AbstractAnnotationProcessorManager) executableExtension;
				}
			}
		});
		return apm[0];
	}

	/*
	 * Discards the per working copy info for the given working copy (making it a compilation unit)
	 * if its use count was 1. Otherwise, just decrement the use count.
	 * If the working copy is primary, computes the delta between its state and the original compilation unit
	 * and register it.
	 * Close the working copy, its buffer and remove it from the shared working copy table.
	 * Ignore if no per-working copy info existed.
	 * NOTE: it must NOT be synchronized as it may interact with the element info cache (if useCount is decremented to 0), see bug 50667.
	 * Returns the new use count (or -1 if it didn't exist).
	 */
	public int discardPerWorkingCopyInfo(CompilationUnit workingCopy) throws JavaModelException {

		// create the delta builder (this remembers the current content of the working copy)
		// outside the perWorkingCopyInfos lock (see bug 50667)
		JavaElementDeltaBuilder deltaBuilder = null;
		if (workingCopy.isPrimary() && workingCopy.hasUnsavedChanges()) {
			deltaBuilder = new JavaElementDeltaBuilder(workingCopy);
		}
		PerWorkingCopyInfo info = null;
		synchronized(this.perWorkingCopyInfos) {
			WorkingCopyOwner owner = workingCopy.owner;
			Map workingCopyToInfos = (Map)this.perWorkingCopyInfos.get(owner);
			if (workingCopyToInfos == null) return -1;

			info = (PerWorkingCopyInfo)workingCopyToInfos.get(workingCopy);
			if (info == null) return -1;

			if (--info.useCount == 0) {
				// remove per working copy info
				workingCopyToInfos.remove(workingCopy);
				if (workingCopyToInfos.isEmpty()) {
					this.perWorkingCopyInfos.remove(owner);
				}
			}
		}
		if (info.useCount == 0) { // info cannot be null here (check was done above)
			// remove infos + close buffer (since no longer working copy)
			// outside the perWorkingCopyInfos lock (see bug 50667)
			removeInfoAndChildren(workingCopy);
			workingCopy.closeBuffer();

			// compute the delta if needed and register it if there are changes
			if (deltaBuilder != null) {
				deltaBuilder.buildDeltas();
				if (deltaBuilder.delta != null) {
					getDeltaProcessor().registerJavaModelDelta(deltaBuilder.delta);
				}
			}
		}
		return info.useCount;
	}

	/**
	 * @see ISaveParticipant
	 */
	public void doneSaving(ISaveContext context){
		// nothing to do for jdt.core
	}

	/**
	 * Flushes ZipFiles cache if there are no more clients.
	 */
	public void flushZipFiles(Object owner) {
		ZipCache zipCache = (ZipCache)this.zipFiles.get();
		if (zipCache == null) {
			return;
		}
		// the owner will be responsible for flushing the cache
		// we want to check object identity to make sure this is the owner that created the cache
		if (zipCache.owner == owner) {
			this.zipFiles.set(null);
			zipCache.flush();
		}
	}

	/*
	 * Returns true if forcing batch initialization was successful.
	 * Returns false if batch initialization is already running.
	 */
	public synchronized boolean forceBatchInitializations(boolean initAfterLoad) {
		switch (this.batchContainerInitializations) {
		case NO_BATCH_INITIALIZATION:
			this.batchContainerInitializations = NEED_BATCH_INITIALIZATION;
			return true;
		case BATCH_INITIALIZATION_FINISHED:
			if (initAfterLoad)
				return false; // no need to initialize again
			this.batchContainerInitializations = NEED_BATCH_INITIALIZATION;
			return true;
		}
		return false;
	}

	private synchronized boolean batchContainerInitializations() {
		switch (this.batchContainerInitializations) {
		case NEED_BATCH_INITIALIZATION:
			this.batchContainerInitializations = BATCH_INITIALIZATION_IN_PROGRESS;
			return true;
		case BATCH_INITIALIZATION_IN_PROGRESS:
			return true;
		}
		return false;
	}

	private synchronized void batchInitializationFinished() {
		this.batchContainerInitializations = BATCH_INITIALIZATION_FINISHED;
	}

	public IClasspathContainer getClasspathContainer(final IPath containerPath, final IJavaProject project) throws JavaModelException {

		IClasspathContainer container = containerGet(project, containerPath);

		if (container == null) {
			if (batchContainerInitializations()) {
				// avoid deep recursion while initializing container on workspace restart
				// (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=60437)
				try {
					container = initializeAllContainers(project, containerPath);
				} finally {
					batchInitializationFinished();
				}
			} else {
				container = initializeContainer(project, containerPath);
				containerBeingInitializedRemove(project, containerPath);
				SetContainerOperation operation = new SetContainerOperation(containerPath, new IJavaProject[] {project}, new IClasspathContainer[] {container});
				operation.runOperation(null);
			}
		}
		return container;
	}

	public IClasspathEntry[] getReferencedClasspathEntries(IClasspathEntry libraryEntry, IJavaProject project) {
		
		IClasspathEntry[] referencedEntries = ((ClasspathEntry)libraryEntry).resolvedChainedLibraries();
		
		if (project == null)
			return referencedEntries;
		
		PerProjectInfo perProjectInfo = getPerProjectInfo(project.getProject(), false);
		if(perProjectInfo == null) 
			return referencedEntries;
		
		List pathToReferencedEntries = new ArrayList(referencedEntries.length);
		for (int index = 0; index < referencedEntries.length; index++) {

			if (pathToReferencedEntries.contains(referencedEntries[index].getPath()))
				continue;

			IClasspathEntry persistedEntry = null;
			if ((persistedEntry = (IClasspathEntry)perProjectInfo.rootPathToResolvedEntries.get(referencedEntries[index].getPath())) != null) {
				// TODO: reconsider this - may want to copy the values instead of reference assignment?
				referencedEntries[index] = persistedEntry;
			}
			pathToReferencedEntries.add(referencedEntries[index].getPath());
		}
		return referencedEntries;
	}
	
	public DeltaProcessor getDeltaProcessor() {
		return this.deltaState.getDeltaProcessor();
	}

	public static DeltaProcessingState getDeltaState() {
		return MANAGER.deltaState;
	}

	/**
	 * Returns the set of elements which are out of synch with their buffers.
	 */
	protected HashSet getElementsOutOfSynchWithBuffers() {
		return this.elementsOutOfSynchWithBuffers;
	}

	public static ExternalFoldersManager getExternalManager() {
		return MANAGER.externalFoldersManager;
	}

	public static IndexManager getIndexManager() {
		return MANAGER.indexManager;
	}

	/**
	 *  Returns the info for the element.
	 */
	public synchronized Object getInfo(IJavaElement element) {
		HashMap tempCache = (HashMap)this.temporaryCache.get();
		if (tempCache != null) {
			Object result = tempCache.get(element);
			if (result != null) {
				return result;
			}
		}
		return this.cache.getInfo(element);
	}

	/**
	 *  Returns the existing element in the cache that is equal to the given element.
	 */
	public synchronized IJavaElement getExistingElement(IJavaElement element) {
		return this.cache.getExistingElement(element);
	}

	public HashSet getExternalWorkingCopyProjects() {
		synchronized (this.perWorkingCopyInfos) {
			HashSet result = null;
			Iterator values = this.perWorkingCopyInfos.values().iterator();
			while (values.hasNext()) {
				Map ownerCopies = (Map) values.next();
				Iterator workingCopies = ownerCopies.keySet().iterator();
				while (workingCopies.hasNext()) {
					ICompilationUnit workingCopy = (ICompilationUnit) workingCopies.next();
					IJavaProject project = workingCopy.getJavaProject();
					if (project.getElementName().equals(ExternalJavaProject.EXTERNAL_PROJECT_NAME)) {
						if (result == null)
							result = new HashSet();
						result.add(project);
					}
				}
			}
			return result;
		}
	}

	/**
	 * Get workspace eclipse preference for JavaCore plug-in.
	 */
	public IEclipsePreferences getInstancePreferences() {
		return this.preferencesLookup[PREF_INSTANCE];
	}

	// If modified, also modify the method getDefaultOptionsNoInitialization()
	public Hashtable getDefaultOptions(){

		Hashtable defaultOptions = new Hashtable(10);

		// see JavaCorePreferenceInitializer#initializeDefaultPluginPreferences() for changing default settings
		// If modified, also modify the method getDefaultOptionsNoInitialization()
		IEclipsePreferences defaultPreferences = getDefaultPreferences();

		// initialize preferences to their default
		Iterator iterator = this.optionNames.iterator();
		while (iterator.hasNext()) {
		    String propertyName = (String) iterator.next();
		    String value = defaultPreferences.get(propertyName, null);
		    if (value != null) defaultOptions.put(propertyName, value);
		}
		// get encoding through resource plugin
		defaultOptions.put(JavaCore.CORE_ENCODING, JavaCore.getEncoding());
		// backward compatibility
		addDeprecatedOptions(defaultOptions);

		return defaultOptions;
	}

	/**
	 * Get default eclipse preference for JavaCore plugin.
	 */
	public IEclipsePreferences getDefaultPreferences() {
		return this.preferencesLookup[PREF_DEFAULT];
	}

	/**
	 * Returns the handle to the active Java Model.
	 */
	public final JavaModel getJavaModel() {
		return this.javaModel;
	}

	/**
	 * Returns the singleton JavaModelManager
	 */
	public final static JavaModelManager getJavaModelManager() {
		return MANAGER;
	}

	/**
	 * Returns the last built state for the given project, or null if there is none.
	 * Deserializes the state if necessary.
	 *
	 * For use by image builder and evaluation support only
	 */
	public Object getLastBuiltState(IProject project, IProgressMonitor monitor) {
		if (!JavaProject.hasJavaNature(project)) {
			if (JavaBuilder.DEBUG)
				System.out.println(project + " is not a Java project"); //$NON-NLS-1$
			return null; // should never be requested on non-Java projects
		}
		PerProjectInfo info = getPerProjectInfo(project, true/*create if missing*/);
		if (!info.triedRead) {
			info.triedRead = true;
			try {
				if (monitor != null)
					monitor.subTask(Messages.bind(Messages.build_readStateProgress, project.getName()));
				info.savedState = readState(project);
			} catch (CoreException e) {
				e.printStackTrace();
			}
		}
		return info.savedState;
	}

	public String getOption(String optionName) {

		if (JavaCore.CORE_ENCODING.equals(optionName)){
			return JavaCore.getEncoding();
		}
		// backward compatibility
		if (isDeprecatedOption(optionName)) {
			return JavaCore.ERROR;
		}
		int optionLevel = getOptionLevel(optionName);
		if (optionLevel != UNKNOWN_OPTION){
			IPreferencesService service = Platform.getPreferencesService();
			String value = service.get(optionName, null, this.preferencesLookup);
			if (value == null && optionLevel == DEPRECATED_OPTION) {
				// May be a deprecated option, retrieve the new value in compatible options
				String[] compatibleOptions = (String[]) this.deprecatedOptions.get(optionName);
				value = service.get(compatibleOptions[0], null, this.preferencesLookup);
			}
			return value==null ? null : value.trim();
		}
		return null;
	}

	/**
	 * Returns the value of the given option for the given Eclipse preferences.
	 * If no value was already set, then inherits from the global options if specified.
	 *
	 * @param optionName The name of the option
	 * @param inheritJavaCoreOptions Tells whether the value can be inherited from global JavaCore options
	 * @param projectPreferences The eclipse preferences from which to get the value
	 * @return The value of the option. May be <code>null</code>
	 */
	public String getOption(String optionName, boolean inheritJavaCoreOptions, IEclipsePreferences projectPreferences) {
		// Return the option value depending on its level
		switch (getOptionLevel(optionName)) {
			case VALID_OPTION:
				// Valid option, return the preference value
				String javaCoreDefault = inheritJavaCoreOptions ? JavaCore.getOption(optionName) : null;
				if (projectPreferences == null) return javaCoreDefault;
				String value = projectPreferences.get(optionName, javaCoreDefault);
				return value == null ? null : value.trim();
			case DEPRECATED_OPTION:
				// Return the deprecated option value if it was already set
				String oldValue = projectPreferences.get(optionName, null);
				if (oldValue != null) {
					return oldValue.trim();
				}
				// Get the new compatible value
				String[] compatibleOptions = (String[]) this.deprecatedOptions.get(optionName);
				String newDefault = inheritJavaCoreOptions ? JavaCore.getOption(compatibleOptions[0]) : null;
				String newValue = projectPreferences.get(compatibleOptions[0], newDefault);
				return newValue == null ? null : newValue.trim();
		}
		return null;
	}

	/**
	 * Returns whether an option name is known or not.
	 * 
	 * @param optionName The name of the option
	 * @return <code>true</code> when the option name is either
	 * {@link #VALID_OPTION valid} or {@link #DEPRECATED_OPTION deprecated},
	 * <code>false</code> otherwise.
	 */
	public boolean knowsOption(String optionName) {
		boolean knownOption = this.optionNames.contains(optionName);
		if (!knownOption) {
			knownOption = this.deprecatedOptions.get(optionName) != null;
		}
		return knownOption;
	}

	/**
	 * Returns the level of the given option.
	 * 
	 * @param optionName The name of the option
	 * @return The level of the option as an int which may have the following
	 * values:
	 * <ul>
	 * <li>{@link #UNKNOWN_OPTION}: the given option is unknown</li>
	 * <li>{@link #DEPRECATED_OPTION}: the given option is deprecated</li>
	 * <li>{@link #VALID_OPTION}: the given option is valid</li>
	 * </ul>
	 */
	public int getOptionLevel(String optionName) {
		if (this.optionNames.contains(optionName)) {
			return VALID_OPTION;
		}
		if (this.deprecatedOptions.get(optionName) != null) {
			return DEPRECATED_OPTION;
		}
		return UNKNOWN_OPTION;
	}

	public Hashtable getOptions() {

		// return cached options if already computed
		Hashtable cachedOptions; // use a local variable to avoid race condition (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=256329 )
		if ((cachedOptions = this.optionsCache) != null) {
			return new Hashtable(cachedOptions);
		}
		if (!Platform.isRunning()) {
			this.optionsCache = getDefaultOptionsNoInitialization();
			return new Hashtable(this.optionsCache);
		}
		// init
		Hashtable options = new Hashtable(10);
		IPreferencesService service = Platform.getPreferencesService();

		// set options using preferences service lookup
		Iterator iterator = this.optionNames.iterator();
		while (iterator.hasNext()) {
			String propertyName = (String) iterator.next();
			String propertyValue = service.get(propertyName, null, this.preferencesLookup);
			if (propertyValue != null) {
				options.put(propertyName, propertyValue);
			}
		}

		// set deprecated options using preferences service lookup
		Iterator deprecatedEntries = this.deprecatedOptions.entrySet().iterator();
		while (deprecatedEntries.hasNext()) {
			Entry entry = (Entry) deprecatedEntries.next();
			String propertyName = (String) entry.getKey();
			String propertyValue = service.get(propertyName, null, this.preferencesLookup);
			if (propertyValue != null) {
				options.put(propertyName, propertyValue);
				String[] compatibleOptions = (String[]) entry.getValue();
				for (int co=0, length=compatibleOptions.length; co < length; co++) {
					String compatibleOption = compatibleOptions[co];
					if (!options.containsKey(compatibleOption))
						options.put(compatibleOption, propertyValue);
				}
			}
		}

		// get encoding through resource plugin
		options.put(JavaCore.CORE_ENCODING, JavaCore.getEncoding());

		// backward compatibility
		addDeprecatedOptions(options);

		Util.fixTaskTags(options);
		// store built map in cache
		this.optionsCache = new Hashtable(options);
		// return built map
		return options;
	}

	// Do not modify without modifying getDefaultOptions()
	private Hashtable getDefaultOptionsNoInitialization() {
		Map defaultOptionsMap = new CompilerOptions().getMap(); // compiler defaults

		// Override some compiler defaults
		defaultOptionsMap.put(JavaCore.COMPILER_LOCAL_VARIABLE_ATTR, JavaCore.GENERATE);
		defaultOptionsMap.put(JavaCore.COMPILER_CODEGEN_UNUSED_LOCAL, JavaCore.PRESERVE);
		defaultOptionsMap.put(JavaCore.COMPILER_TASK_TAGS, JavaCore.DEFAULT_TASK_TAGS);
		defaultOptionsMap.put(JavaCore.COMPILER_TASK_PRIORITIES, JavaCore.DEFAULT_TASK_PRIORITIES);
		defaultOptionsMap.put(JavaCore.COMPILER_TASK_CASE_SENSITIVE, JavaCore.ENABLED);
		defaultOptionsMap.put(JavaCore.COMPILER_DOC_COMMENT_SUPPORT, JavaCore.ENABLED);
		defaultOptionsMap.put(JavaCore.COMPILER_PB_FORBIDDEN_REFERENCE, JavaCore.ERROR);

		// Builder settings
		defaultOptionsMap.put(JavaCore.CORE_JAVA_BUILD_RESOURCE_COPY_FILTER, ""); //$NON-NLS-1$
		defaultOptionsMap.put(JavaCore.CORE_JAVA_BUILD_INVALID_CLASSPATH, JavaCore.ABORT);
		defaultOptionsMap.put(JavaCore.CORE_JAVA_BUILD_DUPLICATE_RESOURCE, JavaCore.WARNING);
		defaultOptionsMap.put(JavaCore.CORE_JAVA_BUILD_CLEAN_OUTPUT_FOLDER, JavaCore.CLEAN);

		// JavaCore settings
		defaultOptionsMap.put(JavaCore.CORE_JAVA_BUILD_ORDER, JavaCore.IGNORE);
		defaultOptionsMap.put(JavaCore.CORE_INCOMPLETE_CLASSPATH, JavaCore.ERROR);
		defaultOptionsMap.put(JavaCore.CORE_CIRCULAR_CLASSPATH, JavaCore.ERROR);
		defaultOptionsMap.put(JavaCore.CORE_INCOMPATIBLE_JDK_LEVEL, JavaCore.IGNORE); 
		defaultOptionsMap.put(JavaCore.CORE_OUTPUT_LOCATION_OVERLAPPING_ANOTHER_SOURCE, JavaCore.ERROR);
		defaultOptionsMap.put(JavaCore.CORE_ENABLE_CLASSPATH_EXCLUSION_PATTERNS, JavaCore.ENABLED);
		defaultOptionsMap.put(JavaCore.CORE_ENABLE_CLASSPATH_MULTIPLE_OUTPUT_LOCATIONS, JavaCore.ENABLED);

		// Formatter settings
		defaultOptionsMap.putAll(DefaultCodeFormatterConstants.getEclipseDefaultSettings());

		// CodeAssist settings
		defaultOptionsMap.put(JavaCore.CODEASSIST_VISIBILITY_CHECK, JavaCore.DISABLED);
		defaultOptionsMap.put(JavaCore.CODEASSIST_DEPRECATION_CHECK, JavaCore.DISABLED);
		defaultOptionsMap.put(JavaCore.CODEASSIST_IMPLICIT_QUALIFICATION, JavaCore.DISABLED);
		defaultOptionsMap.put(JavaCore.CODEASSIST_FIELD_PREFIXES, ""); //$NON-NLS-1$
		defaultOptionsMap.put(JavaCore.CODEASSIST_STATIC_FIELD_PREFIXES, ""); //$NON-NLS-1$
		defaultOptionsMap.put(JavaCore.CODEASSIST_STATIC_FINAL_FIELD_PREFIXES, ""); //$NON-NLS-1$
		defaultOptionsMap.put(JavaCore.CODEASSIST_LOCAL_PREFIXES, ""); //$NON-NLS-1$
		defaultOptionsMap.put(JavaCore.CODEASSIST_ARGUMENT_PREFIXES, ""); //$NON-NLS-1$
		defaultOptionsMap.put(JavaCore.CODEASSIST_FIELD_SUFFIXES, ""); //$NON-NLS-1$
		defaultOptionsMap.put(JavaCore.CODEASSIST_STATIC_FIELD_SUFFIXES, ""); //$NON-NLS-1$
		defaultOptionsMap.put(JavaCore.CODEASSIST_STATIC_FINAL_FIELD_SUFFIXES, ""); //$NON-NLS-1$
		defaultOptionsMap.put(JavaCore.CODEASSIST_LOCAL_SUFFIXES, ""); //$NON-NLS-1$
		defaultOptionsMap.put(JavaCore.CODEASSIST_ARGUMENT_SUFFIXES, ""); //$NON-NLS-1$
		defaultOptionsMap.put(JavaCore.CODEASSIST_FORBIDDEN_REFERENCE_CHECK, JavaCore.ENABLED);
		defaultOptionsMap.put(JavaCore.CODEASSIST_DISCOURAGED_REFERENCE_CHECK, JavaCore.DISABLED);
		defaultOptionsMap.put(JavaCore.CODEASSIST_CAMEL_CASE_MATCH, JavaCore.ENABLED);
		defaultOptionsMap.put(JavaCore.CODEASSIST_SUGGEST_STATIC_IMPORTS, JavaCore.ENABLED);

		// Time out for parameter names
		defaultOptionsMap.put(JavaCore.TIMEOUT_FOR_PARAMETER_NAME_FROM_ATTACHED_JAVADOC, "50"); //$NON-NLS-1$

		return new Hashtable(defaultOptionsMap);
	}

	/*
	 * Returns the per-project info for the given project. If specified, create the info if the info doesn't exist.
	 */
	public PerProjectInfo getPerProjectInfo(IProject project, boolean create) {
		synchronized(this.perProjectInfos) { // use the perProjectInfo collection as its own lock
			PerProjectInfo info= (PerProjectInfo) this.perProjectInfos.get(project);
			if (info == null && create) {
				info= new PerProjectInfo(project);
				this.perProjectInfos.put(project, info);
			}
			return info;
		}
	}

	/*
	 * Returns  the per-project info for the given project.
	 * If the info doesn't exist, check for the project existence and create the info.
	 * @throws JavaModelException if the project doesn't exist.
	 */
	public PerProjectInfo getPerProjectInfoCheckExistence(IProject project) throws JavaModelException {
		JavaModelManager.PerProjectInfo info = getPerProjectInfo(project, false /* don't create info */);
		if (info == null) {
			if (!JavaProject.hasJavaNature(project)) {
				throw ((JavaProject)JavaCore.create(project)).newNotPresentException();
			}
			info = getPerProjectInfo(project, true /* create info */);
		}
		return info;
	}

	/*
	 * Returns the per-working copy info for the given working copy at the given path.
	 * If it doesn't exist and if create, add a new per-working copy info with the given problem requestor.
	 * If recordUsage, increment the per-working copy info's use count.
	 * Returns null if it doesn't exist and not create.
	 */
	public PerWorkingCopyInfo getPerWorkingCopyInfo(CompilationUnit workingCopy,boolean create, boolean recordUsage, IProblemRequestor problemRequestor) {
		synchronized(this.perWorkingCopyInfos) { // use the perWorkingCopyInfo collection as its own lock
			WorkingCopyOwner owner = workingCopy.owner;
			Map workingCopyToInfos = (Map)this.perWorkingCopyInfos.get(owner);
			if (workingCopyToInfos == null && create) {
				workingCopyToInfos = new HashMap();
				this.perWorkingCopyInfos.put(owner, workingCopyToInfos);
			}

			PerWorkingCopyInfo info = workingCopyToInfos == null ? null : (PerWorkingCopyInfo) workingCopyToInfos.get(workingCopy);
			if (info == null && create) {
				info= new PerWorkingCopyInfo(workingCopy, problemRequestor);
				workingCopyToInfos.put(workingCopy, info);
			}
			if (info != null && recordUsage) info.useCount++;
			return info;
		}
	}

	/**
	 * Returns a persisted container from previous session if any. Note that it is not the original container from previous
	 * session (i.e. it did not get serialized) but rather a summary of its entries recreated for CP initialization purpose.
	 * As such it should not be stored into container caches.
	 */
	public IClasspathContainer getPreviousSessionContainer(IPath containerPath, IJavaProject project) {
			Map previousContainerValues = (Map)this.previousSessionContainers.get(project);
			if (previousContainerValues != null){
			    IClasspathContainer previousContainer = (IClasspathContainer)previousContainerValues.get(containerPath);
			    if (previousContainer != null) {
					if (JavaModelManager.CP_RESOLVE_VERBOSE_ADVANCED)
						verbose_reentering_project_container_access(containerPath, project, previousContainer);
					return previousContainer;
			    }
			}
		    return null; // break cycle if none found
	}

	private void verbose_reentering_project_container_access(	IPath containerPath, IJavaProject project, IClasspathContainer previousContainer) {
		StringBuffer buffer = new StringBuffer();
		buffer.append("CPContainer INIT - reentering access to project container during its initialization, will see previous value\n"); //$NON-NLS-1$
		buffer.append("	project: " + project.getElementName() + '\n'); //$NON-NLS-1$
		buffer.append("	container path: " + containerPath + '\n'); //$NON-NLS-1$
		buffer.append("	previous value: "); //$NON-NLS-1$
		buffer.append(previousContainer.getDescription());
		buffer.append(" {\n"); //$NON-NLS-1$
		IClasspathEntry[] entries = previousContainer.getClasspathEntries();
		if (entries != null){
			for (int j = 0; j < entries.length; j++){
				buffer.append(" 		"); //$NON-NLS-1$
				buffer.append(entries[j]);
				buffer.append('\n');
			}
		}
		buffer.append(" 	}"); //$NON-NLS-1$
		Util.verbose(buffer.toString());
		new Exception("<Fake exception>").printStackTrace(System.out); //$NON-NLS-1$
	}

	/**
	 * Returns a persisted container from previous session if any
	 */
	public IPath getPreviousSessionVariable(String variableName) {
		IPath previousPath = (IPath)this.previousSessionVariables.get(variableName);
		if (previousPath != null){
			if (CP_RESOLVE_VERBOSE_ADVANCED)
				verbose_reentering_variable_access(variableName, previousPath);
			return previousPath;
		}
	    return null; // break cycle
	}

	private void verbose_reentering_variable_access(String variableName, IPath previousPath) {
		Util.verbose(
			"CPVariable INIT - reentering access to variable during its initialization, will see previous value\n" + //$NON-NLS-1$
			"	variable: "+ variableName + '\n' + //$NON-NLS-1$
			"	previous value: " + previousPath); //$NON-NLS-1$
		new Exception("<Fake exception>").printStackTrace(System.out); //$NON-NLS-1$
	}

	/**
	 * Returns the temporary cache for newly opened elements for the current thread.
	 * Creates it if not already created.
	 */
	public HashMap getTemporaryCache() {
		HashMap result = (HashMap)this.temporaryCache.get();
		if (result == null) {
			result = new HashMap();
			this.temporaryCache.set(result);
		}
		return result;
	}

	private File getVariableAndContainersFile() {
		return JavaCore.getPlugin().getStateLocation().append("variablesAndContainers.dat").toFile(); //$NON-NLS-1$
	}

	/**
 	 * Returns the name of the variables for which an CP variable initializer is registered through an extension point
 	 */
	public static String[] getRegisteredVariableNames(){

		Plugin jdtCorePlugin = JavaCore.getPlugin();
		if (jdtCorePlugin == null) return null;

		ArrayList variableList = new ArrayList(5);
		IExtensionPoint extension = Platform.getExtensionRegistry().getExtensionPoint(JavaCore.PLUGIN_ID, JavaModelManager.CPVARIABLE_INITIALIZER_EXTPOINT_ID);
		if (extension != null) {
			IExtension[] extensions =  extension.getExtensions();
			for(int i = 0; i < extensions.length; i++){
				IConfigurationElement [] configElements = extensions[i].getConfigurationElements();
				for(int j = 0; j < configElements.length; j++){
					String varAttribute = configElements[j].getAttribute("variable"); //$NON-NLS-1$
					if (varAttribute != null) variableList.add(varAttribute);
				}
			}
		}
		String[] variableNames = new String[variableList.size()];
		variableList.toArray(variableNames);
		return variableNames;
	}

	/**
 	 * Returns the name of the container IDs for which an CP container initializer is registered through an extension point
 	 */
	public static String[] getRegisteredContainerIDs(){

		Plugin jdtCorePlugin = JavaCore.getPlugin();
		if (jdtCorePlugin == null) return null;

		ArrayList containerIDList = new ArrayList(5);
		IExtensionPoint extension = Platform.getExtensionRegistry().getExtensionPoint(JavaCore.PLUGIN_ID, JavaModelManager.CPCONTAINER_INITIALIZER_EXTPOINT_ID);
		if (extension != null) {
			IExtension[] extensions =  extension.getExtensions();
			for(int i = 0; i < extensions.length; i++){
				IConfigurationElement [] configElements = extensions[i].getConfigurationElements();
				for(int j = 0; j < configElements.length; j++){
					String idAttribute = configElements[j].getAttribute("id"); //$NON-NLS-1$
					if (idAttribute != null) containerIDList.add(idAttribute);
				}
			}
		}
		String[] containerIDs = new String[containerIDList.size()];
		containerIDList.toArray(containerIDs);
		return containerIDs;
	}

	public IClasspathEntry resolveVariableEntry(IClasspathEntry entry, boolean usePreviousSession) {

		if (entry.getEntryKind() != IClasspathEntry.CPE_VARIABLE)
			return entry;

		IPath resolvedPath = getResolvedVariablePath(entry.getPath(), usePreviousSession);
		if (resolvedPath == null)
			return null;
		// By passing a null reference path, we keep it relative to workspace root.
		resolvedPath = ClasspathEntry.resolveDotDot(null, resolvedPath);

		Object target = JavaModel.getTarget(resolvedPath, false);
		if (target == null)
			return null;

		// inside the workspace
		if (target instanceof IResource) {
			IResource resolvedResource = (IResource) target;
			switch (resolvedResource.getType()) {

				case IResource.PROJECT :
					// internal project
					return JavaCore.newProjectEntry(
							resolvedPath,
							entry.getAccessRules(),
							entry.combineAccessRules(),
							entry.getExtraAttributes(),
							entry.isExported());
				case IResource.FILE :
					// internal binary archive
					return JavaCore.newLibraryEntry(
							resolvedPath,
							getResolvedVariablePath(entry.getSourceAttachmentPath(), usePreviousSession),
							getResolvedVariablePath(entry.getSourceAttachmentRootPath(), usePreviousSession),
							entry.getAccessRules(),
							entry.getExtraAttributes(),
							entry.isExported());
				case IResource.FOLDER :
					// internal binary folder
					return JavaCore.newLibraryEntry(
							resolvedPath,
							getResolvedVariablePath(entry.getSourceAttachmentPath(), usePreviousSession),
							getResolvedVariablePath(entry.getSourceAttachmentRootPath(), usePreviousSession),
							entry.getAccessRules(),
							entry.getExtraAttributes(),
							entry.isExported());
			}
		}
		if (target instanceof File) {
			File externalFile = JavaModel.getFile(target);
			if (externalFile != null) {
				// external binary archive
				return JavaCore.newLibraryEntry(
						resolvedPath,
						getResolvedVariablePath(entry.getSourceAttachmentPath(), usePreviousSession),
						getResolvedVariablePath(entry.getSourceAttachmentRootPath(), usePreviousSession),
						entry.getAccessRules(),
						entry.getExtraAttributes(),
						entry.isExported());
			} else {
				// non-existing file
				if (resolvedPath.isAbsolute()){
					return JavaCore.newLibraryEntry(
							resolvedPath,
							getResolvedVariablePath(entry.getSourceAttachmentPath(), usePreviousSession),
							getResolvedVariablePath(entry.getSourceAttachmentRootPath(), usePreviousSession),
							entry.getAccessRules(),
							entry.getExtraAttributes(),
							entry.isExported());
				}
			}
		}
		return null;
	}

	public IPath getResolvedVariablePath(IPath variablePath, boolean usePreviousSession) {

		if (variablePath == null)
			return null;
		int count = variablePath.segmentCount();
		if (count == 0)
			return null;

		// lookup variable
		String variableName = variablePath.segment(0);
		IPath resolvedPath = usePreviousSession ? getPreviousSessionVariable(variableName) : JavaCore.getClasspathVariable(variableName);
		if (resolvedPath == null)
			return null;

		// append path suffix
		if (count > 1) {
			resolvedPath = resolvedPath.append(variablePath.removeFirstSegments(1));
		}
		return resolvedPath;
	}

	/**
	 * Returns the File to use for saving and restoring the last built state for the given project.
	 */
	private File getSerializationFile(IProject project) {
		if (!project.exists()) return null;
		IPath workingLocation = project.getWorkingLocation(JavaCore.PLUGIN_ID);
		return workingLocation.append("state.dat").toFile(); //$NON-NLS-1$
	}

	public static UserLibraryManager getUserLibraryManager() {
		if (MANAGER.userLibraryManager == null) {
			UserLibraryManager libraryManager = new UserLibraryManager();
			synchronized(MANAGER) {
				if (MANAGER.userLibraryManager == null) { // ensure another library manager was not set while creating the instance above
					MANAGER.userLibraryManager = libraryManager;
				}
			}
		}
		return MANAGER.userLibraryManager;
	}

	/*
	 * Returns all the working copies which have the given owner.
	 * Adds the working copies of the primary owner if specified.
	 * Returns null if it has none.
	 */
	public ICompilationUnit[] getWorkingCopies(WorkingCopyOwner owner, boolean addPrimary) {
		synchronized(this.perWorkingCopyInfos) {
			ICompilationUnit[] primaryWCs = addPrimary && owner != DefaultWorkingCopyOwner.PRIMARY
				? getWorkingCopies(DefaultWorkingCopyOwner.PRIMARY, false)
				: null;
			Map workingCopyToInfos = (Map)this.perWorkingCopyInfos.get(owner);
			if (workingCopyToInfos == null) return primaryWCs;
			int primaryLength = primaryWCs == null ? 0 : primaryWCs.length;
			int size = workingCopyToInfos.size(); // note size is > 0 otherwise pathToPerWorkingCopyInfos would be null
			ICompilationUnit[] result = new ICompilationUnit[primaryLength + size];
			int index = 0;
			if (primaryWCs != null) {
				for (int i = 0; i < primaryLength; i++) {
					ICompilationUnit primaryWorkingCopy = primaryWCs[i];
					ICompilationUnit workingCopy = new CompilationUnit((PackageFragment) primaryWorkingCopy.getParent(), primaryWorkingCopy.getElementName(), owner);
					if (!workingCopyToInfos.containsKey(workingCopy))
						result[index++] = primaryWorkingCopy;
				}
				if (index != primaryLength)
					System.arraycopy(result, 0, result = new ICompilationUnit[index+size], 0, index);
			}
			Iterator iterator = workingCopyToInfos.values().iterator();
			while(iterator.hasNext()) {
				result[index++] = ((JavaModelManager.PerWorkingCopyInfo)iterator.next()).getWorkingCopy();
			}
			return result;
		}
	}

	public JavaWorkspaceScope getWorkspaceScope() {
		if (this.workspaceScope == null) {
			this.workspaceScope = new JavaWorkspaceScope();
		}
		return this.workspaceScope;
	}

	public void verifyArchiveContent(IPath path) throws CoreException {
		if (isInvalidArchive(path)) {
			throw new CoreException(new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, -1, Messages.status_IOException, new ZipException()));			
		}
		ZipFile file = getZipFile(path);
		closeZipFile(file);
	}
	
	/**
	 * Returns the open ZipFile at the given path. If the ZipFile
	 * does not yet exist, it is created, opened, and added to the cache
	 * of open ZipFiles.
	 *
	 * The path must be a file system path if representing an external
	 * zip/jar, or it must be an absolute workspace relative path if
	 * representing a zip/jar inside the workspace.
	 *
	 * @exception CoreException If unable to create/open the ZipFile
	 */
	public ZipFile getZipFile(IPath path) throws CoreException {

		if (isInvalidArchive(path))
			throw new CoreException(new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, -1, Messages.status_IOException, new ZipException()));
		
		ZipCache zipCache;
		ZipFile zipFile;
		if ((zipCache = (ZipCache)this.zipFiles.get()) != null
				&& (zipFile = zipCache.getCache(path)) != null) {
			return zipFile;
		}
		File localFile = null;
		IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
		IResource file = root.findMember(path);
		if (file != null) {
			// internal resource
			URI location;
			if (file.getType() != IResource.FILE || (location = file.getLocationURI()) == null) {
				throw new CoreException(new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, -1, Messages.bind(Messages.file_notFound, path.toString()), null));
			}
			localFile = Util.toLocalFile(location, null/*no progress availaible*/);
			if (localFile == null)
				throw new CoreException(new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, -1, Messages.bind(Messages.file_notFound, path.toString()), null));
		} else {
			// external resource -> it is ok to use toFile()
			localFile= path.toFile();
		}

		try {
			if (ZIP_ACCESS_VERBOSE) {
				System.out.println("(" + Thread.currentThread() + ") [JavaModelManager.getZipFile(IPath)] Creating ZipFile on " + localFile ); //$NON-NLS-1$ //$NON-NLS-2$
			}
			zipFile = new ZipFile(localFile);
			if (zipCache != null) {
				zipCache.setCache(path, zipFile);
			}
			return zipFile;
		} catch (IOException e) {
			addInvalidArchive(path);
			throw new CoreException(new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, -1, Messages.status_IOException, e));
		}
	}

	/*
	 * Returns whether there is a temporary cache for the current thread.
	 */
	public boolean hasTemporaryCache() {
		return this.temporaryCache.get() != null;
	}

	/*
	 * Initialize all container at the same time as the given container.
	 * Return the container for the given path and project.
	 */
	private IClasspathContainer initializeAllContainers(IJavaProject javaProjectToInit, IPath containerToInit) throws JavaModelException {
		if (CP_RESOLVE_VERBOSE_ADVANCED)
			verbose_batching_containers_initialization(javaProjectToInit, containerToInit);

		// collect all container paths
		final HashMap allContainerPaths = new HashMap();
		IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
		for (int i = 0, length = projects.length; i < length; i++) {
			IProject project = projects[i];
			if (!JavaProject.hasJavaNature(project)) continue;
			IJavaProject javaProject = new JavaProject(project, getJavaModel());
			HashSet paths = (HashSet) allContainerPaths.get(javaProject);
			IClasspathEntry[] rawClasspath = javaProject.getRawClasspath();
			for (int j = 0, length2 = rawClasspath.length; j < length2; j++) {
				IClasspathEntry entry = rawClasspath[j];
				IPath path = entry.getPath();
				if (entry.getEntryKind() == IClasspathEntry.CPE_CONTAINER
						&& containerGet(javaProject, path) == null) {
					if (paths == null) {
						paths = new HashSet();
						allContainerPaths.put(javaProject, paths);
					}
					paths.add(path);
				}
			}
			/* TODO (frederic) put back when JDT/UI dummy project will be thrown away...
			 * See https://bugs.eclipse.org/bugs/show_bug.cgi?id=97524
			 *
			if (javaProject.equals(javaProjectToInit)) {
				if (paths == null) {
					paths = new HashSet();
					allContainerPaths.put(javaProject, paths);
				}
				paths.add(containerToInit);
			}
			*/
		}
		// TODO (frederic) remove following block when JDT/UI dummy project will be thrown away...
		if (javaProjectToInit != null) {
			HashSet containerPaths = (HashSet) allContainerPaths.get(javaProjectToInit);
			if (containerPaths == null) {
				containerPaths = new HashSet();
				allContainerPaths.put(javaProjectToInit, containerPaths);
			}
			containerPaths.add(containerToInit);
		}
		// end block

		// initialize all containers
		boolean ok = false;
		try {
			// if possible run inside an IWokspaceRunnable with AVOID_UPATE to avoid unwanted builds
			// (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=118507)
			IWorkspaceRunnable runnable =
				new IWorkspaceRunnable() {
					public void run(IProgressMonitor monitor) throws CoreException {
						try {
							// Collect all containers
							Set entrySet = allContainerPaths.entrySet();
							int length = entrySet.size();
							if (monitor != null)
								monitor.beginTask("", length); //$NON-NLS-1$
							Map.Entry[] entries = new Map.Entry[length]; // clone as the following will have a side effect
							entrySet.toArray(entries);
							for (int i = 0; i < length; i++) {
								Map.Entry entry = entries[i];
								IJavaProject javaProject = (IJavaProject) entry.getKey();
								HashSet pathSet = (HashSet) entry.getValue();
								if (pathSet == null) continue;
								int length2 = pathSet.size();
								IPath[] paths = new IPath[length2];
								pathSet.toArray(paths); // clone as the following will have a side effect
								for (int j = 0; j < length2; j++) {
									IPath path = paths[j];
									initializeContainer(javaProject, path);
									IClasspathContainer container = containerBeingInitializedGet(javaProject, path);
									if (container != null) {
										containerPut(javaProject, path, container);
									}
								}
								if (monitor != null)
									monitor.worked(1);
							}
							
							// Set all containers
							Map perProjectContainers = (Map) JavaModelManager.this.containersBeingInitialized.get();
							if (perProjectContainers != null) {
								Iterator entriesIterator = perProjectContainers.entrySet().iterator();
								while (entriesIterator.hasNext()) {
									Map.Entry entry = (Map.Entry) entriesIterator.next();
									IJavaProject project = (IJavaProject) entry.getKey();
									HashMap perPathContainers = (HashMap) entry.getValue();
									Iterator containersIterator = perPathContainers.entrySet().iterator();
									while (containersIterator.hasNext()) {
										Map.Entry containerEntry = (Map.Entry) containersIterator.next();
										IPath containerPath = (IPath) containerEntry.getKey();
										IClasspathContainer container = (IClasspathContainer) containerEntry.getValue();
										SetContainerOperation operation = new SetContainerOperation(containerPath, new IJavaProject[] {project}, new IClasspathContainer[] {container});
										operation.runOperation(monitor);
									}
								}
								JavaModelManager.this.containersBeingInitialized.set(null);
							}
						} finally {
							if (monitor != null)
								monitor.done();
						}
					}
				};
			IProgressMonitor monitor = this.batchContainerInitializationsProgress;
			IWorkspace workspace = ResourcesPlugin.getWorkspace();
			if (workspace.isTreeLocked())
				runnable.run(monitor);
			else
				workspace.run(
					runnable,
					null/*don't take any lock*/,
					IWorkspace.AVOID_UPDATE,
					monitor);
			ok = true;
		} catch (CoreException e) {
			// ignore
			Util.log(e, "Exception while initializing all containers"); //$NON-NLS-1$
		} finally {
			if (!ok) {
				// if we're being traversed by an exception, ensure that that containers are
				// no longer marked as initialization in progress
				// (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=66437)
				this.containerInitializationInProgress.set(null);
			}
		}

		return containerGet(javaProjectToInit, containerToInit);
	}

	private void verbose_batching_containers_initialization(IJavaProject javaProjectToInit, IPath containerToInit) {
		Util.verbose(
			"CPContainer INIT - batching containers initialization\n" + //$NON-NLS-1$
			"	project to init: " + (javaProjectToInit == null ? "null" : javaProjectToInit.getElementName()) + '\n' + //$NON-NLS-1$ //$NON-NLS-2$
			"	container path to init: " + containerToInit); //$NON-NLS-1$
	}

	IClasspathContainer initializeContainer(IJavaProject project, IPath containerPath) throws JavaModelException {

		IProgressMonitor monitor = this.batchContainerInitializationsProgress;
		if (monitor != null && monitor.isCanceled())
			throw new OperationCanceledException();

		IClasspathContainer container = null;
		final ClasspathContainerInitializer initializer = JavaCore.getClasspathContainerInitializer(containerPath.segment(0));
		if (initializer != null){
			if (CP_RESOLVE_VERBOSE)
				verbose_triggering_container_initialization(project, containerPath, initializer);
			if (CP_RESOLVE_VERBOSE_ADVANCED)
				verbose_triggering_container_initialization_invocation_trace();
			PerformanceStats stats = null;
			if(JavaModelManager.PERF_CONTAINER_INITIALIZER) {
				stats = PerformanceStats.getStats(JavaModelManager.CONTAINER_INITIALIZER_PERF, this);
				stats.startRun(containerPath + " of " + project.getPath()); //$NON-NLS-1$
			}
			containerPut(project, containerPath, CONTAINER_INITIALIZATION_IN_PROGRESS); // avoid initialization cycles
			boolean ok = false;
			try {
				if (monitor != null)
					monitor.subTask(Messages.bind(Messages.javamodel_configuring, initializer.getDescription(containerPath, project)));

				// let OperationCanceledException go through
				// (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=59363)
				initializer.initialize(containerPath, project);

				if (monitor != null)
					monitor.subTask(""); //$NON-NLS-1$

				// retrieve value (if initialization was successful)
				container = containerBeingInitializedGet(project, containerPath);
				if (container == null && containerGet(project, containerPath) == CONTAINER_INITIALIZATION_IN_PROGRESS) {
					// initializer failed to do its job: redirect to the failure container
					container = initializer.getFailureContainer(containerPath, project);
					if (container == null) {
						if (CP_RESOLVE_VERBOSE || CP_RESOLVE_VERBOSE_FAILURE)
							verbose_container_null_failure_container(project, containerPath, initializer);
						return null; // break cycle
					}
					if (CP_RESOLVE_VERBOSE || CP_RESOLVE_VERBOSE_FAILURE)
						verbose_container_using_failure_container(project, containerPath, initializer);
					containerPut(project, containerPath, container);
				}
				ok = true;
			} catch (CoreException e) {
				if (e instanceof JavaModelException) {
					throw (JavaModelException) e;
				} else {
					throw new JavaModelException(e);
				}
			} catch (RuntimeException e) {
				if (JavaModelManager.CP_RESOLVE_VERBOSE || CP_RESOLVE_VERBOSE_FAILURE)
					e.printStackTrace();
				throw e;
			} catch (Error e) {
				if (JavaModelManager.CP_RESOLVE_VERBOSE || CP_RESOLVE_VERBOSE_FAILURE)
					e.printStackTrace();
				throw e;
			} finally {
				if(JavaModelManager.PERF_CONTAINER_INITIALIZER) {
					stats.endRun();
				}
				if (!ok) {
					// just remove initialization in progress and keep previous session container so as to avoid a full build
					// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=92588
					containerRemoveInitializationInProgress(project, containerPath);
					if (CP_RESOLVE_VERBOSE || CP_RESOLVE_VERBOSE_FAILURE)
						verbose_container_initialization_failed(project, containerPath, container, initializer);
				}
			}
			if (CP_RESOLVE_VERBOSE_ADVANCED)
				verbose_container_value_after_initialization(project, containerPath, container);
		} else {
			// create a dummy initializer and get the default failure container
			container = (new ClasspathContainerInitializer() {
				public void initialize(IPath path, IJavaProject javaProject) throws CoreException {
					// not used
				}
			}).getFailureContainer(containerPath, project);
			if (CP_RESOLVE_VERBOSE_ADVANCED || CP_RESOLVE_VERBOSE_FAILURE)
				verbose_no_container_initializer_found(project, containerPath);
		}
		return container;
	}

	private void verbose_no_container_initializer_found(IJavaProject project, IPath containerPath) {
		Util.verbose(
			"CPContainer INIT - no initializer found\n" + //$NON-NLS-1$
			"	project: " + project.getElementName() + '\n' + //$NON-NLS-1$
			"	container path: " + containerPath); //$NON-NLS-1$
	}

	private void verbose_container_value_after_initialization(IJavaProject project, IPath containerPath, IClasspathContainer container) {
		StringBuffer buffer = new StringBuffer();
		buffer.append("CPContainer INIT - after resolution\n"); //$NON-NLS-1$
		buffer.append("	project: " + project.getElementName() + '\n'); //$NON-NLS-1$
		buffer.append("	container path: " + containerPath + '\n'); //$NON-NLS-1$
		if (container != null){
			buffer.append("	container: "+container.getDescription()+" {\n"); //$NON-NLS-2$//$NON-NLS-1$
			IClasspathEntry[] entries = container.getClasspathEntries();
			if (entries != null){
				for (int i = 0; i < entries.length; i++) {
					buffer.append("		" + entries[i] + '\n'); //$NON-NLS-1$
				}
			}
			buffer.append("	}");//$NON-NLS-1$
		} else {
			buffer.append("	container: {unbound}");//$NON-NLS-1$
		}
		Util.verbose(buffer.toString());
	}

	private void verbose_container_initialization_failed(IJavaProject project, IPath containerPath, IClasspathContainer container, ClasspathContainerInitializer initializer) {
		if (container == CONTAINER_INITIALIZATION_IN_PROGRESS) {
			Util.verbose(
				"CPContainer INIT - FAILED (initializer did not initialize container)\n" + //$NON-NLS-1$
				"	project: " + project.getElementName() + '\n' + //$NON-NLS-1$
				"	container path: " + containerPath + '\n' + //$NON-NLS-1$
				"	initializer: " + initializer); //$NON-NLS-1$

		} else {
			Util.verbose(
				"CPContainer INIT - FAILED (see exception above)\n" + //$NON-NLS-1$
				"	project: " + project.getElementName() + '\n' + //$NON-NLS-1$
				"	container path: " + containerPath + '\n' + //$NON-NLS-1$
				"	initializer: " + initializer); //$NON-NLS-1$
		}
	}

	private void verbose_container_null_failure_container(IJavaProject project, IPath containerPath,  ClasspathContainerInitializer initializer) {
		Util.verbose(
			"CPContainer INIT - FAILED (and failure container is null)\n" + //$NON-NLS-1$
			"	project: " + project.getElementName() + '\n' + //$NON-NLS-1$
			"	container path: " + containerPath + '\n' + //$NON-NLS-1$
			"	initializer: " + initializer); //$NON-NLS-1$
	}

	private void verbose_container_using_failure_container(IJavaProject project, IPath containerPath,  ClasspathContainerInitializer initializer) {
		Util.verbose(
			"CPContainer INIT - FAILED (using failure container)\n" + //$NON-NLS-1$
			"	project: " + project.getElementName() + '\n' + //$NON-NLS-1$
			"	container path: " + containerPath + '\n' + //$NON-NLS-1$
			"	initializer: " + initializer); //$NON-NLS-1$
	}

	private void verbose_triggering_container_initialization(IJavaProject project, IPath containerPath,  ClasspathContainerInitializer initializer) {
		Util.verbose(
			"CPContainer INIT - triggering initialization\n" + //$NON-NLS-1$
			"	project: " + project.getElementName() + '\n' + //$NON-NLS-1$
			"	container path: " + containerPath + '\n' + //$NON-NLS-1$
			"	initializer: " + initializer); //$NON-NLS-1$
	}

	private void verbose_triggering_container_initialization_invocation_trace() {
		Util.verbose(
			"CPContainer INIT - triggering initialization\n" + //$NON-NLS-1$
			"	invocation trace:"); //$NON-NLS-1$
		new Exception("<Fake exception>").printStackTrace(System.out); //$NON-NLS-1$
	}

	/**
	 * Initialize preferences lookups for JavaCore plug-in.
	 */
	public void initializePreferences() {

		// Create lookups
		this.preferencesLookup[PREF_INSTANCE] = InstanceScope.INSTANCE.getNode(JavaCore.PLUGIN_ID);
		this.preferencesLookup[PREF_DEFAULT] = DefaultScope.INSTANCE.getNode(JavaCore.PLUGIN_ID);

		// Listen to instance preferences node removal from parent in order to refresh stored one
		this.instanceNodeListener = new IEclipsePreferences.INodeChangeListener() {
			public void added(IEclipsePreferences.NodeChangeEvent event) {
				// do nothing
			}
			public void removed(IEclipsePreferences.NodeChangeEvent event) {
				if (event.getChild() == JavaModelManager.this.preferencesLookup[PREF_INSTANCE]) {
					JavaModelManager.this.preferencesLookup[PREF_INSTANCE] = InstanceScope.INSTANCE.getNode(JavaCore.PLUGIN_ID);
					JavaModelManager.this.preferencesLookup[PREF_INSTANCE].addPreferenceChangeListener(new EclipsePreferencesListener());
				}
			}
		};
		((IEclipsePreferences) this.preferencesLookup[PREF_INSTANCE].parent()).addNodeChangeListener(this.instanceNodeListener);
		this.preferencesLookup[PREF_INSTANCE].addPreferenceChangeListener(this.instancePreferencesListener = new EclipsePreferencesListener());

		// Listen to default preferences node removal from parent in order to refresh stored one
		this.defaultNodeListener = new IEclipsePreferences.INodeChangeListener() {
			public void added(IEclipsePreferences.NodeChangeEvent event) {
				// do nothing
			}
			public void removed(IEclipsePreferences.NodeChangeEvent event) {
				if (event.getChild() == JavaModelManager.this.preferencesLookup[PREF_DEFAULT]) {
					JavaModelManager.this.preferencesLookup[PREF_DEFAULT] = DefaultScope.INSTANCE.getNode(JavaCore.PLUGIN_ID);
				}
			}
		};
		((IEclipsePreferences) this.preferencesLookup[PREF_DEFAULT].parent()).addNodeChangeListener(this.defaultNodeListener);
	}

	public synchronized char[] intern(char[] array) {
		return this.charArraySymbols.add(array);
	}

	public synchronized String intern(String s) {
		// make sure to copy the string (so that it doesn't hold on the underlying char[] that might be much bigger than necessary)
		return (String) this.stringSymbols.add(new String(s));

		// Note1: String#intern() cannot be used as on some VMs this prevents the string from being garbage collected
		// Note 2: Instead of using a WeakHashset, one could use a WeakHashMap with the following implementation
		// 			   This would costs more per entry (one Entry object and one WeakReference more))

		/*
		WeakReference reference = (WeakReference) this.symbols.get(s);
		String existing;
		if (reference != null && (existing = (String) reference.get()) != null)
			return existing;
		this.symbols.put(s, new WeakReference(s));
		return s;
		*/
	}

	private HashSet getClasspathBeingResolved() {
	    HashSet result = (HashSet) this.classpathsBeingResolved.get();
	    if (result == null) {
	        result = new HashSet();
	        this.classpathsBeingResolved.set(result);
	    }
	    return result;
	}

	public boolean isClasspathBeingResolved(IJavaProject project) {
	    return getClasspathBeingResolved().contains(project);
	}

	/**
	 * @deprecated
	 */
	private boolean isDeprecatedOption(String optionName) {
		return JavaCore.COMPILER_PB_INVALID_IMPORT.equals(optionName)
				|| JavaCore.COMPILER_PB_UNREACHABLE_CODE.equals(optionName);
	}
	
	public boolean isNonChainingJar(IPath path) {
		return this.nonChainingJars != null && this.nonChainingJars.contains(path);
	}
	
	public boolean isInvalidArchive(IPath path) {
		return this.invalidArchives != null && this.invalidArchives.contains(path);
	}

	public void removeFromInvalidArchiveCache(IPath path) {
		if (this.invalidArchives != null) {
			this.invalidArchives.remove(path);
		}
	}

	public void setClasspathBeingResolved(IJavaProject project, boolean classpathIsResolved) {
	    if (classpathIsResolved) {
	        getClasspathBeingResolved().add(project);
	    } else {
	        getClasspathBeingResolved().remove(project);
	    }
	}
	
	private Set loadClasspathListCache(String cacheName) {
		Set pathCache = new HashSet();
		File cacheFile = getClasspathListFile(cacheName);
		DataInputStream in = null;
		try {
			in = new DataInputStream(new BufferedInputStream(new FileInputStream(cacheFile)));
			int size = in.readInt();
			while (size-- > 0) {
				String path = in.readUTF();
				pathCache.add(Path.fromPortableString(path));
			}
		} catch (IOException e) {
			if (cacheFile.exists())
				Util.log(e, "Unable to read non-chaining jar cache file"); //$NON-NLS-1$
		} finally {
			if (in != null) {
				try {
					in.close();
				} catch (IOException e) {
					// nothing we can do: ignore
				}
			}
		}
		return Collections.synchronizedSet(pathCache);
	}
	
	private File getClasspathListFile(String fileName) {
		return JavaCore.getPlugin().getStateLocation().append(fileName).toFile(); 
	}
	
	private Set getNonChainingJarsCache() throws CoreException {
		// Even if there is one entry in the cache, just return it. It may not be 
		// the complete cache, but avoid going through all the projects to populate the cache.
		if (this.nonChainingJars != null && this.nonChainingJars.size() > 0) {
			return this.nonChainingJars;
		}
		Set result = new HashSet();
		IJavaProject[] projects = getJavaModel().getJavaProjects();
		for (int i = 0, length = projects.length; i < length; i++) {
			IJavaProject javaProject = projects[i];
			IClasspathEntry[] classpath = ((JavaProject) javaProject).getResolvedClasspath();
			for (int j = 0, length2 = classpath.length; j < length2; j++) {
				IClasspathEntry entry = classpath[j];
				IPath path;
				if (entry.getEntryKind() == IClasspathEntry.CPE_LIBRARY 
					&& !result.contains(path = entry.getPath())
					&& ClasspathEntry.resolvedChainedLibraries(path).length == 0) {
						result.add(path);
				}
			}
		}
		this.nonChainingJars = Collections.synchronizedSet(result);
		return this.nonChainingJars;
	}
	
	private Set getClasspathListCache(String cacheName) throws CoreException {
		if (cacheName == NON_CHAINING_JARS_CACHE) 
			return getNonChainingJarsCache();
		else if (cacheName == INVALID_ARCHIVES_CACHE)
			return this.invalidArchives;
		else 
			return null;
	}
	
	public void loadVariablesAndContainers() throws CoreException {
		// backward compatibility, consider persistent property
		QualifiedName qName = new QualifiedName(JavaCore.PLUGIN_ID, "variables"); //$NON-NLS-1$
		String xmlString = ResourcesPlugin.getWorkspace().getRoot().getPersistentProperty(qName);

		try {
			if (xmlString != null){
				StringReader reader = new StringReader(xmlString);
				Element cpElement;
				try {
					DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder();
					cpElement = parser.parse(new InputSource(reader)).getDocumentElement();
				} catch(SAXException e) {
					return;
				} catch(ParserConfigurationException e){
					return;
				} finally {
					reader.close();
				}
				if (cpElement == null) return;
				if (!cpElement.getNodeName().equalsIgnoreCase("variables")) { //$NON-NLS-1$
					return;
				}

				NodeList list= cpElement.getChildNodes();
				int length= list.getLength();
				for (int i= 0; i < length; ++i) {
					Node node= list.item(i);
					short type= node.getNodeType();
					if (type == Node.ELEMENT_NODE) {
						Element element= (Element) node;
						if (element.getNodeName().equalsIgnoreCase("variable")) { //$NON-NLS-1$
							variablePut(
								element.getAttribute("name"), //$NON-NLS-1$
								new Path(element.getAttribute("path"))); //$NON-NLS-1$
						}
					}
				}
			}
		} catch(IOException e){
			// problem loading xml file: nothing we can do
		} finally {
			if (xmlString != null){
				ResourcesPlugin.getWorkspace().getRoot().setPersistentProperty(qName, null); // flush old one
			}
		}

		// backward compatibility, load variables and containers from preferences into cache
		loadVariablesAndContainers(getDefaultPreferences());
		loadVariablesAndContainers(getInstancePreferences());

		// load variables and containers from saved file into cache
		File file = getVariableAndContainersFile();
		DataInputStream in = null;
		try {
			in = new DataInputStream(new BufferedInputStream(new FileInputStream(file)));
			switch (in.readInt()) {
				case 2 :
					new VariablesAndContainersLoadHelper(in).load();
					break;
				case 1 : // backward compatibility, load old format
					// variables
					int size = in.readInt();
					while (size-- > 0) {
						String varName = in.readUTF();
						String pathString = in.readUTF();
						if (CP_ENTRY_IGNORE.equals(pathString))
							continue;
						IPath varPath = Path.fromPortableString(pathString);
						this.variables.put(varName, varPath);
						this.previousSessionVariables.put(varName, varPath);
					}

					// containers
					IJavaModel model = getJavaModel();
					int projectSize = in.readInt();
					while (projectSize-- > 0) {
						String projectName = in.readUTF();
						IJavaProject project = model.getJavaProject(projectName);
						int containerSize = in.readInt();
						while (containerSize-- > 0) {
							IPath containerPath = Path.fromPortableString(in.readUTF());
							int length = in.readInt();
							byte[] containerString = new byte[length];
							in.readFully(containerString);
							recreatePersistedContainer(project, containerPath, new String(containerString), true/*add to container values*/);
						}
					}
					break;
			}
		} catch (IOException e) {
			if (file.exists())
				Util.log(e, "Unable to read variable and containers file"); //$NON-NLS-1$
		} catch (RuntimeException e) {
			if (file.exists())
				Util.log(e, "Unable to read variable and containers file (file is corrupt)"); //$NON-NLS-1$
		} finally {
			if (in != null) {
				try {
					in.close();
				} catch (IOException e) {
					// nothing we can do: ignore
				}
			}
		}

		// override persisted values for variables which have a registered initializer
		String[] registeredVariables = getRegisteredVariableNames();
		for (int i = 0; i < registeredVariables.length; i++) {
			String varName = registeredVariables[i];
			this.variables.put(varName, null); // reset variable, but leave its entry in the Map, so it will be part of variable names.
		}
		// override persisted values for containers which have a registered initializer
		containersReset(getRegisteredContainerIDs());
	}

	private void loadVariablesAndContainers(IEclipsePreferences preferences) {
		try {
			// only get variable from preferences not set to their default
			String[] propertyNames = preferences.keys();
			int variablePrefixLength = CP_VARIABLE_PREFERENCES_PREFIX.length();
			for (int i = 0; i < propertyNames.length; i++){
				String propertyName = propertyNames[i];
				if (propertyName.startsWith(CP_VARIABLE_PREFERENCES_PREFIX)){
					String varName = propertyName.substring(variablePrefixLength);
					String propertyValue = preferences.get(propertyName, null);
					if (propertyValue != null) {
						String pathString = propertyValue.trim();

						if (CP_ENTRY_IGNORE.equals(pathString)) {
							// cleanup old preferences
							preferences.remove(propertyName);
							continue;
						}

						// add variable to table
						IPath varPath = new Path(pathString);
						this.variables.put(varName, varPath);
						this.previousSessionVariables.put(varName, varPath);
					}
				} else if (propertyName.startsWith(CP_CONTAINER_PREFERENCES_PREFIX)){
					String propertyValue = preferences.get(propertyName, null);
					if (propertyValue != null) {
						// cleanup old preferences
						preferences.remove(propertyName);

						// recreate container
						recreatePersistedContainer(propertyName, propertyValue, true/*add to container values*/);
					}
				}
			}
		} catch (BackingStoreException e1) {
			// TODO (frederic) see if it's necessary to report this failure...
		}
	}

	private static final class PersistedClasspathContainer implements
			IClasspathContainer {

		private final IPath containerPath;

		private final IClasspathEntry[] entries;

		private final IJavaProject project;

		PersistedClasspathContainer(IJavaProject project, IPath containerPath,
				IClasspathEntry[] entries) {
			super();
			this.containerPath = containerPath;
			this.entries = entries;
			this.project = project;
		}

		public IClasspathEntry[] getClasspathEntries() {
			return this.entries;
		}

		public String getDescription() {
			return "Persisted container [" + this.containerPath //$NON-NLS-1$
					+ " for project [" + this.project.getElementName() //$NON-NLS-1$
					+ "]]"; //$NON-NLS-1$
		}

		public int getKind() {
			return 0;
		}

		public IPath getPath() {
			return this.containerPath;
		}

		public String toString() {
			return getDescription();
		}
	}

	private final class VariablesAndContainersLoadHelper {

		private static final int ARRAY_INCREMENT = 200;

		private IClasspathEntry[] allClasspathEntries;
		private int allClasspathEntryCount;

		private final Map allPaths; // String -> IPath

		private String[] allStrings;
		private int allStringsCount;

		private final DataInputStream in;

		VariablesAndContainersLoadHelper(DataInputStream in) {
			super();
			this.allClasspathEntries = null;
			this.allClasspathEntryCount = 0;
			this.allPaths = new HashMap();
			this.allStrings = null;
			this.allStringsCount = 0;
			this.in = in;
		}

		void load() throws IOException {
			loadProjects(getJavaModel());
			loadVariables();
		}

		private IAccessRule loadAccessRule() throws IOException {
			int problemId = loadInt();
			IPath pattern = loadPath();
			return new ClasspathAccessRule(pattern.toString().toCharArray(), problemId);
		}

		private IAccessRule[] loadAccessRules() throws IOException {
			int count = loadInt();

			if (count == 0)
				return ClasspathEntry.NO_ACCESS_RULES;

			IAccessRule[] rules = new IAccessRule[count];

			for (int i = 0; i < count; ++i)
				rules[i] = loadAccessRule();

			return rules;
		}

		private IClasspathAttribute loadAttribute() throws IOException {
			String name = loadString();
			String value = loadString();

			return new ClasspathAttribute(name, value);
		}

		private IClasspathAttribute[] loadAttributes() throws IOException {
			int count = loadInt();

			if (count == 0)
				return ClasspathEntry.NO_EXTRA_ATTRIBUTES;

			IClasspathAttribute[] attributes = new IClasspathAttribute[count];

			for (int i = 0; i < count; ++i)
				attributes[i] = loadAttribute();

			return attributes;
		}

		private boolean loadBoolean() throws IOException {
			return this.in.readBoolean();
		}

		private IClasspathEntry[] loadClasspathEntries() throws IOException {
			int count = loadInt();
			IClasspathEntry[] entries = new IClasspathEntry[count];

			for (int i = 0; i < count; ++i)
				entries[i] = loadClasspathEntry();

			return entries;
		}

		private IClasspathEntry loadClasspathEntry() throws IOException {
			int id = loadInt();

			if (id < 0 || id > this.allClasspathEntryCount)
				throw new IOException("Unexpected classpathentry id"); //$NON-NLS-1$

			if (id < this.allClasspathEntryCount)
				return this.allClasspathEntries[id];

			int contentKind = loadInt();
			int entryKind = loadInt();
			IPath path = loadPath();
			IPath[] inclusionPatterns = loadPaths();
			IPath[] exclusionPatterns = loadPaths();
			IPath sourceAttachmentPath = loadPath();
			IPath sourceAttachmentRootPath = loadPath();
			IPath specificOutputLocation = loadPath();
			boolean isExported = loadBoolean();
			IAccessRule[] accessRules = loadAccessRules();
			boolean combineAccessRules = loadBoolean();
			IClasspathAttribute[] extraAttributes = loadAttributes();

			IClasspathEntry entry = new ClasspathEntry(contentKind, entryKind,
					path, inclusionPatterns, exclusionPatterns,
					sourceAttachmentPath, sourceAttachmentRootPath,
					specificOutputLocation, isExported, accessRules,
					combineAccessRules, extraAttributes);

			IClasspathEntry[] array = this.allClasspathEntries;

			if (array == null || id == array.length) {
				array = new IClasspathEntry[id + ARRAY_INCREMENT];

				if (id != 0)
					System.arraycopy(this.allClasspathEntries, 0, array, 0, id);

				this.allClasspathEntries = array;
			}

			array[id] = entry;
			this.allClasspathEntryCount = id + 1;

			return entry;
		}

		private void loadContainers(IJavaProject project) throws IOException {
			boolean projectIsAccessible = project.getProject().isAccessible();
			int count = loadInt();
			for (int i = 0; i < count; ++i) {
				IPath path = loadPath();
				IClasspathEntry[] entries = loadClasspathEntries();

				if (!projectIsAccessible)
					// avoid leaking deleted project's persisted container,
					// but still read the container as it is is part of the file format
					continue;

				IClasspathContainer container = new PersistedClasspathContainer(project, path, entries);

				containerPut(project, path, container);

				Map oldContainers = (Map) JavaModelManager.this.previousSessionContainers.get(project);

				if (oldContainers == null) {
					oldContainers = new HashMap();
					JavaModelManager.this.previousSessionContainers.put(project, oldContainers);
				}

				oldContainers.put(path, container);
			}
		}

		private int loadInt() throws IOException {
			return this.in.readInt();
		}

		private IPath loadPath() throws IOException {
			if (loadBoolean())
				return null;

			String portableString = loadString();
			IPath path = (IPath) this.allPaths.get(portableString);

			if (path == null) {
				path = Path.fromPortableString(portableString);
				this.allPaths.put(portableString, path);
			}

			return path;
		}

		private IPath[] loadPaths() throws IOException {
			int count = loadInt();
			IPath[] pathArray = new IPath[count];

			for (int i = 0; i < count; ++i)
				pathArray[i] = loadPath();

			return pathArray;
		}

		private void loadProjects(IJavaModel model) throws IOException {
			int count = loadInt();

			for (int i = 0; i < count; ++i) {
				String projectName = loadString();

				loadContainers(model.getJavaProject(projectName));
			}
		}

		private String loadString() throws IOException {
			int id = loadInt();

			if (id < 0 || id > this.allStringsCount)
				throw new IOException("Unexpected string id"); //$NON-NLS-1$

			if (id < this.allStringsCount)
				return this.allStrings[id];

			String string = this.in.readUTF();
			String[] array = this.allStrings;

			if (array == null || id == array.length) {
				array = new String[id + ARRAY_INCREMENT];

				if (id != 0)
					System.arraycopy(this.allStrings, 0, array, 0, id);

				this.allStrings = array;
			}

			array[id] = string;
			this.allStringsCount = id + 1;

			return string;
		}

		private void loadVariables() throws IOException {
			int size = loadInt();
			Map loadedVars = new HashMap(size);

			for (int i = 0; i < size; ++i) {
				String varName = loadString();
				IPath varPath = loadPath();

				if (varPath != null)
					loadedVars.put(varName, varPath);
			}

			JavaModelManager.this.previousSessionVariables.putAll(loadedVars);
			JavaModelManager.this.variables.putAll(loadedVars);
		}
	}

	/**
	 *  Returns the info for this element without
	 *  disturbing the cache ordering.
	 */
	protected synchronized Object peekAtInfo(IJavaElement element) {
		HashMap tempCache = (HashMap)this.temporaryCache.get();
		if (tempCache != null) {
			Object result = tempCache.get(element);
			if (result != null) {
				return result;
			}
		}
		return this.cache.peekAtInfo(element);
	}

	/**
	 * @see ISaveParticipant
	 */
	public void prepareToSave(ISaveContext context) /*throws CoreException*/ {
		// nothing to do
	}
	/*
	 * Puts the infos in the given map (keys are IJavaElements and values are JavaElementInfos)
	 * in the Java model cache in an atomic way if the info is not already present in the cache. 
	 * If the info is already present in the cache, it depends upon the forceAdd parameter.
	 * If forceAdd is false it just returns the existing info and if true, this element and it's children are closed and then 
	 * this particular info is added to the cache.
	 */
	protected synchronized Object putInfos(IJavaElement openedElement, Object newInfo, boolean forceAdd, Map newElements) {
		// remove existing children as the are replaced with the new children contained in newElements
		Object existingInfo = this.cache.peekAtInfo(openedElement);
		if (existingInfo != null && !forceAdd) {
			// If forceAdd is false, then it could mean that the particular element 
			// wasn't in cache at that point of time, but would have got added through 
			// another thread. In that case, removing the children could remove it's own
			// children. So, we should not remove the children but return the already existing 
			// info.
			// https://bugs.eclipse.org/bugs/show_bug.cgi?id=372687
			return existingInfo;
		}
		if (openedElement instanceof IParent) {
			closeChildren(existingInfo);
		}

		// Need to put any JarPackageFragmentRoot in first.
		// This is due to the way the LRU cache flushes entries.
		// When a JarPackageFragment is flushed from the LRU cache, the entire
		// jar is flushed by removing the JarPackageFragmentRoot and all of its
		// children (see ElementCache.close()). If we flush the JarPackageFragment
		// when its JarPackageFragmentRoot is not in the cache and the root is about to be
		// added (during the 'while' loop), we will end up in an inconsistent state.
		// Subsequent resolution against package in the jar would fail as a result.
		// https://bugs.eclipse.org/bugs/show_bug.cgi?id=102422
		// (theodora)
		for(Iterator it = newElements.entrySet().iterator(); it.hasNext(); ) {
			Map.Entry entry = (Map.Entry)it.next();
			IJavaElement element = (IJavaElement)entry.getKey();
			if (element instanceof JarPackageFragmentRoot) {
				Object info = entry.getValue();
				it.remove();
				this.cache.putInfo(element, info);
			}
		}

		Iterator iterator = newElements.entrySet().iterator();
		while (iterator.hasNext()) {
			Map.Entry entry = (Map.Entry) iterator.next();
			this.cache.putInfo((IJavaElement) entry.getKey(), entry.getValue());
		}
		return newInfo;
	}

	private void closeChildren(Object info) {
		if (info instanceof JavaElementInfo) {
			IJavaElement[] children = ((JavaElementInfo)info).getChildren();
			for (int i = 0, size = children.length; i < size; ++i) {
				JavaElement child = (JavaElement) children[i];
				try {
					child.close();
				} catch (JavaModelException e) {
					// ignore
				}
			}
		}
	}

	/*
	 * Remember the info for the jar binary type
	 */
	protected synchronized void putJarTypeInfo(IJavaElement type, Object info) {
		this.cache.jarTypeCache.put(type, info);
	}

	/**
	 * Reads the build state for the relevant project.
	 */
	protected Object readState(IProject project) throws CoreException {
		File file = getSerializationFile(project);
		if (file != null && file.exists()) {
			try {
				DataInputStream in= new DataInputStream(new BufferedInputStream(new FileInputStream(file)));
				try {
					String pluginID= in.readUTF();
					if (!pluginID.equals(JavaCore.PLUGIN_ID))
						throw new IOException(Messages.build_wrongFileFormat);
					String kind= in.readUTF();
					if (!kind.equals("STATE")) //$NON-NLS-1$
						throw new IOException(Messages.build_wrongFileFormat);
					if (in.readBoolean())
						return JavaBuilder.readState(project, in);
					if (JavaBuilder.DEBUG)
						System.out.println("Saved state thinks last build failed for " + project.getName()); //$NON-NLS-1$
				} finally {
					in.close();
				}
			} catch (Exception e) {
				e.printStackTrace();
				throw new CoreException(new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, Platform.PLUGIN_ERROR, "Error reading last build state for project "+ project.getName(), e)); //$NON-NLS-1$
			}
		} else if (JavaBuilder.DEBUG) {
			if (file == null)
				System.out.println("Project does not exist: " + project); //$NON-NLS-1$
			else
				System.out.println("Build state file " + file.getPath() + " does not exist"); //$NON-NLS-1$ //$NON-NLS-2$
		}
		return null;
	}

	public static void recreatePersistedContainer(String propertyName, String containerString, boolean addToContainerValues) {
		int containerPrefixLength = CP_CONTAINER_PREFERENCES_PREFIX.length();
		int index = propertyName.indexOf('|', containerPrefixLength);
		if (containerString != null) containerString = containerString.trim();
		if (index > 0) {
			String projectName = propertyName.substring(containerPrefixLength, index).trim();
			IJavaProject project = getJavaModelManager().getJavaModel().getJavaProject(projectName);
			IPath containerPath = new Path(propertyName.substring(index+1).trim());
			recreatePersistedContainer(project, containerPath, containerString, addToContainerValues);
		}
	}

	private static void recreatePersistedContainer(final IJavaProject project, final IPath containerPath, String containerString, boolean addToContainerValues) {
		if (!project.getProject().isAccessible()) return; // avoid leaking deleted project's persisted container
		if (containerString == null) {
			getJavaModelManager().containerPut(project, containerPath, null);
		} else {
			IClasspathEntry[] entries;
			try {
				entries = ((JavaProject) project).decodeClasspath(containerString, null/*not interested in unknown elements*/)[0];
			} catch (IOException e) {
				Util.log(e, "Could not recreate persisted container: \n" + containerString); //$NON-NLS-1$
				entries = JavaProject.INVALID_CLASSPATH;
			}
			if (entries != JavaProject.INVALID_CLASSPATH) {
				final IClasspathEntry[] containerEntries = entries;
				IClasspathContainer container = new IClasspathContainer() {
					public IClasspathEntry[] getClasspathEntries() {
						return containerEntries;
					}
					public String getDescription() {
						return "Persisted container ["+containerPath+" for project ["+ project.getElementName()+"]"; //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
					}
					public int getKind() {
						return 0;
					}
					public IPath getPath() {
						return containerPath;
					}
					public String toString() {
						return getDescription();
					}

				};
				if (addToContainerValues) {
					getJavaModelManager().containerPut(project, containerPath, container);
				}
				Map projectContainers = (Map)getJavaModelManager().previousSessionContainers.get(project);
				if (projectContainers == null){
					projectContainers = new HashMap(1);
					getJavaModelManager().previousSessionContainers.put(project, projectContainers);
				}
				projectContainers.put(containerPath, container);
			}
		}
	}

	/**
	 * Remembers the given scope in a weak set
	 * (so no need to remove it: it will be removed by the garbage collector)
	 */
	public void rememberScope(AbstractSearchScope scope) {
		// NB: The value has to be null so as to not create a strong reference on the scope
		this.searchScopes.put(scope, null);
	}

	/*
	 * Removes all cached info for the given element (including all children)
	 * from the cache.
	 * Returns the info for the given element, or null if it was closed.
	 */
	public synchronized Object removeInfoAndChildren(JavaElement element) throws JavaModelException {
		Object info = this.cache.peekAtInfo(element);
		if (info != null) {
			boolean wasVerbose = false;
			try {
				if (JavaModelCache.VERBOSE) {
					String elementType;
					switch (element.getElementType()) {
						case IJavaElement.JAVA_PROJECT:
							elementType = "project"; //$NON-NLS-1$
							break;
						case IJavaElement.PACKAGE_FRAGMENT_ROOT:
							elementType = "root"; //$NON-NLS-1$
							break;
						case IJavaElement.PACKAGE_FRAGMENT:
							elementType = "package"; //$NON-NLS-1$
							break;
						case IJavaElement.CLASS_FILE:
							elementType = "class file"; //$NON-NLS-1$
							break;
						case IJavaElement.COMPILATION_UNIT:
							elementType = "compilation unit"; //$NON-NLS-1$
							break;
						default:
							elementType = "element"; //$NON-NLS-1$
					}
					System.out.println(Thread.currentThread() + " CLOSING "+ elementType + " " + element.toStringWithAncestors());  //$NON-NLS-1$//$NON-NLS-2$
					wasVerbose = true;
					JavaModelCache.VERBOSE = false;
				}
				element.closing(info);
				if (element instanceof IParent) {
					closeChildren(info);
				}
				this.cache.removeInfo(element);
				if (wasVerbose) {
					System.out.println(this.cache.toStringFillingRation("-> ")); //$NON-NLS-1$
				}
			} finally {
				JavaModelCache.VERBOSE = wasVerbose;
			}
			return info;
		}
		return null;
	}

	public void removePerProjectInfo(JavaProject javaProject, boolean removeExtJarInfo) {
		synchronized(this.perProjectInfos) { // use the perProjectInfo collection as its own lock
			IProject project = javaProject.getProject();
			PerProjectInfo info= (PerProjectInfo) this.perProjectInfos.get(project);
			if (info != null) {
				this.perProjectInfos.remove(project);
				if (removeExtJarInfo) {
					info.forgetExternalTimestampsAndIndexes();
				}
			}
		}
		resetClasspathListCache();
	}

	/*
	 * Reset project options stored in info cache.
	 */
	public void resetProjectOptions(JavaProject javaProject) {
		synchronized(this.perProjectInfos) { // use the perProjectInfo collection as its own lock
			IProject project = javaProject.getProject();
			PerProjectInfo info= (PerProjectInfo) this.perProjectInfos.get(project);
			if (info != null) {
				info.options = null;
			}
		}
	}

	/*
	 * Reset project preferences stored in info cache.
	 */
	public void resetProjectPreferences(JavaProject javaProject) {
		synchronized(this.perProjectInfos) { // use the perProjectInfo collection as its own lock
			IProject project = javaProject.getProject();
			PerProjectInfo info= (PerProjectInfo) this.perProjectInfos.get(project);
			if (info != null) {
				info.preferences = null;
			}
		}
	}

	public static final void doNotUse() {
		// used by tests to simulate a startup
		MANAGER.deltaState.doNotUse();
		MANAGER = new JavaModelManager();
	}

	/*
	 * Resets the cache that holds on binary type in jar files
	 */
	protected synchronized void resetJarTypeCache() {
		this.cache.resetJarTypeCache();
	}
	
	public void resetClasspathListCache() {
		if (this.nonChainingJars != null) 
			this.nonChainingJars.clear();
		if (this.invalidArchives != null) 
			this.invalidArchives.clear();
	}

	/*
	 * Resets the temporary cache for newly created elements to null.
	 */
	public void resetTemporaryCache() {
		this.temporaryCache.set(null);
	}

	/**
	 * @see ISaveParticipant
	 */
	public void rollback(ISaveContext context){
		// nothing to do
	}

	private void saveState(PerProjectInfo info, ISaveContext context) throws CoreException {

		// passed this point, save actions are non trivial
		if (context.getKind() == ISaveContext.SNAPSHOT) return;

		// save built state
		if (info.triedRead) saveBuiltState(info);
	}

	/**
	 * Saves the built state for the project.
	 */
	private void saveBuiltState(PerProjectInfo info) throws CoreException {
		if (JavaBuilder.DEBUG)
			System.out.println(Messages.bind(Messages.build_saveStateProgress, info.project.getName()));
		File file = getSerializationFile(info.project);
		if (file == null) return;
		long t = System.currentTimeMillis();
		try {
			DataOutputStream out = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(file)));
			try {
				out.writeUTF(JavaCore.PLUGIN_ID);
				out.writeUTF("STATE"); //$NON-NLS-1$
				if (info.savedState == null) {
					out.writeBoolean(false);
				} else {
					out.writeBoolean(true);
					JavaBuilder.writeState(info.savedState, out);
				}
			} finally {
				out.close();
			}
		} catch (RuntimeException e) {
			try {
				file.delete();
			} catch(SecurityException se) {
				// could not delete file: cannot do much more
			}
			throw new CoreException(
				new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, Platform.PLUGIN_ERROR,
					Messages.bind(Messages.build_cannotSaveState, info.project.getName()), e));
		} catch (IOException e) {
			try {
				file.delete();
			} catch(SecurityException se) {
				// could not delete file: cannot do much more
			}
			throw new CoreException(
				new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, Platform.PLUGIN_ERROR,
					Messages.bind(Messages.build_cannotSaveState, info.project.getName()), e));
		}
		if (JavaBuilder.DEBUG) {
			t = System.currentTimeMillis() - t;
			System.out.println(Messages.bind(Messages.build_saveStateComplete, String.valueOf(t)));
		}
	}

	private void saveClasspathListCache(String cacheName) throws CoreException {
		File file = getClasspathListFile(cacheName);
		DataOutputStream out = null;
		try {
			out = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(file)));
			Set pathCache = getClasspathListCache(cacheName);
			synchronized (pathCache) {
				out.writeInt(pathCache.size());
				Iterator entries = pathCache.iterator();
				while (entries.hasNext()) {
					IPath path = (IPath) entries.next();
					out.writeUTF(path.toPortableString());
				}
			}
		} catch (IOException e) {
			IStatus status = new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, IStatus.ERROR, "Problems while saving non-chaining jar cache", e); //$NON-NLS-1$
			throw new CoreException(status);
		} finally {
			if (out != null) {
				try {
					out.close();
				} catch (IOException e) {
					// nothing we can do: ignore
				}
			}
		}
	}
	
	private void saveVariablesAndContainers(ISaveContext context) throws CoreException {
		File file = getVariableAndContainersFile();
		DataOutputStream out = null;
		try {
			out = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(file)));
			out.writeInt(VARIABLES_AND_CONTAINERS_FILE_VERSION);
			new VariablesAndContainersSaveHelper(out).save(context);
		} catch (IOException e) {
			IStatus status = new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, IStatus.ERROR, "Problems while saving variables and containers", e); //$NON-NLS-1$
			throw new CoreException(status);
		} finally {
			if (out != null) {
				try {
					out.close();
				} catch (IOException e) {
					// nothing we can do: ignore
				}
			}
		}
	}

	private final class VariablesAndContainersSaveHelper {

		private final HashtableOfObjectToInt classpathEntryIds; // IClasspathEntry -> int
		private final DataOutputStream out;
		private final HashtableOfObjectToInt stringIds; // Strings -> int

		VariablesAndContainersSaveHelper(DataOutputStream out) {
			super();
			this.classpathEntryIds = new HashtableOfObjectToInt();
			this.out = out;
			this.stringIds = new HashtableOfObjectToInt();
		}

		void save(ISaveContext context) throws IOException, JavaModelException {
			saveProjects(getJavaModel().getJavaProjects());
			// remove variables that should not be saved
			HashMap varsToSave = null;
			Iterator iterator = JavaModelManager.this.variables.entrySet().iterator();
			IEclipsePreferences defaultPreferences = getDefaultPreferences();
			while (iterator.hasNext()) {
				Map.Entry entry = (Map.Entry) iterator.next();
				String varName = (String) entry.getKey();
				if (defaultPreferences.get(CP_VARIABLE_PREFERENCES_PREFIX + varName, null) != null // don't save classpath variables from the default preferences as there is no delta if they are removed
						|| CP_ENTRY_IGNORE_PATH.equals(entry.getValue())) {

					if (varsToSave == null)
						varsToSave = new HashMap(JavaModelManager.this.variables);
					varsToSave.remove(varName);
				}
			}
			saveVariables(varsToSave != null ? varsToSave : JavaModelManager.this.variables);
		}

		private void saveAccessRule(ClasspathAccessRule rule) throws IOException {
			saveInt(rule.problemId);
			savePath(rule.getPattern());
		}

		private void saveAccessRules(IAccessRule[] rules) throws IOException {
			int count = rules == null ? 0 : rules.length;

			saveInt(count);
			for (int i = 0; i < count; ++i)
				saveAccessRule((ClasspathAccessRule) rules[i]);
		}

		private void saveAttribute(IClasspathAttribute attribute)
				throws IOException {
			saveString(attribute.getName());
			saveString(attribute.getValue());
		}

		private void saveAttributes(IClasspathAttribute[] attributes)
				throws IOException {
			int count = attributes == null ? 0 : attributes.length;

			saveInt(count);
			for (int i = 0; i < count; ++i)
				saveAttribute(attributes[i]);
		}

		private void saveClasspathEntries(IClasspathEntry[] entries)
				throws IOException {
			int count = entries == null ? 0 : entries.length;

			saveInt(count);
			for (int i = 0; i < count; ++i)
				saveClasspathEntry(entries[i]);
		}

		private void saveClasspathEntry(IClasspathEntry entry)
				throws IOException {
			if (saveNewId(entry, this.classpathEntryIds)) {
				saveInt(entry.getContentKind());
				saveInt(entry.getEntryKind());
				savePath(entry.getPath());
				savePaths(entry.getInclusionPatterns());
				savePaths(entry.getExclusionPatterns());
				savePath(entry.getSourceAttachmentPath());
				savePath(entry.getSourceAttachmentRootPath());
				savePath(entry.getOutputLocation());
				this.out.writeBoolean(entry.isExported());
				saveAccessRules(entry.getAccessRules());
				this.out.writeBoolean(entry.combineAccessRules());
				saveAttributes(entry.getExtraAttributes());
			}
		}

		private void saveContainers(IJavaProject project, Map containerMap)
				throws IOException {
			saveInt(containerMap.size());

			for (Iterator i = containerMap.entrySet().iterator(); i.hasNext();) {
				Entry entry = (Entry) i.next();
				IPath path = (IPath) entry.getKey();
				IClasspathContainer container = (IClasspathContainer) entry.getValue();
				IClasspathEntry[] cpEntries = null;

				if (container == null) {
					// container has not been initialized yet, use previous
					// session value
					// (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=73969)
					container = getPreviousSessionContainer(path, project);
				}

				if (container != null)
					cpEntries = container.getClasspathEntries();

				savePath(path);
				saveClasspathEntries(cpEntries);
			}
		}

		private void saveInt(int value) throws IOException {
			this.out.writeInt(value);
		}

		private boolean saveNewId(Object key, HashtableOfObjectToInt map) throws IOException {
			int id = map.get(key);

			if (id == -1) {
				int newId = map.size();

				map.put(key, newId);

				saveInt(newId);

				return true;
			} else {
				saveInt(id);

				return false;
			}
		}

		private void savePath(IPath path) throws IOException {
			if (path == null) {
				this.out.writeBoolean(true);
			} else {
				this.out.writeBoolean(false);
				saveString(path.toPortableString());
			}
		}

		private void savePaths(IPath[] paths) throws IOException {
			int count = paths == null ? 0 : paths.length;

			saveInt(count);
			for (int i = 0; i < count; ++i)
				savePath(paths[i]);
		}

		private void saveProjects(IJavaProject[] projects) throws IOException,
				JavaModelException {
			int count = projects.length;

			saveInt(count);

			for (int i = 0; i < count; ++i) {
				IJavaProject project = projects[i];

				saveString(project.getElementName());

				Map containerMap = (Map) JavaModelManager.this.containers.get(project);

				if (containerMap == null) {
					containerMap = Collections.EMPTY_MAP;
				} else {
					// clone while iterating
					// (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=59638)
					containerMap = new HashMap(containerMap);
				}

				saveContainers(project, containerMap);
			}
		}

		private void saveString(String string) throws IOException {
			if (saveNewId(string, this.stringIds))
				this.out.writeUTF(string);
		}

		private void saveVariables(Map map) throws IOException {
			saveInt(map.size());

			for (Iterator i = map.entrySet().iterator(); i.hasNext();) {
				Entry entry = (Entry) i.next();
				String varName = (String) entry.getKey();
				IPath varPath = (IPath) entry.getValue();

				saveString(varName);
				savePath(varPath);
			}
		}
	}

	private void traceVariableAndContainers(String action, long start) {

		Long delta = new Long(System.currentTimeMillis() - start);
		Long length = new Long(getVariableAndContainersFile().length());
		String pattern = "{0} {1} bytes in variablesAndContainers.dat in {2}ms"; //$NON-NLS-1$
		String message = MessageFormat.format(pattern, new Object[]{action, length, delta});

		System.out.println(message);
	}

	/**
	 * @see ISaveParticipant
	 */
	public void saving(ISaveContext context) throws CoreException {

	    long start = -1;
		if (VERBOSE)
			start = System.currentTimeMillis();

		// save variable and container values on snapshot/full save
		saveVariablesAndContainers(context);
		
		if (VERBOSE)
			traceVariableAndContainers("Saved", start); //$NON-NLS-1$

		switch(context.getKind()) {
			case ISaveContext.FULL_SAVE : {
				// save non-chaining jar and invalid jar caches on full save
				saveClasspathListCache(NON_CHAINING_JARS_CACHE);
				saveClasspathListCache(INVALID_ARCHIVES_CACHE);
	
				// will need delta since this save (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=38658)
				context.needDelta();
	
				// clean up indexes on workspace full save
				// (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=52347)
				IndexManager manager = this.indexManager;
				if (manager != null
						// don't force initialization of workspace scope as we could be shutting down
						// (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=93941)
						&& this.workspaceScope != null) {
					manager.cleanUpIndexes();
				}
			}
			//$FALL-THROUGH$
			case ISaveContext.SNAPSHOT : {
				// clean up external folders on full save or snapshot
				this.externalFoldersManager.cleanUp(null);
			}
		}

		IProject savedProject = context.getProject();
		if (savedProject != null) {
			if (!JavaProject.hasJavaNature(savedProject)) return; // ignore
			PerProjectInfo info = getPerProjectInfo(savedProject, true /* create info */);
			saveState(info, context);
			return;
		}

		ArrayList vStats= null; // lazy initialized
		ArrayList values = null;
		synchronized(this.perProjectInfos) {
			values = new ArrayList(this.perProjectInfos.values());
		}
		Iterator iterator = values.iterator();
		while (iterator.hasNext()) {
			try {
				PerProjectInfo info = (PerProjectInfo) iterator.next();
				saveState(info, context);
			} catch (CoreException e) {
				if (vStats == null)
					vStats= new ArrayList();
				vStats.add(e.getStatus());
			}
		}
		if (vStats != null) {
			IStatus[] stats= new IStatus[vStats.size()];
			vStats.toArray(stats);
			throw new CoreException(new MultiStatus(JavaCore.PLUGIN_ID, IStatus.ERROR, stats, Messages.build_cannotSaveStates, null));
		}

		// save external libs timestamps
		this.deltaState.saveExternalLibTimeStamps();

	}

	/**
	 * Add a secondary type in temporary indexing cache for a project got from given path.
	 *
	 * Current secondary types cache is not modified as we want to wait that indexing
	 * was finished before taking new secondary types into account.
	 *
	 * Indexing cache is a specific entry in secondary types cache which key is
	 * {@link #INDEXED_SECONDARY_TYPES } and value a map with same structure than
	 * secondary types cache itself.
	 *
	 * @see #secondaryTypes(IJavaProject, boolean, IProgressMonitor)
	 */
	public void secondaryTypeAdding(String path, char[] typeName, char[] packageName) {
		if (VERBOSE) {
			StringBuffer buffer = new StringBuffer("JavaModelManager.addSecondaryType("); //$NON-NLS-1$
			buffer.append(path);
			buffer.append(',');
			buffer.append('[');
			buffer.append(new String(packageName));
			buffer.append('.');
			buffer.append(new String(typeName));
			buffer.append(']');
			buffer.append(')');
			Util.verbose(buffer.toString());
		}
		IWorkspaceRoot wRoot = ResourcesPlugin.getWorkspace().getRoot();
		IResource resource = wRoot.findMember(path);
		if (resource != null) {
			if (org.eclipse.jdt.internal.core.util.Util.isJavaLikeFileName(path) && resource.getType() == IResource.FILE) {
				IProject project = resource.getProject();
				try {
					PerProjectInfo projectInfo = getPerProjectInfoCheckExistence(project);
					// Get or create map to cache secondary types while indexing (can be not synchronized as indexing insure a non-concurrent usage)
					HashMap indexedSecondaryTypes = null;
					if (projectInfo.secondaryTypes == null) {
						projectInfo.secondaryTypes = new Hashtable(3);
						indexedSecondaryTypes = new HashMap(3);
						projectInfo.secondaryTypes.put(INDEXED_SECONDARY_TYPES, indexedSecondaryTypes);
					} else {
						indexedSecondaryTypes = (HashMap) projectInfo.secondaryTypes.get(INDEXED_SECONDARY_TYPES);
						if (indexedSecondaryTypes == null) {
							indexedSecondaryTypes = new HashMap(3);
							projectInfo.secondaryTypes.put(INDEXED_SECONDARY_TYPES, indexedSecondaryTypes);
						}
					}
					// Store the secondary type in temporary cache (these are just handles => no problem to create it now...)
					HashMap allTypes = (HashMap) indexedSecondaryTypes.get(resource);
					if (allTypes == null) {
						allTypes = new HashMap(3);
						indexedSecondaryTypes.put(resource, allTypes);
					}
					ICompilationUnit unit = JavaModelManager.createCompilationUnitFrom((IFile)resource, null);
					if (unit != null) {
						String typeString = new String(typeName);
						IType type = unit.getType(typeString);
						// String packageString = new String(packageName);
						// use package fragment name instead of parameter as it may be invalid...
						// see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=186781
						String packageString = type.getPackageFragment().getElementName();
						HashMap packageTypes = (HashMap) allTypes.get(packageString);
						if (packageTypes == null) {
							packageTypes = new HashMap(3);
							allTypes.put(packageString, packageTypes);
						}
						packageTypes.put(typeString, type);
					}
					if (VERBOSE) {
						Util.verbose("	- indexing cache:"); //$NON-NLS-1$
						Iterator entries = indexedSecondaryTypes.entrySet().iterator();
						while (entries.hasNext()) {
							Map.Entry entry = (Map.Entry) entries.next();
							IFile file = (IFile) entry.getKey();
							Util.verbose("		+ "+file.getFullPath()+':'+ entry.getValue()); //$NON-NLS-1$
						}
					}
				}
				catch (JavaModelException jme) {
					// do nothing
				}
			}
		}
	}

	/**
	 * Get all secondary types for a project and store result in per project info cache.
	 * <p>
	 * This cache is an <code>Hashtable&lt;String, HashMap&lt;String, IType&gt;&gt;</code>:
	 *  <ul>
	 * 	<li>key: package name
	 * 	<li>value:
	 * 		<ul>
	 * 		<li>key: type name
	 * 		<li>value: java model handle for the secondary type
	 * 		</ul>
	 * </ul>
	 * Hashtable was used to protect callers from possible concurrent access.
	 * </p>
	 * Note that this map may have a specific entry which key is {@link #INDEXED_SECONDARY_TYPES }
	 * and value is a map containing all secondary types created during indexing.
	 * When this key is in cache and indexing is finished, returned map is merged
	 * with the value of this special key. If indexing is not finished and caller does
	 * not wait for the end of indexing, returned map is the current secondary
	 * types cache content which may be invalid...
	 *
	 * @param project Project we want get secondary types from
	 * @return HashMap Table of secondary type names->path for given project
	 */
	public Map secondaryTypes(IJavaProject project, boolean waitForIndexes, IProgressMonitor monitor) throws JavaModelException {
		if (VERBOSE) {
			StringBuffer buffer = new StringBuffer("JavaModelManager.secondaryTypes("); //$NON-NLS-1$
			buffer.append(project.getElementName());
			buffer.append(',');
			buffer.append(waitForIndexes);
			buffer.append(')');
			Util.verbose(buffer.toString());
		}

		// Return cache if not empty and there's no new secondary types created during indexing
		final PerProjectInfo projectInfo = getPerProjectInfoCheckExistence(project.getProject());
		Map indexingSecondaryCache = projectInfo.secondaryTypes == null ? null : (Map) projectInfo.secondaryTypes.get(INDEXED_SECONDARY_TYPES);
		if (projectInfo.secondaryTypes != null && indexingSecondaryCache == null) {
			return projectInfo.secondaryTypes;
		}

		// Perform search request only if secondary types cache is not initialized yet (this will happen only once!)
		if (projectInfo.secondaryTypes == null) {
			return secondaryTypesSearching(project, waitForIndexes, monitor, projectInfo);
		}

		// New secondary types have been created while indexing secondary types cache
		// => need to know whether the indexing is finished or not
		boolean indexing = this.indexManager.awaitingJobsCount() > 0;
		if (indexing) {
			if (!waitForIndexes)  {
				// Indexing is running but caller cannot wait => return current cache
				return projectInfo.secondaryTypes;
			}

			// Wait for the end of indexing or a cancel
			while (this.indexManager.awaitingJobsCount() > 0) {
				if (monitor != null && monitor.isCanceled()) {
					return projectInfo.secondaryTypes;
				}
				try {
					Thread.sleep(10);
				} catch (InterruptedException e) {
					return projectInfo.secondaryTypes;
				}
			}
		}

		// Indexing is finished => merge caches and return result
		return secondaryTypesMerging(projectInfo.secondaryTypes);
	}

	/*
	 * Return secondary types cache merged with new secondary types created while indexing
	 * Note that merge result is directly stored in given parameter map.
	 */
	private Hashtable secondaryTypesMerging(Hashtable secondaryTypes) {
		if (VERBOSE) {
			Util.verbose("JavaModelManager.getSecondaryTypesMerged()"); //$NON-NLS-1$
			Util.verbose("	- current cache to merge:"); //$NON-NLS-1$
			Iterator entries = secondaryTypes.entrySet().iterator();
			while (entries.hasNext()) {
				Map.Entry entry = (Map.Entry) entries.next();
				String packName = (String) entry.getKey();
				Util.verbose("		+ "+packName+':'+ entry.getValue() ); //$NON-NLS-1$
			}
		}

		// Return current cache if there's no indexing cache (double check, this should not happen)
		HashMap indexedSecondaryTypes = (HashMap) secondaryTypes.remove(INDEXED_SECONDARY_TYPES);
		if (indexedSecondaryTypes == null) {
			return secondaryTypes;
		}

		// Merge indexing cache in secondary types one
		Iterator entries = indexedSecondaryTypes.entrySet().iterator();
		while (entries.hasNext()) {
			Map.Entry entry = (Map.Entry) entries.next();
			IFile file = (IFile) entry.getKey();

			// Remove all secondary types of indexed file from cache
			secondaryTypesRemoving(secondaryTypes, file);

			// Add all indexing file secondary types in given secondary types cache
			HashMap fileSecondaryTypes = (HashMap) entry.getValue();
			Iterator entries2 = fileSecondaryTypes.entrySet().iterator();
			while (entries2.hasNext()) {
				Map.Entry entry2 = (Map.Entry) entries2.next();
				String packageName = (String) entry2.getKey();
				HashMap cachedTypes = (HashMap) secondaryTypes.get(packageName);
				if (cachedTypes == null) {
					secondaryTypes.put(packageName, entry2.getValue());
				} else {
					HashMap types = (HashMap) entry2.getValue();
					Iterator entries3 = types.entrySet().iterator();
					while (entries3.hasNext()) {
						Map.Entry entry3 = (Map.Entry) entries3.next();
						String typeName = (String) entry3.getKey();
						cachedTypes.put(typeName, entry3.getValue());
					}
				}
			}
		}
		if (VERBOSE) {
			Util.verbose("	- secondary types cache merged:"); //$NON-NLS-1$
			entries = secondaryTypes.entrySet().iterator();
			while (entries.hasNext()) {
				Map.Entry entry = (Map.Entry) entries.next();
				String packName = (String) entry.getKey();
				Util.verbose("		+ "+packName+':'+ entry.getValue()); //$NON-NLS-1$
			}
		}
		return secondaryTypes;
	}

	/*
	 * Perform search request to get all secondary types of a given project.
	 * If not waiting for indexes and indexing is running, will return types found in current built indexes...
	 */
	private Map secondaryTypesSearching(IJavaProject project, boolean waitForIndexes, IProgressMonitor monitor, final PerProjectInfo projectInfo) throws JavaModelException {
		if (VERBOSE || BasicSearchEngine.VERBOSE) {
			StringBuffer buffer = new StringBuffer("JavaModelManager.secondaryTypesSearch("); //$NON-NLS-1$
			buffer.append(project.getElementName());
			buffer.append(',');
			buffer.append(waitForIndexes);
			buffer.append(')');
			Util.verbose(buffer.toString());
		}

		final Hashtable secondaryTypes = new Hashtable(3);
		IRestrictedAccessTypeRequestor nameRequestor = new IRestrictedAccessTypeRequestor() {
			public void acceptType(int modifiers, char[] packageName, char[] simpleTypeName, char[][] enclosingTypeNames, String path, AccessRestriction access) {
				String key = packageName==null ? "" : new String(packageName); //$NON-NLS-1$
				HashMap types = (HashMap) secondaryTypes.get(key);
				if (types == null) types = new HashMap(3);
				types.put(new String(simpleTypeName), path);
				secondaryTypes.put(key, types);
			}
		};

		// Build scope using prereq projects but only source folders
		IPackageFragmentRoot[] allRoots = project.getAllPackageFragmentRoots();
		int length = allRoots.length, size = 0;
		IPackageFragmentRoot[] allSourceFolders = new IPackageFragmentRoot[length];
		for (int i=0; i<length; i++) {
			if (allRoots[i].getKind() == IPackageFragmentRoot.K_SOURCE) {
				allSourceFolders[size++] = allRoots[i];
			}
		}
		if (size < length) {
			System.arraycopy(allSourceFolders, 0, allSourceFolders = new IPackageFragmentRoot[size], 0, size);
		}

		// Search all secondary types on scope
		new BasicSearchEngine().searchAllSecondaryTypeNames(allSourceFolders, nameRequestor, waitForIndexes, monitor);

		// Build types from paths
		Iterator packages = secondaryTypes.values().iterator();
		while (packages.hasNext()) {
			HashMap types = (HashMap) packages.next();
			Iterator names = types.entrySet().iterator();
			while (names.hasNext()) {
				Map.Entry entry = (Map.Entry) names.next();
				String typeName = (String) entry.getKey();
				String path = (String) entry.getValue();
				if (org.eclipse.jdt.internal.core.util.Util.isJavaLikeFileName(path)) {
					IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(path));
					ICompilationUnit unit = JavaModelManager.createCompilationUnitFrom(file, null);
					IType type = unit.getType(typeName);
					types.put(typeName, type); // replace stored path with type itself
				} else {
					names.remove();
				}
			}
		}

		// Store result in per project info cache if still null or there's still an indexing cache (may have been set by another thread...)
		if (projectInfo.secondaryTypes == null || projectInfo.secondaryTypes.get(INDEXED_SECONDARY_TYPES) != null) {
			projectInfo.secondaryTypes = secondaryTypes;
			if (VERBOSE || BasicSearchEngine.VERBOSE) {
				System.out.print(Thread.currentThread() + "	-> secondary paths stored in cache: ");  //$NON-NLS-1$
				System.out.println();
				Iterator entries = secondaryTypes.entrySet().iterator();
				while (entries.hasNext()) {
					Map.Entry entry = (Map.Entry) entries.next();
					String qualifiedName = (String) entry.getKey();
					Util.verbose("		- "+qualifiedName+'-'+ entry.getValue()); //$NON-NLS-1$
				}
			}
		}
		return projectInfo.secondaryTypes;
	}

	/**
	 * Remove from secondary types cache all types belonging to a given file.
	 * Clean secondary types cache built while indexing if requested.
	 *
	 * Project's secondary types cache is found using file location.
	 *
	 * @param file File to remove
	 */
	public void secondaryTypesRemoving(IFile file, boolean cleanIndexCache) {
		if (VERBOSE) {
			StringBuffer buffer = new StringBuffer("JavaModelManager.removeFromSecondaryTypesCache("); //$NON-NLS-1$
			buffer.append(file.getName());
			buffer.append(')');
			Util.verbose(buffer.toString());
		}
		if (file != null) {
			PerProjectInfo projectInfo = getPerProjectInfo(file.getProject(), false);
			if (projectInfo != null && projectInfo.secondaryTypes != null) {
				if (VERBOSE) {
					Util.verbose("-> remove file from cache of project: "+file.getProject().getName()); //$NON-NLS-1$
				}

				// Clean current cache
				secondaryTypesRemoving(projectInfo.secondaryTypes, file);

				// Clean indexing cache if necessary
				HashMap indexingCache = (HashMap) projectInfo.secondaryTypes.get(INDEXED_SECONDARY_TYPES);
				if (!cleanIndexCache) {
					if (indexingCache == null) {
						// Need to signify that secondary types indexing will happen before any request happens
						// see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=152841
						projectInfo.secondaryTypes.put(INDEXED_SECONDARY_TYPES, new HashMap());
					}
					return;
				}
				if (indexingCache != null) {
					Set keys = indexingCache.keySet();
					int filesSize = keys.size(), filesCount = 0;
					IFile[] removed = null;
					Iterator cachedFiles = keys.iterator();
					while (cachedFiles.hasNext()) {
						IFile cachedFile = (IFile) cachedFiles.next();
						if (file.equals(cachedFile)) {
							if (removed == null) removed = new IFile[filesSize];
							filesSize--;
							removed[filesCount++] = cachedFile;
						}
					}
					if (removed != null) {
						for (int i=0; i<filesCount; i++) {
							indexingCache.remove(removed[i]);
						}
					}
				}
			}
		}
	}

	/*
	 * Remove from a given cache map all secondary types belonging to a given file.
	 * Note that there can have several secondary types per file...
	 */
	private void secondaryTypesRemoving(Hashtable secondaryTypesMap, IFile file) {
		if (VERBOSE) {
			StringBuffer buffer = new StringBuffer("JavaModelManager.removeSecondaryTypesFromMap("); //$NON-NLS-1$
			Iterator entries = secondaryTypesMap.entrySet().iterator();
			while (entries.hasNext()) {
				Map.Entry entry = (Map.Entry) entries.next();
				String qualifiedName = (String) entry.getKey();
				buffer.append(qualifiedName+':'+ entry.getValue());
			}
			buffer.append(',');
			buffer.append(file.getFullPath());
			buffer.append(')');
			Util.verbose(buffer.toString());
		}
		Set packageEntries = secondaryTypesMap.entrySet();
		int packagesSize = packageEntries.size(), removedPackagesCount = 0;
		String[] removedPackages = null;
		Iterator packages = packageEntries.iterator();
		while (packages.hasNext()) {
			Map.Entry entry = (Map.Entry) packages.next();
			String packName = (String) entry.getKey();
			if (packName != INDEXED_SECONDARY_TYPES) { // skip indexing cache entry if present (!= is intentional)
				HashMap types = (HashMap) entry.getValue();
				Set nameEntries = types.entrySet();
				int namesSize = nameEntries.size(), removedNamesCount = 0;
				String[] removedNames = null;
				Iterator names = nameEntries.iterator();
				while (names.hasNext()) {
					Map.Entry entry2 = (Map.Entry) names.next();
					String typeName = (String) entry2.getKey();
					JavaElement type = (JavaElement) entry2.getValue();
					if (file.equals(type.resource())) {
						if (removedNames == null) removedNames = new String[namesSize];
						namesSize--;
						removedNames[removedNamesCount++] = typeName;
					}
				}
				if (removedNames != null) {
					for (int i=0; i<removedNamesCount; i++) {
						types.remove(removedNames[i]);
					}
				}
				if (types.size() == 0) {
					if (removedPackages == null) removedPackages = new String[packagesSize];
					packagesSize--;
					removedPackages[removedPackagesCount++] = packName;
				}
			}
		}
		if (removedPackages != null) {
			for (int i=0; i<removedPackagesCount; i++) {
				secondaryTypesMap.remove(removedPackages[i]);
			}
		}
		if (VERBOSE) {
			Util.verbose("	- new secondary types map:"); //$NON-NLS-1$
			Iterator entries = secondaryTypesMap.entrySet().iterator();
			while (entries.hasNext()) {
				Map.Entry entry = (Map.Entry) entries.next();
				String qualifiedName = (String) entry.getKey();
				Util.verbose("		+ "+qualifiedName+':'+ entry.getValue()); //$NON-NLS-1$
			}
		}
	}

	/**
	 * Record the order in which to build the java projects (batch build). This order is based
	 * on the projects classpath settings.
	 */
	protected void setBuildOrder(String[] javaBuildOrder) throws JavaModelException {

		// optional behaviour
		// possible value of index 0 is Compute
		if (!JavaCore.COMPUTE.equals(JavaCore.getOption(JavaCore.CORE_JAVA_BUILD_ORDER))) return; // cannot be customized at project level

		if (javaBuildOrder == null || javaBuildOrder.length <= 1) return;

		IWorkspace workspace = ResourcesPlugin.getWorkspace();
		IWorkspaceDescription description = workspace.getDescription();
		String[] wksBuildOrder = description.getBuildOrder();

		String[] newOrder;
		if (wksBuildOrder == null){
			newOrder = javaBuildOrder;
		} else {
			// remove projects which are already mentionned in java builder order
			int javaCount = javaBuildOrder.length;
			HashMap newSet = new HashMap(javaCount); // create a set for fast check
			for (int i = 0; i < javaCount; i++){
				newSet.put(javaBuildOrder[i], javaBuildOrder[i]);
			}
			int removed = 0;
			int oldCount = wksBuildOrder.length;
			for (int i = 0; i < oldCount; i++){
				if (newSet.containsKey(wksBuildOrder[i])){
					wksBuildOrder[i] = null;
					removed++;
				}
			}
			// add Java ones first
			newOrder = new String[oldCount - removed + javaCount];
			System.arraycopy(javaBuildOrder, 0, newOrder, 0, javaCount); // java projects are built first

			// copy previous items in their respective order
			int index = javaCount;
			for (int i = 0; i < oldCount; i++){
				if (wksBuildOrder[i] != null){
					newOrder[index++] = wksBuildOrder[i];
				}
			}
		}
		// commit the new build order out
		description.setBuildOrder(newOrder);
		try {
			workspace.setDescription(description);
		} catch(CoreException e){
			throw new JavaModelException(e);
		}
	}

	/**
	 * Sets the last built state for the given project, or null to reset it.
	 */
	public void setLastBuiltState(IProject project, Object state) {
		if (JavaProject.hasJavaNature(project)) {
			// should never be requested on non-Java projects
			PerProjectInfo info = getPerProjectInfo(project, true /*create if missing*/);
			info.triedRead = true; // no point trying to re-read once using setter
			info.savedState = state;
		}
		if (state == null) { // delete state file to ensure a full build happens if the workspace crashes
			try {
				File file = getSerializationFile(project);
				if (file != null && file.exists())
					file.delete();
			} catch(SecurityException se) {
				// could not delete file: cannot do much more
			}
		}
	}

	/**
	 * Store the preferences value for the given option name.
	 *
	 * @param optionName The name of the option
	 * @param optionValue The value of the option. If <code>null</code>, then
	 * 	the option will be removed from the preferences instead.
	 * @param eclipsePreferences The eclipse preferences to be updated
	 * @param otherOptions more options being stored, used to avoid conflict between deprecated option and its compatible
	 * @return <code>true</code> if the preferences have been changed,
	 * 	<code>false</code> otherwise.
	 */
	public boolean storePreference(String optionName, String optionValue, IEclipsePreferences eclipsePreferences, Map otherOptions) {
		int optionLevel = this.getOptionLevel(optionName);
		if (optionLevel == UNKNOWN_OPTION) return false; // unrecognized option
		
		// Store option value
		switch (optionLevel) {
			case JavaModelManager.VALID_OPTION:
				if (optionValue == null) {
					eclipsePreferences.remove(optionName);
				} else {
					eclipsePreferences.put(optionName, optionValue);
				}
				break;
			case JavaModelManager.DEPRECATED_OPTION:
				// Try to migrate deprecated option
				eclipsePreferences.remove(optionName); // get rid off old preference
				String[] compatibleOptions = (String[]) this.deprecatedOptions.get(optionName);
				for (int co=0, length=compatibleOptions.length; co < length; co++) {
					if (otherOptions != null && otherOptions.containsKey(compatibleOptions[co]))
						continue; // don't overwrite explicit value of otherOptions at compatibleOptions[co]
					if (optionValue == null) {
						eclipsePreferences.remove(compatibleOptions[co]);
					} else {
						eclipsePreferences.put(compatibleOptions[co], optionValue);
					}
				}
				break;
			default:
				return false;
		}
		return true;
	}

	public void setOptions(Hashtable newOptions) {
		Hashtable cachedValue = newOptions == null ? null : new Hashtable(newOptions);
		IEclipsePreferences defaultPreferences = getDefaultPreferences();
		IEclipsePreferences instancePreferences = getInstancePreferences();

		if (newOptions == null){
			try {
				instancePreferences.clear();
			} catch(BackingStoreException e) {
				// ignore
			}
		} else {
			Enumeration keys = newOptions.keys();
			while (keys.hasMoreElements()){
				String key = (String)keys.nextElement();
				int optionLevel = getOptionLevel(key);
				if (optionLevel == UNKNOWN_OPTION) continue; // unrecognized option
				if (key.equals(JavaCore.CORE_ENCODING)) {
					if (cachedValue != null) {
						cachedValue.put(key, JavaCore.getEncoding());
					}
					continue; // skipped, contributed by resource prefs
				}
				String value = (String) newOptions.get(key);
				String defaultValue = defaultPreferences.get(key, null);
				// Store value in preferences
				if (defaultValue != null && defaultValue.equals(value)) {
					value = null;
				}
				storePreference(key, value, instancePreferences, newOptions);
			}
			try {
				// persist options
				instancePreferences.flush();
			} catch(BackingStoreException e) {
				// ignore
			}
		}
		// update cache
		Util.fixTaskTags(cachedValue);
		this.optionsCache = cachedValue;
	}

	public void startup() throws CoreException {
		try {
			configurePluginDebugOptions();

			// initialize Java model cache
			this.cache = new JavaModelCache();

			// request state folder creation (workaround 19885)
			JavaCore.getPlugin().getStateLocation();

			// Initialize eclipse preferences
			initializePreferences();

			// Listen to preference changes
			this.propertyListener = new IEclipsePreferences.IPreferenceChangeListener() {
				public void preferenceChange(PreferenceChangeEvent event) {
					JavaModelManager.this.optionsCache = null;
				}
			};
			InstanceScope.INSTANCE.getNode(JavaCore.PLUGIN_ID).addPreferenceChangeListener(this.propertyListener);
			
			// listen for encoding changes (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=255501 )
			this.resourcesPropertyListener = new IEclipsePreferences.IPreferenceChangeListener() {
				public void preferenceChange(PreferenceChangeEvent event) {
					if (ResourcesPlugin.PREF_ENCODING.equals(event.getKey())) {
						JavaModelManager.this.optionsCache = null;
					}
				}
			};
			String resourcesPluginId = ResourcesPlugin.getPlugin().getBundle().getSymbolicName();
			InstanceScope.INSTANCE.getNode(resourcesPluginId).addPreferenceChangeListener(this.resourcesPropertyListener);

			// Listen to content-type changes
			 Platform.getContentTypeManager().addContentTypeChangeListener(this);

			// retrieve variable values
			long start = -1;
			if (VERBOSE)
				start = System.currentTimeMillis();
			loadVariablesAndContainers();
			if (VERBOSE)
				traceVariableAndContainers("Loaded", start); //$NON-NLS-1$

			// listen for resource changes
			this.deltaState.initializeRootsWithPreviousSession();
			final IWorkspace workspace = ResourcesPlugin.getWorkspace();
			workspace.addResourceChangeListener(
				this.deltaState,
				/* update spec in JavaCore#addPreProcessingResourceChangedListener(...) if adding more event types */
				IResourceChangeEvent.PRE_BUILD
					| IResourceChangeEvent.POST_BUILD
					| IResourceChangeEvent.POST_CHANGE
					| IResourceChangeEvent.PRE_DELETE
					| IResourceChangeEvent.PRE_CLOSE
					| IResourceChangeEvent.PRE_REFRESH);

			startIndexing();

			// process deltas since last activated in indexer thread so that indexes are up-to-date.
			// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=38658
			Job processSavedState = new Job(Messages.savedState_jobName) {
				protected IStatus run(IProgressMonitor monitor) {
					try {
						// add save participant and process delta atomically
						// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=59937
						workspace.run(
							new IWorkspaceRunnable() {
								public void run(IProgressMonitor progress) throws CoreException {
									ISavedState savedState = workspace.addSaveParticipant(JavaCore.PLUGIN_ID, JavaModelManager.this);
									if (savedState != null) {
										// the event type coming from the saved state is always POST_AUTO_BUILD
										// force it to be POST_CHANGE so that the delta processor can handle it
										JavaModelManager.this.deltaState.getDeltaProcessor().overridenEventType = IResourceChangeEvent.POST_CHANGE;
										savedState.processResourceChangeEvents(JavaModelManager.this.deltaState);
									}
								}
							},
							monitor);
					} catch (CoreException e) {
						return e.getStatus();
					}
					return Status.OK_STATUS;
				}
			};
			processSavedState.setSystem(true);
			processSavedState.setPriority(Job.SHORT); // process asap
			processSavedState.schedule();
		} catch (RuntimeException e) {
			shutdown();
			throw e;
		}
	}

	/**
	 * Initiate the background indexing process.
	 * This should be deferred after the plug-in activation.
	 */
	private void startIndexing() {
		if (this.indexManager != null) this.indexManager.reset();
	}

	public void shutdown () {
		IEclipsePreferences preferences = InstanceScope.INSTANCE.getNode(JavaCore.PLUGIN_ID);
		try {
			preferences.flush();
		} catch (BackingStoreException e) {
			Util.log(e, "Could not save JavaCore preferences"); //$NON-NLS-1$
		}
		IWorkspace workspace = ResourcesPlugin.getWorkspace();
		workspace.removeResourceChangeListener(this.deltaState);
		workspace.removeSaveParticipant(JavaCore.PLUGIN_ID);

		// Stop listening to content-type changes
		Platform.getContentTypeManager().removeContentTypeChangeListener(this);

		// Stop indexing
		if (this.indexManager != null) {
			this.indexManager.shutdown();
		}

		// Stop listening to preferences changes
		preferences.removePreferenceChangeListener(this.propertyListener);
		((IEclipsePreferences) this.preferencesLookup[PREF_DEFAULT].parent()).removeNodeChangeListener(this.defaultNodeListener);
		this.preferencesLookup[PREF_DEFAULT] = null;
		((IEclipsePreferences) this.preferencesLookup[PREF_INSTANCE].parent()).removeNodeChangeListener(this.instanceNodeListener);
		this.preferencesLookup[PREF_INSTANCE].removePreferenceChangeListener(this.instancePreferencesListener);
		this.preferencesLookup[PREF_INSTANCE] = null;
		String resourcesPluginId = ResourcesPlugin.getPlugin().getBundle().getSymbolicName();
		InstanceScope.INSTANCE.getNode(resourcesPluginId).removePreferenceChangeListener(this.resourcesPropertyListener);

		// wait for the initialization job to finish
		try {
			Job.getJobManager().join(JavaCore.PLUGIN_ID, null);
		} catch (InterruptedException e) {
			// ignore
		}

		// Note: no need to close the Java model as this just removes Java element infos from the Java model cache
	}

	public synchronized IPath variableGet(String variableName){
		// check initialization in progress first
		HashSet initializations = variableInitializationInProgress();
		if (initializations.contains(variableName)) {
			return VARIABLE_INITIALIZATION_IN_PROGRESS;
		}
		return (IPath)this.variables.get(variableName);
	}

	private synchronized IPath variableGetDefaultToPreviousSession(String variableName){
		IPath variablePath = (IPath)this.variables.get(variableName);
		if (variablePath == null)
			return getPreviousSessionVariable(variableName);
		return variablePath;
	}

	/*
	 * Returns the set of variable names that are being initialized in the current thread.
	 */
	private HashSet variableInitializationInProgress() {
		HashSet initializations = (HashSet)this.variableInitializationInProgress.get();
		if (initializations == null) {
			initializations = new HashSet();
			this.variableInitializationInProgress.set(initializations);
		}
		return initializations;
	}

	public synchronized String[] variableNames(){
		int length = this.variables.size();
		String[] result = new String[length];
		Iterator vars = this.variables.keySet().iterator();
		int index = 0;
		while (vars.hasNext()) {
			result[index++] = (String) vars.next();
		}
		return result;
	}

	public synchronized void variablePut(String variableName, IPath variablePath){

		// set/unset the initialization in progress
		HashSet initializations = variableInitializationInProgress();
		if (variablePath == VARIABLE_INITIALIZATION_IN_PROGRESS) {
			initializations.add(variableName);

			// do not write out intermediate initialization value
			return;
		} else {
			initializations.remove(variableName);

			// update cache - do not only rely on listener refresh
			if (variablePath == null) {
				// if path is null, record that the variable was removed to avoid asking the initializer to initialize it again
				// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=112609
				this.variables.put(variableName, CP_ENTRY_IGNORE_PATH);
				// clean other variables caches
				this.variablesWithInitializer.remove(variableName);
				this.deprecatedVariables.remove(variableName);
			} else {
				this.variables.put(variableName, variablePath);
			}
			// discard obsoleted information about previous session
			this.previousSessionVariables.remove(variableName);
		}
	}

	public void variablePreferencesPut(String variableName, IPath variablePath) {
		String variableKey = CP_VARIABLE_PREFERENCES_PREFIX+variableName;
		if (variablePath == null) {
			getInstancePreferences().remove(variableKey);
		} else {
			getInstancePreferences().put(variableKey, variablePath.toString());
		}
		try {
			getInstancePreferences().flush();
		} catch (BackingStoreException e) {
			// ignore exception
		}
	}

	/*
	 * Optimize startup case where 1 variable is initialized at a time with the same value as on shutdown.
	 */
	public boolean variablePutIfInitializingWithSameValue(String[] variableNames, IPath[] variablePaths) {
		if (variableNames.length != 1)
			return false;
		String variableName = variableNames[0];
		IPath oldPath = variableGetDefaultToPreviousSession(variableName);
		if (oldPath == null)
			return false;
		IPath newPath = variablePaths[0];
		if (!oldPath.equals(newPath))
			return false;
		variablePut(variableName, newPath);
		return true;
	}

	public void contentTypeChanged(ContentTypeChangeEvent event) {
		Util.resetJavaLikeExtensions();

		// Walk through projects to reset their secondary types cache
		IJavaProject[] projects;
		try {
			projects = JavaModelManager.getJavaModelManager().getJavaModel().getJavaProjects();
		} catch (JavaModelException e) {
			return;
		}
		for (int i = 0, length = projects.length; i < length; i++) {
			IJavaProject project = projects[i];
			final PerProjectInfo projectInfo = getPerProjectInfo(project.getProject(), false /* don't create info */);
			if (projectInfo != null) {
				projectInfo.secondaryTypes = null;
			}
		}
	}

	public synchronized String cacheToString(String prefix) {
		return this.cache.toStringFillingRation(prefix);
	}
	
	public Stats debugNewOpenableCacheStats() {
		return this.cache.openableCache.new Stats();
	}
	
	public int getOpenableCacheSize() {
		return this.cache.openableCache.getSpaceLimit();
	}
}
