/*******************************************************************************
 * Copyright (c) 2010, 2011 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.wst.sse.core.indexing;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IResourceDeltaVisitor;
import org.eclipse.core.resources.IResourceProxy;
import org.eclipse.core.resources.IResourceProxyVisitor;
import org.eclipse.core.resources.ISaveParticipant;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.ISafeRunnable;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.SafeRunner;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.osgi.util.NLS;
import org.eclipse.wst.sse.core.internal.Logger;
import org.eclipse.wst.sse.core.internal.SSECoreMessages;

/**
 * <p>
 * A generic class for implementing a resource index manager. It is important
 * to note that this only provides the framework for managing an index, not
 * actually indexing. The subtle difference is that the manager is in charge
 * of paying attention to all of the resource actions that take place in the
 * workspace and filtering those actions down to simple actions that need to
 * be performed on whatever index this manager is managing.
 * </p>
 * 
 * <p>
 * The manager does its very best to make sure the index is always consistent,
 * even if resource events take place when the manager is not running. In the
 * event that the manager determines it has missed, lost, or corrupted any
 * resource change events that have occurred before, during, or after its
 * activation or deactivation then the manager will inspect the entire
 * workspace to insure the index it is managing is consistent.
 * </p>
 * 
 */
public abstract class AbstractIndexManager {

	/** Used to encode path bytes in case they contain double byte characters */
	private static final String ENCODING_UTF16 = "utf16"; //$NON-NLS-1$

	/** Default time to wait for other tasks to finish */
	private static final int WAIT_TIME = 300;

	/**
	 * <p>
	 * Used to report progress on jobs where the total work to complete is
	 * unknown. The created effect is a progress bar that moves but that will
	 * never complete.
	 * </p>
	 */
	private static final int UNKNOWN_WORK = 100;

	/**
	 * The amount of events to batch up before sending them off to the
	 * processing job
	 */
	private static final int BATCH_UP_AMOUNT = 100;

	/** If this file exists then a full workspace re-processing is needed */
	private static final String RE_PROCESS_FILE_NAME = ".re-process"; //$NON-NLS-1$

	/** Common error message to log */
	private static final String LOG_ERROR_INDEX_INVALID = "Index may become invalid, incomplete, or enter some other inconsistent state."; //$NON-NLS-1$

	/** State: manager is stopped */
	private static final byte STATE_DISABLED = 0;

	/** State: manager is running */
	private static final byte STATE_ENABLED = 1;

	/** Action: add to index */
	protected static final byte ACTION_ADD = 0;

	/** Action: remove from index */
	protected static final byte ACTION_REMOVE = 1;

	/** Action: add to index caused by move operation */
	protected static final byte ACTION_ADD_MOVE_FROM = 2;

	/** Action: remove from index caused by move operation */
	protected static final byte ACTION_REMOVE_MOVE_TO = 3;

	/** Source: action originated from resource change event */
	protected static final byte SOURCE_RESOURCE_CHANGE = 0;

	/** Source: action originated from workspace scan */
	protected static final byte SOURCE_WORKSPACE_SCAN = 1;

	/** Source: action originated from saved state */
	protected static final byte SOURCE_SAVED_STATE = 2;

	/** Source: preserved resources to index */
	protected static final byte SOURCE_PRESERVED_RESOURCES_TO_INDEX = 3;

	/** the name of this index manager */
	private String fName;

	/** {@link IResourceChangeListener} to listen for file changes */
	private ResourceChangeListener fResourceChangeListener;

	/** The {@link Job} that does all of the indexing */
	private ResourceEventProcessingJob fResourceEventProcessingJob;

	/** A {@link Job} to search the workspace for all files */
	private Job fWorkspaceVisitorJob;

	/**
	 * <p>
	 * Current state of the manager
	 * </p>
	 * 
	 * @see #STATE_DISABLED
	 * @see #STATE_ENABLED
	 */
	private volatile byte fState;

	/** used to prevent manager from starting and stopping at the same time */
	private Object fStartStopLock = new Object();

	/**
	 * <code>true</code> if the manager is currently starting,
	 * <code>false</code> otherwise
	 */
	private boolean fStarting;

	/**
	 * <p>
	 * Creates the manager with a given name.
	 * </p>
	 * 
	 * @param name
	 *            This will be pre-pended to progress reporting messages and
	 *            thus should be translated
	 */
	protected AbstractIndexManager(String name) {
		this.fName = name;
		this.fState = STATE_DISABLED;
		this.fResourceChangeListener = new ResourceChangeListener();
		this.fResourceEventProcessingJob = new ResourceEventProcessingJob();
		this.fStarting = false;
	}

	/**
	 * <p>
	 * Creates the manager with a given name.
	 * </p>
	 * 
	 * @param name
	 *            This will be pre-pended to progress reporting messages and
	 *            thus should be translated
	 * 
	 * @param messageRunning
	 *            ignored
	 * @param messageInitializing
	 *            ignored
	 * @param messageProcessingFiles
	 *            ignored
	 * 
	 * @deprecated This constructor ignores the last three parameters.
	 * @see #AbstractIndexManager(String)
	 */

	protected AbstractIndexManager(String name, String messageRunning, String messageInitializing, String messageProcessingFiles) {
		this(name);
	}

	/**
	 * <p>
	 * Starts up the {@link AbstractIndexManager}. If a {@link IResourceDelta}
	 * is provided then it is assumed that all other files in the workspace
	 * have already been index and thus only those in the provided
	 * {@link IResourceDelta} will be processed. Else if the provided
	 * {@link IResourceDelta} is <code>null</code> it is assumed no files have
	 * been indexed yet so the entire workspace will be searched for files to
	 * be indexed.
	 * </p>
	 * 
	 * <p>
	 * If {@link IResourceDelta} is provided this will block until that delta
	 * has finished processing. If no {@link IResourceDelta} provided then a
	 * separate job will be created to process the entire workspace and this
	 * method will return without waiting for that job to complete
	 * </p>
	 * 
	 * <p>
	 * Will block until {@link #stop()} has finished running if it is
	 * currently running
	 * </p>
	 * 
	 * @param savedStateDelta
	 *            the delta from a saved state, if <code>null</code> then the
	 *            entire workspace will be searched for files to index, else
	 *            only files in this {@link IResourceDelta} will be indexed
	 * @param monitor
	 *            This action can not be canceled but this monitor will be
	 *            used to report progress
	 */
	public final void start(IResourceDelta savedStateDelta, IProgressMonitor monitor) {
		SubMonitor progress = SubMonitor.convert(monitor);
		synchronized (this.fStartStopLock) {
			this.fStarting = true;

			try {
				if (this.fState == STATE_DISABLED) {
					// report status
					progress.beginTask(NLS.bind(SSECoreMessages.IndexManager_0_starting, this.fName), 2);

					// start listening for resource change events
					this.fResourceChangeListener.start();

					// check to see if a full re-index is required
					boolean forcedFullReIndexNeeded = this.isForcedFullReIndexNeeded();

					/*
					 * start the indexing job only loading preserved state if
					 * not doing full index if failed loading preserved state
					 * then force full re-index
					 */
					forcedFullReIndexNeeded = !this.fResourceEventProcessingJob.start(!forcedFullReIndexNeeded, progress.newChild(1));
					progress.setWorkRemaining(1);

					// don't bother processing saved delta if forced full
					// re-index is needed
					if (!forcedFullReIndexNeeded) {
						/*
						 * if there is a delta attempt to process it else need
						 * to do a full workspace index
						 */
						if (savedStateDelta != null) {
							forcedFullReIndexNeeded = false;
							try {
								// deal with reporting progress
								SubMonitor savedStateProgress = progress.newChild(1, SubMonitor.SUPPRESS_NONE);

								savedStateProgress.setTaskName(NLS.bind(SSECoreMessages.IndexManager_0_starting_1, new String[]{this.fName, SSECoreMessages.IndexManager_processing_deferred_resource_changes}));

								// process delta
								ResourceDeltaVisitor visitor = new ResourceDeltaVisitor(savedStateProgress, AbstractIndexManager.SOURCE_SAVED_STATE);
								savedStateDelta.accept(visitor);

								// process any remaining batched up resources
								// to index
								visitor.processBatchedResourceEvents();
							}
							catch (CoreException e) {
								forcedFullReIndexNeeded = true;
								Logger.logException(this.fName + ": Could not process saved state. " + //$NON-NLS-1$
											"Forced to do a full workspace re-index.", e); //$NON-NLS-1$
							}
						}
						else {
							forcedFullReIndexNeeded = true;
						}
					}
					progress.worked(1);

					// if need to process the entire workspace do so in
					// another job
					if (forcedFullReIndexNeeded) {
						this.fWorkspaceVisitorJob = new WorkspaceVisitorJob();
						this.fWorkspaceVisitorJob.schedule();
					}

					// update state
					this.fState = STATE_ENABLED;
				}
			}
			finally {
				this.fStarting = false;
				progress.done();
			}
		}
	}

