/*******************************************************************************
 * Copyright (c) 2005 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.jem.internal.beaninfo.core;

import java.io.*;
import java.util.*;
import java.util.logging.Level;

import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.emf.common.notify.*;
import org.eclipse.emf.common.notify.impl.AdapterImpl;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.change.ChangeDescription;
import org.eclipse.emf.ecore.change.impl.EObjectToChangesMapEntryImpl;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.ecore.xmi.XMLResource;
import org.eclipse.jdt.core.*;

import org.eclipse.jem.internal.beaninfo.adapters.*;
import org.eclipse.jem.internal.java.beaninfo.IIntrospectionAdapter;
import org.eclipse.jem.java.JavaClass;
import org.eclipse.jem.util.emf.workbench.ProjectResourceSet;
import org.eclipse.jem.util.logger.proxy.Logger;
import org.eclipse.jem.util.plugin.JEMUtilPlugin;
import org.eclipse.jem.util.plugin.JEMUtilPlugin.CleanResourceChangeListener;

/**
 * Controller of the BeanInfo cache. There is one per workspace (it is a static).
 * 
 * The cache is stored on a per IPackageFragmentRoot basis. Each package fragment root will be:
 * 
 * <pre>
 * 
 *  root{999}/classname.xmi
 *  
 * </pre>
 * 
 * "root{999}" will be a unigue name (root appended with a number}, one for each package fragment root. The "classname.xmi" will be the BeanInfo cache
 * for a class in the root. A root can't have more than one class with the same name, so there shouldn't be any collisions.
 * <p>
 * Now roots can either be in a project, or they can be an external jar (which can be shared between projects).
 * <p>
 * Now all roots for a project will be stored in the project's working location
 * {@link org.eclipse.core.resources.IProject#getWorkingLocation(java.lang.String)}under the ".cache" directory. It will be this format in each
 * project location (under the org.eclipse.jem.beaninfo directory):
 * 
 * <pre>
 * 
 *  .index
 *  root{999}/...
 *  
 * </pre>
 * 
 * The ".index" file will be stored/loaded through an ObjectStream. It will be a {@link BeanInfoCacheController.Index}. It is the index to all of the
 * root's in the directory.
 * <p>
 * All of the external jar roots will be stored in the org.eclipse.jem.beaninfo plugin's state location
 * {@link org.eclipse.core.runtime.Platform#getStateLocation(org.osgi.framework.Bundle)}under the ".cache" directory. The format of this directory
 * will be the same as for each project. And the roots will be for each unique shared external jar (such as the differnt jre's rt.jars).
 * <p>
 * Note: There are so many places where synchronization is needed, so it is decided to synchronize only on BeanInfoCacheController.INSTANCE. It would
 * be too easy to get a dead-lock because the order of synchronizations can't be easily controlled. Since each piece of sync control is very short
 * (except for save of the indices, but that is ok because we don't want them changing while saving) it shouldn't block a lot. There is one place we
 * violate this and that is we do a sync on ClassEntry instance when working with the pending. This is necessary because we don't want the cache write
 * job to hold up everything while writing, so we sync on the entry being written instead. There we must be very careful that we never to
 * BeanInfoCacheControler.INSTANCE sync and then a ClassEntry sync because we could deadlock. The CE access under the covers may do a CE sync and then
 * a BeanInfoCacheController.INSTANCE sync.
 * 
 * @since 1.1.0
 */
public class BeanInfoCacheController {

	/**
	 * Singleton cache controller.
	 * 
	 * @since 1.1.0
	 */
	public static final BeanInfoCacheController INSTANCE = new BeanInfoCacheController();

	private BeanInfoCacheController() {
		// Start up save participent. This only is used for saving indexes and shutdown. Currently the saved state delta
		// is of no interest. If a project is deleted while we were not up, then the project index would be gone, so
		// our data will automatically be gone for the project. 
		// If a class was deleted while the project's beaninfo was not active, the cache will still contain it. If the class ever came back it
		// would be stale and so recreated. If it never comes back, until a clean is done, it would just hang around.
		// The problem with delete is it is hard to determine that the file is actually a class of interest. The javamodel
		// handles that for us but we won't have a javamodel to handle this on start up to tell us the file was a class of interest. So
		// we'll take the hit of possible cache for non-existant classes. A clean will take care of this.
		saveParticipant = new SaveParticipant();
		try {
			ResourcesPlugin.getWorkspace().addSaveParticipant(BeaninfoPlugin.getPlugin(), saveParticipant);
		} catch (CoreException e) {
			BeaninfoPlugin.getPlugin().getLogger().log(e.getStatus());
		}
		
		// Create a cleanup listener to handle clean requests and project deletes. We need to know about project deletes while
		// active because we may have a project index in memory and that needs to be thrown away.
		JEMUtilPlugin.addCleanResourceChangeListener(new CleanResourceChangeListener() {
		
			protected void cleanProject(IProject project) {
				// Get rid of the project index and the data for the project.
				synchronized (BeanInfoCacheController.this) {
					try {
						Index projectIndex = (Index) project.getSessionProperty(PROJECT_INDEX_KEY);
						if (projectIndex != null) {
							project.setSessionProperty(PROJECT_INDEX_KEY, null);
							projectIndex.markDead();
							cleanDirectory(getCacheDir(project).toFile(), true);
						}
						BeaninfoNature nature = BeaninfoPlugin.getPlugin().getNature(project);
						if (nature != null) {
							nature.projectCleaned();
							BeaninfoAdapterFactory adapterFactory = (BeaninfoAdapterFactory) EcoreUtil.getAdapterFactory(nature.getResourceSet().getAdapterFactories(), IIntrospectionAdapter.ADAPTER_KEY);
							if (adapterFactory != null) {
								adapterFactory.markAllStale(true);	// Also clear the overrides.
							}
						}						
					} catch (CoreException e) {
						// Shouldn't occur. 
					}
				}
			}
			
			protected void cleanAll() {
				synchronized(BeanInfoCacheController.this) {
					// Get MAIN_INDEX, mark it dead, and then delete everything under it.
					if (MAIN_INDEX != null) {
						MAIN_INDEX.markDead();
						MAIN_INDEX = null;
						cleanDirectory(getCacheDir(null).toFile(), true);
					}
				}
				super.cleanAll();
			}
			
			public void resourceChanged(IResourceChangeEvent event) {
				// We don't need to handle PRE_CLOSE because SaveParticipent project save will handle closing.
				switch (event.getType()) {
					case IResourceChangeEvent.PRE_DELETE:
						// Don't need to clear the cache directory because Eclipse will get rid of it.
						synchronized (BeanInfoCacheController.this) {
							try {
								Index projectIndex = (Index) event.getResource().getSessionProperty(PROJECT_INDEX_KEY);
								if (projectIndex != null) {
									// No need to remove from the project because the project is going away and will clean itself up.
									projectIndex.markDead();
								}
							} catch (CoreException e) {
								// Shouldn't occur.
							}
						}
						// Flow into PRE_CLOSE to release the nature.
					case IResourceChangeEvent.PRE_CLOSE:
						// About to close or delete, so release the nature, if any.
						IProject project = (IProject) event.getResource();
						BeaninfoNature nature = BeaninfoPlugin.getPlugin().getNature(project);
						if (nature != null) {
							nature.cleanup(false, true);
						}
						break;
					default:
						super.resourceChanged(event);
						break;
				}
			}
		
		}, IResourceChangeEvent.PRE_DELETE | IResourceChangeEvent.PRE_CLOSE);
	}

	protected SaveParticipant saveParticipant;

