/*******************************************************************************
 * Copyright (c) 2000, 2010 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.jdt.internal.core.search.indexing;

import java.io.*;
import java.util.*;
import java.util.zip.CRC32;

import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Path;
import org.eclipse.jdt.core.*;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.core.search.*;
import org.eclipse.jdt.internal.compiler.ISourceElementRequestor;
import org.eclipse.jdt.internal.compiler.SourceElementParser;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable;
import org.eclipse.jdt.internal.compiler.util.SimpleSet;
import org.eclipse.jdt.internal.core.*;
import org.eclipse.jdt.internal.core.index.*;
import org.eclipse.jdt.internal.core.search.BasicSearchEngine;
import org.eclipse.jdt.internal.core.search.PatternSearchJob;
import org.eclipse.jdt.internal.core.search.processing.IJob;
import org.eclipse.jdt.internal.core.search.processing.JobManager;
import org.eclipse.jdt.internal.core.util.Messages;
import org.eclipse.jdt.internal.core.util.Util;

public class IndexManager extends JobManager implements IIndexConstants {

	// key = containerPath, value = indexLocation path
	// indexLocation path is created by appending an index file name to the getJavaPluginWorkingLocation() path
	public SimpleLookupTable indexLocations = new SimpleLookupTable();
	// key = indexLocation path, value = an index
	private SimpleLookupTable indexes = new SimpleLookupTable();

	/* need to save ? */
	private boolean needToSave = false;
	private IPath javaPluginLocation = null;

	/* can only replace a current state if its less than the new one */
	// key = indexLocation path, value = index state integer
	private SimpleLookupTable indexStates = null;
	private File savedIndexNamesFile = new File(getSavedIndexesDirectory(), "savedIndexNames.txt"); //$NON-NLS-1$
	private File participantIndexNamesFile = new File(getSavedIndexesDirectory(), "participantsIndexNames.txt"); //$NON-NLS-1$
	private boolean javaLikeNamesChanged = true;
	public static final Integer SAVED_STATE = new Integer(0);
	public static final Integer UPDATING_STATE = new Integer(1);
	public static final Integer UNKNOWN_STATE = new Integer(2);
	public static final Integer REBUILDING_STATE = new Integer(3);
	
	// search participants who register indexes with the index manager
	private SimpleLookupTable participantsContainers = null;
	private boolean participantUpdated = false;

	// Debug
	public static boolean DEBUG = false;

	public synchronized void aboutToUpdateIndex(IPath containerPath, Integer newIndexState) {
	// newIndexState is either UPDATING_STATE or REBUILDING_STATE
	// must tag the index as inconsistent, in case we exit before the update job is started
	IPath indexLocation = computeIndexLocation(containerPath);
	Object state = getIndexStates().get(indexLocation);
	Integer currentIndexState = state == null ? UNKNOWN_STATE : (Integer) state;
	if (currentIndexState.equals(REBUILDING_STATE)) return; // already rebuilding the index

	int compare = newIndexState.compareTo(currentIndexState);
	if (compare > 0) {
		// so UPDATING_STATE replaces SAVED_STATE and REBUILDING_STATE replaces everything
		updateIndexState(indexLocation, newIndexState);
	} else if (compare < 0 && this.indexes.get(indexLocation) == null) {
		// if already cached index then there is nothing more to do
		rebuildIndex(indexLocation, containerPath);
	}
}
/**
 * Trigger addition of a resource to an index
 * Note: the actual operation is performed in background
 */
public void addBinary(IFile resource, IPath containerPath) {
	if (JavaCore.getPlugin() == null) return;
	SearchParticipant participant = SearchEngine.getDefaultSearchParticipant();
	SearchDocument document = participant.getDocument(resource.getFullPath().toString());
	IPath indexLocation = computeIndexLocation(containerPath);
	scheduleDocumentIndexing(document, containerPath, indexLocation, participant);
}
/**
 * Trigger addition of a resource to an index
 * Note: the actual operation is performed in background
 */
public void addSource(IFile resource, IPath containerPath, SourceElementParser parser) {
	if (JavaCore.getPlugin() == null) return;
	SearchParticipant participant = SearchEngine.getDefaultSearchParticipant();
	SearchDocument document = participant.getDocument(resource.getFullPath().toString());
	document.setParser(parser);
	IPath indexLocation = computeIndexLocation(containerPath);
	scheduleDocumentIndexing(document, containerPath, indexLocation, participant);
}
/*
 * Removes unused indexes from disk.
 */