	/**
	 * <p>
	 * Safely shuts down the manager.
	 * </p>
	 * 
	 * <p>
	 * This will block until the
	 * {@link #start(IResourceDelta, IProgressMonitor)} has finished (if
	 * running). Also until the current resource event has finished being
	 * processed. Finally it will block until the events still to be processed
	 * by the processing job have been preserved to be processed on the next
	 * call to {@link #start(IResourceDelta, IProgressMonitor)}.
	 * </p>
	 * 
	 * <p>
	 * If at any point during this shut down processes something goes wrong
	 * the manager will be sure that on the next call to
	 * {@link #start(IResourceDelta, IProgressMonitor)} the entire workspace
	 * will be re-processed.
	 * </p>
	 * 
	 * @throws InterruptedException
	 */
	public final void stop() throws InterruptedException {
		synchronized (this.fStartStopLock) {
			if (this.fState != STATE_DISABLED) {

				// stop listening for events, and wait for the current event
				// to finish
				this.fResourceChangeListener.stop();

				// if currently visiting entire workspace, give up and try
				// again next load
				boolean forceFullReIndexNextStart = false;
				if (this.fWorkspaceVisitorJob != null) {
					if (this.fWorkspaceVisitorJob.getState() != Job.NONE) {
						this.fWorkspaceVisitorJob.cancel();

						this.forceFullReIndexNextStart();
						forceFullReIndexNextStart = true;
					}
				}

				// stop the indexing job, only preserve if not already forcing
				// a re-index
				forceFullReIndexNextStart = !this.fResourceEventProcessingJob.stop(!forceFullReIndexNextStart);

				// if preserving failed, then force re-index
				if (forceFullReIndexNextStart) {
					this.forceFullReIndexNextStart();
				}

				// update status
				this.fState = STATE_DISABLED;
			}
		}
	}

	/**
	 * @return the name of this indexer
	 */
	protected String getName() {
		return this.fName;
	}

	/**
	 * <p>
	 * Should be called by a client of the index this manager manages before
	 * the index is accessed, assuming the client wants an index consistent
	 * with the latest resource changes.
	 * </p>
	 * 
	 * <p>
	 * The supplied monitor will be used to supply user readable progress as
	 * the manager insures the index has been given all the latest resource
	 * events. This monitor may be canceled, but if it is the state of the
	 * index is not guaranteed to be consistent with the latest resource
	 * change events.
	 * </p>
	 * 
	 * @param monitor
	 *            Used to report user readable progress as the manager insures
	 *            the index is consistent with the latest resource events.
	 *            This monitor can be canceled to stop waiting for consistency
	 *            but then no guaranty is made about the consistency of the
	 *            index in relation to unprocessed resource changes
	 * 
	 * @return <code>true</code> if the wait finished successfully and the
	 *         manager is consistent, <code>false</code> otherwise, either an
	 *         error occurred while waiting for the manager or the monitor was
	 *         canceled
	 * 
	 * @throws InterruptedException
	 *             This can happen when waiting for other jobs
	 */
	public final boolean waitForConsistent(IProgressMonitor monitor) {
		boolean success = true;
		boolean interupted = false;
		SubMonitor progress = SubMonitor.convert(monitor);

		// set up the progress of waiting
		int remainingWork = 4;
		progress.beginTask(NLS.bind(SSECoreMessages.IndexManager_Waiting_for_0, this.fName), remainingWork);

		// wait for start up
		if (this.fStarting && !monitor.isCanceled()) {
			SubMonitor startingProgress = progress.newChild(1);
			startingProgress.subTask(NLS.bind(SSECoreMessages.IndexManager_0_starting, this.fName));
			while (this.fStarting && !monitor.isCanceled()) {
				// this creates a never ending progress that still moves
				// forward
				startingProgress.setWorkRemaining(UNKNOWN_WORK);
				startingProgress.newChild(1).worked(1);
				try {
					Thread.sleep(WAIT_TIME);
				}
				catch (InterruptedException e) {
					interupted = true;
				}
			}
		}
		progress.setWorkRemaining(--remainingWork);

		// wait for workspace visiting job
		if (this.fWorkspaceVisitorJob != null && this.fWorkspaceVisitorJob.getState() != Job.NONE && !monitor.isCanceled()) {
			SubMonitor workspaceVisitorProgress = progress.newChild(1);
			workspaceVisitorProgress.subTask(SSECoreMessages.IndexManager_Processing_entire_workspace_for_the_first_time);
			while (this.fWorkspaceVisitorJob.getState() != Job.NONE && !monitor.isCanceled()) {
				// this creates a never ending progress that still moves
				// forward
				workspaceVisitorProgress.setWorkRemaining(UNKNOWN_WORK);
				workspaceVisitorProgress.newChild(1).worked(1);
				try {
					Thread.sleep(WAIT_TIME);
				}
				catch (InterruptedException e) {
					interupted = true;
				}
			}
		}
		progress.setWorkRemaining(--remainingWork);

		// wait for the current resource event
		if (this.fResourceChangeListener.isProcessingEvents() && !monitor.isCanceled()) {
			SubMonitor workspaceVisitorProgress = progress.newChild(1);
			workspaceVisitorProgress.subTask(SSECoreMessages.IndexManager_processing_recent_resource_changes);
			while (this.fResourceChangeListener.isProcessingEvents() && !monitor.isCanceled()) {
				workspaceVisitorProgress.setWorkRemaining(UNKNOWN_WORK);
				workspaceVisitorProgress.newChild(1).worked(1);
				try {
					this.fResourceChangeListener.waitForCurrentEvent(WAIT_TIME);
				}
				catch (InterruptedException e) {
					interupted = true;
				}
			}
		}
		progress.setWorkRemaining(--remainingWork);

		// wait for all files to be indexed
		if (this.fResourceEventProcessingJob.getNumResourceEventsToProcess() != 0 && !monitor.isCanceled()) {
			SubMonitor indexingProgress = progress.newChild(1);
			int prevNumResources;
			int numResources = this.fResourceEventProcessingJob.getNumResourceEventsToProcess();
			while (numResources != 0 && !monitor.isCanceled()) {
				// update the progress indicator
				indexingProgress.subTask(NLS.bind(SSECoreMessages.IndexManager_0_Indexing_1_Files, new Object[]{AbstractIndexManager.this.fName, "" + numResources})); //$NON-NLS-1$
				indexingProgress.setWorkRemaining(numResources);
				prevNumResources = numResources;
				numResources = this.fResourceEventProcessingJob.getNumResourceEventsToProcess();
				int numProcessed = prevNumResources - numResources;
				indexingProgress.worked(numProcessed > 0 ? numProcessed : 0);

				// give the index some time to do some indexing
				try {
					this.fResourceEventProcessingJob.waitForConsistant(WAIT_TIME);
				}
				catch (InterruptedException e) {
					interupted = true;
				}
			}
		}
		progress.setWorkRemaining(--remainingWork);

		if (monitor.isCanceled()) {
			success = false;
		}

		// reset the interrupted flag if we were interrupted
		if (interupted) {
			Thread.currentThread().interrupt();
		}

		progress.done();
		return success;
	}