	/**
	 * An index structure for the Main and Project indexes. Access to the index contents and methods should synchronize on the index itself.
	 * <p>
	 * Getting to the index instance should only be through the <code>getMainIndex()</code> and <code>getProjectIndex(IProject)</code> accessors
	 * so that synchronization and serialization is controlled.
	 * 
	 * @since 1.1.0
	 */
	protected static class Index implements Serializable {

		private static final long serialVersionUID = 1106864425567L;

		/*
		 * Is this a dirty index, i.e. it has been changed and needs to be saved.
		 */
		transient private boolean dirty;

		private static final int DEAD = -1;	// Used in highRootNumber to indicate the index is dead.
		/**
		 * The highest root number used. It is incremented everytime one is needed. It doesn't ever decrease to recover removed roots.
		 * 
		 * @since 1.1.0
		 */
		public int highRootNumber;

		/**
		 * Map of root names to the root Index. The key is a {@link IPath}. The path will be relative to the workspace if a project root, or an
		 * absolute local path to the archive if it is an external archive. It is the IPath to package fragment root (either a folder or a jar file).
		 * <p>
		 * The value will be a {@link BeanInfoCacheController.RootIndex}. This is the index for the contents of that root.
		 * 
		 * @since 1.1.0
		 */
		transient public Map rootToRootIndex;

		/**
		 * @param dirty
		 *            The dirty to set.
		 * 
		 * @since 1.1.0
		 */
		public void setDirty(boolean dirty) {
			synchronized (BeanInfoCacheController.INSTANCE) {
				this.dirty = dirty;
			}
		}

		/**
		 * @return Returns the dirty.
		 * 
		 * @since 1.1.0
		 */
		public boolean isDirty() {
			synchronized (BeanInfoCacheController.INSTANCE) {
				return dirty;
			}
		}
		
		/**
		 * Answer if this index is dead. It is dead if a clean has occurred. This is needed because there could be some ClassEntry's still
		 * around (such as in the pending write queue) that are for cleaned roots. This is used to test if it has been cleaned.
		 * @return
		 * 
		 * @since 1.1.0
		 */
		public boolean isDead() {
			return highRootNumber == DEAD;
		}
		
		/**
		 * Mark the index as dead.
		 * 
		 * 
		 * @since 1.1.0
		 */
		void markDead() {
			highRootNumber = DEAD;
		}

		private void writeObject(ObjectOutputStream os) throws IOException {
			os.defaultWriteObject();
			// Now write out the root to root index map. We are not serializing the Map directly using normal Map serialization because
			// the key of the map is an IPath (which is a Path under the covers) and Path is not serializable.
			os.writeInt(rootToRootIndex.size());
			for (Iterator mapItr = rootToRootIndex.entrySet().iterator(); mapItr.hasNext();) {
				Map.Entry entry = (Map.Entry) mapItr.next();
				os.writeUTF(((IPath) entry.getKey()).toString());
				os.writeObject(entry.getValue());
			}
		}

		private void readObject(ObjectInputStream is) throws IOException, ClassNotFoundException {
			is.defaultReadObject();
			int size = is.readInt();
			rootToRootIndex = new HashMap(size < 100 ? 100 : size);
			while (size-- > 0) {
				rootToRootIndex.put(new Path(is.readUTF()), is.readObject());
			}
		}
	}

	/**
	 * An index for a root. It has an entry for each class in this root. The class cache entry describes the cache, whether it is stale, what the
	 * current mod stamp is, etc.
	 * 
	 * @since 1.1.0
	 */
	public static abstract class RootIndex implements Serializable {

		private static final long serialVersionUID = 1106868674101L;

		transient private IPath cachePath; // Absolute local filesystem IPath to the root cache directory. Computed at runtime because it may change
										   // if workspace relocated.

		protected Map classNameToClassEntry; // Map of class names to class entries.

		private String rootName; // Name of the root directory in the cache (e.g. "root1").

		protected Index index; // Index containing this root index.

		protected RootIndex() {
		}

		public RootIndex(String rootName, Index index) {
			this.rootName = rootName;
			classNameToClassEntry = new HashMap(100); // When created brand new, put in a map. Otherwise object stream will create the map.
			this.index = index;
		}
		
		/**
		 * Get the index that points to this root.
		 * @return
		 * 
		 * @since 1.1.0
		 */
		Index getIndex() {
			return index;
		}

		/**
		 * Return the root directory name
		 * 
		 * @return rootname
		 * 
		 * @since 1.1.0
		 */
		public String getRootName() {
			return rootName;
		}

		/**
		 * Set this RootIndex (and the containing Index) as being dirty and in need of saving.
		 * 
		 * 
		 * @since 1.1.0
		 */
		public void setDirty() {
			index.setDirty(true);
		}

		/*
		 * Setup for index. It will initialize the path. Once set it won't set it again. This will be called repeatedly by the cache controller
		 * because there is no way to know if it was lazily created or was brought in from file. When brought in from file the path is not set because
		 * it should be relocatable and we don't want absolute paths out on the disk caches, and we don't want to waste time creating the path at load
		 * time because it may not be needed for a while. So it will be lazily created. <p> If the project is set, then the path will be relative to
		 * the project's working location. If project is <code> null </code> then it will be relative to the BeanInfo plugin's state location. <p>
		 * This is <package-protected> because only the creator (BeanInfoCacheController class) should set this up.
		 * 
		 * @param project
		 * 
		 * @since 1.1.0
		 */
		void setupIndex(IProject project) {
			if (getCachePath() == null)
				cachePath = getCacheDir(project).append(rootName);
		}

		/**
		 * @return Returns the path of the cache directory for the root.
		 * 
		 * @since 1.1.0
		 */
		public IPath getCachePath() {
			return cachePath;
		}

		/**
		 * Return whether this is a root for a archive or a folder.
		 * 
		 * @return <code>true</code> if archive for a root. <code>false</code> if archive for a folder.
		 * 
		 * @since 1.1.0
		 */
		public abstract boolean isArchiveRoot();
	}

	/**
	 * A root index that is for an archive, either internal or external. It contains the archive's modification stamp. Each class cache entry will
	 * have this same modification stamp. If the archive is changed then all of the class cache entries will be removed because they are all possibly
	 * stale. No way to know which may be stale and which not.
	 * 
	 * @since 1.1.0
	 */
	public static class ArchiveRootIndex extends RootIndex {

		private static final long serialVersionUID = 110686867444L;

		private long archiveModificationStamp;

		/*
		 * For serializer to call.
		 */
		protected ArchiveRootIndex() {
		}

		public ArchiveRootIndex(String rootName, long archiveModificationStamp, Index index) {
			super(rootName, index);
			this.archiveModificationStamp = archiveModificationStamp;
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see org.eclipse.jem.internal.beaninfo.core.BeanInfoCacheController.RootIndex#isArchiveRoot()
		 */
		public boolean isArchiveRoot() {
			return true;
		}

		/*
		 * Set the modification stamp. <p> <package-protected> because only the cache controller should change it.
		 * 
		 * @param archiveModificationStamp The archiveModificationStamp to set.
		 * 
		 * @see BeanInfoCacheController#MODIFICATION_STAMP_STALE
		 * @since 1.1.0
		 */
		void setArchiveModificationStamp(long archiveModificationStamp) {
			this.archiveModificationStamp = archiveModificationStamp;
			setDirty();
		}

		/**
		 * Returns the modification stamp.
		 * 
		 * @return Returns the archiveModificationStamp.
		 * @see BeanInfoCacheController#MODIFICATION_STAMP_STALE
		 * @since 1.1.0
		 */
		public long getArchiveModificationStamp() {
			return archiveModificationStamp;
		}
	}

	/**
	 * This is a root index for a folder (which will be in the workspace). Each class cache entry can have a different modification stamp with a
	 * folder root index.
	 * 
	 * @since 1.1.0
	 */
	public static class FolderRootIndex extends RootIndex {