public void cleanUpIndexes() {
	SimpleSet knownPaths = new SimpleSet();
	IJavaSearchScope scope = BasicSearchEngine.createWorkspaceScope();
	PatternSearchJob job = new PatternSearchJob(null, SearchEngine.getDefaultSearchParticipant(), scope, null);
	Index[] selectedIndexes = job.getIndexes(null);
	for (int i = 0, l = selectedIndexes.length; i < l; i++) {
		String path = selectedIndexes[i].getIndexFile().getAbsolutePath();
		knownPaths.add(path);
	}

	if (this.indexStates != null) {
		Object[] keys = this.indexStates.keyTable;
		IPath[] locations = new IPath[this.indexStates.elementSize];
		int count = 0;
		for (int i = 0, l = keys.length; i < l; i++) {
			IPath key = (IPath) keys[i];
			if (key != null && !knownPaths.includes(key.toOSString()))
				locations[count++] = key;
		}
		if (count > 0)
			removeIndexesState(locations);
	}
	deleteIndexFiles(knownPaths);
}
public synchronized IPath computeIndexLocation(IPath containerPath) {
	IPath indexLocation = (IPath) this.indexLocations.get(containerPath);
	if (indexLocation == null) {
		String pathString = containerPath.toOSString();
		CRC32 checksumCalculator = new CRC32();
		checksumCalculator.update(pathString.getBytes());
		String fileName = Long.toString(checksumCalculator.getValue()) + ".index"; //$NON-NLS-1$
		if (VERBOSE)
			Util.verbose("-> index name for " + pathString + " is " + fileName); //$NON-NLS-1$ //$NON-NLS-2$
		// to share the indexLocation between the indexLocations and indexStates tables, get the key from the indexStates table
		indexLocation = (IPath) getIndexStates().getKey(getJavaPluginWorkingLocation().append(fileName));
		this.indexLocations.put(containerPath, indexLocation);
	}
	return indexLocation;
}
public void deleteIndexFiles() {
	if (DEBUG)
		Util.verbose("Deleting index files"); //$NON-NLS-1$
	this.savedIndexNamesFile.delete(); // forget saved indexes & delete each index file
	deleteIndexFiles(null);
}
private void deleteIndexFiles(SimpleSet pathsToKeep) {
	File[] indexesFiles = getSavedIndexesDirectory().listFiles();
	if (indexesFiles == null) return;

	for (int i = 0, l = indexesFiles.length; i < l; i++) {
		String fileName = indexesFiles[i].getAbsolutePath();
		if (pathsToKeep != null && pathsToKeep.includes(fileName)) continue;
		String suffix = ".index"; //$NON-NLS-1$
		if (fileName.regionMatches(true, fileName.length() - suffix.length(), suffix, 0, suffix.length())) {
			if (VERBOSE || DEBUG)
				Util.verbose("Deleting index file " + indexesFiles[i]); //$NON-NLS-1$
			indexesFiles[i].delete();
		}
	}
}
/*
 * Creates an empty index at the given location, for the given container path, if none exist.
 */
public synchronized void ensureIndexExists(IPath indexLocation, IPath containerPath) {
	SimpleLookupTable states = getIndexStates();
	Object state = states.get(indexLocation);
	if (state == null) {
		updateIndexState(indexLocation, REBUILDING_STATE);
		getIndex(containerPath, indexLocation, true, true);
	}
}
public SourceElementParser getSourceElementParser(IJavaProject project, ISourceElementRequestor requestor) {
	// disable task tags to speed up parsing
	Map options = project.getOptions(true);
	options.put(JavaCore.COMPILER_TASK_TAGS, ""); //$NON-NLS-1$

	SourceElementParser parser = new IndexingParser(
		requestor,
		new DefaultProblemFactory(Locale.getDefault()),
		new CompilerOptions(options),
		true, // index local declarations
		true, // optimize string literals
		false); // do not use source javadoc parser to speed up parsing
	parser.reportOnlyOneSyntaxError = true;

	// Always check javadoc while indexing
	parser.javadocParser.checkDocComment = true;
	parser.javadocParser.reportProblems = false;

	return parser;
}
/**
 * Returns the index for a given index location
 *
 * @param indexLocation The path of the index file
 * @return The corresponding index or <code>null</code> if not found
 */
public synchronized Index getIndex(IPath indexLocation) {
	return (Index) this.indexes.get(indexLocation); // is null if unknown, call if the containerPath must be computed
}
/**
 * Returns the index for a given project, according to the following algorithm:
 * - if index is already in memory: answers this one back
 * - if (reuseExistingFile) then read it and return this index and record it in memory
 * - if (createIfMissing) then create a new empty index and record it in memory
 *
 * Warning: Does not check whether index is consistent (not being used)
 */
public synchronized Index getIndex(IPath containerPath, boolean reuseExistingFile, boolean createIfMissing) {
	IPath indexLocation = computeIndexLocation(containerPath);
	return getIndex(containerPath, indexLocation, reuseExistingFile, createIfMissing);
}
/**
 * Returns the index for a given project, according to the following algorithm:
 * - if index is already in memory: answers this one back
 * - if (reuseExistingFile) then read it and return this index and record it in memory
 * - if (createIfMissing) then create a new empty index and record it in memory
 *
 * Warning: Does not check whether index is consistent (not being used)
 */