	/**
	 * <p>
	 * Called for each {@link IResource} given in a resource delta. If the
	 * resource type is a file then used to determine if that file should be
	 * processed by the manager, if the resource type is a project or
	 * directory then it is used to determine if the children of the project
	 * or directory should be processed looking for file resources.
	 * </p>
	 * 
	 * <p>
	 * <b>NOTE:</b> Even if <code>true</code> is returned for a directory
	 * resource that only means the children of the directory should be
	 * inspected for possible files to index. Directories themselves can not
	 * be managed in order to add to an index.
	 * </p>
	 * 
	 * @param type
	 *            the {@link IResource#getType()} result of the resource to
	 *            possibly index
	 * @param path
	 *            the full {@link IPath} to the resource to possibly index
	 * @return <code>true</code> If the resource with the given
	 *         <code>type</code> and <code>path</code> should either itself be
	 *         indexed, or its children should be indexed, <code>false</code>
	 *         if neither the described resource or any children should be
	 *         indexed
	 */
	protected abstract boolean isResourceToIndex(int type, IPath path);

	/**
	 * <p>
	 * Called for each {@link ResourceEvent} gathered by the various sources
	 * and processed by the {@link ResourceEventProcessingJob}. The
	 * implementation of this method should use the given information to
	 * update the index this manager is managing.
	 * </p>
	 * 
	 * @param source
	 *            The source that reported this resource event
	 * @param action
	 *            The action to be taken on the given <code>resource</code>
	 * @param resource
	 *            The index should perform the given <code>action</code> on
	 *            this resource
	 * @param movePath
	 *            If the given <code>action</code> is
	 *            {@link AbstractIndexManager#ACTION_ADD_MOVE_FROM} or
	 *            {@link AbstractIndexManager#ACTION_REMOVE_MOVE_TO} then this
	 *            field will not be null and reports the path the given
	 *            <code>resource</code> was either moved from or moved to
	 *            respectively.
	 * 
	 * @see AbstractIndexManager#SOURCE_RESOURCE_CHANGE
	 * @see AbstractIndexManager#SOURCE_SAVED_STATE
	 * @see AbstractIndexManager#SOURCE_WORKSPACE_SCAN
	 * @see AbstractIndexManager#SOURCE_PRESERVED_RESOURCES_TO_INDEX
	 * 
	 * @see AbstractIndexManager#ACTION_ADD
	 * @see AbstractIndexManager#ACTION_REMOVE
	 * @see AbstractIndexManager#ACTION_ADD_MOVE_FROM
	 * @see AbstractIndexManager#ACTION_REMOVE_MOVE_TO
	 */
	protected abstract void performAction(byte source, byte action, IResource resource, IPath movePath);

	/**
	 * <p>
	 * Gets the working location of the manager. This is where any relevant
	 * state can be persisted.
	 * </p>
	 * 
	 * @return the working location of the manager
	 */
	protected abstract IPath getWorkingLocation();

	/**
	 * <p>
	 * Next time the manager starts up force a full workspace index
	 * </p>
	 */
	private void forceFullReIndexNextStart() {
		IPath reIndexPath = AbstractIndexManager.this.getWorkingLocation().append(RE_PROCESS_FILE_NAME);
		File file = new File(reIndexPath.toOSString());
		try {
			file.createNewFile();
		}
		catch (IOException e) {
			Logger.logException(this.fName + ": Could not create file to tell manager to" + " do a full re-index on next load. " + AbstractIndexManager.LOG_ERROR_INDEX_INVALID, e); //$NON-NLS-1$ //$NON-NLS-2$
		}
	}

	/**
	 * @return <code>true</code> if a full workspace index is needed as
	 *         dictated by a previous call to
	 *         {@link #forceFullReIndexNextStart()}, <code>false</code>
	 *         otherwise
	 */
	private boolean isForcedFullReIndexNeeded() {
		boolean forcedFullReIndexNeeded = false;
		IPath reIndexPath = AbstractIndexManager.this.getWorkingLocation().append(RE_PROCESS_FILE_NAME);
		File file = new File(reIndexPath.toOSString());
		if (file.exists()) {
			forcedFullReIndexNeeded = true;
			file.delete();
		}

		return forcedFullReIndexNeeded;
	}

	/**
	 * <p>
	 * A system {@link Job} used to visit all of the files in the workspace
	 * looking for files to index.
	 * </p>
	 * 
	 * <p>
	 * This should only have to be done once per workspace on the first load,
	 * but if it fails or a SavedState can not be retrieved on a subsequent
	 * workspace load then this will have to be done again.
	 * </p>
	 */
	private class WorkspaceVisitorJob extends Job {
		/**
		 * <p>
		 * Default constructor that sets up this job as a system job
		 * </p>
		 */
		protected WorkspaceVisitorJob() {
			super(NLS.bind(SSECoreMessages.IndexManager_0_Processing_entire_workspace_for_the_first_time, AbstractIndexManager.this.fName));

			this.setUser(false);
			this.setSystem(true);
			this.setPriority(Job.LONG);
		}

		/**
		 * @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor)
		 */
		protected IStatus run(IProgressMonitor monitor) {
			try {
				// update status
				monitor.beginTask(NLS.bind(SSECoreMessages.IndexManager_0_Processing_entire_workspace_for_the_first_time, AbstractIndexManager.this.fName), IProgressMonitor.UNKNOWN);

				// visit the workspace
				WorkspaceVisitor visitor = new WorkspaceVisitor(monitor);
				ResourcesPlugin.getWorkspace().getRoot().accept(visitor, IResource.NONE);

				// process any remaining batched up resources to index
				visitor.processBatchedResourceEvents();
			}
			catch (CoreException e) {
				Logger.logException(AbstractIndexManager.this.fName + ": Failed visiting entire workspace for initial index. " + AbstractIndexManager.LOG_ERROR_INDEX_INVALID, e); //$NON-NLS-1$
			}

			IStatus status;
			if (monitor.isCanceled()) {
				status = Status.CANCEL_STATUS;
			}
			else {
				status = Status.OK_STATUS;
			}

			monitor.done();
			return status;
		}

		/**
		 * <p>
		 * An {@link IResourceProxyVisitor} used to visit all of the files in
		 * the workspace looking for files to add to the index.
		 * </p>
		 * 
		 * <p>
		 * <b>NOTE: </b>After this visitor is used
		 * {@link WorkspaceVisitor#processBatchedResourceEvents() must be
		 * called to flush out the last of the {@link ResourceEvent}s produced
		 * by this visitor.
		 * </p>
		 */
		private class WorkspaceVisitor implements IResourceProxyVisitor {
			/**
			 * {@link IProgressMonitor} used to report status and check for
			 * cancellation
			 */
			private SubMonitor fProgress;

			/**
			 * {@link Map}&lt{@link IResource}, {@link ResourceEvent}&gt
			 * <p>
			 * Map of resources events created and batched up by this visitor.
			 * These events are periodical be sent off to the
			 * {@link ResourceEventProcessingJob} but need to be sent off one
			 * final time after this visitor finishes it work.
			 * </p>
			 * 
			 * @see #processBatchedResourceEvents()
			 */
			private Map fBatchedResourceEvents;

			/**
			 * <p>
			 * Default constructor
			 * </p>
			 * 
			 * @param monitor
			 *            used to report status and allow this visitor to be
			 *            canceled
			 */
			protected WorkspaceVisitor(IProgressMonitor monitor) {
				this.fProgress = SubMonitor.convert(monitor);
				this.fBatchedResourceEvents = new LinkedHashMap(BATCH_UP_AMOUNT);
			}

			/**
			 * <p>
			 * As long as the monitor is not canceled visit each file in the
			 * workspace that should be visited.
			 * </p>
			 * 
			 * @see org.eclipse.core.resources.IResourceProxyVisitor#visit(org.eclipse.core.resources.IResourceProxy)
			 * @see AbstractIndexManager#shouldVisit(String)
			 */
			public boolean visit(IResourceProxy proxy) throws CoreException {
				this.fProgress.subTask(proxy.getName());

				boolean visitChildren = false;

				/*
				 * if not canceled or a hidden resource then process file else
				 * don't visit children
				 */
				if (!this.fProgress.isCanceled()) {
					if (proxy.isDerived()) {
						/*
						 * Do not include derived resources
						 */
						visitChildren = false;
					}
					else if (proxy.requestFullPath().isRoot()) {
						visitChildren = true;
					}
					else if (isResourceToIndex(proxy.getType(), proxy.requestFullPath())) {
						if (proxy.getType() == IResource.FILE) {
							// add the file to be indexed
							IFile file = (IFile) proxy.requestResource();
							if (file.exists()) {
								this.fBatchedResourceEvents.put(file, new ResourceEvent(AbstractIndexManager.SOURCE_WORKSPACE_SCAN, AbstractIndexManager.ACTION_ADD, null));
							}
						}
						visitChildren = true;
					}
				}

				// batch up resource changes before sending them out
				if (this.fBatchedResourceEvents.size() >= BATCH_UP_AMOUNT) {
					this.processBatchedResourceEvents();
				}

				return visitChildren;
			}