		private static final long serialVersionUID = 1106868674922L;

		/*
		 * For serialization.
		 */
		protected FolderRootIndex() {
		}

		/**
		 * @param rootName
		 * 
		 * @since 1.1.0
		 */
		public FolderRootIndex(String rootName, Index index) {
			super(rootName, index);
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see org.eclipse.jem.internal.beaninfo.core.BeanInfoCacheController.RootIndex#isArchiveRoot()
		 */
		public boolean isArchiveRoot() {
			return false;
		}
	}

	/**
	 * An individual class entry from the cache. It has an entry for each class in the root. The class cache entry describes the cache, whether it is
	 * stale, what the current mod stamp is, etc.
	 * <p>
	 * There is a method to call to see if deleted. This should only be called if entry is being held on to because
	 * <code>getClassEntry(JavaClass)</code> will never return a deleted entry. There is a method to get the modification stamp of the current cache
	 * entry. This is the time stamp of the cooresponding class resource (or archive file) that the cache file was created from. If the value is
	 * <code>IResource.NULL_STAMP</code>, then the cache file is known to be stale. Otherwise if the value is less than a modification stamp of a
	 * super class then the cache file is stale.
	 * 
	 * @see ClassEntry#isDeleted()
	 * @see ClassEntry#getModificationStamp()
	 * @see BeanInfoCacheController#getClassEntry(JavaClass)
	 * @since 1.1.0
	 */
	public static class ClassEntry implements Serializable {

		private static final long serialVersionUID = 1106868674333L;

		public static final long DELETED_MODIFICATION_STAMP = Long.MIN_VALUE; // This flag won't be seen externally. It is used to indicate the entry
																			  // has been deleted for those that have been holding a CE.
		
		/**
		 * Check against the super modification stamp and the interface stamps to see if they were set
		 * by undefined super class or interface at cache creation time. 
		 * 
		 * @since 1.1.0
		 */
		public static final long SUPER_UNDEFINED_MODIFICATION_STAMP = Long.MIN_VALUE+1;	

		private long modificationStamp;
		private long superModificationStamp;	// Stamp of superclass, if any, at time of cache creation.
		private String[] interfaceNames;	// Interfaces names (null if no interfaces)
		private long[] interfaceModicationStamps;	// Modification stamps of interfaces, if any. (null if no interfaces).
		private transient Resource pendingResource;	// Resource is waiting to be saved, but the timestamps are for this pending resource so that we know what it will be ahead of time. At this point the class will be introspected. 

		private RootIndex rootIndex; // The root index this class entry is in, so that any changes can mark the entry as dirty.

		private String className; // The classname for this entry.
		
		private boolean saveOperations;	// Flag for saving operations. Once this is set, it will continue to save operations in the cache in addition to everything else.

		private long configurationModificationStamp;	// Modification stamp of the Eclipse configuration. Used to determine if the cache of override files is out of date due to a config change.
		private boolean overrideCacheExists;	// Flag that there is an override cache to load. This is orthogonal to the config mod stamp because it simply means that on the current configuration there is no override cache.
		private transient Resource pendingOverrideResource;	// Override resource is waiting to be saved.
		
		protected ClassEntry() {
		}

		ClassEntry(RootIndex rootIndex, String className) {
			this.setRootIndex(rootIndex);
			this.className = className;
			modificationStamp = IResource.NULL_STAMP;
			rootIndex.classNameToClassEntry.put(className, this);
		}

		/**
		 * 
		 * @return
		 * 
		 * @since 1.1.0
		 */
		public String getClassName() {
			return className;
		}

		/**
		 * Return whether the entry has been deleted. This will never be seen in an entry that is still in an index. It is used for entries that have
		 * been removed from the index. It is for classes (such as the BeanInfoClassAdapter) which are holding onto a copy of entry to let them know.
		 * <p>
		 * Holders of entries should call isDeleted if they don't need to further check the mod stamp. Else they should call getModificationStamp and
		 * check of deleted, stale, or mod stamp. That would save extra synchronizations. If entry is deleted then it should throw the entry away.
		 * 
		 * @return <code>true</code> if the entry has been deleted, <code>false</code> if still valid.
		 * 
		 * @see ClassEntry#getModificationStamp()
		 * @see ClassEntry#isStale()
		 * @see ClassEntry#DELETED_MODIFICATION_STAMP
		 * @since 1.1.0
		 */
		public boolean isDeleted() {
			return getModificationStamp() == DELETED_MODIFICATION_STAMP;
		}

		/**
		 * Mark the entry as deleted. It will also be removed from root index in that case.
		 * <p>
		 * Note: It is public only so that BeanInfoClassAdapter can access it. It should not be called by anyone else outside of BeanInfo.
		 */
		public synchronized void markDeleted() {
			if (!isDeleted()) {
				getRootIndex().classNameToClassEntry.remove(className);
				setModificationStamp(DELETED_MODIFICATION_STAMP); // Also marks index as dirty.
			}
		}

		/**
		 * Return whether the entry is stale or not. This orthoganal to isDeleted. isDeleted will not be true if isStale and isStale will not be true
		 * if isDeleted. Normally you should use getModificationStamp and check the value for IResource.NULL_STAMP and other values to bring it down
		 * to only one synchronized call to CE, but if only needing to know if stale, you can use this.
		 * 
		 * @return
		 * 
		 * @since 1.1.0
		 * @see IResource#NULL_STAMP
		 * @see ClassEntry#getModificationStamp()
		 * @see ClassEntry#isDeleted()
		 */
		public boolean isStale() {
			return getModificationStamp() == IResource.NULL_STAMP;
		}

		/**
		 * Return the modification stamp. For those holding onto an entry, and they need to know more than if just deleted, then they should just the
		 * return value from getModificationStamp. Else they should use isDeleted or isStale.
		 * 
		 * @return modification stamp, or {@link IResource#NULL_STAMP}if stale or not yet created, or {@link ClassEntry#DELETED_MODIFICATION_STAMP}
		 *         if deleted.
		 * 
		 * @see ClassEntry#isDeleted()
		 * @see ClassEntry#isStale()
		 * @since 1.1.0
		 */
		public synchronized long getModificationStamp() {
			return modificationStamp;
		}
		
		/**
		 * Return the super modification stamp.
		 * @return
		 * 
		 * @since 1.1.0
		 */
		public synchronized long getSuperModificationStamp() {
			return superModificationStamp;
		}
		
		/**
		 * Return the interface names or <code>null</code> if no interface names.
		 * @return
		 * 
		 * @since 1.1.0
		 */
		public synchronized String[] getInterfaceNames() {
			return interfaceNames;
		}

		/**
		 * Return the interface modification stamps or <code>null</code> if no interfaces.
		 * @return
		 * 
		 * @since 1.1.0
		 */
		public synchronized long[] getInterfaceModificationStamps() {
			return interfaceModicationStamps;
		}
		
		/*
		 * Set the modification stamp. <p> <package-protected> because only the cache controller should set it. @param modificationStamp
		 * 
		 * @since 1.1.0
		 */
		void setModificationStamp(long modificationStamp) {
			if (this.modificationStamp != modificationStamp) {
				this.modificationStamp = modificationStamp;
				getRootIndex().setDirty();
			}
		}

		/**
		 * Answer whether operations are also stored in the cache for this class. By default they are not. Once turned on they
		 * will always be stored for this class until the class is deleted.
		 * 
		 * @return <code>true</code> if operations are cached, <code>false</code> if they are not cached.
		 * 
		 * @since 1.1.0
		 */
		public synchronized boolean isOperationsStored() {
			return saveOperations;
		}
		