public synchronized Index getIndex(IPath containerPath, IPath indexLocation, boolean reuseExistingFile, boolean createIfMissing) {
	// Path is already canonical per construction
	Index index = getIndex(indexLocation);
	if (index == null) {
		Object state = getIndexStates().get(indexLocation);
		Integer currentIndexState = state == null ? UNKNOWN_STATE : (Integer) state;
		if (currentIndexState == UNKNOWN_STATE) {
			// should only be reachable for query jobs
			// IF you put an index in the cache, then AddJarFileToIndex fails because it thinks there is nothing to do
			rebuildIndex(indexLocation, containerPath);
			return null;
		}

		// index isn't cached, consider reusing an existing index file
		String containerPathString = containerPath.getDevice() == null ? containerPath.toString() : containerPath.toOSString();
		String indexLocationString = indexLocation.toOSString();
		if (reuseExistingFile) {
			File indexFile = new File(indexLocationString);
			if (indexFile.exists()) { // check before creating index so as to avoid creating a new empty index if file is missing
				try {
					index = new Index(indexLocationString, containerPathString, true /*reuse index file*/);
					this.indexes.put(indexLocation, index);
					return index;
				} catch (IOException e) {
					// failed to read the existing file or its no longer compatible
					if (currentIndexState != REBUILDING_STATE) { // rebuild index if existing file is corrupt, unless the index is already being rebuilt
						if (VERBOSE)
							Util.verbose("-> cannot reuse existing index: "+indexLocationString+" path: "+containerPathString); //$NON-NLS-1$ //$NON-NLS-2$
						rebuildIndex(indexLocation, containerPath);
						return null;
					}
					/*index = null;*/ // will fall thru to createIfMissing & create a empty index for the rebuild all job to populate
				}
			}
			if (currentIndexState == SAVED_STATE) { // rebuild index if existing file is missing
				rebuildIndex(indexLocation, containerPath);
				return null;
			}
		}
		// index wasn't found on disk, consider creating an empty new one
		if (createIfMissing) {
			try {
				if (VERBOSE)
					Util.verbose("-> create empty index: "+indexLocationString+" path: "+containerPathString); //$NON-NLS-1$ //$NON-NLS-2$
				index = new Index(indexLocationString, containerPathString, false /*do not reuse index file*/);
				this.indexes.put(indexLocation, index);
				return index;
			} catch (IOException e) {
				if (VERBOSE)
					Util.verbose("-> unable to create empty index: "+indexLocationString+" path: "+containerPathString); //$NON-NLS-1$ //$NON-NLS-2$
				// The file could not be created. Possible reason: the project has been deleted.
				return null;
			}
		}
	}
	//System.out.println(" index name: " + path.toOSString() + " <----> " + index.getIndexFile().getName());
	return index;
}
/**
 * Returns all the existing indexes for a list of index locations.
 * Note that this may trigger some indexes recreation work
 *
 * @param locations The list of of the index files path
 * @return The corresponding indexes list.
 */
public Index[] getIndexes(IPath[] locations, IProgressMonitor progressMonitor) {
	// acquire the in-memory indexes on the fly
	int length = locations.length;
	Index[] locatedIndexes = new Index[length];
	int count = 0;
	if (this.javaLikeNamesChanged) {
		this.javaLikeNamesChanged = hasJavaLikeNamesChanged();
	}
	for (int i = 0; i < length; i++) {
		if (progressMonitor != null && progressMonitor.isCanceled()) {
			throw new OperationCanceledException();
		}
		// may trigger some index recreation work
		IPath indexLocation = locations[i];
		Index index = getIndex(indexLocation);
		if (index == null) {
			// only need containerPath if the index must be built
			IPath containerPath = (IPath) this.indexLocations.keyForValue(indexLocation);
			if (containerPath != null) {// sanity check
				index = getIndex(containerPath, indexLocation, true /*reuse index file*/, false /*do not create if none*/);
				if (index != null && this.javaLikeNamesChanged && !index.isIndexForJar()) {
					// When a change in java like names extension has been detected, all
					// non jar files indexes (i.e. containing sources) need to be rebuilt.
					// see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=286379
					File indexFile = index.getIndexFile();
					if (indexFile.exists()) {
						if (DEBUG)
							Util.verbose("Change in javaLikeNames - removing index file for " + containerPath ); //$NON-NLS-1$
						indexFile.delete();
					}
					this.indexes.put(indexLocation, null);
					rebuildIndex(indexLocation, containerPath);
					index = null;
				}
			} else {
				if (!getJavaPluginWorkingLocation().isPrefixOf(indexLocation)) { // the index belongs to non-jdt search participant
					if (indexLocation.toFile().exists()) { 
						try {
							IPath container = getParticipantsContainer(indexLocation);
							if (container != null) {
								index = new Index(indexLocation.toOSString(), container.toOSString(), true /*reuse index file*/);
								this.indexes.put(indexLocation, index);
							}
						} catch (IOException e) {
							// ignore
						}
					} 
				}
			}
		}
		if (index != null)
			locatedIndexes[count++] = index; // only consider indexes which are ready
	}
	if (this.javaLikeNamesChanged) {
		writeJavaLikeNamesFile();
		this.javaLikeNamesChanged = false;
	}
	if (count < length) {
		System.arraycopy(locatedIndexes, 0, locatedIndexes=new Index[count], 0, count);
	}
	return locatedIndexes;
}
public synchronized Index getIndexForUpdate(IPath containerPath, boolean reuseExistingFile, boolean createIfMissing) {
	IPath indexLocation = computeIndexLocation(containerPath);
	if (getIndexStates().get(indexLocation) == REBUILDING_STATE)
		return getIndex(containerPath, indexLocation, reuseExistingFile, createIfMissing);

	return null; // abort the job since the index has been removed from the REBUILDING_STATE
}
private SimpleLookupTable getIndexStates() {
	if (this.indexStates != null) return this.indexStates;

	this.indexStates = new SimpleLookupTable();
	IPath indexesDirectoryPath = getJavaPluginWorkingLocation();
	char[][] savedNames = readIndexState(indexesDirectoryPath.toOSString());
	if (savedNames != null) {
		for (int i = 1, l = savedNames.length; i < l; i++) { // first name is saved signature, see readIndexState()
			char[] savedName = savedNames[i];
			if (savedName.length > 0) {
				IPath indexLocation = indexesDirectoryPath.append(new String(savedName)); // shares indexesDirectoryPath's segments
				if (VERBOSE)
					Util.verbose("Reading saved index file " + indexLocation); //$NON-NLS-1$
				this.indexStates.put(indexLocation, SAVED_STATE);
			}
		}
	} else {
		// All the index files are getting deleted and hence there is no need to 
		// further check for change in javaLikeNames. 
		writeJavaLikeNamesFile();
		this.javaLikeNamesChanged = false;
		deleteIndexFiles();
	}
	return this.indexStates;
}
private IPath getParticipantsContainer(IPath indexLocation) {
	if (this.participantsContainers == null) {
		readParticipantsIndexNamesFile();
	}
	return (IPath)this.participantsContainers.get(indexLocation);
}
private IPath getJavaPluginWorkingLocation() {
	if (this.javaPluginLocation != null) return this.javaPluginLocation;

	IPath stateLocation = JavaCore.getPlugin().getStateLocation();
	return this.javaPluginLocation = stateLocation;
}
private File getSavedIndexesDirectory() {
	return new File(getJavaPluginWorkingLocation().toOSString());
}
/*
 * see https://bugs.eclipse.org/bugs/show_bug.cgi?id=286379
 * Returns true if there is a change in javaLikeNames since it
 * has been last stored. 
 * The javaLikeNames stored in the file javaLikeNames.txt 
 * is compared with the current javaLikeNames and if there is a change, this 
 * function returns true. If the file javaLikeNames.txt doesn't exist and there 
 * is only one javaLikeName (.java), then this returns false so that no-reindexing 
 * happens. 
 */