			/**
			 * <p>
			 * Sends any batched up resource events created by this visitor to
			 * the {@link ResourceEventProcessingJob}.
			 * <p>
			 * 
			 * <p>
			 * <b>NOTE:</b> This will be called every so often as the visitor
			 * is visiting resources but needs to be called a final time by
			 * the user of this visitor to be sure the final events are sent
			 * off
			 * </p>
			 */
			protected void processBatchedResourceEvents() {
				AbstractIndexManager.this.fResourceEventProcessingJob.addResourceEvents(this.fBatchedResourceEvents);
				this.fBatchedResourceEvents.clear();
			}
		}
	}

	/**
	 * <p>
	 * Used to listen to resource change events in the workspace. These events
	 * are batched up and then passed onto the
	 * {@link ResourceEventProcessingJob}.
	 * </p>
	 */
	private class ResourceChangeListener implements IResourceChangeListener {
		/**
		 * <p>
		 * The number of events currently being processed by this listener.
		 * </p>
		 * <p>
		 * Use the {@link #fEventsBeingProcessedLock} when reading or writing
		 * this field
		 * </p>
		 * 
		 * @see #fEventsBeingProcessedLock
		 */
		private volatile int fEventsBeingProcessed;

		/**
		 * Lock to use when reading or writing {@link #fEventsBeingProcessed}
		 * 
		 * @see #fEventsBeingProcessed
		 */
		private final Object fEventsBeingProcessedLock = new Object();

		/**
		 * <p>
		 * Current state of this listener
		 * </p>
		 * 
		 * @see AbstractIndexManager#STATE_DISABLED
		 * @see AbstractIndexManager#STATE_ENABLED
		 */
		private volatile byte fState;

		/**
		 * <p>
		 * Default constructor
		 * </p>
		 */
		protected ResourceChangeListener() {
			this.fState = STATE_DISABLED;
			this.fEventsBeingProcessed = 0;
		}

		/**
		 * <p>
		 * Start listening for resource change events
		 * </p>
		 */
		protected void start() {
			this.fState = STATE_ENABLED;
			ResourcesPlugin.getWorkspace().addResourceChangeListener(this);
		}

		/**
		 * <p>
		 * Stop listening for resource change events and if already processing
		 * an event then wait for that processing to finish
		 * </p>
		 * 
		 * @throws InterruptedException
		 *             waiting for a current event to finish processing could
		 *             be interrupted
		 */
		protected void stop() throws InterruptedException {
			ResourcesPlugin.getWorkspace().removeResourceChangeListener(this);

			// wait indefinitely for current event to finish processing
			this.waitForCurrentEvent(0);

			this.fState = STATE_DISABLED;
		}

		/**
		 * <p>
		 * Blocks until either the current resource event has been processed
		 * or until the given timeout has passed.
		 * </p>
		 * 
		 * @param timeout
		 *            block until either this timeout elapses (0 means never
		 *            to timeout) or the current resource change event
		 *            finishes being processed
		 * 
		 * @throws InterruptedException
		 *             This can happen when waiting for a lock
		 */
		protected void waitForCurrentEvent(int timeout) throws InterruptedException {
			synchronized (this.fEventsBeingProcessedLock) {
				if (this.fEventsBeingProcessed != 0) {
					this.fEventsBeingProcessedLock.wait(timeout);
				}
			}
		}

		/**
		 * @return <code>true</code> if this listener is currently processing
		 *         any events, <code>false</code> otherwise.
		 */
		protected boolean isProcessingEvents() {
			return this.fEventsBeingProcessed != 0;
		}

		/**
		 * <p>
		 * Process a resource change event. If it is a pre-close or pre-delete
		 * then the {@link ResourceEventProcessingJob} is paused so it does
		 * not try to process resources that are about to be deleted. The
		 * {@link ResourceDeltaVisitor} is used to actually process the event.
		 * </p>
		 * 
		 * @see org.eclipse.core.resources.IResourceChangeListener#resourceChanged(org.eclipse.core.resources.IResourceChangeEvent)
		 * @see ResourceDeltaVisitor
		 */
		public void resourceChanged(IResourceChangeEvent event) {
			try {
				// update the number of events being processed
				synchronized (this.fEventsBeingProcessedLock) {
					++this.fEventsBeingProcessed;
				}

				if (this.fState == STATE_ENABLED) {
					switch (event.getType()) {
						case IResourceChangeEvent.PRE_CLOSE :
						case IResourceChangeEvent.PRE_DELETE : {
							/*
							 * pause the persister job so it does not
							 * interfere
							 */
							AbstractIndexManager.this.fResourceEventProcessingJob.pause();
							break;
						}
						case IResourceChangeEvent.POST_BUILD :
						case IResourceChangeEvent.POST_CHANGE : {
							// post change start up the indexer job and
							// process the delta
							AbstractIndexManager.this.fResourceEventProcessingJob.unPause();

							// only analyze the full (starting at root) delta
							// hierarchy
							IResourceDelta delta = event.getDelta();
							if (delta != null && delta.getFullPath().toString().equals("/")) { //$NON-NLS-1$
								try {
									// use visitor to visit all children
									ResourceDeltaVisitor visitor = new ResourceDeltaVisitor(AbstractIndexManager.SOURCE_RESOURCE_CHANGE);
									delta.accept(visitor, false);

									// process any remaining batched up
									// resources to index
									visitor.processBatchedResourceEvents();
								}
								catch (CoreException e) {
									Logger.logException(AbstractIndexManager.this.fName + ": Failed visiting resource change delta. " + AbstractIndexManager.LOG_ERROR_INDEX_INVALID, e); //$NON-NLS-1$
								}
							}
							break;
						}
					}
				}
				else {
					Logger.log(Logger.ERROR, "A resource change event came in after " + //$NON-NLS-1$
								AbstractIndexManager.this.fName + " shut down. This should never " + //$NON-NLS-1$
								"ever happen, but if it does the index may now be inconsistant."); //$NON-NLS-1$
				}
			}
			finally {
				// no matter how we exit be sure to update the number of
				// events being processed
				synchronized (this.fEventsBeingProcessedLock) {
					--this.fEventsBeingProcessed;

					// if currently not events being processed, then notify
					if (this.fEventsBeingProcessed == 0) {
						this.fEventsBeingProcessedLock.notifyAll();
					}
				}
			}
		}
	}

	/**
	 * <p>
	 * Used to visit {@link IResourceDelta}s from both the
	 * {@link IResourceChangeListener} and from a {@link ISaveParticipant}
	 * given to
	 * {@link AbstractIndexManager#start(IResourceDelta, IProgressMonitor)}.
	 * The resource events are batched into groups of
	 * {@link AbstractIndexManager#BATCH_UP_AMOUNT} before being passed onto
	 * the {@link ResourceEventProcessingJob}.
	 * </p>
	 * 
	 * <p>
	 * <b>NOTE 1: </b> This class is intended for one time use, thus a new
	 * instance should be instantiated each time this visitor is needed to
	 * process a new {@link IResourceDelta}.
	 * </p>
	 * 
	 * <p>
	 * <b>NOTE 2: </b> Be sure to call
	 * {@link ResourceDeltaVisitor#processBatchedResourceEvents()} after using
	 * this visitor to be sure any remaining events get passed onto the
	 * {@link ResourceEventProcessingJob}.
	 * </p>
	 * 
	 * @see ResourceDeltaVisitor#processBatchedResourceEvents()
	 */
	private class ResourceDeltaVisitor implements IResourceDeltaVisitor {
		/** {@link IProgressMonitor} used to report status */
		private SubMonitor fProgress;