		/*
		 * Set the operations stored flag.
		 * @param storeOperations
		 * 
		 * @see BeanInfoCacheController.ClassEntry#isOperationsStored()
		 * @since 1.1.0
		 */
		void setOperationsStored(boolean storeOperations) {
			saveOperations = storeOperations;
		}
		
		/**
		 * Get the configuration modification stamp of the last saved override cache.
		 * 
		 * @return
		 * 
		 * @since 1.1.0
		 */
		public synchronized long getConfigurationModificationStamp() {
			return configurationModificationStamp;
		}

		/* 
		 * Set the configuration modification stamp.
		 * <p> <package-protected> because only the cache controller should access it.
		 * 
		 * @param configurationModificationStamp
		 * 
		 * @since 1.1.0
		 */
		void setConfigurationModificationStamp(long configurationModificationStamp) {
			this.configurationModificationStamp = configurationModificationStamp;
			getRootIndex().setDirty();
		}
		
		/**
		 * Answer whether there is an override cache available.
		 * @return
		 * 
		 * @since 1.1.0
		 */
		public synchronized boolean overrideCacheExists() {
			return overrideCacheExists;
		}
		
		/*
		 * Set the override cache exists flag.
		 * <p> <package-protected> because only the cache controller should access it.
		 * @param overrideCacheExists
		 * 
		 * @since 1.1.0
		 */
		void setOverrideCacheExists(boolean overrideCacheExists) {
			this.overrideCacheExists = overrideCacheExists;
		}
		
		/**
		 * Get the pending resource or <code>null</code> if not pending.
		 * 
		 * @return the pending resource or <code>null</code> if not pending.
		 * 
		 * @since 1.1.0
		 */
		public synchronized Resource getPendingResource() {
			return pendingResource;
		}
		
		/*
		 * Set the entry. The sequence get,do something,set must be grouped within a synchronized(ClassEntry). 
		 * <p> <package-protected> because only the cache controller should access it. 
		 * @param cacheResource The cacheResource to set.
		 * 
		 * @since 1.1.0
		 */
		void setPendingResource(Resource pendingResource) {
			this.pendingResource = pendingResource;
		}

		/**
		 * Get the pending override resource or <code>null</code> if not pending.
		 * 
		 * @return the pending override resource or <code>null</code> if not pending.
		 * 
		 * @since 1.1.0
		 */
		public synchronized Resource getPendingOverrideResource() {
			return pendingOverrideResource;
		}
		
		/*
		 * Set the entry. The sequence get,do something,set must be grouped within a synchronized(ClassEntry). 
		 * <p> <package-protected> because only the cache controller should access it. 
		 * @param cacheResource The cacheResource to set.
		 * 
		 * @since 1.1.0
		 */
		void setPendingOverrideResource(Resource pendingOverrideResource) {
			this.pendingOverrideResource = pendingOverrideResource;
		}

		/*
		 * <package-protected> because only the cache controller should access it. @param rootIndex The rootIndex to set.
		 * 
		 * @since 1.1.0
		 */
		void setRootIndex(RootIndex rootIndex) {
			this.rootIndex = rootIndex;
		}

		/*
		 * <package-protected> because only the cache controller should access it. @return Returns the rootIndex.
		 * 
		 * @since 1.1.0
		 */
		RootIndex getRootIndex() {
			return rootIndex;
		}
		
		/*
		 * <package-protected> because only the cache controller should access it.
		 * 
		 * @since 1.1.0
		 */
		void setSuperModificationStamp(long superModificationStamp) {
			this.superModificationStamp = superModificationStamp;
		}

		/*
		 * <package-protected> because only the cache controller should access it.
		 * 
		 * @since 1.1.0
		 */
		void setInterfaceNames(String[] interfaceNames) {
			this.interfaceNames = interfaceNames;
		}

		/*
		 * <package-protected> because only the cache controller should access it.
		 * 
		 * @since 1.1.0
		 */
		void setInterfaceModificationStamps(long[] interfaceModificationStamps) {
			this.interfaceModicationStamps = interfaceModificationStamps;
		}
		
	}

	/*
	 * Main index for the external jars. This variable should not be referenced directly except through the getMainIndex() accessor. That controls
	 * synchronization and restoration as needed.
	 */
	private static Index MAIN_INDEX;

	/*
	 * Key into the Project's session data for the project index. The Project index is stored in the project's session data. That
	 * way when the project is closed or deleted it will go away. 
	 * 
	 * The project indexes will be read in as needed on a per-project basis. This variable should not be
	 * referenced directly except through the getProjectIndex(IProject) accessor. That controls synchronization and restoration as needed.
	 * Only during cleanup and such where we don't want to create one if it doesn't exist you must use sync(this). Be careful to keep 
	 * the sync small.
	 */
	private static final QualifiedName PROJECT_INDEX_KEY = new QualifiedName(BeaninfoPlugin.PI_BEANINFO_PLUGINID, "project_index");	//$NON-NLS-1$

	/*
	 * Suffix for class cache files.
	 */
	private static final String CLASS_CACHE_SUFFIX = ".xmi"; //$NON-NLS-1$
	/*
	 * Suffic for class override cache files.
	 */
	private static final String OVERRIDE_CACHE_SUFFIX = ".override.xmi"; //$NON-NLS-1$

	/**
	 * Return the current class entry for the JavaClass, or <code>null</code> if no current entry.
	 * 
	 * @param jclass
	 * @return class entry or <code>null</code> if no current entry.
	 * 
	 * @since 1.1.0
	 */
	public ClassEntry getClassEntry(JavaClass jclass) {
		IType type = (IType) jclass.getReflectionType();
		RootIndex rootIndex = getRootIndex(type);
		String className = jclass.getQualifiedNameForReflection();
		return getClassEntry(rootIndex, className, false);
	}