private boolean hasJavaLikeNamesChanged() {
	char[][] currentNames = Util.getJavaLikeExtensions();
	int current = currentNames.length;
	char[][] prevNames = readJavaLikeNamesFile();
	if (prevNames == null) {
		if (VERBOSE && current != 1)
			Util.verbose("No Java like names found and there is atleast one non-default javaLikeName", System.err); //$NON-NLS-1$
		return (current != 1); //Ignore if only java
	}
	int prev = prevNames.length;
	if (current != prev) {
		if (VERBOSE)
			Util.verbose("Java like names have changed", System.err); //$NON-NLS-1$
		return true;
	}
	if (current > 1) {
		// Sort the current java like names. 
		// Copy the array to avoid modifying the Util static variable
		System.arraycopy(currentNames, 0, currentNames = new char[current][], 0, current);
		Util.sort(currentNames);
	}
	
	// The JavaLikeNames would have been sorted before getting stored in the file,
	// hence just do a direct compare.
	for (int i = 0; i < current; i++) {
		if (!CharOperation.equals(currentNames[i],prevNames[i])) {
			if (VERBOSE)
				Util.verbose("Java like names have changed", System.err); //$NON-NLS-1$
			return true;
		}
	}
	return false;
}
public void indexDocument(SearchDocument searchDocument, SearchParticipant searchParticipant, Index index, IPath indexLocation) {
	try {
		searchDocument.setIndex(index);
		searchParticipant.indexDocument(searchDocument, indexLocation);
	} finally {
		searchDocument.setIndex(null);
	}
}
/**
 * Trigger addition of the entire content of a project
 * Note: the actual operation is performed in background
 */
public void indexAll(IProject project) {
	if (JavaCore.getPlugin() == null) return;

	// Also request indexing of binaries on the classpath
	// determine the new children
	try {
		JavaModel model = JavaModelManager.getJavaModelManager().getJavaModel();
		JavaProject javaProject = (JavaProject) model.getJavaProject(project);
		// only consider immediate libraries - each project will do the same
		// NOTE: force to resolve CP variables before calling indexer - 19303, so that initializers
		// will be run in the current thread.
		IClasspathEntry[] entries = javaProject.getResolvedClasspath();
		for (int i = 0; i < entries.length; i++) {
			IClasspathEntry entry= entries[i];
			if (entry.getEntryKind() == IClasspathEntry.CPE_LIBRARY)
				indexLibrary(entry.getPath(), project);
		}
	} catch(JavaModelException e){ // cannot retrieve classpath info
	}

	// check if the same request is not already in the queue
	IndexRequest request = new IndexAllProject(project, this);
	if (!isJobWaiting(request))
		request(request);
}
/**
 * Trigger addition of a library to an index
 * Note: the actual operation is performed in background
 */
public void indexLibrary(IPath path, IProject requestingProject) {
	// requestingProject is no longer used to cancel jobs but leave it here just in case
	if (JavaCore.getPlugin() == null) return;

	Object target = JavaModel.getTarget(path, true);
	IndexRequest request = null;
	if (target instanceof IFile) {
		request = new AddJarFileToIndex((IFile) target, this);
	} else if (target instanceof File) {
		request = new AddJarFileToIndex(path, this);
	} else if (target instanceof IContainer) {
		request = new IndexBinaryFolder((IContainer) target, this);
	} else {
		return;
	}

	// check if the same request is not already in the queue
	if (!isJobWaiting(request))
		request(request);
}
/**
 * Index the content of the given source folder.
 */