		/**
		 * <p>
		 * The source that should be used when sending resource events to the
		 * {@link ResourceEventProcessingJob}.
		 * </p>
		 * 
		 * @see AbstractIndexManager#SOURCE_SAVED_STATE
		 * @see AbstractIndexManager#SOURCE_RESOURCE_CHANGE
		 */
		private byte fSource;

		/**
		 * <p>
		 * Due to the nature of a visitor it has no way of knowing the total
		 * amount of work it has to do but it can start to predict it based on
		 * the number of children of each event it processes and whether it
		 * plans on visiting those children
		 * </p>
		 */
		private int fPredictedWorkRemaining;

		/**
		 * {@link Map}&lt{@link IResource}, {@link ResourceEvent}&gt
		 * <p>
		 * Map of resources events created and batched up by this visitor.
		 * These events are periodical be sent off to the
		 * {@link ResourceEventProcessingJob} but need to be sent off one
		 * final time after this visitor finishes it work.
		 * </p>
		 * 
		 * @see #processBatchedResourceEvents()
		 */
		private Map fBatchedResourceEvents;

		/**
		 * <p>
		 * Creates a visitor that will create resource events based on the
		 * resources it visits and using the given source as the source of the
		 * events.
		 * </p>
		 * 
		 * @param source
		 *            The source of the events that should be used when
		 *            creating resource events from visited resources
		 * 
		 * @see AbstractIndexManager#SOURCE_RESOURCE_CHANGE
		 * @see AbstractIndexManager#SOURCE_SAVED_STATE
		 */
		protected ResourceDeltaVisitor(byte source) {
			this(SubMonitor.convert(null), source);
		}

		/**
		 * <p>
		 * Creates a visitor that will create resource events based on the
		 * resources it visits and using the given source as the source of the
		 * events and report its status to the given progress as best it can
		 * as it visits resources.
		 * </p>
		 * 
		 * <p>
		 * <b>NOTE:</b> While the {@link SubMonitor} is provided to report
		 * status the visitor will not honor any cancellation requests.
		 * </p>
		 * 
		 * @param progress
		 *            Used to report status. This visitor can <b>not</b> be
		 *            canceled
		 * @param source
		 *            The source of the events that should be used when
		 *            creating resource events from visited resources
		 * 
		 * @see AbstractIndexManager#SOURCE_RESOURCE_CHANGE
		 * @see AbstractIndexManager#SOURCE_SAVED_STATE
		 */
		protected ResourceDeltaVisitor(SubMonitor progress, byte source) {
			this.fProgress = progress;
			this.fSource = source;
			this.fBatchedResourceEvents = new LinkedHashMap(BATCH_UP_AMOUNT);
			this.fPredictedWorkRemaining = 1;
		}

		/**
		 * <p>
		 * Transforms each {@link IResourceDelta} into a {@link ResourceEvent}
		 * . Batches up these {@link ResourceEvent}s and then passes them onto
		 * the {@link ResourceEventProcessingJob}.
		 * </p>
		 * 
		 * <p>
		 * <b>NOTE 1: </b> Be sure to call
		 * {@link ResourceDeltaVisitor#processBatchedResourceEvents()} after
		 * using this visitor to be sure any remaining events get passed onto
		 * the {@link ResourceEventProcessingJob}.
		 * </p>
		 * 
		 * @see org.eclipse.core.resources.IResourceDeltaVisitor#visit(org.eclipse.core.resources.IResourceDelta)
		 * @see #processBatchedResourceEvents()
		 */
		public boolean visit(IResourceDelta delta) throws CoreException {
			// report status
			this.fProgress.subTask(NLS.bind(SSECoreMessages.IndexManager_0_resources_to_go_1, new Object[]{"" + fPredictedWorkRemaining, delta.getFullPath().toString()})); //$NON-NLS-1$

			// process delta if resource not hidden
			boolean visitChildren = false;

			/*
			 * if root node always visit its children else ask manager
			 * implementation if resource and its children should be visited
			 */
			if (delta.getResource().isDerived()) { // Do not include derived
													// resources
				visitChildren = false;
			}
			else if (delta.getFullPath().isRoot()) { //$NON-NLS-1$
				visitChildren = true;
			}
			else {
				IResource resource = delta.getResource();

				// check if should index resource or its children
				if (isResourceToIndex(resource.getType(), resource.getFullPath())) {
					if (resource.getType() == IResource.FILE) {

						switch (delta.getKind()) {
							case IResourceDelta.CHANGED : {
								/*
								 * ignore any change that is not a CONTENT,
								 * REPLACED, TYPE, or MOVE_FROM change
								 */
								if (!((delta.getFlags() & IResourceDelta.CONTENT) != 0) && !((delta.getFlags() & IResourceDelta.REPLACED) != 0) && !((delta.getFlags() & IResourceDelta.TYPE) != 0) && !(((delta.getFlags() & IResourceDelta.MOVED_FROM) != 0))) {

									break;
								}
							}
							/*
							 * it is intended that sometimes a change will
							 * fall through to add
							 */
							//$FALL-THROUGH$
							case IResourceDelta.ADDED : {
								if ((delta.getFlags() & IResourceDelta.MOVED_FROM) != 0) {
									// create add move from action
									this.fBatchedResourceEvents.put(resource, new ResourceEvent(this.fSource, AbstractIndexManager.ACTION_ADD_MOVE_FROM, delta.getMovedFromPath()));

								}
								else {
									// create add action
									this.fBatchedResourceEvents.put(resource, new ResourceEvent(this.fSource, AbstractIndexManager.ACTION_ADD, null));
								}

								break;
							}
							case IResourceDelta.REMOVED : {
								if ((delta.getFlags() & IResourceDelta.MOVED_TO) != 0) {
									// create remove move to action
									this.fBatchedResourceEvents.put(resource, new ResourceEvent(this.fSource, AbstractIndexManager.ACTION_REMOVE_MOVE_TO, delta.getMovedToPath()));
								}
								else {
									// create remove action
									this.fBatchedResourceEvents.put(resource, new ResourceEvent(this.fSource, AbstractIndexManager.ACTION_REMOVE, null));
								}
								break;
							}
						}
					}// end is file

					visitChildren = true;
				}
				else {
					visitChildren = false;
				}



				// deal with trying to report progress
				if (visitChildren) {
					this.fPredictedWorkRemaining += delta.getAffectedChildren().length;
				}
				this.fProgress.setWorkRemaining(this.fPredictedWorkRemaining);
				this.fProgress.worked(1);
				--this.fPredictedWorkRemaining;

				// batch up resource changes before sending them out
				if (this.fBatchedResourceEvents.size() >= BATCH_UP_AMOUNT) {
					this.processBatchedResourceEvents();
				}
			}

			return visitChildren;
		}

		/**
		 * <p>
		 * Sends any batched up resource events created by this visitor to the
		 * {@link ResourceEventProcessingJob}.
		 * <p>
		 * 
		 * <p>
		 * <b>NOTE:</b> This will be called every so often as the visitor is
		 * visiting resources but needs to be called a final time by the user
		 * of this visitor to be sure the final events are sent off
		 * </p>
		 */
		protected void processBatchedResourceEvents() {
			AbstractIndexManager.this.fResourceEventProcessingJob.addResourceEvents(this.fBatchedResourceEvents);
			this.fBatchedResourceEvents.clear();
		}
	}

	/**
	 * <p>
	 * Collects {@link ResourceEvent}s from the different sources and then
	 * processes each one by calling
	 * {@link AbstractIndexManager#performAction(byte, byte, IResource, IPath)}
	 * for each {@link ResourceEvent}.
	 * </p>
	 * 
	 * @see AbstractIndexManager#performAction(byte, byte, IResource, IPath)
	 */
	private class ResourceEventProcessingJob extends Job {
		/** Length to delay when scheduling job */
		private static final int DELAY = 500;

		/**
		 * <p>
		 * Name of the file where resource events still to index will be
		 * preserved for the next start up.
		 * </p>
		 */
		private static final String PRESERVED_RESOURCE_EVENTS_TO_PROCESS_FILE_NAME = ".preservedResourceEvents"; //$NON-NLS-1$