	/**
	 * Enumeration for newCache: Signals that this cache is the Reflection Cache with no operations in it.
	 * @since 1.1.0
	 */
	public final static int REFLECTION_CACHE = 1;
	/**
	 * Enumeration for newCache: Signals that this cache is the Reflection Cache with operations in it.
	 * @since 1.1.0
	 */
	public final static int REFLECTION_OPERATIONS_CACHE = 2;
	/**
	 * Enumeration for newCache: Signals that this cache is the Overrides cache.
	 * @since 1.1.0
	 */
	public final static int OVERRIDES_CACHE = 3;
	/**
	 * A new cache entry for the given class has been created. Need to write it out.
	 * 
	 * @param jclass
	 *            the JavaClass the cache is for.
	 * @param cache
	 *            the ChangeDescription to put out if cacheType is Reflection types, a List if override cache type.
	 * @param cacheType
	 *            {@link BeanInfoCacheController.ClassEntry#REFLECTION_CACHE} for the enum values.
	 * @return new class entry (or old one if same one). Should always replace one being held by this one. <code>null</code> if cache could not be
	 *         updated for some reason.
	 * @since 1.1.0
	 */
	public ClassEntry newCache(JavaClass jclass, Object cache, int cacheType) {
		if (BeaninfoPlugin.getPlugin().getLogger().isLoggingLevel(Level.FINER)) {
			Logger logger = BeaninfoPlugin.getPlugin().getLogger();
			String type = cacheType!=OVERRIDES_CACHE?"Class":"Overrides"; //$NON-NLS-1$ //$NON-NLS-2$
			if (cacheType == OVERRIDES_CACHE && cache == null)
				type+="  empty"; //$NON-NLS-1$
			logger.log("Creating cache for class "+jclass.getQualifiedNameForReflection()+" cache type="+type, Level.FINER); //$NON-NLS-1$ //$NON-NLS-2$
		}
		ChangeDescription cd = null;
		if (cacheType != OVERRIDES_CACHE) {
			// First go through the cd and remove any empty changes. This is because we created the feature change before we knew what went into
			// it, and at times nothing goes into it.
			cd = (ChangeDescription) cache;
			for (Iterator iter = cd.getObjectChanges().iterator(); iter.hasNext();) {
				EObjectToChangesMapEntryImpl fcEntry = (EObjectToChangesMapEntryImpl) iter.next();
				if (((List) fcEntry.getValue()).isEmpty())
					iter.remove(); // Empty changes, remove it.
			}
		}
		IType type = (IType) jclass.getReflectionType();
		RootIndex rootIndex = getRootIndex(type);
		String className = jclass.getQualifiedNameForReflection();
		ClassEntry ce = getClassEntry(rootIndex, className, true); // Create it if not existing.
		// Sync on ce so that only can create a cache for a class at a time and so that writing (if occurring at the same time for the class) can be
		// held up.
		// this is a violation of the agreement to only sync on THIS, but it is necessary or else the write job would lock everything out while it is
		// writing. This way it only locks out one class, if the class is at the same time.
		// We shouldn't have deadlock because here we lock ce and then THIS (maybe). The write job will lock ce, and then lock THIS. Everywhere else
		// we must
		// also do lock ce then THIS. Mustn't do other way around or possibility of deadlock. Be careful that any synchronized methods in this class
		// do
		// not lock an existing ce.
		ResourceSet cacheRset = null;
		synchronized (ce) {
			Resource cres;
			if (cacheType != OVERRIDES_CACHE) {
				cres = ce.getPendingResource();
				if (cres != null) {
					// We have a pending, so clear and reuse the resource.
					cres.getContents().clear();
				} else {
					// Not currently writing or waiting to write, so create a new resource.
					cres = jclass.eResource().getResourceSet().createResource(
							URI.createFileURI(rootIndex.getCachePath().append(className + CLASS_CACHE_SUFFIX).toString()));
				}
				cacheRset = cres.getResourceSet();
				ce.setOperationsStored(cacheType == REFLECTION_OPERATIONS_CACHE);
				ce.setPendingResource(cres);
				cres.getContents().add(cd);
				// Archives use same mod as archive (retrieve from rootindex), while non-archive use the underlying resource's mod stamp.
				if (rootIndex.isArchiveRoot())
					ce.setModificationStamp(((ArchiveRootIndex) rootIndex).getArchiveModificationStamp());
				else {
					try {
						ce.setModificationStamp(type.getUnderlyingResource().getModificationStamp());
					} catch (JavaModelException e) {
						BeaninfoPlugin.getPlugin().getLogger().log(e);
						ce.markDeleted(); // Mark as deleted in case this was an existing that someone is holding.
						return null; // Couldn't do it, throw cache entry away. This actually should never occur.
					}
				}
				// Need to get the supers info. 
				List supers = jclass.getESuperTypes();
				if (!supers.isEmpty()) {
					// We assume that they all have been introspected. This was done back in main introspection. If they are introspected they will have a class entry.
					BeaninfoClassAdapter bca = BeaninfoClassAdapter.getBeaninfoClassAdapter((EObject) supers.get(0));
					ClassEntry superCE = bca.getClassEntry();
					if (superCE != null)
						ce.setSuperModificationStamp(superCE.getModificationStamp());
					else
						ce.setSuperModificationStamp(ClassEntry.SUPER_UNDEFINED_MODIFICATION_STAMP);	// No classentry means undefined. So put something in so that when it becomes defined we will know.
					if(supers.size() == 1) {
						ce.setInterfaceNames(null);
						ce.setInterfaceModificationStamps(null);
					} else {
						String[] interNames = new String[supers.size()-1];
						long[] interMods = new long[interNames.length];
						for (int i = 1, indx = 0; indx < interNames.length; i++, indx++) {
							JavaClass javaClass = (JavaClass) supers.get(i);
							bca = BeaninfoClassAdapter.getBeaninfoClassAdapter(javaClass);
							bca.introspectIfNecessary();	// Force introspection to get a valid super mod stamp.
							superCE = bca.getClassEntry();
							interNames[indx] = javaClass.getQualifiedNameForReflection();
							if (superCE != null)
								interMods[indx] = superCE.getModificationStamp();
							else
								interMods[indx] = ClassEntry.SUPER_UNDEFINED_MODIFICATION_STAMP;	// No classentry means undefined. So put something in so that when it becomes defined we will know.
						}
						ce.setInterfaceNames(interNames);
						ce.setInterfaceModificationStamps(interMods);
					}
				} else {
					ce.setSuperModificationStamp(IResource.NULL_STAMP);
					ce.setInterfaceNames(null);
					ce.setInterfaceModificationStamps(null);
				}
			} else {
				// We are an override cache.
				if (cache != null) { 
					cres = ce.getPendingOverrideResource();
					if (cres != null) {
						// We have a pending, so clear and reuse the resource.
						cres.getContents().clear();
					} else {
						// Not currently writing or waiting to write, so create a new resource.
						cres = jclass.eResource().getResourceSet().createResource(
								URI.createFileURI(rootIndex.getCachePath().append(className + OVERRIDE_CACHE_SUFFIX).toString()));
					}
					cacheRset = cres.getResourceSet();
					cres.getContents().addAll((List) cache);
					ce.setPendingOverrideResource(cres);
					ce.setOverrideCacheExists(true);
				} else {
					ce.setPendingOverrideResource(null);
					ce.setOverrideCacheExists(false);
				}
				ce.setConfigurationModificationStamp(Platform.getPlatformAdmin().getState(false).getTimeStamp());
			}
		}
		queueClassEntry(ce, cacheRset); // Now queue it up.
		return ce;
	}

	/**
	 * Get the cache resource for the given java class.
	 * <p>
	 * NOTE: It is the responsibility of the caller to ALWAYS remove the Resource from its resource set when done with it.
	 * 
	 * @param jclass
	 * @param ce the class entry for the jclass
	 * @param reflectCache <code>true</code> if this the reflection/introspection cache or <code>false</code> if this is the override cache.
	 * @return the loaded cache resource, or <code>null</code> if not there (for some reason) or an error trying to load it.
	 * 
	 * @since 1.1.0
	 */
	public Resource getCache(JavaClass jclass, ClassEntry ce, boolean reflectCache) {
		String className = jclass.getQualifiedNameForReflection();
		if (BeaninfoPlugin.getPlugin().getLogger().isLoggingLevel(Level.FINER)) {
			Logger logger = BeaninfoPlugin.getPlugin().getLogger();
			String type = reflectCache?"Class":"Overrides"; //$NON-NLS-1$ //$NON-NLS-2$
			logger.log("Loading cache for class "+className+" cache type="+type, Level.FINER); //$NON-NLS-1$ //$NON-NLS-2$
		}

		if (reflectCache) {
			boolean waitForJob = false;
			synchronized (ce) {
				if (ce.getPendingResource() != null) {
					// We have one pending. So wait until write cache job is done, and then load it in.
					// Note: Can't just copy the pending resource because it has references to JavaClasses
					// and these could be in a different project (since this could be a workspace wide class).
					// We would get the wrong java classes then when we apply it. 
					waitForJob = true;
					if (BeaninfoPlugin.getPlugin().getLogger().isLoggingLevel(Level.FINER))
						BeaninfoPlugin.getPlugin().getLogger().log("Using pending class cache.", Level.FINER); //$NON-NLS-1$
				}
			}
			if (waitForJob)
				waitForCacheSaveJob();	

			try {
				return jclass.eResource().getResourceSet().getResource(
						URI.createFileURI(ce.getRootIndex().getCachePath().append(
								className + CLASS_CACHE_SUFFIX).toString()), true);
			} catch (Exception e) {
				// Something happened and couldn't load it.
				// TODO - need to remove the Level.INFO arg when the beaninfo cache is working dynamically
				BeaninfoPlugin.getPlugin().getLogger().log(e, Level.INFO);
				return null;
			}
		} else {
			boolean waitForJob = false;
			synchronized (ce) {
				if (ce.getPendingOverrideResource() != null) {
					// We have one pending. So wait until write cache job is done, and then load it in.
					// Note: Can't just copy the pending resource because it has references to JavaClasses
					// and these could be in a different project (since this could be a workspace wide class).
					// We would get the wrong java classes then when we apply it. 
					waitForJob = true;
					if (BeaninfoPlugin.getPlugin().getLogger().isLoggingLevel(Level.FINER))
						BeaninfoPlugin.getPlugin().getLogger().log("Using pending override cache.", Level.FINER); //$NON-NLS-1$
				}
			}
			if (waitForJob)
				waitForCacheSaveJob();	

			try {
				return jclass.eResource().getResourceSet().getResource(
						URI.createFileURI(ce.getRootIndex().getCachePath().append(
								className + OVERRIDE_CACHE_SUFFIX).toString()), true);
			} catch (Exception e) {
				// Something happened and couldn't load it.
				// TODO - need to remove the Level.INFO arg when the beaninfo cache is working dynamically
				BeaninfoPlugin.getPlugin().getLogger().log(e, Level.INFO);
				return null;
			}
		}
	}