public void indexSourceFolder(JavaProject javaProject, IPath sourceFolder, char[][] inclusionPatterns, char[][] exclusionPatterns) {
	IProject project = javaProject.getProject();
	if (this.jobEnd > this.jobStart) {
		// skip it if a job to index the project is already in the queue
		IndexRequest request = new IndexAllProject(project, this);
		if (isJobWaiting(request)) return;
	}

	request(new AddFolderToIndex(sourceFolder, project, inclusionPatterns, exclusionPatterns, this));
}
public synchronized void jobWasCancelled(IPath containerPath) {
	IPath indexLocation = computeIndexLocation(containerPath);
	Index index = getIndex(indexLocation);
	if (index != null) {
		index.monitor = null;
		this.indexes.removeKey(indexLocation);
	}
	updateIndexState(indexLocation, UNKNOWN_STATE);
}
/**
 * Advance to the next available job, once the current one has been completed.
 * Note: clients awaiting until the job count is zero are still waiting at this point.
 */
protected synchronized void moveToNextJob() {
	// remember that one job was executed, and we will need to save indexes at some point
	this.needToSave = true;
	super.moveToNextJob();
}
/**
 * No more job awaiting.
 */
protected void notifyIdle(long idlingTime){
	if (idlingTime > 1000 && this.needToSave) saveIndexes();
}
/**
 * Name of the background process
 */
public String processName(){
	return Messages.process_name;
}
private char[][] readJavaLikeNamesFile() {
	try {
		String pathName = getJavaPluginWorkingLocation().toOSString();	
		File javaLikeNamesFile = new File(pathName, "javaLikeNames.txt"); //$NON-NLS-1$
		if (!javaLikeNamesFile.exists())
			return null;
		char[] javaLikeNames = org.eclipse.jdt.internal.compiler.util.Util.getFileCharContent(javaLikeNamesFile, null);
		if (javaLikeNames.length > 0) {
			char[][] names = CharOperation.splitOn('\n', javaLikeNames);
			return names;
		}
	} catch (IOException ignored) {
		if (VERBOSE)
			Util.verbose("Failed to read javaLikeNames file"); //$NON-NLS-1$
	}
	return null;
}
private void rebuildIndex(IPath indexLocation, IPath containerPath) {
	Object target = JavaModel.getTarget(containerPath, true);
	if (target == null) return;

	if (VERBOSE)
		Util.verbose("-> request to rebuild index: "+indexLocation+" path: "+containerPath); //$NON-NLS-1$ //$NON-NLS-2$

	updateIndexState(indexLocation, REBUILDING_STATE);
	IndexRequest request = null;
	if (target instanceof IProject) {
		IProject p = (IProject) target;
		if (JavaProject.hasJavaNature(p))
			request = new IndexAllProject(p, this);
	} else if (target instanceof IFolder) {
		request = new IndexBinaryFolder((IFolder) target, this);
	} else if (target instanceof IFile) {
		request = new AddJarFileToIndex((IFile) target, this);
	} else if (target instanceof File) {
		request = new AddJarFileToIndex(containerPath, this);
	}
	if (request != null)
		request(request);
}
/**
 * Recreates the index for a given path, keeping the same read-write monitor.
 * Returns the new empty index or null if it didn't exist before.
 * Warning: Does not check whether index is consistent (not being used)
 */
public synchronized Index recreateIndex(IPath containerPath) {
	// only called to over write an existing cached index...
	String containerPathString = containerPath.getDevice() == null ? containerPath.toString() : containerPath.toOSString();
	try {
		// Path is already canonical
		IPath indexLocation = computeIndexLocation(containerPath);
		Index index = getIndex(indexLocation);
		ReadWriteMonitor monitor = index == null ? null : index.monitor;

		if (VERBOSE)
			Util.verbose("-> recreating index: "+indexLocation+" for path: "+containerPathString); //$NON-NLS-1$ //$NON-NLS-2$
		index = new Index(indexLocation.toOSString(), containerPathString, false /*do not reuse index file*/);
		this.indexes.put(indexLocation, index);
		index.monitor = monitor;
		return index;
	} catch (IOException e) {
		// The file could not be created. Possible reason: the project has been deleted.
		if (VERBOSE) {
			Util.verbose("-> failed to recreate index for path: "+containerPathString); //$NON-NLS-1$
			e.printStackTrace();
		}
		return null;
	}
}
/**
 * Trigger removal of a resource to an index
 * Note: the actual operation is performed in background
 */
public void remove(String containerRelativePath, IPath indexedContainer){
	request(new RemoveFromIndex(containerRelativePath, indexedContainer, this));
}
/**
 * Removes the index for a given path.
 * This is a no-op if the index did not exist.
 */