		/**
		 * <p>
		 * This needs to be updated if
		 * {@link #preserveReceivedResourceEvents()} ever changes how it
		 * persists resource events so that
		 * {@link #loadPreservedReceivedResourceEvents(SubMonitor)} knows when
		 * opening a file that the format is of the current version and if not
		 * knows it does not know how to read the older version.
		 * </p>
		 * 
		 * @see #preserveReceivedResourceEvents()
		 * @see #loadPreservedReceivedResourceEvents(SubMonitor)
		 */
		private static final long serialVersionUID = 1L;

		/** Whether this job has been paused or not */
		private volatile boolean fIsPaused;

		/**
		 * {@link Map}&lt{@link IResource}, {@link ResourceEvent}&gt
		 * <p>
		 * The list of resources events to be processed
		 * </p>
		 */
		private Map fResourceEvents;

		/** Lock used when accessing {@link #fBatchedResourceEvents} */
		private final Object fResourceEventsLock = new Object();

		/**
		 * Locked used for allowing other jobs to wait on this job. This job
		 * will notify those waiting on this lock whenever it is done
		 * processing all resource events it currently knows about.
		 * 
		 * @see #waitForConsistant(int)
		 */
		private final Object fToNotifyLock = new Object();

		/**
		 * <p>
		 * Sets up this job as a long running system job
		 * </p>
		 */
		protected ResourceEventProcessingJob() {
			super(NLS.bind(SSECoreMessages.IndexManager_0_Processing_resource_events, AbstractIndexManager.this.fName));

			// set this up as a long running system job
			this.setUser(false);
			this.setSystem(true);
			this.setPriority(Job.LONG);

			this.fIsPaused = false;
			this.fResourceEvents = new LinkedHashMap();
		}

		/**
		 * <p>
		 * Loads any preserved {@link ResourceEvent}s from the last time
		 * {@link #stop(boolean)} was invoked and schedules the job to be run
		 * </p>
		 * 
		 * <p>
		 * <b>NOTE: </b>Should be used instead of of calling
		 * {@link Job#schedule()} because this method also takes care of
		 * loading preserved state.
		 * </p>
		 * 
		 * @param loadPreservedResourceEvents
		 *            <code>true</code> if should load any preserved
		 *            {@link ResourceEvent}s from the last time
		 *            {@link #stop(boolean)} was invoked
		 * 
		 * @return <code>true</code> if either
		 *         <code>loadPreservedResourceEvents</code> was false or there
		 *         was success in loading the preserved {@link ResourceEvent}
		 *         s. If <code>false</code> then some {@link ResourceEvent}s
		 *         may have been loosed and to insure index consistency with
		 *         the workspace a full workspace re-index is needed.
		 * 
		 * @see #stop(boolean)
		 */
		protected synchronized boolean start(boolean loadPreservedResourceEvents, SubMonitor progress) {

			boolean successLoadingPreserved = true;

			// attempt to load preserved resource events if requested
			if (!loadPreservedResourceEvents) {
				File preservedResourceEventsFile = this.getPreservedResourceEventsFile();
				preservedResourceEventsFile.delete();
			}
			else {
				successLoadingPreserved = this.loadPreservedReceivedResourceEvents(progress);
			}

			// start up the job
			this.schedule();

			return successLoadingPreserved;
		}

		/**
		 * <p>
		 * Immediately stops the job and preserves any {@link ResourceEvent}s
		 * in the queue to be processed by not yet processed if requested
		 * </p>
		 * 
		 * @param preserveResourceEvents
		 *            <code>true</code> to preserve any {@link ResourceEvent}s
		 *            in the queue yet to be processed, <code>false</code>
		 *            otherwise
		 * 
		 * @return <code>true</code> if either
		 *         <code>preserveResourceEvents</code> is <code>false</code>
		 *         or if there was success in preserving the
		 *         {@link ResourceEvent}s yet to be processed. If
		 *         <code>false</code> then the preserving failed and a full
		 *         workspace re-processing is needed the next time the manager
		 *         is started
		 * 
		 * @throws InterruptedException
		 *             This could happen when trying to cancel or join the job
		 *             in progress, but it really shouldn't
		 * 
		 * @see #start(boolean, SubMonitor)
		 */
		protected synchronized boolean stop(boolean preserveResourceEvents) throws InterruptedException {
			// this will not block indefinitely because it is known this job
			// can be canceled
			this.cancel();
			this.join();

			// preserve if requested, else be sure no preserve file is left
			// over for next start
			boolean success = true;
			if (preserveResourceEvents && this.hasResourceEventsToProcess()) {
				success = this.preserveReceivedResourceEvents();
			}
			else {
				this.getPreservedResourceEventsFile().delete();
			}

			return success;
		}

		/**
		 * @return <code>true</code> if job is currently running or paused
		 * 
		 * @see #pause()
		 * @see #unPause()
		 */
		protected synchronized boolean isProcessing() {
			return this.getState() != Job.NONE || this.fIsPaused;
		}

		/**
		 * <p>
		 * Un-pauses this job. This has no effect if the job is already
		 * running.
		 * </p>
		 * <p>
		 * This should be used in place of {@link Job#schedule()} to reset
		 * state caused by calling {@link #pause()}
		 * </p>
		 * 
		 * @see #pause()
		 */
		protected synchronized void unPause() {
			this.fIsPaused = false;

			// get the job running again depending on its current state
			if (this.getState() == Job.SLEEPING) {
				this.wakeUp(DELAY);
			}
			else {
				this.schedule(DELAY);
			}
		}

		/**
		 * <p>
		 * Pauses this job, even if it is running
		 * </p>
		 * <p>
		 * This should be used in place of {@link Job#sleep()} because
		 * {@link Job#sleep()} will not pause a job that is already running
		 * but calling this will pause this job even if it is running.
		 * {@link #unPause()} must be used to start this job again
		 * </p>
		 * 
		 * @see #unPause()
		 */
		protected synchronized void pause() {
			// if job is already running this will force it to pause
			this.fIsPaused = true;

			// this only works if the job is not running
			this.sleep();
		}

		/**
		 * <p>
		 * Adds a batch of {@link ResourceEvent}s to the queue of events to be
		 * processed. Will also un-pause the job if it is not already running
		 * </p>
		 * 
		 * @param resourceEvents
		 *            {@link Map}&lt{@link IResource}, {@link ResourceEvent}
		 *            &gt A batch of {@link ResourceEvent}s to be processed
		 * 
		 * @see #addResourceEvent(ResourceEvent)
		 * @see #unPause()
		 */
		protected void addResourceEvents(Map resourceEvents) {
			Iterator iter = resourceEvents.keySet().iterator();
			while (iter.hasNext()) {
				IResource resource = (IResource) iter.next();
				ResourceEvent resourceEvent = (ResourceEvent) resourceEvents.get(resource);
				addResourceEvent(resource, resourceEvent);
			}

			// un-pause the processor if it is not already running
			if (!isProcessing()) {
				this.unPause();
			}
		}

		/**
		 * <p>
		 * Gets the number of {@link ResourceEvent}s left to process by this
		 * job. This count is only valid for the exact moment it is returned
		 * because events are constantly being added and removed from the
		 * queue of events to process
		 * </p>
		 * 
		 * @return the number of {@link ResourceEvent}s left to process
		 */
		protected int getNumResourceEventsToProcess() {
			return this.fResourceEvents.size();
		}

		/**
		 * <p>
		 * Blocks until either the given timeout elapses (0 means never to
		 * timeout), or there are currently no {@link ResourceEvent}s to
		 * process or being processed by this job
		 * </p>
		 * 
		 * @param timeout
		 *            block until either this timeout elapses (0 means never
		 *            to timeout) or there are currently no
		 *            {@link ResourceEvent}s to process or being processed by
		 *            this job
		 * 
		 * @throws InterruptedException
		 *             This can happen when waiting for a lock
		 */
		protected void waitForConsistant(int timeout) throws InterruptedException {
			if (hasResourceEventsToProcess() || isProcessing()) {
				synchronized (this.fToNotifyLock) {
					this.fToNotifyLock.wait(timeout);
				}
			}
		}

