/*******************************************************************************
 * Copyright (c) 2000, 2018 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 - Contributions for
 *								Bug 346010 - [model] strange initialization dependency in OptionTests
 *								Bug 440477 - [null] Infrastructure for feeding external annotations into compilation
 *     Terry Parker <tparker@google.com> - DeltaProcessor misses state changes in archive files, see https://bugs.eclipse.org/bugs/show_bug.cgi?id=357425
 *     Thirumala Reddy Mutchukota <thirumala@google.com> - Contribution to bug: https://bugs.eclipse.org/bugs/show_bug.cgi?id=411423
 *     Terry Parker <tparker@google.com> - [performance] Low hit rates in JavaModel caches - https://bugs.eclipse.org/421165
 *     Terry Parker <tparker@google.com> - Enable the Java model caches to recover from IO errors - https://bugs.eclipse.org/455042
 *     Gábor Kövesdán - Contribution for Bug 350000 - [content assist] Include non-prefix matches in auto-complete suggestions
 *     Karsten Thoms - Bug 532505 - Reduce memory footprint of ClasspathAccessRule
 *******************************************************************************/
package org.eclipse.jdt.internal.core;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.StringReader;
import java.net.URI;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.WeakHashMap;
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.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.ISaveContext;
import org.eclipse.core.resources.ISaveParticipant;
import org.eclipse.core.resources.ISavedState;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.IWorkspaceDescription;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.resources.WorkspaceJob;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtension;
import org.eclipse.core.runtime.IExtensionPoint;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.ISafeRunnable;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.PerformanceStats;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Plugin;
import org.eclipse.core.runtime.QualifiedName;
import org.eclipse.core.runtime.SafeRunner;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.core.runtime.content.IContentTypeManager;
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.IEclipsePreferences.PreferenceChangeEvent;
import org.eclipse.core.runtime.preferences.IPreferencesService;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.jdt.core.ClasspathContainerInitializer;
import org.eclipse.jdt.core.IAccessRule;
import org.eclipse.jdt.core.IClassFile;
import org.eclipse.jdt.core.IClasspathAttribute;
import org.eclipse.jdt.core.IClasspathContainer;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaModel;
import org.eclipse.jdt.core.IJavaModelStatus;
import org.eclipse.jdt.core.IJavaModelStatusConstants;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.IParent;
import org.eclipse.jdt.core.IProblemRequestor;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.ITypeRoot;
import org.eclipse.jdt.core.JavaConventions;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.WorkingCopyOwner;
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.lookup.TypeConstants;
import org.eclipse.jdt.internal.compiler.util.HashtableOfObjectToInt;
import org.eclipse.jdt.internal.compiler.util.JRTUtil;
import org.eclipse.jdt.internal.compiler.util.ObjectVector;
import org.eclipse.jdt.internal.core.DeltaProcessor.RootInfo;
import org.eclipse.jdt.internal.core.JavaProjectElementInfo.ProjectCache;
import org.eclipse.jdt.internal.core.builder.JavaBuilder;
import org.eclipse.jdt.internal.core.dom.SourceRangeVerifier;
import org.eclipse.jdt.internal.core.dom.rewrite.RewriteEventStore;
import org.eclipse.jdt.internal.core.hierarchy.TypeHierarchy;
import org.eclipse.jdt.internal.core.nd.IReader;
import org.eclipse.jdt.internal.core.nd.Nd;
import org.eclipse.jdt.internal.core.nd.db.Database;
import org.eclipse.jdt.internal.core.nd.indexer.Indexer;
import org.eclipse.jdt.internal.core.nd.java.JavaIndex;
import org.eclipse.jdt.internal.core.nd.java.NdResourceFile;
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.IJob;
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.formatter.DefaultCodeFormatter;
import org.eclipse.osgi.service.debug.DebugOptions;
import org.eclipse.osgi.service.debug.DebugOptionsListener;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
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 ServiceRegistration<DebugOptionsListener> DEBUG_REGISTRATION;
	private static final String NON_CHAINING_JARS_CACHE = "nonChainingJarsCache"; //$NON-NLS-1$
	private static final String EXTERNAL_FILES_CACHE = "externalFilesCache";  //$NON-NLS-1$
	private static final String ASSUMED_EXTERNAL_FILES_CACHE = "assumedExternalFilesCache";  //$NON-NLS-1$

	public static enum ArchiveValidity {
		BAD_FORMAT, UNABLE_TO_READ, FILE_NOT_FOUND, VALID;

		public boolean isValid() {
			return this == VALID;
		}
	}

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

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

		public void flush() {
			Thread currentThread = Thread.currentThread();
			Iterator<ZipFile> iterator = this.map.values().iterator();
			while (iterator.hasNext()) {
				ZipFile zipFile = iterator.next();
				try {
					if (JavaModelManager.ZIP_ACCESS_VERBOSE) {
						System.out.println("(" + currentThread + ") [ZipCache[" + this.owner //$NON-NLS-1$//$NON-NLS-2$
								+ "].flush()] Closing ZipFile on " + zipFile.getName()); //$NON-NLS-1$
					}
					zipFile.close();
				} catch (IOException e) {
					// problem occured closing zip file: cannot do much more
					JavaCore.getPlugin().getLog().log(new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, "Error closing " + zipFile.getName(), e)); //$NON-NLS-1$
				}
			}
		}

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

		public void setCache(IPath path, ZipFile zipFile) {
			ZipFile old = this.map.put(path, zipFile);
			if(old != null) {
				if (JavaModelManager.ZIP_ACCESS_VERBOSE) {
					Thread currentThread = Thread.currentThread();
					System.out.println("(" + currentThread + ") [ZipCache[" + this.owner //$NON-NLS-1$//$NON-NLS-2$
							+ "].setCache()] leaked ZipFile on " + old.getName() + " for path: " + path); //$NON-NLS-1$ //$NON-NLS-2$
				}
			}
		}
	}
	/**
	 * Unique handle onto the JavaModel
	 */
	final JavaModel javaModel = new JavaModel();

	/**
	 * Classpath variables pool
	 */
	public HashMap<String, IPath> variables = new HashMap<>(5);
	public HashSet<String> variablesWithInitializer = new HashSet<>(5);
	public HashMap<String, String> deprecatedVariables = new HashMap<>(5);
	public HashSet<String> readOnlyVariables = new HashSet<>(5);
	public HashMap<String, IPath> previousSessionVariables = new HashMap<>(5);
	private ThreadLocal<Set<String>> variableInitializationInProgress = new ThreadLocal<>();

	/**
	 * Classpath containers pool
	 */
	public HashMap<IJavaProject, Map<IPath, IClasspathContainer>> containers = new HashMap<>(5);
	public HashMap<IJavaProject, Map<IPath, IClasspathContainer>> previousSessionContainers = new HashMap<>(5);
	private ThreadLocal<Map<IJavaProject, Set<IPath>>> containerInitializationInProgress = new ThreadLocal<>();
	ThreadLocal<Map<IJavaProject, Map<IPath, IClasspathContainer>>> 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 Object batchContainerInitializationsLock = new Object();

	public BatchInitializationMonitor batchContainerInitializationsProgress = new BatchInitializationMonitor();
	public Hashtable<String, ClasspathContainerInitializer> containerInitializersCache = new Hashtable<>(5);

	/*
	 * A HashSet that contains the IJavaProject whose classpath is being resolved.
	 */
	private ThreadLocal<Set<IJavaProject>> 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<IPath, String> 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$

	/**
	 * Name of the JVM parameter to specify how many compilation units must be handled at once by the builder.
	 * The default value is represented by <code>AbstractImageBuilder#MAX_AT_ONCE</code>.
	 */
	public static final String MAX_COMPILED_UNITS_AT_ONCE = "maxCompiledUnitsAtOnce"; //$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() {
		@Override
		public IClasspathEntry[] getClasspathEntries() { return null; }
		@Override
		public String getDescription() { return "Container Initialization In Progress"; } //$NON-NLS-1$
		@Override
		public int getKind() { return 0; }
		@Override
		public IPath getPath() { return null; }
		@Override
		public String toString() { return getDescription(); }
	};

	private static final String DEBUG = JavaCore.PLUGIN_ID + "/debug"; //$NON-NLS-1$
	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_CLASSPATH = JavaCore.PLUGIN_ID + "/debug/javamodel/classpath" ; //$NON-NLS-1$
	private static final String JAVAMODEL_DEBUG = JavaCore.PLUGIN_ID + "/debug/javamodel" ; //$NON-NLS-1$
	private static final String JAVAMODEL_INVALID_ARCHIVES = JavaCore.PLUGIN_ID + "/debug/javamodel/invalid_archives" ; //$NON-NLS-1$
	private static final String JAVAMODELCACHE_DEBUG = JavaCore.PLUGIN_ID + "/debug/javamodel/cache" ; //$NON-NLS-1$
	private static final String JAVAMODELCACHE_INSERTIONS_DEBUG = JavaCore.PLUGIN_ID + "/debug/javamodel/insertions" ; //$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 DOM_AST_DEBUG = JavaCore.PLUGIN_ID + "/debug/dom/ast" ; //$NON-NLS-1$
	private static final String DOM_AST_DEBUG_THROW = JavaCore.PLUGIN_ID + "/debug/dom/ast/throw" ; //$NON-NLS-1$
	private static final String DOM_REWRITE_DEBUG = JavaCore.PLUGIN_ID + "/debug/dom/rewrite" ; //$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$
	private static final String INDEX_DEBUG_LARGE_CHUNKS = JavaCore.PLUGIN_ID + "/debug/index/freespacetest" ; //$NON-NLS-1$
	private static final String INDEX_DEBUG_PAGE_CACHE = JavaCore.PLUGIN_ID + "/debug/index/pagecache" ; //$NON-NLS-1$
	private static final String INDEX_INDEXER_DEBUG = JavaCore.PLUGIN_ID + "/debug/index/indexer" ; //$NON-NLS-1$
	private static final String INDEX_INDEXER_INSERTIONS = JavaCore.PLUGIN_ID + "/debug/index/insertions" ; //$NON-NLS-1$
	private static final String INDEX_INDEXER_SCHEDULING = JavaCore.PLUGIN_ID + "/debug/index/scheduling" ; //$NON-NLS-1$
	private static final String INDEX_INDEXER_SELFTEST = JavaCore.PLUGIN_ID + "/debug/index/selftest" ; //$NON-NLS-1$
	private static final String INDEX_LOCKS_DEBUG = JavaCore.PLUGIN_ID + "/debug/index/locks" ; //$NON-NLS-1$
	private static final String INDEX_INDEXER_SPACE = JavaCore.PLUGIN_ID + "/debug/index/space" ; //$NON-NLS-1$
	private static final String INDEX_INDEXER_TIMING = JavaCore.PLUGIN_ID + "/debug/index/timing" ; //$NON-NLS-1$
	private static final String INDEX_INDEXER_LOG_SIZE_MEGS = JavaCore.PLUGIN_ID + "/debug/index/logsizemegs"; //$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$

	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<String> optionNames = new HashSet<>(20);
	Map<String, String[]> deprecatedOptions = new HashMap<>();
	Hashtable<String, String> 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 = 10 ; // 1.1 to 1.8 and 9, 10

		/*
		 * 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<String> 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() {
						@Override
						public void handleException(Throwable exception) {
							Util.log(exception, "Exception occurred while creating compilation participant"); //$NON-NLS-1$
						}
						@Override
						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<String> 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<IConfigurationElement> modifyingEnv = new ArrayList<>();
			final ArrayList<IConfigurationElement> creatingProblems = new ArrayList<>();
			final ArrayList<IConfigurationElement> 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
		 * 1.8 -> 7
		 * 9 -> 8
		 * 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;
				case ClassFileConstants.MAJOR_VERSION_1_8:
					return 7;
				case ClassFileConstants.MAJOR_VERSION_9:
					return 8;
				case ClassFileConstants.MAJOR_VERSION_10:
					return 9;
				default:
					// all other cases including ClassFileConstants.MAJOR_VERSION_1_1
					return 0;
			}
		}

		private int sortParticipants(ArrayList<IConfigurationElement> group, IConfigurationElement[] configElements, int index) {
			int size = group.size();
			if (size == 0) return index;
			Object[] elements = group.toArray();
			Util.sort(elements, new Util.Comparer() {
				@Override
				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<Boolean> 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<IPath, IClasspathContainer> projectContainers = this.containers.get(project);
		if (projectContainers == null){
			return null;
		}
		IClasspathContainer container = projectContainers.get(containerPath);
		return container;
	}

	synchronized boolean containerIsSet(IJavaProject project, IPath containerPath) {
		Map<IPath, IClasspathContainer> projectContainers = this.containers.get(project);
		if (projectContainers == null){
			return false;
		}
		IClasspathContainer container = projectContainers.get(containerPath);
		return container != null;
	}

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

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

	private void containerAddInitializationInProgress(IJavaProject project, IPath containerPath) {
		Map<IJavaProject, Set<IPath>> initializations = this.containerInitializationInProgress.get();
		if (initializations == null)
			this.containerInitializationInProgress.set(initializations = new HashMap<>());
		Set<IPath> projectInitializations = 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<IJavaProject, Map<IPath, IClasspathContainer>> perProjectContainers = this.containersBeingInitialized.get();
		if (perProjectContainers == null)
			this.containersBeingInitialized.set(perProjectContainers = new HashMap<>());
		Map<IPath, IClasspathContainer> perPathContainers = perProjectContainers.get(project);
		if (perPathContainers == null)
			perProjectContainers.put(project, perPathContainers = new HashMap<>());
		perPathContainers.put(containerPath, container);
	}

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

	public IClasspathContainer containerBeingInitializedRemove(IJavaProject project, IPath containerPath) {
		Map<IJavaProject, Map<IPath, IClasspathContainer>> perProjectContainers = this.containersBeingInitialized.get();
		if (perProjectContainers == null)
			return null;
		Map<IPath, IClasspathContainer> perPathContainers = perProjectContainers.get(project);
		if (perPathContainers == null)
			return null;
		IClasspathContainer container = perPathContainers.remove(containerPath);
		if (perPathContainers.size() == 0)
			perProjectContainers.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<IPath, IClasspathContainer> projectContainers = 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<IPath, IClasspathContainer> previousContainers = 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<IJavaProject, Set<IPath>> initializations = 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(){
					@Override
					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(){
					@Override
					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(){
					@Override
					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(){
					@Override
					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<IJavaProject, Set<IPath>> initializations = this.containerInitializationInProgress.get();
		if (initializations == null)
			return;
		Set<IPath> projectInitializations = 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<Map<IPath, IClasspathContainer>> projectIterator = this.containers.values().iterator();
			while (projectIterator.hasNext()){
				Map<IPath, IClasspathContainer> projectContainers = projectIterator.next();
				if (projectContainers != null){
					Iterator<IPath> containerIterator = projectContainers.keySet().iterator();
					while (containerIterator.hasNext()){
						IPath containerPath = 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);
		}
		String fileName = file.getName();
		if (TypeConstants.MODULE_INFO_CLASS_NAME_STRING.equals(fileName))
			return pkg.getModularClassFile();
		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<HashMap<IJavaElement, Object>> temporaryCache = new ThreadLocal<>();

	/**
	 * Set of elements which are out of sync with their buffers.
	 */
	protected HashSet<Openable> 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<IProject, PerProjectInfo> 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 HashMap<WorkingCopyOwner, Map<CompilationUnit, PerWorkingCopyInfo>> perWorkingCopyInfos = new HashMap<>(5);

	/**
	 * A weak set of the known search scopes.
	 */
	protected WeakHashMap<AbstractSearchScope, ?> 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<IPath, IClasspathEntry> rootPathToRawEntries; // reverse map from a package fragment root's path to the raw entry
		public Map<IPath, IClasspathEntry> rootPathToResolvedEntries; // map from a package fragment root's path to the resolved entry
		public IPath outputLocation;
		public Map<IPath, ObjectVector> jrtRoots; // A map between a JRT file system (as a string) and the package fragment roots found in it.

		public IEclipsePreferences preferences;
		public Hashtable<String, String> options;
		public Hashtable<String, Map<String, IType>> secondaryTypes;
		/**
		 * The temporary structure used while indexing, previously known as INDEXED_SECONDARY_TYPES entry
		 */
		volatile Map<IFile, Map<String, Map<String, IType>>> indexingSecondaryCache;


		// NB: PackageFragment#getAttachedJavadoc uses this map differently
		// and stores String data, not JavadocContents as values
		public LRUCache<IJavaElement, Object> 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;
			Hashtable<IPath, Long> externalTimeStamps = manager.deltaState.getExternalLibTimeStamps();
			Map<IPath, List<RootInfo>> 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<IPath, Long> 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, Long.valueOf(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<IPath, IClasspathEntry> newRootPathToRawEntries, Map<IPath, IClasspathEntry> newRootPathToResolvedEntries, IJavaModelStatus newUnresolvedEntryStatus, boolean addClasspathChange) {
			if (DEBUG_CLASSPATH) {
				System.out.println("Setting resolved classpath for " + this.project.getFullPath()); //$NON-NLS-1$
				if (newResolvedClasspath == null) {
					System.out.println("New classpath = null"); //$NON-NLS-1$
				} else {
					for (IClasspathEntry next : newResolvedClasspath) {
						System.out.println("    " + next); //$NON-NLS-1$
					}
				}
			}
			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<IPath, IClasspathEntry> newRootPathToRawEntries, Map<IPath, IClasspathEntry> 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<IPath, IClasspathEntry> newRootPathToRawEntries, Map<IPath, IClasspathEntry> 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);
		}

		public synchronized void setJrtPackageRoots(IPath jrtPath, ObjectVector roots) {
			if (this.jrtRoots == null) this.jrtRoots = new HashMap<>();
			this.jrtRoots.put(jrtPath, roots);
		}

		/**
		 * 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;
		}

		@Override
		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;
		}
		@Override
		public void acceptProblem(IProblem problem) {
			IProblemRequestor requestor = getProblemRequestor();
			if (requestor == null) return;
			requestor.acceptProblem(problem);
		}
		@Override
		public void beginReporting() {
			IProblemRequestor requestor = getProblemRequestor();
			if (requestor == null) return;
			requestor.beginReporting();
		}
		@Override
		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;
		}
		@Override
		public boolean isActive() {
			IProblemRequestor requestor = getProblemRequestor();
			return requestor != null && requestor.isActive();
		}
		@Override
		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 DEBUG_CLASSPATH = false;
	public static boolean DEBUG_INVALID_ARCHIVES = 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;
	public static boolean JRT_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<ZipCache> zipFiles = new ThreadLocal<>();

	private UserLibraryManager userLibraryManager;

	private ModuleSourcePathManager modulePathManager;
	/*
	 * A set of IPaths for jars that are known to not contain a chaining (through MANIFEST.MF) to another library
	 */
	private Set<IPath> nonChainingJars;

	// The amount of time from when an invalid archive is first sensed until that state is considered stale.
	private static long INVALID_ARCHIVE_TTL_MILLISECONDS = 2 * 60 * 1000;

	private static class InvalidArchiveInfo {
		/**
		 * Time at which this entry will be removed from the invalid archive list.
		 */
		final long evictionTimestamp;

		/**
		 * Reason the entry was added to the invalid archive list.
		 */
		final ArchiveValidity reason;

		InvalidArchiveInfo(long evictionTimestamp, ArchiveValidity reason) {
			this.evictionTimestamp = evictionTimestamp;
			this.reason = reason;
		}
	}

	/*
	 * A map of IPaths for jars that are known to be invalid (such as not being in a valid/known format), to an eviction timestamp.
	 * Synchronize on invalidArchivesMutex before accessing.
	 */
	private final Map<IPath, InvalidArchiveInfo> invalidArchives = new HashMap<>();
	private final Object invalidArchivesMutex = new Object();

	/*
	 * A set of IPaths for files that are known to be external to the workspace.
	 * Need not be referenced by the classpath.
	 */
	private Set<IPath> externalFiles;

	/*
	 * A set of IPaths for files that do not exist on the file system but are assumed to be
	 * external archives (rather than external folders).
	 */
	private Set<IPath> assumedExternalFiles;

	/**
	 * 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)
         */
        @Override
		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.COMPILER_CODEGEN_TARGET_PLATFORM) ||
					propertyName.equals(JavaCore.CORE_OUTPUT_LOCATION_OVERLAPPING_ANOTHER_SOURCE)) {
					JavaModelManager manager = JavaModelManager.getJavaModelManager();
					IJavaModel model = manager.getJavaModel();
					IJavaProject[] jProjects;
					try {
						jProjects = model.getJavaProjects();
						IProject[] projects = new IProject[jProjects.length];
						for (int i = 0, pl = jProjects.length; i < pl; i++) {
							JavaProject javaProject = (JavaProject) jProjects[i];
							projects[i] = javaProject.getProject();
							manager.deltaState.addClasspathValidation(javaProject);
						}
						manager.touchProjects(projects, null);
					} 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() {
		@Override
		public void added(IEclipsePreferences.NodeChangeEvent event) {
			// do nothing
		}
		@Override
		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() {
		@Override
		public void added(IEclipsePreferences.NodeChangeEvent event) {
			// do nothing
		}
		@Override
		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.externalFiles = loadClasspathListCache(EXTERNAL_FILES_CACHE);
			this.assumedExternalFiles = loadClasspathListCache(ASSUMED_EXTERNAL_FILES_CACHE);
			String includeContainerReferencedLib = System.getProperty(RESOLVE_REFERENCED_LIBRARIES_FOR_CONTAINERS);
			this.resolveReferencedLibrariesForContainers = TRUE.equalsIgnoreCase(includeContainerReferencedLib);
		}
	}

	/**
	 * @deprecated
	 */
	private void addDeprecatedOptions(Hashtable<String, String> 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, ArchiveValidity reason) {
		if (DEBUG_INVALID_ARCHIVES) {
			System.out.println("Invalid JAR cache: adding " + path + ", reason: " + reason);  //$NON-NLS-1$//$NON-NLS-2$
		}
		synchronized (this.invalidArchivesMutex) {
			this.invalidArchives.put(path, new InvalidArchiveInfo(System.currentTimeMillis() + INVALID_ARCHIVE_TTL_MILLISECONDS, reason));
		}
	}

	/**
	 * Adds a path to the external files cache. It is the responsibility of callers to
	 * determine the file's existence, as determined by  {@link File#isFile()}.
	 */
	public void addExternalFile(IPath path) {
		// unlikely to be null
		if (this.externalFiles == null) {
			this.externalFiles = Collections.synchronizedSet(new HashSet<IPath>());
		}
		if(this.externalFiles != null) {
			this.externalFiles.add(path);
		}
	}

	/**
	 * Starts caching ZipFiles.
	 * Ignores if there are already clients.
	 */
	public void cacheZipFiles(Object owner) {
		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) {
			if (JavaModelManager.ZIP_ACCESS_VERBOSE) {
				System.out.println("(" + Thread.currentThread() + ") [JavaModelManager.closeZipFile(ZipFile)] NOT closed ZipFile (cache exist!) on " +zipFile.getName()); //$NON-NLS-1$	//$NON-NLS-2$
			}
			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
			JavaCore.getPlugin().getLog().log(new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, "Error closing " + zipFile.getName(), e)); //$NON-NLS-1$
		}
	}

	public static void registerDebugOptionsListener(BundleContext context) {
		// register debug options listener
		Hashtable<String, String> properties = new Hashtable<>(2);
		properties.put(DebugOptions.LISTENER_SYMBOLICNAME, JavaCore.PLUGIN_ID);
		DEBUG_REGISTRATION = context.registerService(DebugOptionsListener.class, new DebugOptionsListener() {
			@Override
			public void optionsChanged(DebugOptions options) {
				boolean debug = options.getBooleanOption(DEBUG, false);
				BufferManager.VERBOSE = debug && options.getBooleanOption(BUFFER_MANAGER_DEBUG, false);
				JavaBuilder.DEBUG = debug && options.getBooleanOption(BUILDER_DEBUG, false);
				Compiler.DEBUG = debug && options.getBooleanOption(COMPILER_DEBUG, false);
				JavaBuilder.SHOW_STATS = debug && options.getBooleanOption(BUILDER_STATS_DEBUG, false);
				CompletionEngine.DEBUG = debug && options.getBooleanOption(COMPLETION_DEBUG, false);
				JavaModelManager.CP_RESOLVE_VERBOSE = debug && options.getBooleanOption(CP_RESOLVE_DEBUG, false);
				JavaModelManager.CP_RESOLVE_VERBOSE_ADVANCED = debug && options.getBooleanOption(CP_RESOLVE_ADVANCED_DEBUG, false);
				JavaModelManager.CP_RESOLVE_VERBOSE_FAILURE = debug && options.getBooleanOption(CP_RESOLVE_FAILURE_DEBUG, false);
				DeltaProcessor.DEBUG = debug && options.getBooleanOption(DELTA_DEBUG, false);
				DeltaProcessor.VERBOSE = debug && options.getBooleanOption(DELTA_DEBUG_VERBOSE, false);
				SourceRangeVerifier.DEBUG = debug && options.getBooleanOption(DOM_AST_DEBUG, false);
				SourceRangeVerifier.DEBUG_THROW = debug && options.getBooleanOption(DOM_AST_DEBUG_THROW, false);
				SourceRangeVerifier.DEBUG |= SourceRangeVerifier.DEBUG_THROW;
				RewriteEventStore.DEBUG = debug && options.getBooleanOption(DOM_REWRITE_DEBUG, false);
				TypeHierarchy.DEBUG = debug && options.getBooleanOption(HIERARCHY_DEBUG, false);
				JobManager.VERBOSE = debug && options.getBooleanOption(INDEX_MANAGER_DEBUG, false);
				IndexManager.DEBUG = debug && options.getBooleanOption(INDEX_MANAGER_ADVANCED_DEBUG, false);
				JavaModelManager.DEBUG_CLASSPATH = debug && options.getBooleanOption(JAVAMODEL_CLASSPATH, false);
				JavaModelManager.DEBUG_INVALID_ARCHIVES = debug && options.getBooleanOption(JAVAMODEL_INVALID_ARCHIVES, false);
				JavaModelManager.VERBOSE = debug && options.getBooleanOption(JAVAMODEL_DEBUG, false);
				JavaModelCache.VERBOSE = debug && options.getBooleanOption(JAVAMODELCACHE_DEBUG, false);
				JavaModelCache.DEBUG_CACHE_INSERTIONS = debug && options.getBooleanOption(JAVAMODELCACHE_INSERTIONS_DEBUG, false);
				JavaModelOperation.POST_ACTION_VERBOSE = debug && options.getBooleanOption(POST_ACTION_DEBUG, false);
				NameLookup.VERBOSE = debug && options.getBooleanOption(RESOLUTION_DEBUG, false);
				BasicSearchEngine.VERBOSE = debug && options.getBooleanOption(SEARCH_DEBUG, false);
				SelectionEngine.DEBUG = debug && options.getBooleanOption(SELECTION_DEBUG, false);
				JavaModelManager.ZIP_ACCESS_VERBOSE = debug && options.getBooleanOption(ZIP_ACCESS_DEBUG, false);
				SourceMapper.VERBOSE = debug && options.getBooleanOption(SOURCE_MAPPER_DEBUG_VERBOSE, false);
				DefaultCodeFormatter.DEBUG = debug && options.getBooleanOption(FORMATTER_DEBUG, false);
				Database.DEBUG_FREE_SPACE = debug && options.getBooleanOption(INDEX_DEBUG_LARGE_CHUNKS, false);
				Database.DEBUG_PAGE_CACHE = debug && options.getBooleanOption(INDEX_DEBUG_PAGE_CACHE, false);
				Indexer.DEBUG = debug && options.getBooleanOption(INDEX_INDEXER_DEBUG, false);
				Indexer.DEBUG_INSERTIONS = debug  && options.getBooleanOption(INDEX_INDEXER_INSERTIONS, false);
				Indexer.DEBUG_ALLOCATIONS = debug && options.getBooleanOption(INDEX_INDEXER_SPACE, false);
				Indexer.DEBUG_TIMING = debug && options.getBooleanOption(INDEX_INDEXER_TIMING, false);
				Indexer.DEBUG_SCHEDULING = debug && options.getBooleanOption(INDEX_INDEXER_SCHEDULING, false);
				Indexer.DEBUG_SELFTEST = debug && options.getBooleanOption(INDEX_INDEXER_SELFTEST, false);
				Indexer.DEBUG_LOG_SIZE_MB = debug ? options.getIntegerOption(INDEX_INDEXER_LOG_SIZE_MEGS, 0) : 0;
				Nd.sDEBUG_LOCKS = debug && options.getBooleanOption(INDEX_LOCKS_DEBUG, false);

				// 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);
				}
			}
		}, properties);
	}

	public static void unregisterDebugOptionsListener() {
		// unregister debug options listener
		DEBUG_REGISTRATION.unregister();
		DEBUG_REGISTRATION = null;
	}

	/*
	 * 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() {
			@Override
			public void handleException(Throwable exception) {
				Util.log(exception, "Exception occurred while loading annotation processor manager"); //$NON-NLS-1$
			}
			@Override
			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<CompilationUnit, PerWorkingCopyInfo> workingCopyToInfos = this.perWorkingCopyInfos.get(owner);
			if (workingCopyToInfos == null) return -1;

			info = 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
	 */
	@Override
	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 = this.zipFiles.get();
		if (zipCache == null) {
			if (JavaModelManager.ZIP_ACCESS_VERBOSE) {
				System.out.println("(" + Thread.currentThread() + ") [JavaModelManager.flushZipFiles(String)] NOT found cache for " + owner); //$NON-NLS-1$	//$NON-NLS-2$
			}
			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();
		} else {
			if (JavaModelManager.ZIP_ACCESS_VERBOSE) {
				System.out.println("(" + Thread.currentThread() //$NON-NLS-1$
						+ ") [JavaModelManager.flushZipFiles(String)] NOT closed cache, wrong owner, expected: " //$NON-NLS-1$
						+ zipCache.owner + ", got: " + owner); //$NON-NLS-1$
			}
		}
	}

	/*
	 * 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;

		LinkedHashSet<IPath> pathToReferencedEntries = new LinkedHashSet<>(referencedEntries.length);
		for (int index = 0; index < referencedEntries.length; index++) {

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

			IClasspathEntry persistedEntry = null;
			if ((persistedEntry = 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<Openable> 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<IJavaElement, Object> tempCache = 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<IJavaProject> getExternalWorkingCopyProjects() {
		synchronized (this.perWorkingCopyInfos) {
			HashSet<IJavaProject> result = null;
			Iterator<Map<CompilationUnit, PerWorkingCopyInfo>> values = this.perWorkingCopyInfos.values().iterator();
			while (values.hasNext()) {
				Map<CompilationUnit, PerWorkingCopyInfo> ownerCopies = values.next();
				Iterator<CompilationUnit> workingCopies = ownerCopies.keySet().iterator();
				while (workingCopies.hasNext()) {
					ICompilationUnit workingCopy = 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<String, String> getDefaultOptions(){

		Hashtable<String, String> 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<String> iterator = this.optionNames.iterator();
		while (iterator.hasNext()) {
		    String propertyName = 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 = 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 = 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<String, String> getOptions() {

		// return cached options if already computed
		Hashtable<String, String> 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<String, String> options = new Hashtable<>(10);
		IPreferencesService service = Platform.getPreferencesService();

		// set options using preferences service lookup
		Iterator<String> iterator = this.optionNames.iterator();
		while (iterator.hasNext()) {
			String propertyName = 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<Entry<String, String[]>> deprecatedEntries = this.deprecatedOptions.entrySet().iterator();
		while (deprecatedEntries.hasNext()) {
			Entry<String, String[]> entry = deprecatedEntries.next();
			String propertyName = entry.getKey();
			String propertyValue = service.get(propertyName, null, this.preferencesLookup);
			if (propertyValue != null) {
				options.put(propertyName, propertyValue);
				String[] compatibleOptions = 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<String, String> getDefaultOptionsNoInitialization() {
		Map<String, String> 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_SUBSTRING_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= 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<CompilationUnit, PerWorkingCopyInfo> workingCopyToInfos = this.perWorkingCopyInfos.get(owner);
			if (workingCopyToInfos == null && create) {
				workingCopyToInfos = new HashMap<>();
				this.perWorkingCopyInfos.put(owner, workingCopyToInfos);
			}

			PerWorkingCopyInfo info = workingCopyToInfos == null ? null : 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<IPath, IClasspathContainer> previousContainerValues = this.previousSessionContainers.get(project);
			if (previousContainerValues != null){
			    IClasspathContainer previousContainer = 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 = 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<IJavaElement, Object> getTemporaryCache() {
		HashMap<IJavaElement, Object> result = 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<String> 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<String> 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;
	}

	public static ModuleSourcePathManager getModulePathManager() {
		if (MANAGER.modulePathManager == null) {
			ModuleSourcePathManager modulePathManager = new ModuleSourcePathManager();
			synchronized(MANAGER) {
				if (MANAGER.modulePathManager == null) { // ensure another library manager was not set while creating the instance above
					MANAGER.modulePathManager = modulePathManager;
				}
			}
		}
		return MANAGER.modulePathManager;
	}
	/*
	 * 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<CompilationUnit, PerWorkingCopyInfo> workingCopyToInfos = 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<PerWorkingCopyInfo> iterator = workingCopyToInfos.values().iterator();
			while(iterator.hasNext()) {
				result[index++] = iterator.next().getWorkingCopy();
			}
			return result;
		}
	}

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

	public static boolean isJrt(IPath path) {
		return path.toString().endsWith(JRTUtil.JRT_FS_JAR);
	}

	public static boolean isJrt(String path) {
		return isJrt(new Path(path));
	}

	public void verifyArchiveContent(IPath path) throws CoreException {
		// TODO: we haven't finalized what path the JRT is represented by. Don't attempt to validate it.
		if (isJrt(path)) {
			return;
		}
		throwExceptionIfArchiveInvalid(path);
		// Check if we can determine the archive's validity by examining the index
		if (JavaIndex.isEnabled()) {
			JavaIndex index = JavaIndex.getIndex();
			String location = JavaModelManager.getLocalFile(path).getAbsolutePath();
			try (IReader reader = index.getNd().acquireReadLock()) {
				NdResourceFile resourceFile = index.getResourceFile(location.toCharArray());
				if (index.isUpToDate(resourceFile)) {
					// We have this file in the index and the index is up-to-date, so we can determine the file's
					// validity without touching the filesystem.
					if (resourceFile.isCorruptedZipFile()) {
						throw new CoreException(new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, -1,
								Messages.status_IOException, new ZipException()));
					}
					return;
				}
			}
		}

		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. The
	 * cause will be a {@link ZipException} if the file was corrupt, a
	 * {@link FileNotFoundException} if the file does not exist, or a
	 * {@link IOException} if we were unable to read the file.
	 */
	public ZipFile getZipFile(IPath path) throws CoreException {
		return getZipFile(path, true);
	}

	/**
	 * For use in the JDT unit tests only. Used for testing error handling. Causes an
	 * {@link IOException} to be thrown in {@link #getZipFile} whenever it attempts to
	 * read a zip file.
	 *
	 * @noreference This field is not intended to be referenced by clients.
	 */
	public static boolean throwIoExceptionsInGetZipFile = false;

	public ZipFile getZipFile(IPath path, boolean checkInvalidArchiveCache) throws CoreException {
		if (checkInvalidArchiveCache) {
			throwExceptionIfArchiveInvalid(path);
		}
		ZipCache zipCache;
		ZipFile zipFile;
		if ((zipCache = this.zipFiles.get()) != null
				&& (zipFile = zipCache.getCache(path)) != null) {
			return zipFile;
		}
		File localFile = getLocalFile(path);

		try {
			if (ZIP_ACCESS_VERBOSE) {
				System.out.println("(" + Thread.currentThread() + ") [JavaModelManager.getZipFile(IPath)] Creating ZipFile on " + localFile ); //$NON-NLS-1$ //$NON-NLS-2$
			}
			if (throwIoExceptionsInGetZipFile) {
				throw new IOException();
			}
			zipFile = new ZipFile(localFile);
			if (zipCache != null) {
				zipCache.setCache(path, zipFile);
			}
			return zipFile;
		} catch (IOException e) {
			ArchiveValidity reason;

			if (e instanceof ZipException) {
				reason = ArchiveValidity.BAD_FORMAT;
			} else if (e instanceof FileNotFoundException) {
				reason = ArchiveValidity.FILE_NOT_FOUND;
			} else {
				reason = ArchiveValidity.UNABLE_TO_READ;
			}
			addInvalidArchive(path, reason);
			throw new CoreException(new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, -1, Messages.status_IOException, e));
		}
	}

	public static File getLocalFile(IPath path) throws CoreException {
		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();
		}
		return localFile;
	}

	private void throwExceptionIfArchiveInvalid(IPath path) throws CoreException {
		ArchiveValidity validity = getArchiveValidity(path);
		IOException reason;
		switch (validity) {
			case BAD_FORMAT: reason = new ZipException(); break;
			case FILE_NOT_FOUND: reason = new FileNotFoundException(); break;
			case UNABLE_TO_READ: reason = new IOException(); break;
			default: reason = null;
		}
		if (reason != null) {
			throw new CoreException(new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, -1, Messages.status_IOException, reason));
		}
	}

	/*
	 * 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<IJavaProject, Set<IPath>> 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());
			Set<IPath> paths = 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) {
			Set<IPath> containerPaths = 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() {
					@Override
					public void run(IProgressMonitor monitor) throws CoreException {
						try {
							// Collect all containers
							Set<Entry<IJavaProject, Set<IPath>>> entrySet = allContainerPaths.entrySet();
							int length = entrySet.size();
							if (monitor != null)
								monitor.beginTask("", length); //$NON-NLS-1$
							Set<Entry<IJavaProject, Set<IPath>>> entries = new HashSet<>(entrySet);  // clone as the following will have a side effect
							for (Entry<IJavaProject, Set<IPath>> entry : entries) {
								IJavaProject javaProject = entry.getKey();
								Set<IPath> pathSet = 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];
									synchronized(JavaModelManager.this.batchContainerInitializationsLock) {
										if (containerIsSet(javaProject, path)) {
											// another thread has concurrently initialized the container.
											continue;
										}
									}
									initializeContainer(javaProject, path);
									IClasspathContainer container = containerBeingInitializedGet(javaProject, path);
									if (container != null) {
										synchronized(JavaModelManager.this.batchContainerInitializationsLock) {
											if (containerIsSet(javaProject, path)) {
												// another thread has concurrently initialized the container.
												containerBeingInitializedRemove(javaProject, path);
											} else {
												containerPut(javaProject, path, container);
											}
										}
									}
								}
								if (monitor != null)
									monitor.worked(1);
							}

							// Set all containers
							Map<IJavaProject, Map<IPath, IClasspathContainer>> perProjectContainers = JavaModelManager.this.containersBeingInitialized.get();
							// Note that during the operation below new containers could be added to the map,
							// so we should loop until containersBeingInitialized will be empty
							while (perProjectContainers != null && !perProjectContainers.isEmpty()) {
								initKnownContainers(perProjectContainers, monitor);
							}
							JavaModelManager.this.containersBeingInitialized.set(null);
						} finally {
							if (monitor != null)
								monitor.done();
						}
					}

					private void initKnownContainers(Map<IJavaProject, Map<IPath, IClasspathContainer>> perProjectContainers, IProgressMonitor monitor)
							throws JavaModelException {
						Iterator<Entry<IJavaProject, Map<IPath, IClasspathContainer>>> entriesIterator = perProjectContainers.entrySet().iterator();
						List<SetContainerOperation> operations = new ArrayList<>();
						while (entriesIterator.hasNext()) {
							Entry<IJavaProject, Map<IPath, IClasspathContainer>> entry = entriesIterator.next();
							IJavaProject project = entry.getKey();
							Map<IPath, IClasspathContainer> perPathContainers = entry.getValue();
							Iterator<Entry<IPath, IClasspathContainer>> containersIterator = perPathContainers.entrySet().iterator();
							while (containersIterator.hasNext()) {
								Entry<IPath, IClasspathContainer> containerEntry = containersIterator.next();
								IPath containerPath = containerEntry.getKey();
								IClasspathContainer container = containerEntry.getValue();
								SetContainerOperation operation = new SetContainerOperation(containerPath, new IJavaProject[] {project}, new IClasspathContainer[] {container});
								operations.add(operation);
							}
						}
						// operation.runOperation() below could put something into the map again
						// so we clear the map to make sure we only see new content there
						perProjectContainers.clear();
						for (SetContainerOperation operation : operations) {
							operation.runOperation(monitor);
						}
					}
				};
			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() {
				@Override
				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() {
			@Override
			public void added(IEclipsePreferences.NodeChangeEvent event) {
				// do nothing
			}
			@Override
			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() {
			@Override
			public void added(IEclipsePreferences.NodeChangeEvent event) {
				// do nothing
			}
			@Override
			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) {
		return (String) this.stringSymbols.add(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;
		*/
	}

	void touchProjects(final IProject[] projectsToTouch, IProgressMonitor progressMonitor) throws JavaModelException {
		WorkspaceJob touchJob = new WorkspaceJob(Messages.synchronizing_projects_job) {
			@Override
			public IStatus runInWorkspace(IProgressMonitor monitor) throws CoreException {
				SubMonitor subMonitor = SubMonitor.convert(monitor, projectsToTouch.length);
				for (IProject iProject : projectsToTouch) {
					if (JavaBuilder.DEBUG) {
						System.out.println("Touching project " + iProject.getName()); //$NON-NLS-1$
					}
					if (iProject.isAccessible()) {
						iProject.touch(subMonitor.split(1));
					}
				}
				return Status.OK_STATUS;
			}

			@Override
			public boolean belongsTo(Object family) {
				return ResourcesPlugin.FAMILY_MANUAL_REFRESH == family;
			}
		};
		touchJob.schedule();
	}

	private Set<IJavaProject> getClasspathBeingResolved() {
	    Set<IJavaProject> result = 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 ArchiveValidity getArchiveValidity(IPath path) {
		InvalidArchiveInfo invalidArchiveInfo;
		synchronized (this.invalidArchivesMutex) {
			invalidArchiveInfo = this.invalidArchives.get(path);
		}
		if (invalidArchiveInfo == null)
			return ArchiveValidity.VALID;
		long now = System.currentTimeMillis();

		// If the TTL for this cache entry has expired, directly check whether the archive is still invalid.
		// If it transitioned to being valid, remove it from the cache and force an update to project caches.
		if (now > invalidArchiveInfo.evictionTimestamp) {
			try {
				getZipFile(path, false);
				removeFromInvalidArchiveCache(path);
			} catch (CoreException e) {
				// Archive is still invalid, fall through to reporting it is invalid.
			}
			// Retry the test from the start, now that we have an up-to-date result
			return getArchiveValidity(path);
		}
		return invalidArchiveInfo.reason;
	}

	public void removeFromInvalidArchiveCache(IPath path) {
		synchronized(this.invalidArchivesMutex) {
			if (this.invalidArchives.remove(path) != null) {
				if (DEBUG_INVALID_ARCHIVES) {
					System.out.println("Invalid JAR cache: removed " + path);  //$NON-NLS-1$
				}
				try {
					// Bug 455042: Force an update of the JavaProjectElementInfo project caches.
					for (IJavaProject project : getJavaModel().getJavaProjects()) {
						if (project.findPackageFragmentRoot(path) != null) {
							((JavaProject) project).resetCaches();
						}
					}
				} catch (JavaModelException e) {
					Util.log(e, "Unable to retrieve the Java model."); //$NON-NLS-1$
				}
			}
		}
	}

	/**
	 * Returns the cached value for whether the file referred to by <code>path</code> exists
	 * and is a file, as determined by the return value of {@link File#isFile()}.
	 */
	public boolean isExternalFile(IPath path) {
		return this.externalFiles != null && this.externalFiles.contains(path);
	}

	/**
	 * Removes the cached state of a single entry in the externalFiles cache.
	 */
	public void clearExternalFileState(IPath path) {
		if (this.externalFiles != null) {
			this.externalFiles.remove(path);
		}
	}

	/**
	 * Resets the entire externalFiles cache.
	 */
	public void resetExternalFilesCache() {
		if (this.externalFiles != null) {
			this.externalFiles.clear();
		}
	}

	/**
	 * Returns whether the provided {@link IPath} appears to be an external file,
	 * which is true if the path does not represent an internal resource, does not
	 * exist on the file system, and does have a file extension (this is the definition
	 * provided by {@link ExternalFoldersManager#isExternalFolderPath}).
	 */
	public boolean isAssumedExternalFile(IPath path) {
		if (this.assumedExternalFiles == null) {
			return false;
		}
		return this.assumedExternalFiles.contains(path);
	}

	/**
	 * Adds the provided {@link IPath} to the list of assumed external files.
	 */
	public void addAssumedExternalFile(IPath path) {
		this.assumedExternalFiles.add(path);
	}

	public void setClasspathBeingResolved(IJavaProject project, boolean classpathIsResolved) {
	    if (classpathIsResolved) {
	        getClasspathBeingResolved().add(project);
	    } else {
	        getClasspathBeingResolved().remove(project);
	    }
	}

	private Set<IPath> loadClasspathListCache(String cacheName) {
		Set<IPath> 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 JavaModelManager " + cacheName + " file"); //$NON-NLS-1$ //$NON-NLS-2$
		} 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<IPath> 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<IPath> 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<IPath> getClasspathListCache(String cacheName) throws CoreException {
		if (cacheName == NON_CHAINING_JARS_CACHE)
			return getNonChainingJarsCache();
		else if (cacheName == EXTERNAL_FILES_CACHE)
			return this.externalFiles;
		else if (cacheName == ASSUMED_EXTERNAL_FILES_CACHE)
			return this.assumedExternalFiles;
		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;
		}

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

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

		@Override
		public int getKind() {
			return 0;
		}

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

		@Override
		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<String, IPath> allPaths;

		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 getAccessRuleForProblemId(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<IPath, IClasspathContainer> oldContainers = 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 = 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<String, IPath> 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<IJavaElement, Object> tempCache = this.temporaryCache.get();
		if (tempCache != null) {
			Object result = tempCache.get(element);
			if (result != null) {
				return result;
			}
		}
		return this.cache.peekAtInfo(element);
	}

	/**
	 * @see ISaveParticipant
	 */
	@Override
	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<IJavaElement, Object> 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<Entry<IJavaElement, Object>> it = newElements.entrySet().iterator(); it.hasNext(); ) {
			Entry<IJavaElement, Object> entry = it.next();
			IJavaElement element = entry.getKey();
			if (element instanceof JarPackageFragmentRoot) {
				JavaElementInfo info = (JavaElementInfo) entry.getValue();
				it.remove();
				this.cache.putInfo(element, info);
			}
		}

		Iterator<Entry<IJavaElement, Object>> iterator = newElements.entrySet().iterator();
		while (iterator.hasNext()) {
			Entry<IJavaElement, Object> entry = iterator.next();
			this.cache.putInfo(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
	 * @param info instanceof IBinaryType or {@link JavaModelCache#NON_EXISTING_JAR_TYPE_INFO}
	 */
	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() {
					@Override
					public IClasspathEntry[] getClasspathEntries() {
						return containerEntries;
					}
					@Override
					public String getDescription() {
						return "Persisted container ["+containerPath+" for project ["+ project.getElementName()+"]"; //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
					}
					@Override
					public int getKind() {
						return 0;
					}
					@Override
					public IPath getPath() {
						return containerPath;
					}
					@Override
					public String toString() {
						return getDescription();
					}

				};
				if (addToContainerValues) {
					getJavaModelManager().containerPut(project, containerPath, container);
				}
				Map<IPath, IClasspathContainer> projectContainers = 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 = JavaModelCache.getElementType(element);
					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;
	}

	void removeFromJarTypeCache(BinaryType type) {
		this.cache.removeFromJarTypeCache(type);
	}

	public void removePerProjectInfo(JavaProject javaProject, boolean removeExtJarInfo) {
		synchronized(this.perProjectInfos) { // use the perProjectInfo collection as its own lock
			IProject project = javaProject.getProject();
			PerProjectInfo info= 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= 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= 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 (DEBUG_INVALID_ARCHIVES) {
			synchronized(this.invalidArchivesMutex) {
				if (!this.invalidArchives.isEmpty()) {
					System.out.println("Invalid JAR cache: clearing cache"); //$NON-NLS-1$
				}
			}
		}
		synchronized(this.invalidArchivesMutex) {
			this.invalidArchives.clear();
		}
		if (this.externalFiles != null)
			this.externalFiles.clear();
		if (this.assumedExternalFiles != null)
			this.assumedExternalFiles.clear();
	}

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

	/**
	 * @see ISaveParticipant
	 */
	@Override
	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<IPath> pathCache = getClasspathListCache(cacheName);
			synchronized (pathCache) {
				out.writeInt(pathCache.size());
				Iterator<IPath> entries = pathCache.iterator();
				while (entries.hasNext()) {
					IPath path = 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<String, IPath> varsToSave = null;
			Iterator<Entry<String, IPath>> iterator = JavaModelManager.this.variables.entrySet().iterator();
			IEclipsePreferences defaultPreferences = getDefaultPreferences();
			while (iterator.hasNext()) {
				Entry<String, IPath> entry = iterator.next();
				String varName = 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<IPath, IClasspathContainer> containerMap)
				throws IOException {
			saveInt(containerMap.size());

			for (Iterator<Entry<IPath, IClasspathContainer>> i = containerMap.entrySet().iterator(); i.hasNext();) {
				Entry<IPath, IClasspathContainer> entry = i.next();
				IPath path = entry.getKey();
				IClasspathContainer container = 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<IPath, IClasspathContainer> containerMap = 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<String, IPath> map) throws IOException {
			saveInt(map.size());

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

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

	private void traceVariableAndContainers(String action, long start) {

		Long delta = Long.valueOf(System.currentTimeMillis() - start);
		Long length = Long.valueOf(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
	 */
	@Override
	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, invalid jar and external file caches on full save
				saveClasspathListCache(NON_CHAINING_JARS_CACHE);
				saveClasspathListCache(EXTERNAL_FILES_CACHE);
				saveClasspathListCache(ASSUMED_EXTERNAL_FILES_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<IStatus> vStats= null; // lazy initialized
		ArrayList<PerProjectInfo> values = null;
		synchronized(this.perProjectInfos) {
			values = new ArrayList<>(this.perProjectInfos.values());
		}
		Iterator<PerProjectInfo> iterator = values.iterator();
		while (iterator.hasNext()) {
			try {
				PerProjectInfo info = 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.
	 *
	 * @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 instanceof IFile) {
			if (org.eclipse.jdt.internal.core.util.Util.isJavaLikeFileName(path)) {
				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)
					Map<IFile, Map<String, Map<String, IType>>> indexedSecondaryTypes;
					if (projectInfo.secondaryTypes == null) {
						projectInfo.secondaryTypes = new Hashtable<>(3);
						indexedSecondaryTypes = new HashMap<>(3);
						projectInfo.indexingSecondaryCache = indexedSecondaryTypes;
					} else {
						indexedSecondaryTypes = projectInfo.indexingSecondaryCache;
						if (indexedSecondaryTypes == null) {
							indexedSecondaryTypes = new HashMap<>(3);
							projectInfo.indexingSecondaryCache = indexedSecondaryTypes;
						}
					}
					// Store the secondary type in temporary cache (these are just handles => no problem to create it now...)
					Map<String, Map<String, IType>> allTypes = indexedSecondaryTypes.get(resource);
					if (allTypes == null) {
						allTypes = new HashMap<>(3);
						indexedSecondaryTypes.put((IFile) 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();
						Map<String, IType> packageTypes = 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<Entry<IFile, Map<String, Map<String, IType>>>> entries = indexedSecondaryTypes.entrySet().iterator();
						while (entries.hasNext()) {
							Entry<IFile, Map<String, Map<String, IType>>> entry = entries.next();
							IFile file = 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, 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<String, Map<String, IType>> 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<IFile, Map<String, Map<String, IType>>> indexingSecondaryCache = projectInfo.secondaryTypes == null ? null : projectInfo.indexingSecondaryCache;
		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
			try {
				this.indexManager.performConcurrentJob(new IJob() {
					@Override
					public boolean belongsTo(String jobFamily) {
						return true;
					}

					@Override
					public void cancel() {
						// job is cancelled through progress
					}

					@Override
					public void ensureReadyToRun() {
						// always ready
					}

					@Override
					public boolean execute(IProgressMonitor progress) {
						return progress == null || !progress.isCanceled();
					}

					@Override
					public String getJobFamily() {
						return ""; //$NON-NLS-1$
					}

				}, IJob.WaitUntilReady, monitor);
			} catch (OperationCanceledException oce) {
				return projectInfo.secondaryTypes;
			}
		}

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

	/*
	 * Return secondary types cache merged with new secondary types created while indexing
	 * Note that merge result is directly stored in given parameter map.
	 */
	private Map<String, Map<String, IType>> secondaryTypesMerging(PerProjectInfo projectInfo) {
		Map<String, Map<String, IType>> secondaryTypes = projectInfo.secondaryTypes;
		if (VERBOSE) {
			Util.verbose("JavaModelManager.getSecondaryTypesMerged()"); //$NON-NLS-1$
			Util.verbose("	- current cache to merge:"); //$NON-NLS-1$
			Iterator<Entry<String, Map<String, IType>>> entries = secondaryTypes.entrySet().iterator();
			while (entries.hasNext()) {
				Entry<String, Map<String, IType>> entry = entries.next();
				String packName = 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)
		Map<IFile, Map<String, Map<String, IType>>> indexedSecondaryTypes = projectInfo.indexingSecondaryCache;
		projectInfo.indexingSecondaryCache = null;
		if (indexedSecondaryTypes == null) {
			return secondaryTypes;
		}

		// Merge indexing cache in secondary types one
		Iterator<Entry<IFile, Map<String, Map<String, IType>>>> entries = indexedSecondaryTypes.entrySet().iterator();
		while (entries.hasNext()) {
			Entry<IFile, Map<String, Map<String, IType>>> entry = entries.next();
			IFile file = 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
			Map<String, Map<String, IType>> fileSecondaryTypes = entry.getValue();
			Iterator<Entry<String, Map<String, IType>>> entries2 = fileSecondaryTypes.entrySet().iterator();
			while (entries2.hasNext()) {
				Entry<String, Map<String, IType>> entry2 = entries2.next();
				String packageName = entry2.getKey();
				Map<String, IType> cachedTypes = secondaryTypes.get(packageName);
				if (cachedTypes == null) {
					secondaryTypes.put(packageName, entry2.getValue());
				} else {
					Map<String, IType> types = entry2.getValue();
					Iterator<Entry<String, IType>> entries3 = types.entrySet().iterator();
					while (entries3.hasNext()) {
						Entry<String, IType> entry3 = entries3.next();
						String typeName = entry3.getKey();
						cachedTypes.put(typeName, entry3.getValue());
					}
				}
			}
		}
		if (VERBOSE) {
			Util.verbose("	- secondary types cache merged:"); //$NON-NLS-1$
			Iterator<Entry<String, Map<String, IType>>> entries2 = secondaryTypes.entrySet().iterator();
			while (entries.hasNext()) {
				Entry<String, Map<String, IType>> entry = entries2.next();
				String packName = 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 static Map<String, Map<String, IType>> 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<String, Map<String, String>> secondaryTypesSearch = new Hashtable<>(3);
		IRestrictedAccessTypeRequestor nameRequestor = new IRestrictedAccessTypeRequestor() {
			@Override
			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$
				Map<String, String> types = secondaryTypesSearch.get(key);
				if (types == null) types = new HashMap<>(3);
				types.put(new String(simpleTypeName), path);
				secondaryTypesSearch.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
		final Hashtable<String, Map<String, IType>> secondaryTypes = new Hashtable<>(secondaryTypesSearch.size());
		for (Entry<String, Map<String, String>> packageEntry : secondaryTypesSearch.entrySet()) {
			String packageName = packageEntry.getKey();
			Map<String, String> types = packageEntry.getValue();
			Map<String, IType> tempTypes = new HashMap<>(types.size());
			for (Entry<String, String> entry : types.entrySet()) {
				String typeName = entry.getKey();
				String path = 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);
					tempTypes.put(typeName, type);
				}
			}
			secondaryTypes.put(packageName, tempTypes);
		}

		// 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.indexingSecondaryCache != 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<Entry<String, Map<String, IType>>> entries = secondaryTypes.entrySet().iterator();
				while (entries.hasNext()) {
					Entry<String, Map<String, IType>> entry = entries.next();
					String qualifiedName = 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
				Map<IFile, Map<String, Map<String, IType>>> indexingCache = projectInfo.indexingSecondaryCache;
				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.indexingSecondaryCache = new HashMap<>();
					}
					return;
				}
				if (indexingCache != null) {
					Set<IFile> keys = indexingCache.keySet();
					int filesSize = keys.size(), filesCount = 0;
					IFile[] removed = null;
					Iterator<IFile> cachedFiles = keys.iterator();
					while (cachedFiles.hasNext()) {
						IFile cachedFile = 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(Map<String, Map<String, IType>> secondaryTypesMap, IFile file) {
		if (VERBOSE) {
			StringBuffer buffer = new StringBuffer("JavaModelManager.removeSecondaryTypesFromMap("); //$NON-NLS-1$
			Iterator<Entry<String, Map<String, IType>>> entries = secondaryTypesMap.entrySet().iterator();
			while (entries.hasNext()) {
				Entry<String, Map<String, IType>> entry = entries.next();
				String qualifiedName = entry.getKey();
				buffer.append(qualifiedName+':'+ entry.getValue());
			}
			buffer.append(',');
			buffer.append(file.getFullPath());
			buffer.append(')');
			Util.verbose(buffer.toString());
		}
		Set<Entry<String, Map<String, IType>>> packageEntries = secondaryTypesMap.entrySet();
		int packagesSize = packageEntries.size(), removedPackagesCount = 0;
		String[] removedPackages = null;
		Iterator<Entry<String, Map<String, IType>>> packages = packageEntries.iterator();
		while (packages.hasNext()) {
			Entry<String, Map<String, IType>> entry = packages.next();
			String packName = entry.getKey();
			Map<String, IType> types = entry.getValue();
			Set<Entry<String, IType>> nameEntries = types.entrySet();
			int namesSize = nameEntries.size(), removedNamesCount = 0;
			String[] removedNames = null;
			Iterator<Entry<String, IType>> names = nameEntries.iterator();
			while (names.hasNext()) {
				Entry<String, IType> entry2 = names.next();
				String typeName = 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<Entry<String, Map<String, IType>>> entries = secondaryTypesMap.entrySet().iterator();
			while (entries.hasNext()) {
				Entry<String, Map<String, IType>> entry = entries.next();
				String qualifiedName = 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<String, String> 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<String, String> 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 = 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<String, String> newOptions) {
		Hashtable<String, String> 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<String> keys = newOptions.keys();
			while (keys.hasMoreElements()){
				String key = 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 = 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 {
			// 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() {
				@Override
				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() {
				@Override
				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);

			Indexer.getInstance().addListener(this.deltaState);

			// listen to resource changes affecting external annotations
			ExternalAnnotationTracker.start(workspace);

			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) {
				@Override
				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() {
								@Override
								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) {
			try {
				shutdown();
			} catch (RuntimeException e2) {
				e.addSuppressed(e2);
			}
			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);

		ExternalAnnotationTracker.shutdown(workspace);

		// Stop listening to content-type changes
		IContentTypeManager contentTypeManager = Platform.getContentTypeManager();
		if (contentTypeManager != null) {
			contentTypeManager.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
		Set<String> initializations = variableInitializationInProgress();
		if (initializations.contains(variableName)) {
			return VARIABLE_INITIALIZATION_IN_PROGRESS;
		}
		return this.variables.get(variableName);
	}

	private synchronized IPath variableGetDefaultToPreviousSession(String variableName){
		IPath variablePath = 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 Set<String> variableInitializationInProgress() {
		Set<String> initializations = 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<String> vars = this.variables.keySet().iterator();
		int index = 0;
		while (vars.hasNext()) {
			result[index++] = vars.next();
		}
		return result;
	}

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

		// set/unset the initialization in progress
		Set<String> 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;
	}

	@Override
	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 ElementCache<ITypeRoot>.Stats debugNewOpenableCacheStats() {
		return this.cache.openableCache.new Stats();
	}

	public int getOpenableCacheSize() {
		return this.cache.openableCache.getSpaceLimit();
	}

	/**
	 * Get a cached access rule, or when the cache did not contain the rule, creates a new one.
	 *
	 * @param filePattern the file pattern this access rule should match
	 * @param kind one of {@link IAccessRule#K_ACCESSIBLE}, {@link IAccessRule#K_DISCOURAGED},
	 *                     or {@link IAccessRule#K_NON_ACCESSIBLE}, optionally combined with
	 *                     {@link IAccessRule#IGNORE_IF_BETTER}
	 * @return an access rule
	 */
	public IAccessRule getAccessRule(IPath filePattern, int kind) {
		ClasspathAccessRule rule = new ClasspathAccessRule(filePattern, kind);
		return getFromCache(rule);
	}

	/**
	 * Used only for loading rules from disk.
	 */
	public ClasspathAccessRule getAccessRuleForProblemId(char [] filePattern, int problemId) {
		ClasspathAccessRule rule = new ClasspathAccessRule(filePattern, problemId);
		return getFromCache(rule);
	}

	private ClasspathAccessRule getFromCache(ClasspathAccessRule rule) {
		ClasspathAccessRule cachedRule = this.cache.accessRuleCache.get(rule);
		if (cachedRule != null) {
			return cachedRule;
		}
		this.cache.accessRuleCache.put(rule, rule);
		return rule;
	}
}
