/*******************************************************************************
 * Copyright (c) 2005, 2018 IBM Corporation and others.
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 * 
 * SPDX-License-Identifier: EPL-2.0
 *
 *******************************************************************************/
package org.eclipse.dltk.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.FileOutputStream;
import java.io.IOException;
import java.net.URI;
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.Map;
import java.util.Map.Entry;
import java.util.Set;

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.IWorkspaceRoot;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.AssertionFailedException;
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.IStatus;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Plugin;
import org.eclipse.core.runtime.Status;
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.IPreferenceChangeListener;
import org.eclipse.core.runtime.preferences.IPreferencesService;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.dltk.compiler.problem.IProblem;
import org.eclipse.dltk.compiler.util.HashtableOfObjectToInt;
import org.eclipse.dltk.core.BuildpathContainerInitializer;
import org.eclipse.dltk.core.DLTKContentTypeManager;
import org.eclipse.dltk.core.DLTKCore;
import org.eclipse.dltk.core.DLTKLanguageManager;
import org.eclipse.dltk.core.IAccessRule;
import org.eclipse.dltk.core.IArchive;
import org.eclipse.dltk.core.IBuildpathAttribute;
import org.eclipse.dltk.core.IBuildpathContainer;
import org.eclipse.dltk.core.IBuildpathEntry;
import org.eclipse.dltk.core.IDLTKLanguageToolkit;
import org.eclipse.dltk.core.IModelElement;
import org.eclipse.dltk.core.IModelStatus;
import org.eclipse.dltk.core.IModelStatusConstants;
import org.eclipse.dltk.core.IParent;
import org.eclipse.dltk.core.IProblemRequestor;
import org.eclipse.dltk.core.IProjectFragment;
import org.eclipse.dltk.core.IProjectFragmentTimestamp;
import org.eclipse.dltk.core.IScriptFolder;
import org.eclipse.dltk.core.IScriptModel;
import org.eclipse.dltk.core.IScriptProject;
import org.eclipse.dltk.core.ISourceModule;
import org.eclipse.dltk.core.ISourceModuleInfoCache;
import org.eclipse.dltk.core.ModelException;
import org.eclipse.dltk.core.WorkingCopyOwner;
import org.eclipse.dltk.core.caching.IContentCache;
import org.eclipse.dltk.core.environment.EnvironmentPathUtils;
import org.eclipse.dltk.core.environment.IFileHandle;
import org.eclipse.dltk.core.search.indexing.IndexManager;
import org.eclipse.dltk.internal.core.builder.ScriptBuilder;
import org.eclipse.dltk.internal.core.caching.DLTKCoreCache;
import org.eclipse.dltk.internal.core.search.DLTKWorkspaceScope;
import org.eclipse.dltk.internal.core.search.ProjectIndexerManager;
import org.eclipse.dltk.internal.core.util.Messages;
import org.eclipse.dltk.internal.core.util.Util;
import org.eclipse.dltk.internal.core.util.WeakHashSet;
import org.eclipse.osgi.util.NLS;
import org.osgi.service.prefs.BackingStoreException;

public class ModelManager implements ISaveParticipant {
	private final static int CONTAINERS_FILE_VERSION = 1;
	public final static String BP_VARIABLE_PREFERENCES_PREFIX = DLTKCore.PLUGIN_ID + ".buildpathVariable."; //$NON-NLS-1$
	public final static String BP_CONTAINER_PREFERENCES_PREFIX = DLTKCore.PLUGIN_ID + ".buildpathContainer."; //$NON-NLS-1$
	public final static String BP_USERLIBRARY_PREFERENCES_PREFIX = DLTKCore.PLUGIN_ID + ".userLibrary."; //$NON-NLS-1$
	public final static String BP_ENTRY_IGNORE = "##<cp entry ignore>##"; //$NON-NLS-1$
	public final static IPath BP_ENTRY_IGNORE_PATH = new Path(BP_ENTRY_IGNORE);
	public final static String TRUE = "true"; //$NON-NLS-1$
	/**
	 * Unique handle onto the Model
	 */
	final Model model = new Model();
	/**
	 * Buildpath variables pool
	 */
	public HashMap variables = new HashMap(5);
	public HashSet variablesWithInitializer = new HashSet(5);
	public HashSet readOnlyVariables = new HashSet(5);
	public HashMap previousSessionVariables = new HashMap(5);
	private ThreadLocal variableInitializationInProgress = new ThreadLocal();

	/**
	 * Buildpath containers pool
	 */
	public HashMap containers = new HashMap(5);
	public HashMap previousSessionContainers = new HashMap(5);
	private ThreadLocal containerInitializationInProgress = new ThreadLocal();
	public boolean batchContainerInitializations = false;
	public final Hashtable<String, BuildpathContainerInitializer> containerInitializersCache = new Hashtable<>(5);
	/**
	 * 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 IBuildpathContainer CONTAINER_INITIALIZATION_IN_PROGRESS = new IBuildpathContainer() {
		@Override
		public IBuildpathEntry[] getBuildpathEntries() {
			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();
		}

	};
	/*
	 * A HashSet that contains the IScriptProject whose buildpath is being resolved.
	 */
	private ThreadLocal<HashSet<IScriptProject>> buildpathsBeingResolved = new ThreadLocal<>();

	public static class PerProjectInfo {
		static final IModelStatus NEED_RESOLUTION = new ModelStatus();

		public IProject project;
		public Object savedState;
		public boolean triedRead;
		public IBuildpathEntry[] rawBuildpath;
		public IModelStatus rawBuildpathStatus;
		public int rawTimeStamp = 0;
		public boolean writtingRawClasspath = false;
		public IBuildpathEntry[] resolvedBuildpath;
		public IModelStatus unresolvedEntryStatus;
		// reverse map from a package fragment root's path to the raw entry
		public Map<IPath, IBuildpathEntry> rootPathToRawEntries;
		// map from a package fragment root's path to the resolved entry
		public Map<IPath, IBuildpathEntry> rootPathToResolvedEntries;

		public IEclipsePreferences preferences;
		public Hashtable options;

		public PerProjectInfo(IProject project) {
			this.triedRead = false;
			this.savedState = null;
			this.project = project;
		}

		public synchronized IBuildpathEntry[] getResolvedBuildpath() {
			if (this.unresolvedEntryStatus == NEED_RESOLUTION)
				return null;
			return this.resolvedBuildpath;
		}

		public void rememberExternalLibTimestamps() {
			IBuildpathEntry[] buildpath = this.resolvedBuildpath;
			if (buildpath == null)
				return;
			Map<IPath, Long> externalTimeStamps = ModelManager.getModelManager().deltaState.getExternalLibTimeStamps();
			for (int i = 0, length = buildpath.length; i < length; i++) {
				IBuildpathEntry entry = buildpath[i];
				if (entry.getEntryKind() == IBuildpathEntry.BPE_LIBRARY) {
					IPath path = entry.getPath();
					if (externalTimeStamps.get(path) == null) {
						Object target = Model.getTarget(ResourcesPlugin.getWorkspace().getRoot(), path, true);
						if (target instanceof IFileHandle) {
							long timestamp = DeltaProcessor.getTimeStamp((IFileHandle) target);
							externalTimeStamps.put(path, Long.valueOf(timestamp));
						}
					}
				}
			}
			Map<IPath, Long> customTimeStamps = ModelManager.getModelManager().deltaState.getCustomTimeStamps();
			// Save custom project fragments timestamps.
			try {
				IScriptProject scriptProject = DLTKCore.create(project);
				IProjectFragment[] fragments = scriptProject.getAllProjectFragments();
				for (int i = 0; i < fragments.length; i++) {
					if (fragments[i] instanceof IProjectFragmentTimestamp) {
						IProjectFragmentTimestamp stamp = (IProjectFragmentTimestamp) fragments[i];
						long timeStamp = stamp.getTimeStamp();
						customTimeStamps.put(fragments[i].getPath(), Long.valueOf(timeStamp));
					}
				}
			} catch (ModelException e) {
				if (DLTKCore.DEBUG) {
					e.printStackTrace();
				}
			}
		}

		public synchronized BuildpathChange resetResolvedBuildpath() {
			return setResolvedBuildpath(null, null, null, null, rawTimeStamp, true);
		}

		protected BuildpathChange addBuildpathChange() {
			// remember old info
			ModelManager manager = ModelManager.getModelManager();
			BuildpathChange buildpathChange = manager.deltaState.addBuildpathChange(this.project, this.rawBuildpath,
					this.resolvedBuildpath);
			return buildpathChange;
		}

		public synchronized BuildpathChange setRawBuildpath(IBuildpathEntry[] newRawBuildpath,
				IModelStatus newRawBuildpathStatus) {
			this.rawTimeStamp++;
			return setBuildpath(newRawBuildpath, newRawBuildpathStatus, null/* resolved classpath */,
					null/* rootPathToRawEntries */, null/* rootPathToResolvedEntries */, null/* unresolved status */,
					true/* add classpath change */);
		}

		public synchronized BuildpathChange setResolvedBuildpath(IBuildpathEntry[] newResolvedClasspath,
				Map<IPath, IBuildpathEntry> newRootPathToRawEntries,
				Map<IPath, IBuildpathEntry> newRootPathToResolvedEntries, IModelStatus newUnresolvedEntryStatus,
				int timeStamp, boolean addBuildpathChange) {
			if (this.rawTimeStamp != timeStamp)
				return null;
			return setBuildpath(this.rawBuildpath, this.rawBuildpathStatus, newResolvedClasspath,
					newRootPathToRawEntries, newRootPathToResolvedEntries, newUnresolvedEntryStatus,
					addBuildpathChange);
		}