		/**
		 * @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor)
		 */
		protected IStatus run(IProgressMonitor monitor) {
			try {
				// report status
				SubMonitor progress = SubMonitor.convert(monitor);

				while (!this.fIsPaused && !monitor.isCanceled() && this.hasResourceEventsToProcess()) {
					// report status
					progress.setTaskName(NLS.bind(SSECoreMessages.IndexManager_0_Indexing_1_Files, new Object[]{AbstractIndexManager.this.fName, "" + getNumResourceEventsToProcess()})); //$NON-NLS-1$
					progress.setWorkRemaining(getNumResourceEventsToProcess());

					// get the next event to process
					ResourceEvent resourceEvent = null;
					IResource resource = null;
					synchronized (this.fResourceEventsLock) {
						resource = (IResource) this.fResourceEvents.keySet().iterator().next();
						resourceEvent = (ResourceEvent) this.fResourceEvents.remove(resource);
					}

					// report status
					monitor.subTask(resource.getName());

					// perform action safely
					final byte source = resourceEvent.fSource;
					final byte action = resourceEvent.fAction;
					final IResource finResource = resource;
					final IPath movePath = resourceEvent.fMovePath;
					SafeRunner.run(new ISafeRunnable() {
						public void run() throws Exception {
							AbstractIndexManager.this.performAction(source, action, finResource, movePath);
						}

						public void handleException(Throwable e) {
							Logger.logException("Error while performing an update to the index. " + //$NON-NLS-1$
										AbstractIndexManager.LOG_ERROR_INDEX_INVALID, e);
						}
					});

					// report progress
					progress.worked(1);

					// avoid dead locks
					Job.getJobManager().currentJob().yieldRule(monitor);
				}

				// done work
				monitor.done();
			}
			finally {
				// want to be sure we notify no matter how we exit
				this.notifyIfConsistant();
			}

			/*
			 * if canceled then return CANCEL, else if done or paused return
			 * OK
			 */
			IStatus exitStatus;
			if (monitor.isCanceled()) {
				exitStatus = Status.CANCEL_STATUS;
			}
			else {
				exitStatus = Status.OK_STATUS;
			}

			return exitStatus;
		}

		/**
		 * <p>
		 * If resource not already scheduled to be processed, schedule it else
		 * if resource already scheduled to be processed, update the action
		 * only if the new action comes from a resource change event.
		 * </p>
		 * 
		 * <p>
		 * Ignore other sources for updating existing resource events because
		 * all other sources are "start-up" type sources and thus only
		 * {@link ResourceEvent} with a source of a resource change event
		 * trump existing events.
		 * </p>
		 * 
		 * @param resourceEvent
		 *            {@link ResourceEvent} to be processed by this job
		 */
		private void addResourceEvent(IResource resource, ResourceEvent resourceEvent) {

			synchronized (this.fResourceEventsLock) {
				/*
				 * if resource not already scheduled to be processed, schedule
				 * it else if resource already scheduled to be processed,
				 * update the action only if the new action comes from a
				 * resource change event
				 */
				if (!this.fResourceEvents.containsKey(resource)) {
					this.fResourceEvents.put(resource, resourceEvent);
				}
				else if (resourceEvent.fSource == AbstractIndexManager.SOURCE_RESOURCE_CHANGE) {
					((ResourceEvent) this.fResourceEvents.get(resource)).fAction = resourceEvent.fAction;
				}
				else {
					// Purposely ignoring all other resource events
				}
			}
		}

		/**
		 * @return <code>true</code> if there are any resources to process,
		 *         <code>false</code> otherwise
		 */
		private boolean hasResourceEventsToProcess() {
			return !this.fResourceEvents.isEmpty();
		}

		/**
		 * <p>
		 * Preserves all of the resource events that have been received by
		 * this manager but not yet processed
		 * </p>
		 * 
		 * <p>
		 * If this operation was successful then the next time the manager
		 * starts it can load these events and process them. If it was not
		 * successful then a full re-processing of the entire workspace will
		 * need to take place to be sure the index is consistent.
		 * </p>
		 * 
		 * <p>
		 * <b>NOTE:</b> If this method changes how it preserves these events
		 * then {@link #serialVersionUID} will need to be incremented so that
		 * the manager does not attempt to load an old version of the file
		 * that may exist in a users workspace. Also
		 * {@link #loadPreservedReceivedResourceEvents(SubMonitor)} will have
		 * to be updated to load the new file structure.
		 * </p>
		 * 
		 * @return <code>true</code> if successfully preserved the resource
		 *         events that have been received by not yet processed,
		 *         <code>false</code> otherwise
		 * 
		 * @see #serialVersionUID
		 * @see #loadPreservedReceivedResourceEvents(SubMonitor)
		 */
		private boolean preserveReceivedResourceEvents() {
			File preservedResourceEventsFile = this.getPreservedResourceEventsFile();
			boolean success = true;

			synchronized (this.fResourceEventsLock) {
				DataOutputStream dos = null;
				try {
					// if file already exists delete it
					if (preservedResourceEventsFile.exists()) {
						preservedResourceEventsFile.delete();
						preservedResourceEventsFile.createNewFile();
					}

					// create output objects
					FileOutputStream fos = new FileOutputStream(preservedResourceEventsFile);
					BufferedOutputStream bos = new BufferedOutputStream(fos);
					dos = new DataOutputStream(bos);

					// write serial version
					dos.writeLong(serialVersionUID);

					// write size
					dos.writeInt(this.getNumResourceEventsToProcess());

					// write out all the information needed to restore the
					// resource events to process
					Iterator iter = this.fResourceEvents.keySet().iterator();
					while (iter.hasNext()) {
						IResource resource = (IResource) iter.next();
						ResourceEvent resourceEvent = (ResourceEvent) this.fResourceEvents.get(resource);

						if (resourceEvent.fSource != AbstractIndexManager.SOURCE_WORKSPACE_SCAN) {
							// write out information
							dos.writeByte(resourceEvent.fAction);
							dos.writeByte(resource.getType());
							byte[] pathBytes = resource.getFullPath().toString().getBytes(ENCODING_UTF16);
							dos.write(pathBytes);
							dos.writeByte('\0');
							if (resourceEvent.fMovePath != null) {
								dos.writeBytes(resourceEvent.fMovePath.toPortableString());
							}
							dos.writeByte('\0');
						}
					}

					this.fResourceEvents.clear();

					dos.flush();
				}
				catch (FileNotFoundException e) {
					Logger.logException(AbstractIndexManager.this.fName + ": Exception while opening file to preserve resources to index.", //$NON-NLS-1$
								e);
					success = false;
				}
				catch (IOException e) {
					Logger.logException(AbstractIndexManager.this.fName + ": Exception while writing to file to preserve resources to index.", //$NON-NLS-1$
								e);
					success = false;
				}
				finally {
					// be sure to close output
					if (dos != null) {
						try {
							dos.close();
						}
						catch (IOException e) {
							Logger.logException(AbstractIndexManager.this.fName + ": Exception while closing file with preserved resources to index.", //$NON-NLS-1$
										e);
							success = false;
						}
					}
				}

				// if failed, for consistency must do a full re-process next
				// workspace load
				if (!success) {
					preservedResourceEventsFile.delete();
				}
			}

			return success;
		}