public synchronized void removeIndex(IPath containerPath) {
	if (VERBOSE || DEBUG)
		Util.verbose("removing index " + containerPath); //$NON-NLS-1$
	IPath indexLocation = computeIndexLocation(containerPath);
	Index index = getIndex(indexLocation);
	File indexFile = null;
	if (index != null) {
		index.monitor = null;
		indexFile = index.getIndexFile();
	}
	if (indexFile == null)
		indexFile = new File(indexLocation.toOSString()); // index is not cached yet, but still want to delete the file
	if (indexFile.exists()) {
		if (DEBUG)
			Util.verbose("removing index file " + indexFile); //$NON-NLS-1$
		indexFile.delete();
	}
	this.indexes.removeKey(indexLocation);
	updateIndexState(indexLocation, null);
}
/**
 * Removes all indexes whose paths start with (or are equal to) the given path.
 */
public synchronized void removeIndexPath(IPath path) {
	if (VERBOSE || DEBUG)
		Util.verbose("removing index path " + path); //$NON-NLS-1$
	Object[] keyTable = this.indexes.keyTable;
	Object[] valueTable = this.indexes.valueTable;
	IPath[] locations = null;
	int max = this.indexes.elementSize;
	int count = 0;
	for (int i = 0, l = keyTable.length; i < l; i++) {
		IPath indexLocation = (IPath) keyTable[i];
		if (indexLocation == null)
			continue;
		if (path.isPrefixOf(indexLocation)) {
			Index index = (Index) valueTable[i];
			index.monitor = null;
			if (locations == null)
				locations = new IPath[max];
			locations[count++] = indexLocation;
			File indexFile = index.getIndexFile();
			if (indexFile.exists()) {
				if (DEBUG)
					Util.verbose("removing index file " + indexFile); //$NON-NLS-1$
				indexFile.delete();
			}
		} else {
			max--;
		}
	}
	if (locations != null) {
		for (int i = 0; i < count; i++)
			this.indexes.removeKey(locations[i]);
		removeIndexesState(locations);
		if (this.participantsContainers != null && this.participantsContainers.get(path.toOSString()) != null) {
			this.participantsContainers.removeKey(path.toOSString());	
			writeParticipantsIndexNamesFile();
		}
	}
}
/**
 * Removes all indexes whose paths start with (or are equal to) the given path.
 */
public synchronized void removeIndexFamily(IPath path) {
	// only finds cached index files... shutdown removes all non-cached index files
	ArrayList toRemove = null;
	Object[] containerPaths = this.indexLocations.keyTable;
	for (int i = 0, length = containerPaths.length; i < length; i++) {
		IPath containerPath = (IPath) containerPaths[i];
		if (containerPath == null) continue;
		if (path.isPrefixOf(containerPath)) {
			if (toRemove == null)
				toRemove = new ArrayList();
			toRemove.add(containerPath);
		}
	}
	if (toRemove != null)
		for (int i = 0, length = toRemove.size(); i < length; i++)
			removeIndex((IPath) toRemove.get(i));
}
/**
 * Remove the content of the given source folder from the index.
 */
public void removeSourceFolderFromIndex(JavaProject javaProject, IPath sourceFolder, char[][] inclusionPatterns, char[][] exclusionPatterns) {
	IProject project = javaProject.getProject();
	if (this.jobEnd > this.jobStart) {
		// skip it if a job to index the project is already in the queue
		IndexRequest request = new IndexAllProject(project, this);
		if (isJobWaiting(request)) return;
	}

	request(new RemoveFolderFromIndex(sourceFolder, inclusionPatterns, exclusionPatterns, project, this));
}
/**
 * Flush current state
 */
public synchronized void reset() {
	super.reset();
	if (this.indexes != null) {
		this.indexes = new SimpleLookupTable();
		this.indexStates = null;
	}
	this.indexLocations = new SimpleLookupTable();
	this.javaPluginLocation = null;
}
/**
 * Resets the index for a given path.
 * Returns true if the index was reset, false otherwise.
 */
public synchronized boolean resetIndex(IPath containerPath) {
	// only called to over write an existing cached index...
	String containerPathString = containerPath.getDevice() == null ? containerPath.toString() : containerPath.toOSString();
	try {
		// Path is already canonical
		IPath indexLocation = computeIndexLocation(containerPath);
		Index index = getIndex(indexLocation);
		if (VERBOSE) {
			Util.verbose("-> reseting index: "+indexLocation+" for path: "+containerPathString); //$NON-NLS-1$ //$NON-NLS-2$
		}
		if (index == null) {
			// the index does not exist, try to recreate it
			return recreateIndex(containerPath) != null;
		}
		index.reset();
		return true;
	} catch (IOException e) {
		// The file could not be created. Possible reason: the project has been deleted.
		if (VERBOSE) {
			Util.verbose("-> failed to reset index for path: "+containerPathString); //$NON-NLS-1$
			e.printStackTrace();
		}
		return false;
	}
}
public void saveIndex(Index index) throws IOException {
	// must have permission to write from the write monitor
	if (index.hasChanged()) {
		if (VERBOSE)
			Util.verbose("-> saving index " + index.getIndexFile()); //$NON-NLS-1$
		index.save();
	}
	synchronized (this) {
		IPath containerPath = new Path(index.containerPath);
		if (this.jobEnd > this.jobStart) {
			for (int i = this.jobEnd; i > this.jobStart; i--) { // skip the current job
				IJob job = this.awaitingJobs[i];
				if (job instanceof IndexRequest)
					if (((IndexRequest) job).containerPath.equals(containerPath)) return;
			}
		}
		IPath indexLocation = computeIndexLocation(containerPath);
		updateIndexState(indexLocation, SAVED_STATE);
	}
}
/**
 * Commit all index memory changes to disk
 */