		private BuildpathChange setBuildpath(IBuildpathEntry[] newRawBuildpath, IModelStatus newRawBuildpathStatus,
				IBuildpathEntry[] newResolvedBuildpath, Map<IPath, IBuildpathEntry> newRootPathToRawEntries,
				Map<IPath, IBuildpathEntry> newRootPathToResolvedEntries, IModelStatus newUnresolvedEntryStatus,
				boolean addBuildpathChange) {
			BuildpathChange classpathChange = addBuildpathChange ? addBuildpathChange() : null;
			this.rawBuildpath = newRawBuildpath;
			this.rawBuildpathStatus = newRawBuildpathStatus;
			this.resolvedBuildpath = newResolvedBuildpath;
			this.rootPathToRawEntries = newRootPathToRawEntries;
			this.rootPathToResolvedEntries = newRootPathToResolvedEntries;
			this.unresolvedEntryStatus = newUnresolvedEntryStatus;
			return classpathChange;
		}

		/**
		 * Reads the buildpath and caches the entries. Returns an array of raw buildpath
		 * entries.
		 */
		public synchronized IBuildpathEntry[] readAndCacheBuildpath(ScriptProject javaProject) {
			// read file entries and update status
			IBuildpathEntry[] classpath;
			IModelStatus status;
			try {
				classpath = javaProject.readFileEntriesWithException(null/*
																			 * not interested in unknown elements
																			 */);
				status = ModelStatus.VERIFIED_OK;
			} catch (CoreException e) {
				classpath = ScriptProject.INVALID_BUILDPATH;
				status = new ModelStatus(IModelStatusConstants.INVALID_BUILDPATH_FILE_FORMAT,
						Messages.bind(Messages.buildpath_cannotReadBuildpathFile, javaProject.getElementName()));
			} catch (IOException e) {
				classpath = ScriptProject.INVALID_BUILDPATH;
				if (Messages.file_badFormat.equals(e.getMessage()))
					status = new ModelStatus(IModelStatusConstants.INVALID_BUILDPATH_FILE_FORMAT, Messages.bind(
							Messages.buildpath_xmlFormatError, javaProject.getElementName(), Messages.file_badFormat));
				else
					status = new ModelStatus(IModelStatusConstants.INVALID_BUILDPATH_FILE_FORMAT,
							Messages.bind(Messages.buildpath_cannotReadBuildpathFile, javaProject.getElementName()));
			} catch (/* BuildpathEntry. */AssertionFailedException e) {
				classpath = ScriptProject.INVALID_BUILDPATH;
				status = new ModelStatus(IModelStatusConstants.INVALID_BUILDPATH_FILE_FORMAT,
						Messages.bind(Messages.buildpath_illegalEntryInBuildpathFile,
								new String[] { javaProject.getElementName(), e.getMessage() }));
			}

			// store new raw buildpath and new status, and null out
			// resolved info
			setRawBuildpath(classpath, 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 buildpath:\n"); //$NON-NLS-1$
			if (this.rawBuildpath == null) {
				buffer.append("  <null>\n"); //$NON-NLS-1$
			} else {
				for (int i = 0, length = this.rawBuildpath.length; i < length; i++) {
					buffer.append("  "); //$NON-NLS-1$
					buffer.append(this.rawBuildpath[i]);
					buffer.append('\n');
				}
			}
			buffer.append("Resolved buildpath:\n"); //$NON-NLS-1$
			IBuildpathEntry[] resolvedCP = this.resolvedBuildpath;
			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');
				}
			}
			return buffer.toString();
		}