		/**
		 * <p>
		 * Loads the received resource events that were preserved during the
		 * manager's last shut down so they can be processed now
		 * </p>
		 * 
		 * <p>
		 * If this operation is not successful then a full re-processing of
		 * the entire workspace is needed to be sure the index is consistent.
		 * </p>
		 * 
		 * @param progress
		 *            used to report status of loading the preserved received
		 *            resource events
		 * @return <code>true</code> if the loading of the preserved received
		 *         resource events was successful, <code>false</code>
		 *         otherwise.
		 * 
		 * @see #serialVersionUID
		 * @see #preserveReceivedResourceEvents()
		 */
		private boolean loadPreservedReceivedResourceEvents(SubMonitor progress) {
			progress.subTask(SSECoreMessages.IndexManager_processing_deferred_resource_changes);

			boolean success = true;
			File preservedResourceEventsFile = this.getPreservedResourceEventsFile();

			if (preservedResourceEventsFile.exists()) {
				Map preservedResourceEvents = null;

				DataInputStream dis = null;
				try {
					FileInputStream fis = new FileInputStream(preservedResourceEventsFile);
					BufferedInputStream bis = new BufferedInputStream(fis);
					dis = new DataInputStream(bis);

					// check serial version first
					long preservedSerialVersionUID = dis.readLong();
					if (preservedSerialVersionUID == serialVersionUID) {

						// read each record
						int numberOfRecords = dis.readInt();
						preservedResourceEvents = new LinkedHashMap(numberOfRecords);
						progress.setWorkRemaining(numberOfRecords);
						for (int i = 0; i < numberOfRecords; ++i) {
							// action is first byte
							byte action = dis.readByte();

							// file type is the next byte
							byte fileType = dis.readByte();

							// resource location are the next bytes
							ByteArrayOutputStream resourceLocationStream = new ByteArrayOutputStream();
							byte b = dis.readByte();
							while (b != '\0') {
								resourceLocationStream.write(b);
								b = dis.readByte();
							}

							// move path are the next bytes
							ByteArrayOutputStream movePathBOS = new ByteArrayOutputStream();
							b = dis.readByte();
							while (b != '\0') {
								movePathBOS.write(b);
								b = dis.readByte();
							}

							// get the resource
							IResource resource = null;
							IPath resourcePath = new Path(new String(resourceLocationStream.toByteArray(), ENCODING_UTF16));
							if (!resourcePath.isRoot() && resourcePath.segmentCount() > 1) {
								if (fileType == IResource.FILE) {
									resource = ResourcesPlugin.getWorkspace().getRoot().getFile(resourcePath);
								}
								else {
									resource = ResourcesPlugin.getWorkspace().getRoot().getFolder(resourcePath);
								}
							}
							else {
								Logger.log(Logger.WARNING, "The AbstractIndexManager " + AbstractIndexManager.this.fName + " attempted to load an invlaid preserved resource event:\n" + "(" + resourcePath + ")");
							}

							// get the move path
							IPath movePath = null;
							if (movePathBOS.size() != 0) {
								movePath = new Path(new String(movePathBOS.toByteArray(), ENCODING_UTF16));
							}

							// add the object to the list of of preserved
							// resources
							preservedResourceEvents.put(resource, new ResourceEvent(AbstractIndexManager.SOURCE_PRESERVED_RESOURCES_TO_INDEX, action, movePath));

							progress.worked(1);
						}
					}
					else {
						success = false;
					}
				}
				catch (FileNotFoundException e) {
					Logger.logException(AbstractIndexManager.this.fName + ": Exception while opening file to read preserved resources to index. Index manager will recover by re-indexing workspace.", //$NON-NLS-1$
								e);
					success = false;
				}
				catch (IOException e) {
					Logger.logException(AbstractIndexManager.this.fName + ": Exception while reading from file of preserved resources to index. Index manager will recover by re-indexing workspace.", //$NON-NLS-1$
								e);
					success = false;
				}
				catch (Exception e) {
					// Purposely catching all exceptions here so that index
					// manager can recover gracefully
					Logger.logException(AbstractIndexManager.this.fName + ": Unexpected exception while reading from file of preserved resources to index. Index manager will recover by re-indexing workspace.", //$NON-NLS-1$
								e);
					success = false;
				}
				finally {
					if (dis != null) {
						try {
							dis.close();
						}
						catch (IOException e) {
							Logger.logException(AbstractIndexManager.this.fName + ": Exception while closing file of preserved resources" + //$NON-NLS-1$
										" to index that was just read.  This should have no" + //$NON-NLS-1$
										" effect on the consistency of the index.", //$NON-NLS-1$
										e);
						}
					}
				}

				// if success loading preserved then add to master list
				if (success && preservedResourceEvents != null) {
					synchronized (this.fResourceEventsLock) {
						Iterator iter = preservedResourceEvents.keySet().iterator();
						while (iter.hasNext()) {
							IResource resource = (IResource) iter.next();
							ResourceEvent event = (ResourceEvent) preservedResourceEvents.get(resource);
							this.fResourceEvents.put(resource, event);
						}
					}
				}
				else {
					// failed reading file, so delete it
					preservedResourceEventsFile.delete();
				}
			}

			progress.done();
			return success;
		}

		/**
		 * @return {@link File} that contains any resource events received but
		 *         not processed by this manager the last time it shutdown.
		 *         This file may or may not actually exist.
		 * 
		 * @see #preserveReceivedResourceEvents()
		 * @see #loadPreservedReceivedResourceEvents(SubMonitor)
		 */
		private File getPreservedResourceEventsFile() {
			IPath preservedResourcesToIndexPath = AbstractIndexManager.this.getWorkingLocation().append(PRESERVED_RESOURCE_EVENTS_TO_PROCESS_FILE_NAME);
			return new File(preservedResourcesToIndexPath.toOSString());
		}

		/**
		 * <p>
		 * If all resource events have been processed
		 */
		private void notifyIfConsistant() {
			if (!this.hasResourceEventsToProcess()) {
				synchronized (this.fToNotifyLock) {
					this.fToNotifyLock.notifyAll();
				}
			}
		}
	}

	/**
	 * <p>
	 * Represents a resource that was discovered by this manager. Contains all
	 * the information this manager and the index needs to know about this
	 * resource. Such has how the manager was notified about this resource and
	 * the type of action occurring on the resource.
	 * </p>
	 */
	private static class ResourceEvent {
		/**
		 * <p>
		 * The source of this resource event
		 * </p>
		 * 
		 * @see AbstractIndexManager#SOURCE_RESOURCE_CHANGE
		 * @see AbstractIndexManager#SOURCE_SAVED_STATE
		 * @see AbstractIndexManager#SOURCE_WORKSPACE_SCAN
		 * @see AbstractIndexManager#SOURCE_PRESERVED_RESOURCES_TO_INDEX
		 */
		protected byte fSource;

		/**
		 * <p>
		 * The action that the index should take with this resource
		 * </p>
		 * 
		 * @see AbstractIndexManager#ACTION_ADD
		 * @see AbstractIndexManager#ACTION_REMOVE
		 * @see AbstractIndexManager#ACTION_ADD_MOVE_FROM
		 * @see AbstractIndexManager#ACTION_REMOVE_MOVE_TO
		 */
		protected byte fAction;

		/**
		 * 
		 * <p>
		 * If the {@link #fAction} is
		 * {@link AbstractIndexManager#ACTION_ADD_MOVE_FROM} or
		 * {@link AbstractIndexManager#ACTION_REMOVE_MOVE_TO} then this field
		 * will have the path the resource was moved from or moved to. Else
		 * this field will be <code>null</code>
		 * </p>
		 * 
		 * <p>
		 * <b>NOTE: </b>Maybe <code>null</code>.
		 * </p>
		 * 
		 * @see AbstractIndexManager#ACTION_ADD_MOVE_FROM
		 * @see AbstractIndexManager#ACTION_REMOVE_MOVE_TO
		 */
		protected IPath fMovePath;

		/**
		 * <p>
		 * Creates a resource event that the index needs to react to in some
		 * way
		 * </p>
		 * 
		 * @param source
		 *            source that the manager used to learn of this resource
		 * @param action
		 *            action the index should take on this resource
		 * @param resource
		 *            resource that the index should know about
		 * @param movePath
		 *            if action is
		 *            {@link AbstractIndexManager#ACTION_ADD_MOVE_FROM} or
		 *            {@link AbstractIndexManager#ACTION_REMOVE_MOVE_TO} then
		 *            this should be the path the resource was moved from or
		 *            moved to respectively, else should be <code>null</code>
		 * 
		 * @see AbstractIndexManager#SOURCE_RESOURCE_CHANGE
		 * @see AbstractIndexManager#SOURCE_SAVED_STATE
		 * @see AbstractIndexManager#SOURCE_WORKSPACE_SCAN
		 * @see AbstractIndexManager#SOURCE_PRESERVED_RESOURCES_TO_INDEX
		 * 
		 * @see AbstractIndexManager#ACTION_ADD
		 * @see AbstractIndexManager#ACTION_REMOVE
		 * @see AbstractIndexManager#ACTION_ADD_MOVE_FROM
		 * @see AbstractIndexManager#ACTION_REMOVE_MOVE_TO
		 */
		protected ResourceEvent(byte source, byte action, IPath movePath) {
			this.fSource = source;
			this.fAction = action;
			this.fMovePath = movePath;
		}
	}
}