	private synchronized ClassEntry getClassEntry(RootIndex rootIndex, String className, boolean createEntry) {
		ClassEntry ce = (ClassEntry) rootIndex.classNameToClassEntry.get(className);
		if (createEntry && ce == null) {
			// Need to create one.
			ce = new ClassEntry(rootIndex, className);
			// Don't actually mark the rootIndex dirty until the cache for it is actually saved out.
		}
		return ce;
	}

	private static final String ROOT_PREFIX = "root"; //$NON-NLS-1$

	/*
	 * Get the root index for the appropriate cache for the given java class.
	 */
	private RootIndex getRootIndex(IType type) {
		IPackageFragmentRoot root = (IPackageFragmentRoot) type.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);
		if (!root.isExternal()) {
			// So it is in a project. Get the project index.
			return getRootIndex(root, root.getJavaProject().getProject());
		} else {
			// It is an external jar (archive), so needs to come from main index, no project.
			return getRootIndex(root, null);
		}
	}

	/*
	 * Get the root index for the given root. A Project index if project is not null.
	 */
	private synchronized RootIndex getRootIndex(IPackageFragmentRoot root, IProject project) {
		Index index = project != null ? getProjectIndex(project) : getMainIndex();
		IPath rootPath = root.getPath();
		RootIndex rootIndex = (RootIndex) index.rootToRootIndex.get(rootPath);
		if (rootIndex == null) {
			// Need to do a new root path.
			String rootName = ROOT_PREFIX + (++index.highRootNumber);
			rootIndex = root.isArchive() ? createArchiveRootIndex(root, rootName, index) : new FolderRootIndex(rootName, index);
			index.rootToRootIndex.put(rootPath, rootIndex);
			// Don't set index dirty until we actually save a class cache file. Until then it only needs to be in memory.
		}
		rootIndex.setupIndex(project); // Set it up, or may already be set, so it will do nothing in that case.
		return rootIndex;
	}

	/*
	 * Create an archive root with the given root number and root.
	 */
	private RootIndex createArchiveRootIndex(IPackageFragmentRoot rootArchive, String rootName, Index index) {
		long modStamp = IResource.NULL_STAMP;
		if (rootArchive.isExternal()) {
			modStamp = rootArchive.getPath().toFile().lastModified();
		} else {
			try {
				modStamp = rootArchive.getUnderlyingResource().getModificationStamp();
			} catch (JavaModelException e) {
				BeaninfoPlugin.getPlugin().getLogger().log(e);
			}
		}
		return new ArchiveRootIndex(rootName, modStamp, index);
	}

	private static final String INDEXFILENAME = ".index"; //$NON-NLS-1$

	private static final String CACHEDIR = ".cache"; // Cache directory (so as not to conflict with any future BeanInfo Plugin specific data files. //$NON-NLS-1$

	/*
	 * Get the cache directory for the project (or if project is null, the main plugin cache directory).
	 */
	// TODO: make this one private
	public static IPath getCacheDir(IProject project) {
		if (project != null)
			return project.getWorkingLocation(BeaninfoPlugin.getPlugin().getBundle().getSymbolicName()).append(CACHEDIR);
		else
			return BeaninfoPlugin.getPlugin().getStateLocation().append(CACHEDIR);
	}

	/*
	 * Get the project index. Synchronized so that we can create it if necessary and not get race conditions.
	 */
	private synchronized Index getProjectIndex(IProject project) {
		try {
			Index index = (Index) project.getSessionProperty(PROJECT_INDEX_KEY);
			if (index == null) {
				// Read the index in.
				File indexDirFile = getCacheDir(project).append(INDEXFILENAME).toFile();
				if (indexDirFile.canRead()) {
					ObjectInputStream ois = null;
					try {
						ois = new ObjectInputStream(new BufferedInputStream(new FileInputStream(indexDirFile)));
						index = (Index) ois.readObject();
					} catch (InvalidClassException e) {
						// This is ok. It simply means the cache index is at a downlevel format and needs to be reconstructed.
					} catch (IOException e) {
						BeaninfoPlugin.getPlugin().getLogger().log(e);
					} catch (ClassNotFoundException e) {
						BeaninfoPlugin.getPlugin().getLogger().log(e);
					} finally {
						if (ois != null)
							try {
								ois.close();
							} catch (IOException e) {
								BeaninfoPlugin.getPlugin().getLogger().log(e);
							}
					}
				}

				if (index == null) {
					// Doesn't yet exist or it couldn't be read for some reason, or it was downlevel cache in which case we just throw it away and create
					// new).
					index = new Index();
					index.highRootNumber = 0;
					index.rootToRootIndex = new HashMap();
				}

				project.setSessionProperty(PROJECT_INDEX_KEY, index); // We either created a new one, or we were able to load it.
			}
			return index;
		} catch (CoreException e) {
			// Shouldn't occur,
			return null;
		}
	}

	/*
	 * Get the main index. Synchronized so that we can create it if necessary and not get race conditions.
	 */
	private synchronized Index getMainIndex() {
		if (MAIN_INDEX == null) {
			// Read the index in.
			File indexDirFile = getCacheDir(null).append(INDEXFILENAME).toFile();
			if (indexDirFile.canRead()) {
				ObjectInputStream ois = null;
				try {
					ois = new ObjectInputStream(new BufferedInputStream(new FileInputStream(indexDirFile)));
					MAIN_INDEX = (Index) ois.readObject();
				} catch (InvalidClassException e) {
					// This is ok. It just means that the cache index is at a downlevel format and needs to be reconstructed.
				} catch (IOException e) {
					BeaninfoPlugin.getPlugin().getLogger().log(e);
				} catch (ClassNotFoundException e) {
					BeaninfoPlugin.getPlugin().getLogger().log(e);
				} finally {
					if (ois != null)
						try {
							ois.close();
						} catch (IOException e) {
							BeaninfoPlugin.getPlugin().getLogger().log(e);
						}
				}
			}

			if (MAIN_INDEX == null) {
				// Doesn't yet exist or it couldn't be read for some reason, or it was downlevel cache in which case we just throw it away and create
				// new).
				MAIN_INDEX = new Index();
				MAIN_INDEX.highRootNumber = 0;
				MAIN_INDEX.rootToRootIndex = new HashMap();
			}

		}
		return MAIN_INDEX;
	}

	// -------------- Save Participant code -----------------