		public boolean writeAndCacheBuildpath(ScriptProject scriptProject, final IBuildpathEntry[] newRawBuildpath)
				throws ModelException {
			try {
				this.writtingRawClasspath = true;

				// write .classpath
				if (!scriptProject.writeFileEntries(newRawBuildpath)) {
					return false;
				}
				// store new raw classpath, new output and new status, and null
				// out resolved info
				setRawBuildpath(newRawBuildpath, ModelStatus.VERIFIED_OK);
			} finally {
				this.writtingRawClasspath = false;
			}
			return true;
		}

	}

	public static class PerWorkingCopyInfo implements IProblemRequestor {
		int useCount = 0;
		IProblemRequestor problemRequestor;
		ISourceModule workingCopy;

		public PerWorkingCopyInfo(ISourceModule workingCopy, IProblemRequestor problemRequestor) {
			this.workingCopy = workingCopy;
			this.problemRequestor = problemRequestor;
		}

		@Override
		public void acceptProblem(IProblem problem) {
			if (this.problemRequestor == null)
				return;
			this.problemRequestor.acceptProblem(problem);
		}

		@Override
		public void beginReporting() {
			if (this.problemRequestor == null)
				return;
			this.problemRequestor.beginReporting();
		}

		@Override
		public void endReporting() {
			if (this.problemRequestor == null)
				return;
			this.problemRequestor.endReporting();
		}

		public ISourceModule getWorkingCopy() {
			return this.workingCopy;
		}

		@Override
		public boolean isActive() {
			return this.problemRequestor != null && this.problemRequestor.isActive();
		}

		@Override
		public String toString() {
			StringBuffer buffer = new StringBuffer();
			buffer.append("Info for "); //$NON-NLS-1$
			buffer.append(((ModelElement) 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);
			return buffer.toString();
		}
	}

	public static boolean VERBOSE = DLTKCore.VERBOSE_MODEL_MANAGER;
	public static boolean BP_RESOLVE_VERBOSE = DLTKCore.VERBOSE_BP_RESOLVE;
	public static final boolean BP_RESOLVE_VERBOSE_ADVANCED = false;
	/**
	 * Name of the extension point for contributing buildpath variable initializers
	 */
	public static final String BPVARIABLE_INITIALIZER_EXTPOINT_ID = "buildpathVariableInitializer"; //$NON-NLS-1$

	/**
	 * Name of the extension point for contributing buildpath container initializers
	 */
	public static final String BPCONTAINER_INITIALIZER_EXTPOINT_ID = "buildpathContainerInitializer"; //$NON-NLS-1$
	public static boolean ZIP_ACCESS_VERBOSE = DLTKCore.VERBOSE_ZIP_ACCESS;
	/**
	 * 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<Map<IPath, IArchive>> zipFiles = new ThreadLocal<>();

	private UserLibraryManager userLibraryManager;

	public final static ISourceModule[] NO_WORKING_COPY = new ISourceModule[0];
	/**
	 * The singleton manager
	 */
	private static ModelManager MANAGER = new ModelManager();
	/**
	 * Infos cache.
	 */
	public ModelCache cache;// = new ModelCache();
	/*
	 * Temporary cache of newly opened elements
	 */
	private ThreadLocal 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;
	/**
	 * Table from IProject to PerProjectInfo. NOTE: this object itself is used as a
	 * lock to synchronize creation/removal of per project infos
	 */
	protected Map perProjectInfos = new HashMap(5);
	/**
	 * Table from WorkingCopyOwner to a table of ISourceModule (working copy handle)
	 * to PerWorkingCopyInfo. NOTE: this object itself is used as a lock to
	 * synchronize creation/removal of per working copy infos
	 */
	protected Map perWorkingCopyInfos = new HashMap(5);
	public final IEclipsePreferences[] preferencesLookup = new IEclipsePreferences[2];
	static final int PREF_INSTANCE = 0;
	static final int PREF_DEFAULT = 1;
	// Preferences
	HashSet<String> optionNames = new HashSet<>(20);
	Hashtable<String, String> optionsCache;
	/*
	 * Pools of symbols used in the model. Used as a replacement for String#intern()
	 * that could prevent garbage collection of strings on some VMs.
	 */
	private WeakHashSet stringSymbols = new WeakHashSet(5);
	Map workspaceScope = null;
	public static final String DELTA_LISTENER_PERF = DLTKCore.PLUGIN_ID + "/perf/deltalistener"; //$NON-NLS-1$

	private ExternalFoldersManager externalFoldersManager = new ExternalFoldersManager();
	private DLTKCoreCache coreCache = null;

	final boolean resolveReferencedLibrariesForContainers = false;

	public IContentCache getCoreCache() {
		if (coreCache == null) {
			coreCache = new DLTKCoreCache();
		}
		return coreCache;
	}

	/**
	 * Listener on properties changes.
	 */
	private IEclipsePreferences.IPreferenceChangeListener propertyListener;
	private IEclipsePreferences.IPreferenceChangeListener resourcesPropertyListener;

	/**
	 * Constructs a new ModelManager
	 */
	private ModelManager() {
		// singleton: prevent others from creating a new instance
		if (Platform.isRunning())
			this.indexManager = new IndexManager();
	}

	/**
	 * Returns the handle to the active script model.
	 */
	public final Model getModel() {
		return this.model;
	}

	/**
	 * Returns the singleton ModelManager
	 */
	public final static ModelManager getModelManager() {
		return MANAGER;
	}

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

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

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

	/*
	 * 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(ModelElement element) throws ModelException {
		Object info = this.cache.peekAtInfo(element);
		if (info != null) {
			boolean wasVerbose = false;
			try {
				if (VERBOSE) {
					String elementType;
					switch (element.getElementType()) {
					case IModelElement.SCRIPT_PROJECT:
						elementType = "project"; //$NON-NLS-1$
						break;
					case IModelElement.PROJECT_FRAGMENT:
						elementType = "root"; //$NON-NLS-1$
						break;
					case IModelElement.SCRIPT_FOLDER:
						elementType = "folder"; //$NON-NLS-1$
						break;
					case IModelElement.BINARY_MODULE:
						elementType = "binary module"; //$NON-NLS-1$
						break;
					case IModelElement.SOURCE_MODULE:
						elementType = "source module"; //$NON-NLS-1$
						break;
					default:
						elementType = "element"; //$NON-NLS-1$
					}
					System.out.println(Thread.currentThread() + " CLOSING " + elementType //$NON-NLS-1$
							+ " " + element.toStringWithAncestors()); //$NON-NLS-1$
					wasVerbose = true;
					VERBOSE = false;
				}
				element.closing(info);
				if (element instanceof IParent && info instanceof ModelElementInfo) {
					IModelElement[] children = ((ModelElementInfo) info).getChildren();
					for (int i = 0, size = children.length; i < size; ++i) {
						ModelElement child = (ModelElement) children[i];
						child.close();
					}
				}
				this.cache.removeInfo(element);
				if (wasVerbose) {
					System.out.println(this.cache.toStringFillingRation("-> ")); //$NON-NLS-1$
				}
			} finally {
				ModelManager.VERBOSE = wasVerbose;
			}
			return info;
		}
		return null;
	}

	/*
	 * Puts the infos in the given map (keys are IModelElements and values are
	 * ModelElementInfos) in the model cache in an atomic way. First checks that the
	 * info for the opened element (or one of its ancestors) has not been added to
	 * the cache. If it is the case, another thread has opened the element (or one
	 * of its ancestors). So returns without updating the cache.
	 */
	protected synchronized void putInfos(IModelElement openedElement, Map newElements) {
		// remove children
		Object existingInfo = this.cache.peekAtInfo(openedElement);
		if (openedElement instanceof IParent && existingInfo instanceof ModelElementInfo) {
			IModelElement[] children = ((ModelElementInfo) existingInfo).getChildren();
			for (int i = 0, size = children.length; i < size; ++i) {
				ModelElement child = (ModelElement) children[i];
				try {
					child.close();
				} catch (ModelException e) {
					// ignore
				}
			}
		}
		// Need to put any ArchiveProjectFragment in first.
		// This is due to the way the LRU cache flushes entries.
		// When a BinaryFolder is flused from the LRU cache, the entire
		// archive is flushed by removing the ArchiveProjectFragment and all of
		// its
		// children (see ElementCache.close()). If we flush the BinaryFolder
		// when its ArchiveProjectFragment is not in the cache and the root is
		// about to be
		// added (during the 'while' loop), we will end up in an inconsist
		// state.
		// Subsequent resolution against package in the archive would fail as a
		// result.
		for (Iterator it = newElements.entrySet().iterator(); it.hasNext();) {
			Map.Entry entry = (Map.Entry) it.next();
			IModelElement element = (IModelElement) entry.getKey();
			if (element instanceof ArchiveProjectFragment || element instanceof ExternalScriptFolder) {
				Object info = entry.getValue();
				it.remove();
				this.cache.putInfo(element, info);
			}
		}
		Iterator iterator = newElements.keySet().iterator();
		while (iterator.hasNext()) {
			IModelElement element = (IModelElement) iterator.next();
			Object info = newElements.get(element);
			this.cache.putInfo(element, info);
		}
	}

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

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

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

	/**
	 * Returns the model 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 model element.
	 *
	 * Creating a model element has the side effect of creating and opening all of
	 * the element's parents if they are not yet open.
	 */
	public static IModelElement create(IFile file, IScriptProject project) {
		if (file == null) {
			return null;
		}
		if (project == null) {
			project = DLTKCore.create(file.getProject());
		}
		// FIXME at the moment we can create source modules only
		if (Util.isValidSourceModule(project, file)) {
			return createSourceModuleFrom(file, project);
		}
		return null;
	}

	/**
	 * Creating an element has the side effect of creating and opening all of the
	 * element's parents if they are not yet open.
	 */
	public static IModelElement create(IResource resource, IScriptProject project) {
		if (resource == null) {
			return null;
		}
		int type = resource.getType();
		switch (type) {
		case IResource.PROJECT:
			return DLTKCore.create((IProject) resource);
		case IResource.FILE:
			return create((IFile) resource, project);
		case IResource.FOLDER:
			return create((IFolder) resource, project);
		case IResource.ROOT:
			return DLTKCore.create((IWorkspaceRoot) resource);
		default:
			return null;
		}
	}

	public static IModelElement create(IFolder folder, IScriptProject project) {
		if (folder == null) {
			return null;
		}
		IModelElement element;
		if (project == null) {
			project = DLTKCore.create(folder.getProject());
			element = determineIfOnBuildpath(folder, project);
			if (element == null) {
				// walk all projects and find one that have the given folder on
				// its buildpath
				IScriptProject[] projects;
				try {
					projects = ModelManager.getModelManager().getModel().getScriptProjects();
				} catch (ModelException e) {
					return null;
				}
				for (int i = 0, length = projects.length; i < length; i++) {
					project = projects[i];
					element = determineIfOnBuildpath(folder, project);
					if (element != null)
						break;
				}
			}
			if (element == null) {
				// not on buildpath - make the root its folder
				IProjectFragment root = project.getProjectFragment(Path.EMPTY);
				element = root.getScriptFolder(folder.getProjectRelativePath());
				if (VERBOSE) {
					System.out.println("WARNING : creating dir outside buildpath (" //$NON-NLS-1$
							+ Thread.currentThread() + "): " //$NON-NLS-1$
							+ folder.getFullPath());
				}
			}
		} else {
			element = determineIfOnBuildpath(folder, project);
		}
		return element;
	}

	/**
	 * Creates and returns a source module element for the given file, its project
	 * being the given project. Returns <code>null</code> if unable to recognize the
	 * source module.
	 */
	public static ISourceModule createSourceModuleFrom(IFile file, IScriptProject project) {
		if (file == null)
			return null;
		if (project == null) {
			project = DLTKCore.create(file.getProject());
		}
		IScriptFolder folder = (IScriptFolder) determineIfOnBuildpath(file, project);
		if (folder == null) {
			// not on buildpath - make the root its folder
			IProjectFragment root = project.getProjectFragment(file.getParent());
			folder = root.getScriptFolder(Path.EMPTY);
			if (VERBOSE) {
				System.out.println("WARNING : creating module element outside buildpath (" //$NON-NLS-1$
						+ Thread.currentThread() + "): " //$NON-NLS-1$
						+ file.getFullPath());
			}
		}
		return folder.getSourceModule(file.getName());
	}

	/**
	 * Returns the project fragment root represented by the resource, or the folder
	 * the given resource is located in, or <code>null</code> if the given resource
	 * is not on the buildpath of the given project.
	 */
	public static IModelElement determineIfOnBuildpath(IResource resource, IScriptProject project) {
		IPath resourcePath = resource.getFullPath();
		try {
			IBuildpathEntry[] entries = ((ScriptProject) project).getResourceOnlyResolvedBuildpath();

			for (int i = 0; i < entries.length; i++) {
				IBuildpathEntry entry = entries[i];
				if (entry.getEntryKind() == IBuildpathEntry.BPE_PROJECT)
					continue;
				IPath rootPath = entry.getPath();
				if (rootPath.equals(resourcePath)) {
					return project.getProjectFragment(resource);
				} else if (rootPath.isPrefixOf(resourcePath)) {
					BuildpathEntry bpe = (BuildpathEntry) entry;
					if (!Util.isExcluded(resource, bpe.fullInclusionPatternChars(), bpe.fullExclusionPatternChars())) {
						/*
						 * given we have a resource child of the root, it cannot be a ZIP fragment
						 */
						IProjectFragment root = ((ScriptProject) project).getFolderProjectFragment(rootPath);
						if (root == null)
							return null;
						IPath folderPath = 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 folder
							 */
							folderPath = folderPath.removeLastSegments(1);
						}
						return root.getScriptFolder(folderPath);
					}
				}
			}
		} catch (ModelException npe) {
			return null;
		}
		return null;
	}

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

	/*
	 * Returns the per-project info for the given project. If the info doesn't
	 * exist, check for the project existence and create the info. @throws
	 * ModelException if the project doesn't exist.
	 */
	public PerProjectInfo getPerProjectInfoCheckExistence(IProject project) throws ModelException {
		ModelManager.PerProjectInfo info = getPerProjectInfo(project, false /*
																			 * don't create info
																			 */);
		if (info == null) {
			if (!ScriptProject.hasScriptNature(project)) {
				throw ((ScriptProject) DLTKCore.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(SourceModule workingCopy, boolean create, boolean recordUsage,
			IProblemRequestor problemRequestor) {
		synchronized (this.perWorkingCopyInfos) {
			// use the perWorkingCopyInfo collection as its own lock
			WorkingCopyOwner owner = workingCopy.getOwner();
			Map workingCopyToInfos = (Map) this.perWorkingCopyInfos.get(owner);
			if (workingCopyToInfos == null && create) {
				workingCopyToInfos = new HashMap();
				this.perWorkingCopyInfos.put(owner, workingCopyToInfos);
			}
			PerWorkingCopyInfo info = workingCopyToInfos == null ? null
					: (PerWorkingCopyInfo) workingCopyToInfos.get(workingCopy);
			if (info == null && create) {
				info = new PerWorkingCopyInfo(workingCopy, problemRequestor);
				workingCopyToInfos.put(workingCopy, info);
			}
			if (info != null && recordUsage)
				info.useCount++;
			return info;
		}
	}

	/*
	 * Returns 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 ISourceModule[] getWorkingCopies(WorkingCopyOwner owner, boolean addPrimary) {
		synchronized (this.perWorkingCopyInfos) {
			ISourceModule[] primaryWCs = addPrimary && owner != DefaultWorkingCopyOwner.PRIMARY
					? getWorkingCopies(DefaultWorkingCopyOwner.PRIMARY, false)
					: null;
			Map workingCopyToInfos = (Map) this.perWorkingCopyInfos.get(owner);
			if (workingCopyToInfos == null)
				return primaryWCs;
			int primaryLength = primaryWCs == null ? 0 : primaryWCs.length;
			int size = workingCopyToInfos.size(); // note size is > 0
			// otherwise
			// pathToPerWorkingCopyInfos
			// would be null
			ISourceModule[] result = new ISourceModule[primaryLength + size];
			int index = 0;
			if (primaryWCs != null) {
				for (int i = 0; i < primaryLength; i++) {
					ISourceModule primaryWorkingCopy = primaryWCs[i];
					boolean validSrcModule = false;
					IResource res = primaryWorkingCopy.getResource();
					if (res != null) {
						validSrcModule = Util.isValidSourceModule(primaryWorkingCopy, res);
					} else {
						validSrcModule = Util.isValidSourceModule(primaryWorkingCopy, primaryWorkingCopy.getPath());
					}
					if (validSrcModule) {
						ISourceModule workingCopy = new SourceModule((ModelElement) primaryWorkingCopy.getParent(),
								primaryWorkingCopy.getElementName(), owner);
						if (!workingCopyToInfos.containsKey(workingCopy))
							result[index++] = primaryWorkingCopy;
					} else {
						System.err.println("Not valid primary working copy:" //$NON-NLS-1$
								+ primaryWorkingCopy.getElementName());
					}
				}
				if (index != primaryLength)
					System.arraycopy(result, 0, result = new ISourceModule[index + size], 0, index);
			}
			Iterator iterator = workingCopyToInfos.values().iterator();
			while (iterator.hasNext()) {
				result[index++] = ((ModelManager.PerWorkingCopyInfo) iterator.next()).getWorkingCopy();
			}
			return result;
		}
	}

	public DeltaProcessor getDeltaProcessor() {
		return this.deltaState.getDeltaProcessor();
	}

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

	public IndexManager getIndexManager() {
		return this.indexManager;
	}

	public Object getLastBuiltState(IProject project, IProgressMonitor monitor) {
		if (!DLTKLanguageManager.hasScriptNature(project)) {
			if (ScriptBuilder.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 (DLTKCore.CORE_ENCODING.equals(optionName)) {
			return DLTKCore.getEncoding();
		}
		String propertyName = optionName;
		if (this.optionNames.contains(propertyName)) {
			IPreferencesService service = Platform.getPreferencesService();
			String value = service.get(optionName, null, this.preferencesLookup);
			return value == null ? null : value.trim();
		}
		return null;
	}

	/**
	 * Get workpsace eclipse preference for ScriptCore plugin.
	 */
	public IEclipsePreferences getInstancePreferences() {
		return preferencesLookup[PREF_INSTANCE];
	}

	public void setOptions(Hashtable newOptions) {
		try {
			IEclipsePreferences defaultPreferences = getDefaultPreferences();
			IEclipsePreferences instancePreferences = getInstancePreferences();
			if (newOptions == null) {
				instancePreferences.clear();
			} else {
				Enumeration keys = newOptions.keys();
				while (keys.hasMoreElements()) {
					String key = (String) keys.nextElement();
					if (!this.optionNames.contains(key))
						continue; // unrecognized option
					if (key.equals(DLTKCore.CORE_ENCODING))
						continue; // skipped, contributed by resource prefs
					String value = (String) newOptions.get(key);
					String defaultValue = defaultPreferences.get(key, null);
					if (defaultValue != null && defaultValue.equals(value)) {
						instancePreferences.remove(key);
					} else {
						instancePreferences.put(key, value);
					}
				}
			}
			// persist options
			instancePreferences.flush();
			// update cache
			this.optionsCache = newOptions == null ? null : new Hashtable(newOptions);
		} catch (BackingStoreException e) {
			// ignore
		}
	}

	public Hashtable<String, String> getOptions() {
		// return cached options if already computed
		if (this.optionsCache != null)
			return new Hashtable<>(this.optionsCache);
		if (!Platform.isRunning()) {
			return this.optionsCache = getDefaultOptionsNoInitialization();
		}
		// init
		Hashtable<String, String> options = new Hashtable<>(10);
		IPreferencesService service = Platform.getPreferencesService();
		// set options using preferences service lookup
		for (String propertyName : optionNames) {
			String propertyValue = service.get(propertyName, null, this.preferencesLookup);
			if (propertyValue != null) {
				options.put(propertyName, propertyValue);
			}
		}
		// get encoding through resource plugin
		options.put(DLTKCore.CORE_ENCODING, DLTKCore.getEncoding());
		// store built map in cache
		this.optionsCache = new Hashtable<>(options);
		// return built map
		return options;
	}

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

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

	public void setBuildpathBeingResolved(IScriptProject project, boolean buildpathIsResolved) {
		if (buildpathIsResolved) {
			getBuildpathBeingResolved().add(project);
		} else {
			getBuildpathBeingResolved().remove(project);
		}
	}

	private HashSet<IScriptProject> getBuildpathBeingResolved() {
		HashSet<IScriptProject> result = this.buildpathsBeingResolved.get();
		if (result == null) {
			result = new HashSet<>();
			this.buildpathsBeingResolved.set(result);
		}
		return result;
	}

	public boolean isBuildpathBeingResolved(IScriptProject project) {
		return getBuildpathBeingResolved().contains(project);
	}

	/*
	 * 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(SourceModule workingCopy) throws ModelException {
		// create the delta builder (this remembers the current content of the
		// working copy)
		// outside the perWorkingCopyInfos lock (see bug 50667)
		ModelElementDeltaBuilder deltaBuilder = null;
		if (workingCopy.isPrimary() && workingCopy.hasUnsavedChanges()) {
			deltaBuilder = new ModelElementDeltaBuilder(workingCopy);
		}
		PerWorkingCopyInfo info = null;
		synchronized (this.perWorkingCopyInfos) {
			WorkingCopyOwner owner = workingCopy.getOwner();
			Map workingCopyToInfos = (Map) this.perWorkingCopyInfos.get(owner);
			if (workingCopyToInfos == null)
				return -1;
			info = (PerWorkingCopyInfo) workingCopyToInfos.get(workingCopy);
			if (info == null)
				return -1;
			if (--info.useCount == 0) {
				// remove per working copy info
				workingCopyToInfos.remove(workingCopy);
				if (workingCopyToInfos.isEmpty()) {
					this.perWorkingCopyInfos.remove(owner);
				}
			}
		}
		if (info.useCount == 0) { // info cannot be null here (check was done
			// above)
			// remove infos + close buffer (since no longer working copy)
			// outside the perWorkingCopyInfos lock (see bug 50667)
			removeInfoAndChildren(workingCopy);
			workingCopy.closeBuffer();
			// compute the delta if needed and register it if there are changes
			if (deltaBuilder != null) {
				getSourceModuleInfoCache().remove(workingCopy);
				deltaBuilder.buildDeltas();
				if ((deltaBuilder.delta != null) && (deltaBuilder.delta.getAffectedChildren().length > 0)) {
					getDeltaProcessor().registerModelDelta(deltaBuilder.delta);
				}
			}
		}
		return info.useCount;
	}

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

	public void startup() throws CoreException {
		try {
			// initialize Model model cache
			this.cache = new ModelCache();
			// request state folder creation (workaround 19885)
			DLTKCore.getPlugin().getStateLocation();
			// Initialize eclipse preferences
			initializePreferences();
			// Listen to preference changes
			this.propertyListener = event -> ModelManager.this.optionsCache = null;
			installPreferenceChangeListener(DLTKCore.PLUGIN_ID, this.propertyListener);
			// listen for encoding changes (see
			// https://bugs.eclipse.org/bugs/show_bug.cgi?id=255501 )
			this.resourcesPropertyListener = event -> {
				if (ResourcesPlugin.PREF_ENCODING.equals(event.getKey())) {
					ModelManager.this.optionsCache = null;
				}
			};
			installPreferenceChangeListener(ResourcesPlugin.getPlugin().getBundle().getSymbolicName(),
					this.resourcesPropertyListener);
			long start = -1;
			if (VERBOSE)
				start = System.currentTimeMillis();
			loadContainers();
			if (VERBOSE)
				traceContainers("Loaded", start); //$NON-NLS-1$
			final IWorkspace workspace = ResourcesPlugin.getWorkspace();
			workspace.addResourceChangeListener(this.deltaState,
					IResourceChangeEvent.PRE_BUILD | IResourceChangeEvent.POST_BUILD | IResourceChangeEvent.POST_CHANGE
							| IResourceChangeEvent.PRE_DELETE | IResourceChangeEvent.PRE_CLOSE);
			DLTKContentTypeManager.installListener();
			sourceModuleInfoCache = new SourceModuleInfoCache();
			sourceModuleInfoCache.start();
			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(progress -> {
							ISavedState savedState = workspace.addSaveParticipant(DLTKCore.getPlugin(),
									ModelManager.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
								ModelManager.this.deltaState
										.getDeltaProcessor().overridenEventType = IResourceChangeEvent.POST_CHANGE;
								savedState.processResourceChangeEvents(ModelManager.this.deltaState);
							}
						}, monitor);
					} catch (CoreException e) {
						return e.getStatus();
					}
					return Status.OK_STATUS;
				}
			};
			processSavedState.setSystem(true);
			processSavedState.setPriority(Job.SHORT); // process asap
			processSavedState.schedule();
		} catch (RuntimeException e) {
			shutdown();
			throw e;
		}
	}

	private static IEclipsePreferences getPluginPreferences(String pluginId) {
		return InstanceScope.INSTANCE.getNode(pluginId);
	}

	private static void installPreferenceChangeListener(String pluginId, IPreferenceChangeListener listener) {
		getPluginPreferences(pluginId).addPreferenceChangeListener(listener);
	}

	private void startIndexing() {
		if (indexManager != null) {
			indexManager.reset();
			// create contributed indexers in a job, so
			// dltk.core initialization completes earlier.
			final Job startIndexing = new Job("DLTK indexing initialization") {
				@Override
				protected IStatus run(IProgressMonitor monitor) {
					ProjectIndexerManager.startIndexing();
					return Status.OK_STATUS;
				}
			};
			startIndexing.setSystem(true);
			startIndexing.setPriority(Job.BUILD);
			startIndexing.schedule();
		}
	}

	/**
	 * Update the buildpath 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(BP_CONTAINER_PREFERENCES_PREFIX)) {
				recreatePersistedContainer(propertyName, (String) event.getNewValue(), false);
			} else if (propertyName.startsWith(BP_USERLIBRARY_PREFERENCES_PREFIX)) {
				String libName = propertyName.substring(BP_USERLIBRARY_PREFERENCES_PREFIX.length());
				UserLibraryManager manager = ModelManager.getUserLibraryManager();
				manager.updateUserLibrary(libName, (String) event.getNewValue());
			}
		}
	}

	/**
	 * 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(DLTKCore.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 ScriptBuilder.readState(project, in);
					if (ScriptBuilder.DEBUG)
						System.out.println("Saved state thinks last build failed for " //$NON-NLS-1$
								+ project.getName());
				} finally {
					in.close();
				}
			} catch (Exception e) {
				e.printStackTrace();
				throw new CoreException(new Status(IStatus.ERROR, DLTKCore.PLUGIN_ID, Platform.PLUGIN_ERROR,
						"Error reading last build state for project " //$NON-NLS-1$
								+ project.getName(),
						e));
			}
		} else if (ScriptBuilder.DEBUG) {
			if (file == null)
				System.out.println("Project does not exist: " + project); //$NON-NLS-1$
			else
				System.out.println("Build state file " + file.getPath() //$NON-NLS-1$
						+ " does not exist"); //$NON-NLS-1$
		}
		return null;
	}

	public static void recreatePersistedContainer(String propertyName, String containerString,
			boolean addToContainerValues) {
		int containerPrefixLength = BP_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();
			IScriptProject project = getModelManager().getModel().getScriptProject(projectName);
			IPath containerPath = new Path(propertyName.substring(index + 1).trim());
			recreatePersistedContainer(project, containerPath, containerString, addToContainerValues);
		}
	}

	private static void recreatePersistedContainer(final IScriptProject project, final IPath containerPath,
			String containerString, boolean addToContainerValues) {
		if (!project.getProject().isAccessible())
			return; // avoid leaking deleted project's persisted container
		if (containerString == null) {
			getModelManager().containerPut(project, containerPath, null);
		} else {
			IBuildpathEntry[] entries;
			try {
				entries = ((ScriptProject) project).decodeBuildpath(containerString,
						null/*
							 * not interested in unknown elements
							 */);
			} catch (IOException e) {
				Util.log(e, "Could not recreate persisted container: \n" //$NON-NLS-1$
						+ containerString);
				entries = ScriptProject.INVALID_BUILDPATH;
			}
			if (entries != ScriptProject.INVALID_BUILDPATH) {
				final IBuildpathEntry[] containerEntries = entries;
				IBuildpathContainer container = new IBuildpathContainer() {
					@Override
					public IBuildpathEntry[] getBuildpathEntries() {
						return containerEntries;
					}

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

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

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

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

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

	/**
	 * Initialize preferences lookups for DLTKCore plugin.
	 */
	public void initializePreferences() {
		// Create lookups
		preferencesLookup[PREF_INSTANCE] = InstanceScope.INSTANCE.getNode(DLTKCore.PLUGIN_ID);
		preferencesLookup[PREF_DEFAULT] = DefaultScope.INSTANCE.getNode(DLTKCore.PLUGIN_ID);
		// Listen to instance preferences node removal from parent in order to
		// refresh stored one
		IEclipsePreferences.INodeChangeListener listener = new IEclipsePreferences.INodeChangeListener() {
			@Override
			public void added(IEclipsePreferences.NodeChangeEvent event) {
				// do nothing
			}

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

			@Override
			public void removed(IEclipsePreferences.NodeChangeEvent event) {
				if (event.getChild() == preferencesLookup[PREF_DEFAULT]) {
					preferencesLookup[PREF_DEFAULT] = DefaultScope.INSTANCE.getNode(DLTKCore.PLUGIN_ID);
				}
			}
		};
		((IEclipsePreferences) preferencesLookup[PREF_DEFAULT].parent()).addNodeChangeListener(listener);
	}

	public void shutdown() {
		final IEclipsePreferences preferences = getPluginPreferences(DLTKCore.PLUGIN_ID);
		try {
			preferences.flush();
		} catch (BackingStoreException e) {
			Util.log(e, "Could not save DLTKCore preferences"); //$NON-NLS-1$
		}
		// Stop listening to preferences changes
		preferences.removePreferenceChangeListener(this.propertyListener);
		getPluginPreferences(ResourcesPlugin.getPlugin().getBundle().getSymbolicName())
				.removePreferenceChangeListener(this.resourcesPropertyListener);

		if (coreCache != null) {
			coreCache.stop();
		}
		IWorkspace workspace = ResourcesPlugin.getWorkspace();
		workspace.removeResourceChangeListener(this.deltaState);
		DLTKContentTypeManager.uninstallListener();
		workspace.removeSaveParticipant(DLTKCore.PLUGIN_ID);

		if (sourceModuleInfoCache != null) {
			sourceModuleInfoCache.stop();
		}
		if (this.indexManager != null) { // no more indexing
			this.indexManager.shutdown();
		}
		// wait for the initialization job to finish
		try {
			Job.getJobManager().join(DLTKCore.PLUGIN_ID, null);
		} catch (InterruptedException e) {
			// ignore
		}
	}

	public void removePerProjectInfo(ScriptProject scriptProject) {
		synchronized (this.perProjectInfos) { // use the perProjectInfo
			// collection as its own lock
			IProject project = scriptProject.getProject();
			PerProjectInfo info = (PerProjectInfo) this.perProjectInfos.get(project);
			if (info != null) {
				this.perProjectInfos.remove(project);
			}
		}
	}

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

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

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

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

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

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

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

			// update cache - do not only rely on listener refresh
			if (variablePath == null) {
				// if path is null, record that the variable was removed to
				// avoid asking the initializer to initialize it again
				// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=112609
				this.variables.put(variableName, BP_ENTRY_IGNORE_PATH);
				// clean other variables caches
				this.variablesWithInitializer.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 = BP_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;
	}

	/**
	 * Sets the last built state for the given project, or null to reset it.
	 */
	public void setLastBuiltState(IProject project, Object state) {
		if (DLTKLanguageManager.hasScriptNature(project)) {
			// should never be requested on non-script 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
			}
		}
	}

	/**
	 * 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(DLTKCore.PLUGIN_ID);
		return workingLocation.append("state.dat").toFile(); //$NON-NLS-1$
	}

	// If modified, also modify the method getDefaultOptionsNoInitialization()
	public Hashtable getDefaultOptions() {
		Hashtable defaultOptions = new Hashtable(10);
		// see
		// DLTKCorePreferenceInitializer#initializeDefaultPluginPreferences()
		// for changing default settings
		// If modified, also modify the method
		// getDefaultOptionsNoInitialization()
		IEclipsePreferences defaultPreferences = getDefaultPreferences();
		// initialize preferences to their default
		Iterator iterator = this.optionNames.iterator();
		while (iterator.hasNext()) {
			String propertyName = (String) iterator.next();
			String value = defaultPreferences.get(propertyName, null);
			if (value != null)
				defaultOptions.put(propertyName, value);
		}
		// get encoding through resource plugin
		defaultOptions.put(DLTKCore.CORE_ENCODING, DLTKCore.getEncoding());
		return defaultOptions;
	}

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

	// Do not modify without modifying getDefaultOptions()
	private Hashtable<String, String> getDefaultOptionsNoInitialization() {
		System.err.println("Add language dependent compiler options. Or implement it in another whan in DLTK way..."); //$NON-NLS-1$
		Map defaultOptionsMap = new HashMap(); // compiler defaults
		return new Hashtable(defaultOptionsMap);
	}

	public IBuildpathContainer getBuildpathContainer(IPath containerPath, IScriptProject project)
			throws ModelException {
		IBuildpathContainer container = containerGet(project, containerPath);
		if (container == null) {
			if (this.batchContainerInitializations) {
				// avoid deep recursion while initializaing container on
				// workspace restart
				// (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=60437)
				this.batchContainerInitializations = false;
				return initializeAllContainers(project, containerPath);
			}
			return initializeContainer(project, containerPath);
		}
		return container;
	}

	public synchronized IBuildpathContainer containerGet(IScriptProject project, IPath containerPath) {
		// check initialization in progress first
		HashSet projectInitializations = containerInitializationInProgress(project);
		if (projectInitializations.contains(containerPath)) {
			return CONTAINER_INITIALIZATION_IN_PROGRESS;
		}
		Map projectContainers = (Map) this.containers.get(project);
		if (projectContainers == null) {
			return null;
		}
		IBuildpathContainer container = (IBuildpathContainer) projectContainers.get(containerPath);
		return container;
	}

	/*
	 * Returns the set of container paths for the given project that are being
	 * initialized in the current thread.
	 */
	private HashSet containerInitializationInProgress(IScriptProject project) {
		Map initializations = (Map) this.containerInitializationInProgress.get();
		if (initializations == null) {
			initializations = new HashMap();
			this.containerInitializationInProgress.set(initializations);
		}
		HashSet projectInitializations = (HashSet) initializations.get(project);
		if (projectInitializations == null) {
			projectInitializations = new HashSet();
			initializations.put(project, projectInitializations);
		}
		return projectInitializations;
	}

	/*
	 * Initialize all container at the same time as the given container. Return the
	 * container for the given path and project.
	 */
	private IBuildpathContainer initializeAllContainers(IScriptProject scriptProjectToInit, IPath containerToInit)
			throws ModelException {
		/*
		 * if (BP_RESOLVE_VERBOSE) { Util.verbose( "CPContainer INIT - batching
		 * containers initialization\n" + //$NON-NLS-1$ " project to init: " +
		 * scriptProjectToInit.getElementName() + '\n' + //$NON-NLS-1$ " container path
		 * to init: " + containerToInit); //$NON-NLS-1$ }
		 */
		// collect all container paths
		final HashMap allContainerPaths = new HashMap();
		IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
		for (int i = 0, length = projects.length; i < length; i++) {
			IProject project = projects[i];
			if (!DLTKLanguageManager.hasScriptNature(project))
				continue;
			ScriptProject scriptProject = new ScriptProject(project, getModel());
			HashSet paths = null;
			IBuildpathEntry[] rawBuildpath = scriptProject.getRawBuildpath();
			for (int j = 0, length2 = rawBuildpath.length; j < length2; j++) {
				IBuildpathEntry entry = rawBuildpath[j];
				IPath path = entry.getPath();
				if (entry.getEntryKind() == IBuildpathEntry.BPE_CONTAINER
						&& containerGet(scriptProject, path) == null) {
					if (paths == null) {
						paths = new HashSet();
						allContainerPaths.put(scriptProject, paths);
					}
					paths.add(path);
				}
			}
		}
		HashSet containerPaths = (HashSet) allContainerPaths.get(scriptProjectToInit);
		if (containerPaths == null) {
			containerPaths = new HashSet();
			allContainerPaths.put(scriptProjectToInit, containerPaths);
		}
		containerPaths.add(containerToInit);
		// end block
		// mark all containers as being initialized
		this.containerInitializationInProgress.set(allContainerPaths);
		// 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 = monitor -> {
				Set keys = allContainerPaths.keySet();
				int length = keys.size();
				IScriptProject[] scriptProjects = new IScriptProject[length]; // clone
				// as
				// the
				// following
				// will
				// have
				// a
				// side
				// effect
				keys.toArray(scriptProjects);
				for (int i = 0; i < length; i++) {
					IScriptProject scriptProject = scriptProjects[i];
					HashSet pathSet = (HashSet) allContainerPaths.get(scriptProject);
					if (pathSet == null)
						continue;
					int length2 = pathSet.size();
					IPath[] paths = new IPath[length2];
					pathSet.toArray(paths); // clone as the following will
					// have a side effect
					for (int j = 0; j < length2; j++) {
						IPath path = paths[j];
						initializeContainer(scriptProject, path);
					}
				}
			};
			IWorkspace workspace = ResourcesPlugin.getWorkspace();
			if (workspace.isTreeLocked())
				runnable.run(null/* no progress available */);
			else
				workspace.run(runnable, null/* don't take any lock */, IWorkspace.AVOID_UPDATE,
						null/*
							 * no progress available here
							 */);
			ok = true;
		} catch (CoreException e) {
			// ignore
			System.err.println("Exception while initializing all containers"); //$NON-NLS-1$
			// 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(scriptProjectToInit, containerToInit);
	}

	IBuildpathContainer initializeContainer(IScriptProject project, IPath containerPath) throws ModelException {
		IBuildpathContainer container = null;
		final BuildpathContainerInitializer initializer = DLTKCore
				.getBuildpathContainerInitializer(containerPath.segment(0));
		if (initializer != null) {
			if (BP_RESOLVE_VERBOSE) {
				verbose_triggering_container_initialization(project, containerPath, initializer);
			}
			// PerformanceStats stats = null;
			containerPut(project, containerPath, CONTAINER_INITIALIZATION_IN_PROGRESS); // avoid
			// initialization
			// cycles
			boolean ok = false;
			try {
				// let OperationCanceledException go through
				// (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=59363)
				initializer.initialize(containerPath, project);
				// retrieve value (if initialization was successful)
				container = containerGet(project, containerPath);
				if (container == CONTAINER_INITIALIZATION_IN_PROGRESS)
					return null; // break cycle
				ok = true;
			} catch (CoreException e) {
				if (e instanceof ModelException) {
					throw (ModelException) e;
				} else {
					throw new ModelException(e);
				}
			} catch (RuntimeException e) {
				if (ModelManager.BP_RESOLVE_VERBOSE) {
					e.printStackTrace();
				}
				throw e;
			} catch (Error e) {
				if (ModelManager.BP_RESOLVE_VERBOSE) {
					e.printStackTrace();
				}
				throw e;
			} finally {
				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 (BP_RESOLVE_VERBOSE) {
						verbose_container_initialization_failed(project, containerPath, container, initializer);
					}
				}
			}
			if (BP_RESOLVE_VERBOSE) {
				verbose_container_value_after_initialization(project, containerPath, container);
			}
		} else {
			if (BP_RESOLVE_VERBOSE) {
				Util.verbose("CPContainer INIT - no initializer found\n" + //$NON-NLS-1$
						"	project: " + project.getElementName() + '\n' + //$NON-NLS-1$
						"	container path: " + containerPath); //$NON-NLS-1$
			}
		}
		return container;
	}

	private void verbose_triggering_container_initialization(IScriptProject project, IPath containerPath,
			final BuildpathContainerInitializer initializer) {
		Util.verbose("BPContainer INIT - triggering initialization\n" + //$NON-NLS-1$
				"	project: " + project.getElementName() + '\n' + //$NON-NLS-1$
				"	container path: " + containerPath + '\n' + //$NON-NLS-1$
				"	initializer: " + initializer + '\n' + //$NON-NLS-1$
				"	invocation stack trace:"); //$NON-NLS-1$
		new Exception("<Fake exception>").printStackTrace(System.out); //$NON-NLS-1$
	}

	private void verbose_container_value_after_initialization(IScriptProject project, IPath containerPath,
			IBuildpathContainer 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$
			IBuildpathEntry[] entries = container.getBuildpathEntries();
			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(IScriptProject project, IPath containerPath,
			IBuildpathContainer container, final BuildpathContainerInitializer 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' + "	container path: " //$NON-NLS-2$
					+ containerPath + '\n' + "	initializer: " //$NON-NLS-1$
					+ initializer);
		} else {
			Util.verbose("CPContainer INIT - FAILED (see exception above)\n" + //$NON-NLS-1$
					"	project: " //$NON-NLS-1$
					+ project.getElementName() + '\n' + "	container path: " //$NON-NLS-1$
					+ containerPath + '\n' + "	initializer: " + initializer); //$NON-NLS-1$
		}
	}

	/**
	 * 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 IBuildpathContainer getPreviousSessionContainer(IPath containerPath, IScriptProject project) {
		Map previousContainerValues = (Map) this.previousSessionContainers.get(project);
		if (previousContainerValues != null) {
			IBuildpathContainer previousContainer = (IBuildpathContainer) previousContainerValues.get(containerPath);
			if (previousContainer != null) {
				if (ModelManager.BP_RESOLVE_VERBOSE) {
					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$
					IBuildpathEntry[] entries = previousContainer.getBuildpathEntries();
					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>") //$NON-NLS-1$
							.printStackTrace(System.out);
				}
				return previousContainer;
			}
		}
		return null; // break cycle if none found
	}

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

	public synchronized void containerPut(IScriptProject project, IPath containerPath, IBuildpathContainer container) {
		// set/unset the initialization in progress
		if (container == CONTAINER_INITIALIZATION_IN_PROGRESS) {
			HashSet projectInitializations = containerInitializationInProgress(project);
			projectInitializations.add(containerPath);
			// do not write out intermediate initialization value
			return;
		} else {
			containerRemoveInitializationInProgress(project, containerPath);
			Map projectContainers = (Map) this.containers.get(project);
			if (projectContainers == null) {
				projectContainers = new HashMap(1);
				this.containers.put(project, projectContainers);
			}
			if (container == null) {
				projectContainers.remove(containerPath);
			} else {
				projectContainers.put(containerPath, container);
			}
			// discard obsoleted information about previous session
			Map previousContainers = (Map) this.previousSessionContainers.get(project);
			if (previousContainers != null) {
				previousContainers.remove(containerPath);
			}
		}
		// container values are persisted in preferences during save operations,
		// see #saving(ISaveContext)
	}

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

	void verbose_missbehaving_container(IScriptProject project, IPath containerPath,
			IBuildpathEntry[] classpathEntries) {
		Util.verbose("CPContainer GET - missbehaving container (returning null classpath entry)\n" //$NON-NLS-1$
				+ "	project: " + project.getElementName() + '\n' + "	container path: " + containerPath + '\n'
				+ "	classpath entries: {\n" + Util.toString(classpathEntries, 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(IScriptProject project, IPath containerPath) {
		Util.verbose("CPContainer GET - missbehaving container (returning null as classpath entries)\n" //$NON-NLS-1$
				+ "	project: " + project.getElementName() + '\n' + "	container path: " + containerPath + '\n'
				+ "	classpath entries: <null>");
	}

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

	/*
	 * Optimize startup case where a container for 1 project is initialized at a
	 * time with the same entries as on shutdown.
	 */
	public boolean containerPutIfInitializingWithSameEntries(IPath containerPath, IScriptProject[] projects,
			IBuildpathContainer[] respectiveContainers) {
		int projectLength = projects.length;
		if (projectLength != 1)
			return false;
		final IBuildpathContainer container = respectiveContainers[0];
		if (container == null)
			return false;
		final IScriptProject project = projects[0];
		if (!containerInitializationInProgress(project).contains(containerPath))
			return false;
		IBuildpathContainer previousSessionContainer = getPreviousSessionContainer(containerPath, project);
		final IBuildpathEntry[] newEntries = container.getBuildpathEntries();
		if (previousSessionContainer == null)
			if (newEntries.length == 0) {
				containerPut(project, containerPath, container);
				return true;
			} else {
				return false;
			}
		final IBuildpathEntry[] oldEntries = previousSessionContainer.getBuildpathEntries();
		if (oldEntries.length != newEntries.length)
			return false;
		for (int i = 0, length = newEntries.length; i < length; i++) {
			if (!newEntries[i].equals(oldEntries[i])) {
				if (BP_RESOLVE_VERBOSE) {
					Util.verbose("CPContainer SET  - missbehaving container\n" + //$NON-NLS-1$
							"	container path: " //$NON-NLS-1$
							+ containerPath + '\n' + "	projects: {" //$NON-NLS-1$
							+ Util.toString(projects, o -> ((IScriptProject) o).getElementName())
							+ "}\n	values on previous session: {\n" + //$NON-NLS-1$
							Util.toString(respectiveContainers, 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 < 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$
							Util.toString(respectiveContainers, 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$
				}
				return false;
			}
		}
		containerPut(project, containerPath, container);
		return true;
	}

	/**
	 * 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.
	 *
	 * NOTE: closeZipFile() must be called for the resulting ZipFile, when the
	 * client is done using it.
	 *
	 * The path must be a file system path if representing an external zip, or it
	 * must be an absolute workspace relative path if representing a zip inside the
	 * workspace.
	 *
	 * @param archiveProjectFragment
	 *
	 * @exception CoreException If unable to create/open the ZipFile
	 */
	public IArchive getArchive(IPath path, IProjectFragment archiveProjectFragment) throws CoreException {
		Map<IPath, IArchive> map;
		IArchive zipFile;
		if ((map = this.zipFiles.get()) != null && (zipFile = map.get(path)) != null) {
			return zipFile;
		}
		File localFile = null;
		IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
		IResource file = root.findMember(path);
		if (file != null) {
			// internal resource
			URI location;
			if (file.getType() != IResource.FILE || (location = file.getLocationURI()) == null) {
				throw new CoreException(new Status(IStatus.ERROR, DLTKCore.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, DLTKCore.PLUGIN_ID, -1,
						Messages.bind(Messages.file_notFound, path.toString()), null));
		} else {
			// external resource -> it is ok to use toFile()
			if (EnvironmentPathUtils.isFull(path)) {
				path = EnvironmentPathUtils.getLocalPath(path);
			}
			localFile = path.toFile();
		}
		try {
			if (ZIP_ACCESS_VERBOSE) {
				System.out.println("(" + Thread.currentThread() //$NON-NLS-1$
						+ ") [ModelManager.getZipFile(IPath)] Creating ZipFile on " //$NON-NLS-1$
						+ localFile);
			}
			zipFile = openArchive(archiveProjectFragment, localFile);

			if (map != null) {
				map.put(path, zipFile);
			}
			return zipFile;
		} catch (IOException e) {
			throw new CoreException(new Status(IStatus.ERROR, DLTKCore.PLUGIN_ID, -1, Messages.status_IOException, e));
		}
	}

	public IArchive openArchive(IProjectFragment archiveProjectFragment, File localFile) throws IOException {
		final IDLTKLanguageToolkit toolkit = DLTKLanguageManager.getLanguageToolkit(archiveProjectFragment);
		if (toolkit != null) {
			return toolkit.openArchive(localFile);
		} else {
			return new ZipArchiveFile(localFile);
		}
	}

	/**
	 * Starts caching ZipFiles. Ignores if there are already clients.
	 */
	public void cacheZipFiles() {
		if (this.zipFiles.get() != null)
			return;
		this.zipFiles.set(new HashMap<IPath, IArchive>());
	}

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

	@Override
	public void doneSaving(ISaveContext context) {
		// nothing
	}

	@Override
	public void prepareToSave(ISaveContext context) throws CoreException {
		// TODO Auto-generated method stub
	}

	@Override
	public void rollback(ISaveContext context) {
		// TODO Auto-generated method stub
	}

	private void traceContainers(String action, long start) {
		Long delta = System.currentTimeMillis() - start;
		Long length = getContainersFile().length();
		String pattern = "{0} {1} bytes in containers.dat in {2}ms"; //$NON-NLS-1$
		String message = NLS.bind(pattern, new Object[] { action, length, delta });
		System.out.println(message);
	}

	@Override
	public void saving(ISaveContext context) throws CoreException {
		// save variable and container values on snapshot/full save
		long start = -1;
		if (VERBOSE)
			start = System.currentTimeMillis();
		savesContainers();
		if (VERBOSE)
			traceContainers("Saved", start); //$NON-NLS-1$
		if (context.getKind() == ISaveContext.FULL_SAVE) {
			// 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();
			}
		}
		IProject savedProject = context.getProject();
		if (savedProject != null) {
			if (!ScriptProject.hasScriptNature(savedProject))
				return; // ignore
			PerProjectInfo info = getPerProjectInfo(savedProject, true /*
																		 * create info
																		 */);
			saveState(info, context);
			info.rememberExternalLibTimestamps();
			return;
		}
		ArrayList vStats = null; // lazy initialized
		ArrayList values = null;
		synchronized (this.perProjectInfos) {
			values = new ArrayList(this.perProjectInfos.values());
		}
		Iterator iterator = values.iterator();
		while (iterator.hasNext()) {
			try {
				PerProjectInfo info = (PerProjectInfo) iterator.next();
				saveState(info, context);
				info.rememberExternalLibTimestamps();
			} 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(DLTKCore.PLUGIN_ID, IStatus.ERROR, stats, Messages.build_cannotSaveStates, null));
		}
		// save external libs timestamps
		this.deltaState.saveExternalLibTimeStamps();
	}

	private File getContainersFile() {
		return DLTKCore.getPlugin().getStateLocation().append("Containers.dat") //$NON-NLS-1$
				.toFile();
	}

	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 (ScriptBuilder.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(DLTKCore.PLUGIN_ID);
				out.writeUTF("STATE"); //$NON-NLS-1$
				if (info.savedState == null) {
					out.writeBoolean(false);
				} else {
					out.writeBoolean(true);
					ScriptBuilder.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, DLTKCore.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, DLTKCore.PLUGIN_ID, Platform.PLUGIN_ERROR,
					Messages.bind(Messages.build_cannotSaveState, info.project.getName()), e));
		}
		if (ScriptBuilder.DEBUG) {
			t = System.currentTimeMillis() - t;
			System.out.println(Messages.bind(Messages.build_saveStateComplete, String.valueOf(t)));
		}
	}

	private void savesContainers() throws CoreException {
		File file = getContainersFile();
		DataOutputStream out = null;
		try {
			out = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(file)));
			out.writeInt(CONTAINERS_FILE_VERSION);
			new ContainersSaveHelper(out).save();
			// old code retained for performance comparisons
			// containers
			IScriptProject[] projects = getModel().getScriptProjects();
			int length = projects.length;
			out.writeInt(length);
			for (int i = 0; i < length; i++) {
				IScriptProject project = projects[i];
				// clone while iterating (see
				// https://bugs.eclipse.org/bugs/show_bug.cgi?id=59638)
				Map projectContainers = containerClone(project);
				out.writeUTF(project.getElementName());
				if (projectContainers == null) {
					out.writeInt(0);
					continue;
				}
				HashMap containersToSave = new HashMap();
				for (Iterator iterator = projectContainers.keySet().iterator(); iterator.hasNext();) {
					IPath containerPath = (IPath) iterator.next();
					IBuildpathContainer container = (IBuildpathContainer) projectContainers.get(containerPath);
					String containerString = null;
					try {
						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(containerPath, project);
						}
						if (container != null) {
							IBuildpathEntry[] entries = container.getBuildpathEntries();
							containerString = ((ScriptProject) project).encodeBuildpath(entries, false,
									null/*
										 * not interested in unknown elements
										 */);
						}
					} catch (ModelException e) {
						// could not encode entry: will not persist
						Util.log(e, "Could not persist container " + containerPath //$NON-NLS-1$
								+ " for project " //$NON-NLS-1$
								+ project.getElementName());
					}
					if (containerString != null)
						containersToSave.put(containerPath, containerString);
				}
				out.writeInt(containersToSave.size());
				Iterator iterator = containersToSave.keySet().iterator();
				while (iterator.hasNext()) {
					IPath containerPath = (IPath) iterator.next();
					out.writeUTF(containerPath.toPortableString());
					String containerString = (String) containersToSave.get(containerPath);
					out.writeInt(containerString.length());
					out.writeBytes(containerString);
				}
			}
		} catch (IOException e) {
			IStatus status = new Status(IStatus.ERROR, DLTKCore.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
				}
			}
		}
	}

	protected synchronized void resetZIPTypeCache() {
		this.cache.resetZIPTypeCache();
	}

	public DLTKWorkspaceScope getWorkspaceScope(IDLTKLanguageToolkit toolkit) {
		if (this.workspaceScope == null) {
			this.workspaceScope = new HashMap();
		}
		if (this.workspaceScope.containsKey(toolkit)) {
			return (DLTKWorkspaceScope) this.workspaceScope.get(toolkit);
		} else {
			DLTKWorkspaceScope scope = new DLTKWorkspaceScope(toolkit);
			this.workspaceScope.put(toolkit, scope);
			return scope;
		}
	}

	private final class ContainersSaveHelper {
		private final HashtableOfObjectToInt buildpathEntryIds;
		// -> int
		private final DataOutputStream out;
		private final HashtableOfObjectToInt stringIds; // Strings -> int

		ContainersSaveHelper(DataOutputStream out) {
			super();
			this.buildpathEntryIds = new HashtableOfObjectToInt();
			this.out = out;
			this.stringIds = new HashtableOfObjectToInt();
		}

		void save() throws IOException, ModelException {
			saveProjects(ModelManager.this.getModel().getScriptProjects());
		}

		private void saveAccessRule(BuildpathAccessRule 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((BuildpathAccessRule) rules[i]);
		}

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

		private void saveAttributes(IBuildpathAttribute[] attributes) throws IOException {
			int count = attributes == null ? 0 : attributes.length;
			saveInt(count);
			for (int i = 0; i < count; ++i)
				saveAttribute(attributes[i]);
		}

		private void saveBuildpathEntries(IBuildpathEntry[] entries) throws IOException {
			int count = entries == null ? 0 : entries.length;
			saveInt(count);
			for (int i = 0; i < count; ++i)
				saveBuildpathEntry(entries[i]);
		}

		private void saveBuildpathEntry(IBuildpathEntry entry) throws IOException {
			if (saveNewId(entry, this.buildpathEntryIds)) {
				saveInt(entry.getContentKind());
				saveInt(entry.getEntryKind());
				savePath(entry.getPath());
				savePaths(entry.getInclusionPatterns());
				savePaths(entry.getExclusionPatterns());
				this.out.writeBoolean(entry.isExported());
				this.out.writeBoolean(entry.isExternal());
				saveAccessRules(entry.getAccessRules());
				this.out.writeBoolean(entry.combineAccessRules());
				saveAttributes(entry.getExtraAttributes());
			}
		}

		private void saveContainers(IScriptProject project, Map containerMap) throws IOException {
			saveInt(containerMap.size());
			for (Iterator i = containerMap.entrySet().iterator(); i.hasNext();) {
				Entry entry = (Entry) i.next();
				IPath path = (IPath) entry.getKey();
				IBuildpathContainer container = (IBuildpathContainer) entry.getValue();
				IBuildpathEntry[] 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 = ModelManager.this.getPreviousSessionContainer(path, project);
				}
				if (container != null)
					cpEntries = container.getBuildpathEntries();
				savePath(path);
				saveBuildpathEntries(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(IScriptProject[] projects) throws IOException, ModelException {
			int count = projects.length;
			saveInt(count);
			for (int i = 0; i < count; ++i) {
				IScriptProject project = projects[i];
				saveString(project.getElementName());
				Map containerMap = (Map) ModelManager.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 synchronized Map containerClone(IScriptProject project) {
		Map originalProjectContainers = (Map) this.containers.get(project);
		if (originalProjectContainers == null)
			return null;
		Map projectContainers = new HashMap(originalProjectContainers.size());
		projectContainers.putAll(originalProjectContainers);
		return projectContainers;
	}

	public void loadContainers() throws CoreException {
		// 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 = getContainersFile();
		DataInputStream in = null;
		try {
			in = new DataInputStream(new BufferedInputStream(new FileInputStream(file)));
			switch (in.readInt()) {
			case 1:
				new ContainersLoadHelper(in).load();
				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 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 = BP_VARIABLE_PREFERENCES_PREFIX.length();
			for (int i = 0; i < propertyNames.length; i++) {
				String propertyName = propertyNames[i];
				if (propertyName.startsWith(BP_VARIABLE_PREFERENCES_PREFIX)) {
					String varName = propertyName.substring(variablePrefixLength);
					String propertyValue = preferences.get(propertyName, null);
					if (propertyValue != null) {
						String pathString = propertyValue.trim();

						if (BP_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(BP_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 PersistedBuildpathContainer implements IBuildpathContainer {
		private final IPath containerPath;
		private final IBuildpathEntry[] entries;
		private final IScriptProject project;

		PersistedBuildpathContainer(IScriptProject project, IPath containerPath, IBuildpathEntry[] entries) {
			super();
			this.containerPath = containerPath;
			this.entries = entries;
			this.project = project;
		}

		@Override
		public IBuildpathEntry[] getBuildpathEntries() {
			return entries;
		}

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

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

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

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

	}

	private final class ContainersLoadHelper {
		private static final int ARRAY_INCREMENT = 200;
		private IBuildpathEntry[] allBuildpathEntries;
		private int allBuildpathEntryCount;
		private final Map allPaths; // String -> IPath
		private String[] allStrings;
		private int allStringsCount;
		private final DataInputStream in;

		ContainersLoadHelper(DataInputStream in) {
			super();
			this.allBuildpathEntries = null;
			this.allBuildpathEntryCount = 0;
			this.allPaths = new HashMap();
			this.allStrings = null;
			this.allStringsCount = 0;
			this.in = in;
		}

		void load() throws IOException {
			loadProjects(ModelManager.this.getModel());
		}

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

		private IAccessRule[] loadAccessRules() throws IOException {
			int count = loadInt();
			if (count == 0)
				return BuildpathEntry.NO_ACCESS_RULES;
			IAccessRule[] rules = new IAccessRule[count];
			for (int i = 0; i < count; ++i)
				rules[i] = loadAccessRule();
			return rules;
		}

		private IBuildpathAttribute loadAttribute() throws IOException {
			String name = loadString();
			String value = loadString();
			return new BuildpathAttribute(name, value);
		}

		private IBuildpathAttribute[] loadAttributes() throws IOException {
			int count = loadInt();
			if (count == 0)
				return BuildpathEntry.NO_EXTRA_ATTRIBUTES;
			IBuildpathAttribute[] attributes = new IBuildpathAttribute[count];
			for (int i = 0; i < count; ++i)
				attributes[i] = loadAttribute();
			return attributes;
		}

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

		private IBuildpathEntry[] loadBuildpathEntries() throws IOException {
			int count = loadInt();
			IBuildpathEntry[] entries = new IBuildpathEntry[count];
			for (int i = 0; i < count; ++i)
				entries[i] = loadBuildpathEntry();
			return entries;
		}

		private IBuildpathEntry loadBuildpathEntry() throws IOException {
			int id = loadInt();
			if (id < 0 || id > this.allBuildpathEntryCount)
				throw new IOException("Unexpected buildpathentry id"); //$NON-NLS-1$
			if (id < this.allBuildpathEntryCount)
				return this.allBuildpathEntries[id];
			int contentKind = loadInt();
			int entryKind = loadInt();
			IPath path = loadPath();
			IPath[] inclusionPatterns = loadPaths();
			IPath[] exclusionPatterns = loadPaths();
			boolean isExported = loadBoolean();
			boolean isExternal = loadBoolean();
			IAccessRule[] accessRules = loadAccessRules();
			boolean combineAccessRules = loadBoolean();
			IBuildpathAttribute[] extraAttributes = loadAttributes();
			IBuildpathEntry entry = new BuildpathEntry(contentKind, entryKind, path, isExported, inclusionPatterns,
					exclusionPatterns, accessRules, combineAccessRules, extraAttributes, isExternal);
			IBuildpathEntry[] array = this.allBuildpathEntries;
			if (array == null || id == array.length) {
				array = new IBuildpathEntry[id + ARRAY_INCREMENT];
				if (id != 0)
					System.arraycopy(this.allBuildpathEntries, 0, array, 0, id);
				this.allBuildpathEntries = array;
			}
			array[id] = entry;
			this.allBuildpathEntryCount = id + 1;
			return entry;
		}

		private void loadContainers(IScriptProject project) throws IOException {
			boolean projectIsAccessible = project.getProject().isAccessible();
			int count = loadInt();
			for (int i = 0; i < count; ++i) {
				IPath path = loadPath();
				IBuildpathEntry[] entries = loadBuildpathEntries();
				if (!projectIsAccessible)
					// avoid leaking deleted project's persisted container,
					// but still read the container as it is is part of the file
					// format
					continue;
				IBuildpathContainer container = new PersistedBuildpathContainer(project, path, entries);
				ModelManager.this.containerPut(project, path, container);
				Map oldContainers = (Map) ModelManager.this.previousSessionContainers.get(project);
				if (oldContainers == null) {
					oldContainers = new HashMap();
					ModelManager.this.previousSessionContainers.put(project, oldContainers);
				}
				oldContainers.put(path, container);
			}
		}

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

		private IPath loadPath() throws IOException {
			if (loadBoolean())
				return null;
			String portableString = loadString();
			IPath path = (IPath) this.allPaths.get(portableString);
			if (path == null) {
				path = Path.fromPortableString(portableString);
				this.allPaths.put(portableString, path);
			}
			return path;
		}

		private IPath[] loadPaths() throws IOException {
			int count = loadInt();
			IPath[] pathArray = new IPath[count];
			for (int i = 0; i < count; ++i)
				pathArray[i] = loadPath();
			return pathArray;
		}

		private void loadProjects(IScriptModel model) throws IOException {
			int count = loadInt();
			for (int i = 0; i < count; ++i) {
				String projectName = loadString();
				loadContainers(model.getScriptProject(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;
		}
	}

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

		Plugin dltkCorePlugin = DLTKCore.getPlugin();
		if (dltkCorePlugin == null)
			return null;

		ArrayList containerIDList = new ArrayList(5);
		IExtensionPoint extension = Platform.getExtensionRegistry().getExtensionPoint(DLTKCore.PLUGIN_ID,
				ModelManager.BPCONTAINER_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;
	}

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

	/**
	 * Flushes ZipFiles cache if there are no more clients.
	 */
	public void flushZipFiles() {
		Thread currentThread = Thread.currentThread();
		Map<IPath, IArchive> map = this.zipFiles.get();
		if (map == null)
			return;
		this.zipFiles.set(null);
		for (IArchive zipFile : map.values()) {
			try {
				if (ModelManager.ZIP_ACCESS_VERBOSE) {
					System.out.println("(" + currentThread //$NON-NLS-1$
							+ ") [ModelManager.flushZipFiles()] Closing ZipFile on " //$NON-NLS-1$
							+ zipFile.getName());
				}
				zipFile.close();
			} catch (IOException e) {
				// problem occured closing zip file: cannot do much more
			}
		}
	}

	private SourceModuleInfoCache sourceModuleInfoCache = null;

	public ISourceModuleInfoCache getSourceModuleInfoCache() {
		return sourceModuleInfoCache;
	}

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