/*******************************************************************************
 * 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
 *******************************************************************************/
/*
 *  $RCSfile: BeanInfoCacheController.java,v $
 *  $Revision: 1.10 $  $Date: 2005/06/22 16:38:57 $ 
 */
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.Adapter;
import org.eclipse.emf.common.notify.Notification;
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.BeaninfoClassAdapter;
import org.eclipse.jem.java.JavaClass;
import org.eclipse.jem.util.emf.workbench.ProjectResourceSet;
import org.eclipse.jem.util.logger.proxy.Logger;

/**
 * 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.
		// TODO For now it only handles final save. It doesn't handle deltas and crashes.
		// It should actually be a job that handles in the background, with a way of cache entries being accessed even when it isn't finished. Such
		// as until finished when checking mod stamp it will check actual file and compare to cache entry to determine if stale.
		saveParticipant = new SaveParticipant();
		try {
			ResourcesPlugin.getWorkspace().addSaveParticipant(BeaninfoPlugin.getPlugin(), saveParticipant);
		} catch (CoreException e) {
			BeaninfoPlugin.getPlugin().getLogger().log(e.getStatus());
		}
	}

	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 = 1106864425465L;

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

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

		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 = 1106868674823L;

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

		/**
		 * 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 = 110686867456L;

		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 = 1106868674842L;

		/*
		 * 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 = 1106868674666L;

		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.

		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;

	/*
	 * Map of project indexes. They are read in as needed. The key will be an IProject and the value will be an Index. This variable should not be
	 * referenced directly except through the getProjectIndex(IProject) accessor. That controls synchronization and restoration as needed.
	 */
	private static Map PROJECT_INDEXES = new HashMap();

	/*
	 * 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));
					ce.setSuperModificationStamp(bca.getClassEntry().getModificationStamp());
					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; i < 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.
							interNames[indx] = javaClass.getQualifiedNameForReflection();
							interMods[indx] = bca.getClassEntry().getModificationStamp();
						}
						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) {
		Index index = (Index) PROJECT_INDEXES.get(project);
		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 (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_INDEXES.put(project, index); // We either created a new one, or we were able to load it. Put it into the map of projects.
		}
		return index;
	}

	/*
	 * 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 (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) {
						Index projectIndex = (Index) PROJECT_INDEXES.get(project);
						if (projectIndex != null && projectIndex.isDirty())
							if (cleanIndexDirectory(project, projectIndex))
								writeIndex(project, projectIndex);
							else {
								// It was empty, just get rid of it the index.
								PROJECT_INDEXES.remove(project);
							}
					}
					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) {
						try {
							if (MAIN_INDEX != null) {
								if (fullsave) {
									if (cleanIndexDirectory(null, MAIN_INDEX)) {
										if (MAIN_INDEX.isDirty())
											writeIndex(null, MAIN_INDEX);
									} else {
										// It was empty, just get rid of the index.
										MAIN_INDEX = null;
									}
								} else if (MAIN_INDEX.isDirty())
									writeIndex(null, MAIN_INDEX);
							}
							// Now do the project indexes.
							for (Iterator projectIndexEntryItr = PROJECT_INDEXES.entrySet().iterator(); projectIndexEntryItr.hasNext();) {
								Map.Entry entry = (Map.Entry) projectIndexEntryItr.next();
								project = (IProject) entry.getKey();
								Index index = (Index) entry.getValue();
								if (fullsave) {
									if (cleanIndexDirectory(project, index)) {
										if (index.isDirty())
											writeIndex(project, index);
									} else {
										// It was empty, just get rid of the index.
										projectIndexEntryItr.remove();
									}
								} else if (index.isDirty())
									writeIndex(project, index);
							}
						} catch (RuntimeException e) {
							e.printStackTrace();
							// TODO Need to fix the case whereas the cache has been removed
							// by Project-->Clean but the memory cache still thinks it exists.
							// This try/catch should be remove once that is fixed.
						}
					}
			}
		}

		/*
		 * 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).append(INDEXFILENAME).toFile();
				oos = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(indexDirFile)));
				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);
					}
			}
		}

		/*
		 * Clean the index directory of unused root directories. If after cleaning 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 cleanIndexDirectory(IProject project, Index index) {
			// clean out unused rootIndexes
			File indexDir = getCacheDir(project).toFile();
			// 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 (cleanClassCacheDirectory(rootIndex, project)) {
						// The class cache has been cleaned, 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;
			}
		}

		/*
		 * Clean out the class cache directory for the root index. Return true if cleaned 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.
		 */
		private boolean cleanClassCacheDirectory(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 void cleanDirectory(File dir, boolean eraseDir) {
			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.
						synchronized (ce) {
							Resource cres = ce.getPendingResource();
							if (cres != null) {
								try {
									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 {
									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.
	}
}