	protected class SaveParticipant implements ISaveParticipant {

		/*
		 * (non-Javadoc)
		 * 
		 * @see org.eclipse.core.resources.ISaveParticipant#doneSaving(org.eclipse.core.resources.ISaveContext)
		 */
		public void doneSaving(ISaveContext context) {
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see org.eclipse.core.resources.ISaveParticipant#prepareToSave(org.eclipse.core.resources.ISaveContext)
		 */
		public void prepareToSave(ISaveContext context) throws CoreException {
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see org.eclipse.core.resources.ISaveParticipant#rollback(org.eclipse.core.resources.ISaveContext)
		 */
		public void rollback(ISaveContext context) {
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see org.eclipse.core.resources.ISaveParticipant#saving(org.eclipse.core.resources.ISaveContext)
		 */
		public void saving(ISaveContext context) throws CoreException {
			boolean fullsave = false;
			switch (context.getKind()) {
				case ISaveContext.PROJECT_SAVE:
					IProject project = context.getProject();
					synchronized (BeanInfoCacheController.INSTANCE) {
						// Write the index. The cache save job will eventually run and at that point write out the pending cache files too.
						// They don't need to be written before the project save is complete.
						Index projectIndex = (Index) project.getSessionProperty(PROJECT_INDEX_KEY);
						if (projectIndex != null && projectIndex.isDirty())
							if (reconcileIndexDirectory(project, projectIndex))
								writeIndex(project, projectIndex);
							else {
								// It was empty, just get rid of the index. The directories have already been cleared.
								projectIndex.markDead();
								project.setSessionProperty(PROJECT_INDEX_KEY, null);
							}
					}
					break;
				case ISaveContext.FULL_SAVE:
					fullsave = true;
					waitForCacheSaveJob();
				// Now flow into the snapshot save to complete the fullsave.
				case ISaveContext.SNAPSHOT:
					// For a snapshot, just the dirty indexes, no clean up. If fullsave, cleanup the indexes, but only save the dirty.
					synchronized (BeanInfoCacheController.INSTANCE) {
						if (MAIN_INDEX != null) {
							if (fullsave) {
								if (reconcileIndexDirectory(null, MAIN_INDEX)) {
									if (MAIN_INDEX.isDirty())
										writeIndex(null, MAIN_INDEX);
								} else {
									// It was empty, just get rid of the index. The directories have already been cleared.
									MAIN_INDEX.markDead();
									MAIN_INDEX = null;
								}
							} else if (MAIN_INDEX.isDirty())
								writeIndex(null, MAIN_INDEX);
						}
						// Now do the project indexes. We have to walk all open projects to see which have an index. Since we are
						// doing a major save, the hit will ok
						IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
						for (int i=0; i<projects.length; i++) {
							project = projects[i];
							if (project.isOpen()) {
								Index index = (Index) project.getSessionProperty(PROJECT_INDEX_KEY);
								if (index != null) {
									if (fullsave) {
										if (reconcileIndexDirectory(project, index)) {
											if (index.isDirty())
												writeIndex(project, index);
										} else {
											// It was empty, just get rid of the index from memory. It has already been deleted from disk.
											index.markDead();
											project.setSessionProperty(PROJECT_INDEX_KEY, null);
										}
									} else if (index.isDirty())
										writeIndex(project, index);
								}
							}
						}
					}
			}
		}

		/*
		 * Write an index. Project if not null indicates a project index.
		 */
		private void writeIndex(IProject project, Index index) {
			ObjectOutputStream oos = null;
			try {
				File indexDirFile = getCacheDir(project).toFile();
				indexDirFile.mkdirs();
				File indexFile = new File(indexDirFile, INDEXFILENAME);
				oos = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(indexFile)));
				oos.writeObject(index);
				index.setDirty(false);
			} catch (IOException e) {
				BeaninfoPlugin.getPlugin().getLogger().log(e);
			} finally {
				if (oos != null)
					try {
						oos.close();
					} catch (IOException e) {
						BeaninfoPlugin.getPlugin().getLogger().log(e);
					}
			}
		}

		/*
		 * Reconcile the index directory of unused (empty) root directories. If after reconciling the index is empty, then it will delete the index file too. @return
		 * true if index not empty, false if index was empty and was erased too.
		 */
		private boolean reconcileIndexDirectory(IProject project, Index index) {
			// clean out unused rootIndexes
			File indexDir = getCacheDir(project).toFile();
			if (indexDir.canWrite()) {
				// Create a set of all root names for quick look up.
				if (index.rootToRootIndex.isEmpty()) {
					// It is empty, clear everything, including index file.
					cleanDirectory(indexDir, false);
					return false;
				} else {
					// Need a set of the valid rootnames for quick lookup of names in the directory list.
					// And while accumulating this list, clean out the root indexes cache too (i.e. the class cache files).
					final Set validFiles = new HashSet(index.rootToRootIndex.size());
					validFiles.add(INDEXFILENAME);
					for (Iterator itr = index.rootToRootIndex.values().iterator(); itr.hasNext();) {
						RootIndex rootIndex = (RootIndex) itr.next();
						if (reconcileClassCacheDirectory(rootIndex, project)) {
							// The class cache has been reconciled, and there are still some classes left, so keep the root index.
							validFiles.add(rootIndex.getRootName());
						} else {
							itr.remove(); // The root index is empty, so get rid of it. Since not a valid name, it will be deleted in next step.
							index.setDirty(true); // Also set it dirty in case it wasn't because we need to write out the container Index since it was
							// changed.
						}
					}
					// Get list of files and delete those that are not a valid name (used root name, or index file)
					String[] fileNames = indexDir.list();
					for (int i = 0; i < fileNames.length; i++) {
						if (!validFiles.contains(fileNames[i])) {
							File file = new File(indexDir, fileNames[i]);
							if (file.isDirectory())
								cleanDirectory(file, true);
							else
								file.delete();
						}
					}
					return true;
				} 
			} else 
				return true;	// Can't write, so treat as leave alone.
		}

		/*
		 * Reconcile the class cache directory for the root index. Return true if reconciled good but not empty. Return false if the class cache
		 * directory is now empty. In this case we should actually get rid of the entire root index. This makes sure that the directory matches
		 * the contents of the index by removing any file not found in the index.
		 */
		private boolean reconcileClassCacheDirectory(RootIndex rootIndex, IProject project) {
			if (rootIndex.classNameToClassEntry.isEmpty())
				return false; // There are no classes, so get rid the entire root index.
			else {
				final Set validFiles = rootIndex.classNameToClassEntry.keySet(); // The keys (classnames) are the filenames (without extension)
																					// that
				// should be kept.
				File indexDir = getCacheDir(project).append(rootIndex.getRootName()).toFile();
				// Get list of files that are not a valid name (used classname)
				String[] fileNames = indexDir.list();
				if (fileNames != null) {
					for (int i = 0; i < fileNames.length; i++) {
						String fileName = fileNames[i];
						if (fileName.endsWith(OVERRIDE_CACHE_SUFFIX)) {
							// Ends with out class cache extension, see if valid classname.
							String classname = fileName.substring(0, fileName.length() - OVERRIDE_CACHE_SUFFIX.length());
							ClassEntry ce = (ClassEntry) rootIndex.classNameToClassEntry.get(classname);
							if (ce != null && ce.overrideCacheExists())
								continue; // It is one of ours. Keep it.
						} else if (fileName.endsWith(CLASS_CACHE_SUFFIX)) {
							// Ends with out class cache extension, see if valid classname.
							if (validFiles.contains(fileName.substring(0, fileName.length() - CLASS_CACHE_SUFFIX.length()))) // Strip down to just
																																// class and see if
																																// one of ours.
								continue; // It is one of ours. Keep it.
						}
						// Not valid, get rid of it.
						File file = new File(indexDir, fileName);
						if (file.isDirectory())
							cleanDirectory(file, true);
						else
							file.delete();

					}
				}
				return true;
			}
		}
	}
	