public void saveIndexes() {
	// only save cached indexes... the rest were not modified
	ArrayList toSave = new ArrayList();
	synchronized(this) {
		Object[] valueTable = this.indexes.valueTable;
		for (int i = 0, l = valueTable.length; i < l; i++) {
			Index index = (Index) valueTable[i];
			if (index != null)
				toSave.add(index);
		}
	}

	boolean allSaved = true;
	for (int i = 0, length = toSave.size(); i < length; i++) {
		Index index = (Index) toSave.get(i);
		ReadWriteMonitor monitor = index.monitor;
		if (monitor == null) continue; // index got deleted since acquired
		try {
			// take read lock before checking if index has changed
			// don't take write lock yet since it can cause a deadlock (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=50571)
			monitor.enterRead();
			if (index.hasChanged()) {
				if (monitor.exitReadEnterWrite()) {
					try {
						saveIndex(index);
					} catch(IOException e) {
						if (VERBOSE) {
							Util.verbose("-> got the following exception while saving:", System.err); //$NON-NLS-1$
							e.printStackTrace();
						}
						allSaved = false;
					} finally {
						monitor.exitWriteEnterRead();
					}
				} else {
					allSaved = false;
				}
			}
		} finally {
			monitor.exitRead();
		}
	}
	if (this.participantsContainers != null && this.participantUpdated) {
		writeParticipantsIndexNamesFile();
		this.participantUpdated = false;
	}
	this.needToSave = !allSaved;
}
public void scheduleDocumentIndexing(final SearchDocument searchDocument, IPath container, final IPath indexLocation, final SearchParticipant searchParticipant) {
	request(new IndexRequest(container, this) {
		public boolean execute(IProgressMonitor progressMonitor) {
			if (this.isCancelled || progressMonitor != null && progressMonitor.isCanceled()) return true;

			/* ensure no concurrent write access to index */
			Index index = getIndex(this.containerPath, indexLocation, true, /*reuse index file*/ true /*create if none*/);
			if (index == null) return true;
			ReadWriteMonitor monitor = index.monitor;
			if (monitor == null) return true; // index got deleted since acquired

			try {
				monitor.enterWrite(); // ask permission to write
				indexDocument(searchDocument, searchParticipant, index, indexLocation);
			} finally {
				monitor.exitWrite(); // free write lock
			}
			return true;
		}
		public String toString() {
			return "indexing " + searchDocument.getPath(); //$NON-NLS-1$
		}
	});
}

public String toString() {
	StringBuffer buffer = new StringBuffer(10);
	buffer.append(super.toString());
	buffer.append("In-memory indexes:\n"); //$NON-NLS-1$
	int count = 0;
	Object[] valueTable = this.indexes.valueTable;
	for (int i = 0, l = valueTable.length; i < l; i++) {
		Index index = (Index) valueTable[i];
		if (index != null)
			buffer.append(++count).append(" - ").append(index.toString()).append('\n'); //$NON-NLS-1$
	}
	return buffer.toString();
}

private char[][] readIndexState(String dirOSString) {
	try {
		char[] savedIndexNames = org.eclipse.jdt.internal.compiler.util.Util.getFileCharContent(this.savedIndexNamesFile, null);
		if (savedIndexNames.length > 0) {
			char[][] names = CharOperation.splitOn('\n', savedIndexNames);
			if (names.length > 1) {
				// First line is DiskIndex signature + saved plugin working location (see writeSavedIndexNamesFile())
				String savedSignature = DiskIndex.SIGNATURE + "+" + dirOSString; //$NON-NLS-1$
				if (savedSignature.equals(new String(names[0])))
					return names;
			}
		}
	} catch (IOException ignored) {
		if (VERBOSE)
			Util.verbose("Failed to read saved index file names"); //$NON-NLS-1$
	}
	return null;
}
private void readParticipantsIndexNamesFile() {
	SimpleLookupTable containers = new SimpleLookupTable(3);
	try {
		char[] participantIndexNames = org.eclipse.jdt.internal.compiler.util.Util.getFileCharContent(this.participantIndexNamesFile, null);
		if (participantIndexNames.length > 0) {
			char[][] names = CharOperation.splitOn('\n', participantIndexNames);
			if (names.length >= 3) {
				// First line is DiskIndex signature  (see writeParticipantsIndexNamesFile())
				if (DiskIndex.SIGNATURE.equals(new String(names[0]))) {					
					for (int i = 1, l = names.length-1 ; i < l ; i+=2) {
						containers.put(new Path(new String(names[i])), new Path(new String(names[i+1])));
					}
				}				
			}
		}	
	} catch (IOException ignored) {
		if (VERBOSE)
			Util.verbose("Failed to read participant index file names"); //$NON-NLS-1$
	}
	this.participantsContainers = containers;
	return;
}
private synchronized void removeIndexesState(IPath[] locations) {
	getIndexStates(); // ensure the states are initialized
	int length = locations.length;
	boolean changed = false;
	for (int i=0; i<length; i++) {
		if (locations[i] == null) continue;
		if ((this.indexStates.removeKey(locations[i]) != null)) {
			changed = true;
			if (VERBOSE) {
				Util.verbose("-> index state updated to: ? for: "+locations[i]); //$NON-NLS-1$
			}
		}
	}
	if (!changed) return;

	writeSavedIndexNamesFile();
}
private synchronized void updateIndexState(IPath indexLocation, Integer indexState) {
	if (indexLocation.isEmpty())
		throw new IllegalArgumentException();

	getIndexStates(); // ensure the states are initialized
	if (indexState != null) {
		if (indexState.equals(this.indexStates.get(indexLocation))) return; // not changed
		this.indexStates.put(indexLocation, indexState);
	} else {
		if (!this.indexStates.containsKey(indexLocation)) return; // did not exist anyway
		this.indexStates.removeKey(indexLocation);
	}

	writeSavedIndexNamesFile();

	if (VERBOSE) {
		if (indexState == null) {
			Util.verbose("-> index state removed for: "+indexLocation); //$NON-NLS-1$
		} else {
			String state = "?"; //$NON-NLS-1$
			if (indexState == SAVED_STATE) state = "SAVED"; //$NON-NLS-1$
			else if (indexState == UPDATING_STATE) state = "UPDATING"; //$NON-NLS-1$
			else if (indexState == UNKNOWN_STATE) state = "UNKNOWN"; //$NON-NLS-1$
			else if (indexState == REBUILDING_STATE) state = "REBUILDING"; //$NON-NLS-1$
			Util.verbose("-> index state updated to: " + state + " for: "+indexLocation); //$NON-NLS-1$ //$NON-NLS-2$
		}
	}

}
public void updateParticipant(IPath indexLocation, IPath containerPath) {
	if (this.participantsContainers == null) {
		readParticipantsIndexNamesFile();
	} 
	if (this.participantsContainers.get(indexLocation) == null) {
		this.participantsContainers.put(indexLocation, containerPath);
		this.participantUpdated  = true;
	}
}
private void writeJavaLikeNamesFile() {
	BufferedWriter writer = null;
	String pathName = getJavaPluginWorkingLocation().toOSString();
	try {		
		char[][] currentNames = Util.getJavaLikeExtensions();
		int length = currentNames.length;
		if (length > 1) {
			// Sort the current java like names. 
			// Copy the array to avoid modifying the Util static variable
			System.arraycopy(currentNames, 0, currentNames=new char[length][], 0, length);
			Util.sort(currentNames);
		}
		File javaLikeNamesFile = new File(pathName, "javaLikeNames.txt"); //$NON-NLS-1$
		writer = new BufferedWriter(new FileWriter(javaLikeNamesFile));
		for (int i = 0; i < length-1; i++) {
			writer.write(currentNames[i]);
			writer.write('\n');
		}
		if (length > 0) 
			writer.write(currentNames[length-1]);
		
	} catch (IOException ignored) {
		if (VERBOSE)
			Util.verbose("Failed to write javaLikeNames file", System.err); //$NON-NLS-1$
	} finally {
		if (writer != null) {
			try {
				writer.close();
			} catch (IOException e) {
				// ignore
			}
		}
	}
}
private void writeParticipantsIndexNamesFile() {
	BufferedWriter writer = null;
	try {
		writer = new BufferedWriter(new FileWriter(this.participantIndexNamesFile));
		writer.write(DiskIndex.SIGNATURE);
		writer.write('\n');
		Object[] indexFiles = this.participantsContainers.keyTable;
		Object[] containers = this.participantsContainers.valueTable;
		for (int i = 0, l = indexFiles.length; i < l; i++) {
			IPath indexFile = (IPath)indexFiles[i];
			if (indexFile != null) {
				writer.write(indexFile.toOSString());
				writer.write('\n');
				writer.write(((IPath)containers[i]).toOSString());
				writer.write('\n');
			}
		}
	} catch (IOException ignored) {
		if (VERBOSE)
			Util.verbose("Failed to write participant index file names", System.err); //$NON-NLS-1$
	} finally {
		if (writer != null) {
			try {
				writer.close();
			} catch (IOException e) {
				// ignore
			}
		}
	}
}
private void writeSavedIndexNamesFile() {
	BufferedWriter writer = null;
	try {
		writer = new BufferedWriter(new FileWriter(this.savedIndexNamesFile));
		writer.write(DiskIndex.SIGNATURE);
		writer.write('+');
		writer.write(getJavaPluginWorkingLocation().toOSString());
		writer.write('\n');
		Object[] keys = this.indexStates.keyTable;
		Object[] states = this.indexStates.valueTable;
		for (int i = 0, l = states.length; i < l; i++) {
			IPath key = (IPath) keys[i];
			if (key != null && !key.isEmpty() && states[i] == SAVED_STATE) {
				writer.write(key.lastSegment());
				writer.write('\n');
			}
		}
	} catch (IOException ignored) {
		if (VERBOSE)
			Util.verbose("Failed to write saved index file names", System.err); //$NON-NLS-1$
	} finally {
		if (writer != null) {
			try {
				writer.close();
			} catch (IOException e) {
				// ignore
			}
		}
	}
}
}