	private static void cleanDirectory(File dir, boolean eraseDir) {
		if (dir.canWrite()) {
			File[] files = dir.listFiles();
			for (int i = 0; i < files.length; i++) {
				if (files[i].isDirectory())
					cleanDirectory(files[i], true);
				else
					files[i].delete();
			}
			if (eraseDir)
				dir.delete();
		}
	}	

	//-------------- Save Class Cache Entry Job -------------------
	// This is write queue for class caches. It is a FIFO queue. It is sychronized so that adds/removes are controlled.
	// Entries are ClassEntry's. The class entry has the resource that needs to be written out. It will be set to null
	// by the job when it is written. The job will have a ClassEntry locked while it is retrieving and resetting the resource
	// field in the entry.
	//
	// The process is the new cache will lock, create resource, set resource into the CE and release lock. Then add the CE to the queue
	// and schedule the job (in case job is not running).
	//
	// The job will lock the CE, get resource from the CE, write it out, set it back to null, release the CE). If the resource is null,
	// then it was already processed (this could happen if the job didn't get a chance to save it before another entry was posted
	// and this is the second request and it was actually processed by the first request).
	// IE:
	// 1) resource created, queue entry added
	// 2) 2nd req, job not processed yet, resource recreated and put back into CE, new queue entry.
	// 3) job pulls from queue, locks ce, grabs resource, writes out the resource, sets back to null, release ce.
	// 4) job pulls from queue. This time the resoure is null so it skips it.
	//
	// Need to lock Ce during entire create and write because the resource set is not reentrant so can't be writing it while creating it.

	private List cacheWriteQueue = null;

	void waitForCacheSaveJob() {
		// For a full save we want to get the class cache files written too, so we need to manipulate the job to get it to finish ASAP.
		if (cacheWriteJob != null) {
			if (BeaninfoPlugin.getPlugin().getLogger().isLoggingLevel(Level.FINER))
				BeaninfoPlugin.getPlugin().getLogger().log("Forcing a cache save job to start early.", Level.FINER); //$NON-NLS-1$
			switch (cacheWriteJob.getState()) {
				case Job.SLEEPING:
					// It could be waiting a long time, so we need to wake it up at a high priority to get it running ASAP.
					cacheWriteJob.setPriority(Job.INTERACTIVE); // Need to get it going right away
					cacheWriteJob.wakeUp();
					// Now drop into the wait.
				default:
					// Now wait for it (if not running this will return right away).
					try {
						cacheWriteJob.join();
					} catch (InterruptedException e) {
					}
			}
		}
	}

	static final Map SAVE_CACHE_OPTIONS;
	static {
		SAVE_CACHE_OPTIONS = new HashMap(3);
		SAVE_CACHE_OPTIONS.put(XMLResource.OPTION_SAVE_TYPE_INFORMATION, Boolean.TRUE);
		SAVE_CACHE_OPTIONS.put(XMLResource.OPTION_USE_ENCODED_ATTRIBUTE_STYLE, Boolean.TRUE);
        SAVE_CACHE_OPTIONS.put(XMLResource.OPTION_ENCODING, "UTF-8"); //$NON-NLS-1$
	}

	protected Job cacheWriteJob = null;
	protected Adapter projectReleaseAdapter = new AdapterImpl() {
		
		/* (non-Javadoc)
		 * @see org.eclipse.emf.common.notify.impl.AdapterImpl#isAdapterForType(java.lang.Object)
		 */
		public boolean isAdapterForType(Object type) {
			return type == BeanInfoCacheController.this;	// We're making the BeanInfoCacheController.this be the adapter type.
		}
		
		
		/* (non-Javadoc)
		 * @see org.eclipse.emf.common.notify.impl.AdapterImpl#notifyChanged(org.eclipse.emf.common.notify.Notification)
		 */
		public void notifyChanged(Notification msg) {
			if (msg.getEventType() == ProjectResourceSet.SPECIAL_NOTIFICATION_TYPE && msg.getFeatureID(BeanInfoCacheController.class) == ProjectResourceSet.PROJECTRESOURCESET_ABOUT_TO_RELEASE_ID) {
				// This is an about to be closed. If we have an active write job, bring it up to top priority and wait for it to finish.
				// This will make sure any resources in the project are written. There may not be any waiting, but this is doing a close
				// project, which is slow already relatively speaking, that waiting for the cache write job to finish is not bad.
				waitForCacheSaveJob();
			}
		}
	};

	private void queueClassEntry(ClassEntry ce, ResourceSet rset) {
		if (cacheWriteQueue == null) {
			cacheWriteQueue = Collections.synchronizedList(new LinkedList());
			cacheWriteJob = new Job(BeaninfoCoreMessages.BeanInfoCacheController_Job_WriteBeaninfoCache_Title) { 

				protected IStatus run(IProgressMonitor monitor) {
					monitor.beginTask("", cacheWriteQueue.size() + 10); // This is actually can change during the run, so we add 10 for the heck of it. //$NON-NLS-1$
					if (BeaninfoPlugin.getPlugin().getLogger().isLoggingLevel(Level.FINER))
						BeaninfoPlugin.getPlugin().getLogger().log("Starting write BeanInfo Cache files.", Level.FINER); //$NON-NLS-1$
					while (!monitor.isCanceled() && !cacheWriteQueue.isEmpty()) {
						ClassEntry ce = (ClassEntry) cacheWriteQueue.remove(0); // Get first one.
						boolean dead = false;
						synchronized (BeanInfoCacheController.this) {
							if (ce.getRootIndex().getIndex().isDead()) {
								dead = true;	// The index is dead, so don't write it. We still need to go through and get the pending resource out of its resource set so that it goes away.
							}
						}
						synchronized (ce) {
							Resource cres = ce.getPendingResource();
							if (cres != null) {
								try {
									if (!dead)
										cres.save(SAVE_CACHE_OPTIONS);
								} catch (IOException e) {
									BeaninfoPlugin.getPlugin().getLogger().log(e);
								} finally {
									// Remove the resource from resource set, clear out the pending.
									cres.getResourceSet().getResources().remove(cres);
									ce.setPendingResource(null);
								}
							}
							cres = ce.getPendingOverrideResource();
							if (cres != null) {
								try {
									if (!dead)
										cres.save(SAVE_CACHE_OPTIONS);
								} catch (IOException e) {
									BeaninfoPlugin.getPlugin().getLogger().log(e);
								} finally {
									// Remove the resource from resource set, clear out the pending.
									cres.getResourceSet().getResources().remove(cres);
									ce.setPendingOverrideResource(null);
								}
							}
							
							monitor.worked(1);
						}
					}
					monitor.done();
					if (BeaninfoPlugin.getPlugin().getLogger().isLoggingLevel(Level.FINER))
						BeaninfoPlugin.getPlugin().getLogger().log("Finished write BeanInfo Cache files.", Level.FINER); //$NON-NLS-1$
					return Status.OK_STATUS;
				}
			};
			cacheWriteJob.setPriority(Job.SHORT);
			cacheWriteJob.setSystem(true);
		}
		if (rset != null && EcoreUtil.getExistingAdapter(rset, this) == null) {
			// If it is a project resource set, then add ourselves as listeners so we know when released.
			if (rset instanceof ProjectResourceSet)
				rset.eAdapters().add(projectReleaseAdapter);
		}
		cacheWriteQueue.add(ce);
		cacheWriteJob.schedule(60 * 1000L); // Put off for 1 minute to let other stuff go on. Not important that it happens immediately.
	}
}