/*******************************************************************************
 * Copyright (c) 2001, 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.adapters;
/*
 *  $RCSfile: BeaninfoNature.java,v $
 *  $Revision: 1.39 $  $Date: 2005/10/26 14:24:56 $ 
 */

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

import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.*;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
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.impl.XMIResourceFactoryImpl;
import org.eclipse.jdt.core.*;
import org.osgi.framework.Bundle;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.InputSource;

import org.eclipse.jem.internal.beaninfo.core.*;
import org.eclipse.jem.internal.java.beaninfo.IIntrospectionAdapter;
import org.eclipse.jem.internal.java.init.JavaInit;
import org.eclipse.jem.internal.plugin.JavaEMFNature;
import org.eclipse.jem.internal.proxy.core.*;
import org.eclipse.jem.internal.proxy.core.IConfigurationContributionInfo.ContainerPaths;
import org.eclipse.jem.java.adapters.JavaXMIFactory;
import org.eclipse.jem.util.emf.workbench.ProjectResourceSet;
import org.eclipse.jem.util.emf.workbench.ResourceHandler;


/**
 * The beaninfo nature. It is created for a project and holds the
 * necessary info for beaninfo to be performed on a project.
 */

public class BeaninfoNature implements IProjectNature {

	public static final String NATURE_ID = BeaninfoPlugin.PI_BEANINFO_PLUGINID + ".BeanInfoNature"; //$NON-NLS-1$
	public static final String P_BEANINFO_SEARCH_PATH = ".beaninfoConfig"; //$NON-NLS-1$
	
	public static final QualifiedName CONFIG_INFO_SESSION_KEY = new QualifiedName(BeaninfoPlugin.PI_BEANINFO_PLUGINID, "CONFIG_INFO"); //$NON-NLS-1$
	public static final QualifiedName BEANINFO_CONTRIBUTORS_SESSION_KEY = new QualifiedName(BeaninfoPlugin.PI_BEANINFO_PLUGINID, "BEANINFO_CONTRIBUTORS"); //$NON-NLS-1$

	private ProxyFactoryRegistry.IRegistryListener registryListener = new ProxyFactoryRegistry.IRegistryListener() {
		/**
		 * @see org.eclipse.jem.internal.proxy.core.ProxyFactoryRegistry.IRegistryListener#registryTerminated(ProxyFactoryRegistry)
		 */
		public void registryTerminated(ProxyFactoryRegistry registry) {
			markAllStale();
		};
	};

	/**
	 * Get the runtime nature for the project, create it if necessary.
	 */
	public static BeaninfoNature getRuntime(IProject project) throws CoreException {
		JavaEMFNature.createRuntime(project);	// Must force JAVAEMFNature creation first before we try to get ours. There is a chicken/egg problem if we let our nature try to get JavaEMFNature during setProject.
		if (project.hasNature(NATURE_ID))
			return (BeaninfoNature) project.getNature(NATURE_ID);
		else
			return createRuntime(project);
	}
	
	/**
	 * Return whether this project has a BeanInfo runtime turned on.
	 * 
	 * @param project
	 * @return <code>true</code> if it has the a BeanInfo runtime.
	 * @throws CoreException
	 * 
	 * @since 1.0.0
	 */
	public static boolean hasRuntime(IProject project) throws CoreException {
		return project.hasNature(NATURE_ID);
	}

	/**
	 * Test if this is a valid project for a Beaninfo Nature. It must be
	 * a JavaProject.
	 */
	public static boolean isValidProject(IProject project) {
		try {
			return project.hasNature(JavaCore.NATURE_ID);
		} catch (CoreException e) {
			return false;
		}
	}

	/**
	 * Create the runtime.
	 */
	private static BeaninfoNature createRuntime(IProject project) throws CoreException {
		if (!isValidProject(project))
			throw new CoreException(
				new Status(
					IStatus.ERROR,
					BeaninfoPlugin.PI_BEANINFO_PLUGINID,
					0,
					MessageFormat.format(
						BeanInfoAdapterMessages.INTROSPECT_FAILED_EXC_, 
						new Object[] { project.getName(), BeanInfoAdapterMessages.BeaninfoNature_InvalidProject}), 
					null));

		addNatureToProject(project, NATURE_ID);
		return (BeaninfoNature) project.getNature(NATURE_ID);
	}

	private static void addNatureToProject(IProject proj, String natureId) throws CoreException {
		IProjectDescription description = proj.getDescription();
		String[] prevNatures = description.getNatureIds();
		String[] newNatures = new String[prevNatures.length + 1];
		System.arraycopy(prevNatures, 0, newNatures, 0, prevNatures.length);
		newNatures[prevNatures.length] = natureId;
		description.setNatureIds(newNatures);
		proj.setDescription(description, null);
	}

	private IProject fProject;
	protected ProxyFactoryRegistry fRegistry;
	protected ResourceSet javaRSet;
	protected BeaninfoModelSynchronizer fSynchronizer;
	protected static BeaninfoJavaReflectionKeyExtension fReflectionKeyExtension;

	/** 
	 * Configures the project with this nature.
	 * This is called by <code>IProject.getNature</code> and should not
	 * be called directly by clients.
	 * The nature extension id is added to the list of natures on the project by
	 * <code>IProject.getNature</code>, and need not be added here.
	 *
	 * @exception CoreException if this method fails.
	 */
	public void configure() throws CoreException {
	}

	/** 
	 * Removes this nature from the project, performing any required deconfiguration.
	 * This is called by <code>IProject.removeNature</code> and should not
	 * be called directly by clients.
	 * The nature id is removed from the list of natures on the project by
	 * <code>IProject.removeNature</code>, and need not be removed here.
	 *
	 * @exception CoreException if this method fails. 
	 */
	public void deconfigure() throws CoreException {
		removeSharedProperty(P_BEANINFO_SEARCH_PATH, null);
		cleanup(true, true);
	}
	
	/**
	 * Shutdown the nature. Called by BeanInfoPlugin to tell the nature that the plugin is being shutdown.
	 * It needs to cleanup.
	 * TODO <package-protected> because only BeanInfoPlugin should call it. (public for now but when we make
	 * BeanInfoNature an API it will be moved into the same package as BeanInfoPlugin).
	 * 
	 * @since 1.0.0
	 */
	public void shutdown() {
		cleanup(true, false);
	}


	/**
	 * Return a new ResourceSet that is linked correctly to this Beaninfo Nature.
	 * <p>
	 * This links up a ResourceSet so that it will work correctly with this nature.
	 * It makes sure that going through the ResourceSet that any "java:/..."
	 * classes can be found and it makes sure that any new classes are placed into the
	 * nature's resource set and not resource set doing the calling.
	 * <p>
	 * This should be used any time a resource set is needed that is not the
	 * project wide resource set associated with beaninfos, but will reference
	 * Java Model classes or instantiate.
	 * <p>
	 * An additional change is made too. The ResourceFactoryRegistry's extensionToResourceFactory map is modified
	 * to have an "java"->XMIResourceFactory entry added to it if EMF Examples is loaded. EMF Examples add
	 * the "java" extension and sets it to their own special JavaResourceFactory. 
	 * If EMF Examples is not loaded, then it falls back to the default "*" mapping, which is to XMIResourceFactory.
	 * This normally causes problems for many
	 * customers. If users of this resource set really want the EMF examples entry instead, after they retrieve the
	 * new resource set they can do this:
	 * <p>
	 * <pre><code>
	 * 	rset = beaninfoNature.newResourceSet();
	 * 	rset.getResourceFactoryRegistry().getExtensionToFactoryMap().remove("java");
	 * </code></pre>
	 * 
	 * @return a ResourceSet that is specially connected to the JEM java model.
	 * 
	 * @since 1.0.0
	 */
	public ProjectResourceSet newResourceSet() {
		SpecialResourceSet rset = new SpecialResourceSet();
		rset.add(new ResourceHandler() {
			public EObject getEObjectFailed(ResourceSet originatingResourceSet, URI uri, boolean loadOnDemand) {
				return null; // We don't have any special things we can do in this case.
			}

			public Resource getResource(ResourceSet originatingResourceSet, URI uri) {
				// Always try to get it out of the nature's resource set because it may of been loaded there either as 
				// the "java:..." type or it could of been an override extra file (such as an override EMF package, for
				// example jcf has a side package containing the definition of the new attribute type. That file
				// will also be loaded into this resourceset. So to find it we need to go in here and try.
				//
				// However, if not found we won't go and try to load the resource. That could load in the wrong place.
				// Kludge: Because of a bug (feature :-)) in XMLHandler.getPackageFromURI(), it doesn't use getResource(...,true) and it tries instead
				// to use uri inputstream to load the package when not found. This bypasses our special create resource and so
				// packages are not automatically created. So we need to do load on demand here instead if it is a java protocol.
				// EMF will not be fixing this. It is working as designed.
				return getResourceSet().getResource(uri, JavaXMIFactory.SCHEME.equals(uri.scheme()));
			}

			public Resource createResource(ResourceSet originatingResourceSet, URI uri) {
				// This is the one. It has got here because it couldn't find a resource already loaded.
				// If it is a "java:/..." protocol resource, then we want to make sure it is loaded at the BeaninfoNature context
				// instead of the lower one.
				if (JavaXMIFactory.SCHEME.equals(uri.scheme()))
					return getResourceSet().getResource(uri, true);
				else
					return null;
			}
		});
		// [71473] Restore "*.java" to be an XMIResource. If EMF Examples are loaded they overload this and load their special resource for "*.java" which we don't want.
		// If some user really wants that, they grab the resource resource set and remove our override.
		if (Resource.Factory.Registry.INSTANCE.getExtensionToFactoryMap().containsKey("java")) { //$NON-NLS-1$
			// Need to add an override to go to XMI instead.
			rset.getResourceFactoryRegistry().getExtensionToFactoryMap().put("java", new XMIResourceFactoryImpl()); //$NON-NLS-1$
		}
		return rset;
	}
	/**
	 * Clean up, this means either the project is being closed, deleted, or it means that
	 * the nature is being removed from the project. Either way that means to
	 * terminate the VM and remove what we added to the context if the flag says clear it.
	 * <p>
	 * This should be called ONLY when this instance of the nature is no longer needed. It
	 * will be recreated for any new uses. That is because we will be removing ourselves
	 * from the list of active natures in the BeanInfoPlugin.
	 * <p>
	 * <b>Note:</b> This will be called from the BeanInfoCacheController. It knows when the project is
	 * being closed or deleted.
	 * 
	 * @param clearResults clear the results such that any JEM model objects have no BeanInfo
	 * adapters attached to them. This allows BeanInfo to be GC'd without being hung onto.
	 *  
	 * @param deregister Deregister from the BeanInfoPlugin. Normally this will always be true, but it
	 * will be called with false when BeanInfoPlugin is calling back to shutdown.
	 */
	public void cleanup(boolean clearResults, boolean deregister) {
		if (deregister)
			BeaninfoPlugin.getPlugin().removeBeanInfoNature(this);
		fSynchronizer.stopSynchronizer(clearResults);
		Init.cleanup(javaRSet, clearResults);
		if (fRegistry != null)
			fRegistry.terminateRegistry(true);

		javaRSet = null;
		fRegistry = null;
		fProject = null;
		fSynchronizer = null;
	}

	/** 
	 * Returns the project to which this project nature applies.
	 *
	 * @return the project handle
	 */
	public IProject getProject() {
		return fProject;
	}

	/**
	 * Sets the project to which this nature applies.
	 * Used when instantiating this project nature runtime.
	 * This is called by <code>IProject.addNature</code>
	 * and should not be called directly by clients.
	 *
	 * @param project the project to which this nature applies
	 */
	public void setProject(IProject project) {
//		BeanInfoCacheController.INSTANCE.getClass();	// Instantiates the controller if not already started.
		fProject = project;
		BeaninfoPlugin.getPlugin().addBeanInfoNature(this);

		try {
			// The nature has been started for this project, need to setup the introspection process now.
			JavaEMFNature javaNature = JavaEMFNature.createRuntime(fProject);
			JavaInit.init();
			if (fReflectionKeyExtension == null) {
				// Register the reflection key extension.
				fReflectionKeyExtension = new BeaninfoJavaReflectionKeyExtension();
				JavaXMIFactory.INSTANCE.registerReflectionKeyExtension(fReflectionKeyExtension);
			}

			javaRSet = javaNature.getResourceSet();
			Init.initialize(javaRSet, new IBeaninfoSupplier() {
				public ProxyFactoryRegistry getRegistry() {
					return BeaninfoNature.this.getRegistry();
				}

				public boolean isRegistryCreated() {
					return BeaninfoNature.this.isRegistryCreated();
				}
				
				public void closeRegistry() {
					BeaninfoNature.this.closeRegistry();
				}
				
				public IProject getProject() {
					return BeaninfoNature.this.getProject();
				}

				public ProjectResourceSet getNewResourceSet() {
					return BeaninfoNature.this.newResourceSet();
				}

				public ResourceSet getProjectResourceSet() {
					return getResourceSet();
				}
			});
			fSynchronizer =
				new BeaninfoModelSynchronizer(
					(BeaninfoAdapterFactory) EcoreUtil.getAdapterFactory(javaRSet.getAdapterFactories(), IIntrospectionAdapter.ADAPTER_KEY),
					JavaCore.create(javaNature.getProject()));
		} catch (CoreException e) {
			BeaninfoPlugin.getPlugin().getLogger().log(e.getStatus());
		}
	}

	/**
	 * Close the registry. It needs to be recycled because a class has changed
	 * and now the new class needs to be accessed.
	 */
	protected void closeRegistry() {
		ProxyFactoryRegistry reg = null;
		synchronized (this) {
			reg = fRegistry;
			fRegistry = null;
			try {
				// Wipe out the Session properties so that they are recomputed.
				getProject().setSessionProperty(CONFIG_INFO_SESSION_KEY, null);
				getProject().setSessionProperty(BEANINFO_CONTRIBUTORS_SESSION_KEY, null);			
			} catch (CoreException e) {
				BeaninfoPlugin.getPlugin().getLogger().log(e, Level.INFO);
			}
		}
		if (reg != null) {
			reg.removeRegistryListener(registryListener);
			reg.terminateRegistry();
		}
	}

	private static final String PI_CLASS = "class"; //$NON-NLS-1$
	
	/**
	 * Using the given configuration info, compute the BeanInfo config info needed. This sets the
	 * session properties BEANINFO_CONTRIBUTORS_SESSION_KEY and CONFIG_INFO_SESSION_KEY.
	 * 
	 * @param info
	 * @throws CoreException
	 * 
	 * @since 1.1.0
	 */
	public static void computeBeanInfoConfigInfo(IConfigurationContributionInfo info) throws CoreException {
		// First time for this nature, or first time after registry reset. Need to compute the info.
		// It is possible for this to be called BEFORE the first usage of BeanInfo. The editor usually
		// brings up the editor's registry before it gets anything from BeanInfo.
		List contributorsList = new ArrayList(10);
		if (!info.getContainerIds().isEmpty()) {
			// Run through all of the visible container ids that are applicable and get BeanInfo contributors.
			Iterator containerIdItr = info.getContainerIds().values().iterator();
			while (containerIdItr.hasNext()) {
				ContainerPaths containerPaths = (ContainerPaths) containerIdItr.next();
				IConfigurationElement[] contributors = BeaninfoPlugin.getPlugin().getContainerIdContributors(containerPaths.getContainerId(), containerPaths.getVisibleContainerPaths());
				for (int i = 0; i < contributors.length; i++) {
					try {
						Object contributor = contributors[i].createExecutableExtension(PI_CLASS);
						if (contributor instanceof IBeanInfoContributor)
							contributorsList.add(contributor);
					} catch (CoreException e) {
						BeaninfoPlugin.getPlugin().getLogger().log(e, Level.WARNING);
					}
				}
			}						
		}
		
		if (!info.getPluginIds().isEmpty()) {
			// Run through all of the visible plugin ids that are applicable and get BeanInfo contributors.
				Iterator pluginIdItr = info.getPluginIds().entrySet().iterator();
				while (pluginIdItr.hasNext()) {
					Map.Entry entry = (Map.Entry) pluginIdItr.next();
					if (((Boolean) entry.getValue()).booleanValue()) {
						IConfigurationElement[] contributors = BeaninfoPlugin.getPlugin().getPluginContributors(
								(String) entry.getKey());
						if (contributors != null) {
							for (int i = 0; i < contributors.length; i++) {
							try {
								Object contributor = contributors[i].createExecutableExtension(PI_CLASS);
								if (contributor instanceof IBeanInfoContributor)
									contributorsList.add(contributor);
							} catch (CoreException e) {
								BeaninfoPlugin.getPlugin().getLogger().log(e, Level.WARNING);
							}
						}
					}
				}
			}
		}
			
			// Save it for all beaninfo processing (and configuration processing if they implement proxy configuration contributor).
		IBeanInfoContributor[] explicitContributors = (IBeanInfoContributor[]) contributorsList.toArray(new IBeanInfoContributor[contributorsList.size()]);
		info.getJavaProject().getProject().setSessionProperty(BEANINFO_CONTRIBUTORS_SESSION_KEY, explicitContributors);
		// Save it for override processing. That happens over and over later after all config processing is done.
		// Do it last so that if there is a race condition, since this property is a flag to indicate we have data,
		// we need to make sure the Beaninfo data is already set at the point we set this.
		// We could actually set it twice because of this, but it is the same data, so, so what.
		info.getJavaProject().getProject().setSessionProperty(CONFIG_INFO_SESSION_KEY, info);
	}

	/**
	 * Get registry, creating it if necessary.
	 * @return the registry.
	 * 
	 * @since 1.0.0
	 */
	public ProxyFactoryRegistry getRegistry() {
		synchronized (this) {
			if (fRegistry != null)
				return fRegistry;
		}
		// Now need to start the appropriate job. In another class so that it can handle dynamically checking if 
		// UI is available to even do this (it maybe not in a UI mode, so then just do it.
		CreateRegistryJobHandler.createRegistry(this);
		return fRegistry;
	}
	
	/*
	 * This is <package-protected> so that only the appropriate create job in this
	 * package can call it. This is because this must be controlled to only be
	 * done when build not in progress and serial access.
	 */
	void createRegistry(IProgressMonitor pm) {
		pm.beginTask(BeanInfoAdapterMessages.UICreateRegistryJobHandler_StartBeaninfoRegistry, 100); 
		if (isRegistryCreated()) {
			pm.done();
			return; // It had already been created. Could of been because threads were racing to do the creation, and one got there first.
		}

		try {
			ConfigurationContributor configurationContributor = (ConfigurationContributor) getConfigurationContributor();
			configurationContributor.setNature(this);
			ProxyFactoryRegistry registry = ProxyLaunchSupport.startImplementation(fProject, "Beaninfo", //$NON-NLS-1$
					new IConfigurationContributor[] { configurationContributor}, false, new SubProgressMonitor(pm, 100));
			registry.addRegistryListener(registryListener);
			synchronized(this) {
				fRegistry = registry;
			}
		} catch (CoreException e) {
			BeaninfoPlugin.getPlugin().getLogger().log(e.getStatus());
		} finally {
			pm.done();
		}
	}
	
	public synchronized boolean isRegistryCreated() {
		return fRegistry != null;
	}
	
	/**
	 * Check to see if the nature is still valid. If the project has been
	 * renamed, the nature is still around, but the project has been closed.
	 * So the nature is now invalid.
	 * 
	 * @return Is this a valid nature. I.e. is the project still open.
	 */
	public boolean isValidNature() {
		return fProject != null;
	}

	/**
	 * Set the search path onto the registry.
	 */
	protected void setProxySearchPath(ProxyFactoryRegistry registry, List searchPaths) {
		if (searchPaths != null) {
			String[] stringSearchPath = (String[]) searchPaths.toArray(new String[searchPaths.size()]);
			Utilities.setBeanInfoSearchPath(registry, stringSearchPath);
		} else
			Utilities.setBeanInfoSearchPath(registry, null);
	}

	private static final String ENCODING = "UTF-8"; //$NON-NLS-1$
	static final String sBeaninfos = "beaninfos"; // Root element name //$NON-NLS-1$
	/**
	 * Get the persistent search path. It is copy.
	 */
	public BeaninfosDoc getSearchPath() {
		BeaninfosDoc bdoc = null;
		try {
			InputStream property = getSharedProperty(P_BEANINFO_SEARCH_PATH);
			if (property != null) {
				try {
					// Need to reconstruct from the XML format.
					Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new InputSource(new InputStreamReader(property, ENCODING)));
					Element root = doc.getDocumentElement();
					if (root != null && root.getNodeName().equalsIgnoreCase(sBeaninfos)) {
						bdoc = BeaninfosDoc.readEntry(new DOMReader(), root, getProject());
					}
				} finally {
					try {
						property.close();
					} catch (IOException e) {
					}
				}
			}
		} catch (CoreException e) {
			BeaninfoPlugin.getPlugin().getLogger().log(e.getStatus());
		} catch (Exception e) {
			BeaninfoPlugin.getPlugin().getLogger().log(new Status(IStatus.WARNING, BeaninfoPlugin.PI_BEANINFO_PLUGINID, 0, "", e)); //$NON-NLS-1$
		}
		return bdoc;
	}

	/**
	 * Set the persistent search path. No progress monitor.
	 */
	public void setSearchPath(BeaninfosDoc searchPath) throws CoreException {
		setSearchPath(searchPath, null);
	}

	/**
	 * Set the persistent search path with a progress monitor
	 */
	public void setSearchPath(BeaninfosDoc searchPath, IProgressMonitor monitor) throws CoreException {
		String property = null;
		if (searchPath != null && searchPath.getSearchpath().length > 0) {
			try {
				Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
				Element root = doc.createElement(sBeaninfos); // Create Root Element
				IBeaninfosDocEntry[] entries = searchPath.getSearchpath();
				for (int i = 0; i < entries.length; i++)
					root.appendChild(entries[i].writeEntry(doc, getProject())); // Add to the search path
				doc.appendChild(root); // Add Root to Document
				StringWriter strWriter = new StringWriter();

				Result result = new StreamResult(strWriter);
				Source source = new DOMSource(doc);
				Transformer transformer = TransformerFactory.newInstance().newTransformer();
				transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$
				transformer.setOutputProperty(OutputKeys.METHOD, "xml"); //$NON-NLS-1$
				transformer.transform(source, result);
				property = strWriter.toString();
			} catch (TransformerConfigurationException e) {
				BeaninfoPlugin.getPlugin().getLogger().log(e, Level.WARNING);
			} catch (TransformerException e) {
				BeaninfoPlugin.getPlugin().getLogger().log(e, Level.WARNING);
			} catch (ParserConfigurationException e) {
				BeaninfoPlugin.getPlugin().getLogger().log(e, Level.WARNING);
			} catch (FactoryConfigurationError e) {
				BeaninfoPlugin.getPlugin().getLogger().log(e, Level.WARNING);
			}
		}

		if (property != null) {
			// If it hasn't changed, don't write it back out. This is so that if the file hasn't
			// been checked out and it is the same, we don't want to bother the user. This is because
			// we don't know if the user had simply browsed the search path or had actually changed and
			// set it back to what it was. In either of those cases it would be a bother to ask the
			// user to checkout the file.
			InputStream is = getSharedProperty(P_BEANINFO_SEARCH_PATH);
			if (is != null) {
				try {
					try {
						InputStreamReader reader = new InputStreamReader(is, ENCODING);
						char[] chars = new char[1000];
						StringBuffer oldProperty = new StringBuffer(1000);
						int read = reader.read(chars);
						while (read != -1) {
							oldProperty.append(chars, 0, read);
							read = reader.read(chars);
						}
						if (oldProperty.toString().equals(property))
							return;
					} catch (IOException e) {
					} // Didn't change.
				} finally {
					try {
						is.close();
					} catch (IOException e) {
					}
				}
			}
			setSharedProperty(P_BEANINFO_SEARCH_PATH, property, monitor);
		} else
			removeSharedProperty(P_BEANINFO_SEARCH_PATH, monitor);
	}

	/**
	 * Return the resource set for all java packages in this nature.
	 */
	public ResourceSet getResourceSet() {
		return javaRSet;
	}

	protected void markAllStale() {
		// Mark all stale so that the registry will be recycled.
		if (fRegistry != null) {
			// We have a registry running, we need to indicate recycle is needed.
			fSynchronizer.getAdapterFactory().markAllStale();
			// Mark all stale. Next time we need anything it will be recycled.
		}
	}

	/**
	 * Compute the file name to use for a given shared property
	 */
	protected String computeSharedPropertyFileName(QualifiedName qName) {
		return qName.getLocalName();
	}

	/**
	 * Retrieve a shared property on a project. If the property is not defined, answers null.
	 * Note that it is orthogonal to IResource persistent properties, and client code has to decide
	 * which form of storage to use appropriately. Shared properties produce real resource files which
	 * can be shared through a VCM onto a server. Persistent properties are not shareable.
	 *
	 */
	protected InputStream getSharedProperty(String propertyFileName) throws CoreException {
		IFile rscFile = getProject().getFile(propertyFileName);
		if (rscFile.exists())
			return rscFile.getContents(true);
		else
			return null;
	}

	/**
	 * Record a shared persistent property onto a project.
	 * Note that it is orthogonal to IResource persistent properties, and client code has to decide
	 * which form of storage to use appropriately. Shared properties produce real resource files which
	 * can be shared through a VCM onto a server. Persistent properties are not shareable.
	 * 
	 * shared properties end up in resource files, and thus cannot be modified during
	 * delta notifications (a CoreException would then be thrown).
	 * 
	 */
	protected void setSharedProperty(String propertyName, String value, IProgressMonitor monitor) throws CoreException {

		try {
			IFile rscFile = getProject().getFile(propertyName);
			InputStream input = new ByteArrayInputStream(value.getBytes(ENCODING));
			// update the resource content
			if (rscFile.exists()) {
				rscFile.setContents(input, true, false, null);
			} else {
				rscFile.create(input, true, monitor);
			}
		} catch (UnsupportedEncodingException e) {
		}
	}

	/**
	 * Remove a shared persistent property onto a project.
	 * Note that it is orthogonal to IResource persistent properties, and client code has to decide
	 * which form of storage to use appropriately. Shared properties produce real resource files which
	 * can be shared through a VCM onto a server. Persistent properties are not shareable.
	 * 
	 * shared properties end up in resource files, and thus cannot be modified during
	 * delta notifications (a CoreException would then be thrown).
	 * 
	 */
	protected void removeSharedProperty(String propertyName, IProgressMonitor monitor) throws CoreException {

		IFile rscFile = getProject().getFile(propertyName);
		rscFile.delete(true, true, monitor);
	}

	/**
	 * Return a configuration contributor that sets up a vm to allow
	 * introspection. This will make sure the appropriate paths
	 * are in the classpath to allow access to the beaninfos, and
	 * it will setup the beaninfo search path for this project.
	 */
	public IConfigurationContributor getConfigurationContributor() {
		return new ConfigurationContributor(getSearchPath());
	}

	private static class ConfigurationContributor extends ConfigurationContributorAdapter {

		private BeaninfosDoc doc;
		List computedSearchPath;
				
		// The nature. If the nature is not set then this contributor is one
		// used by some other later proxy registry to get the beaninfo classes into their paths. In that case
		// we can expect the config info to be in the session variable for our use. Otherwise we will need to
		// add it here. Also don't set searchpath stuff if not nature because only the beaninfo one will do introspection.
		private BeaninfoNature nature;	
		
		private IConfigurationContributionInfo info;
		private IBeanInfoContributor[] explicitContributors;

		public ConfigurationContributor(BeaninfosDoc doc) {
			this.doc = doc;
		}

		/*
		 * Set that this is the nature contributor. Not null, means that this is the contributor being
		 * used to setup the registry for the project's beaninfo nature. null (default) means that this
		 * is one created to add to some editor's registry.
		 * 
		 * Note: This MUST be set before initialize is called or it will not work correctly. If not set, it 
		 * will be considered not for BeanInfo nature directly.
		 */
		public void setNature(BeaninfoNature nature) {
			this.nature = nature;
			if (nature != null)
				computedSearchPath = new ArrayList(3);	// We will be gathering this info.
		}
		
		/* (non-Javadoc)
		 * @see org.eclipse.jem.internal.proxy.core.IConfigurationContributor#initialize(org.eclipse.jem.internal.proxy.core.IConfigurationContributionInfo)
		 */
		public void initialize(IConfigurationContributionInfo info) {
			this.info = info;
			try {
				if (info.getJavaProject().getProject().getSessionProperty(CONFIG_INFO_SESSION_KEY) == null) {
					// TODO For now we will rebuild for each time we open a registry, but it actually is only needed if a classpath
					// changes for some reason. At that point we can get it out of here.
					
					computeBeanInfoConfigInfo(info);					
				} 
				explicitContributors = (IBeanInfoContributor[]) info.getJavaProject().getProject().getSessionProperty(BEANINFO_CONTRIBUTORS_SESSION_KEY);
			} catch (CoreException e) {
				BeaninfoPlugin.getPlugin().getLogger().log(e);
			}
		}
		
		public void contributeClasspaths(final IConfigurationContributionController controller) throws CoreException {
			// Contribute for this project
			contributeClasspathsForProject(controller, info.getJavaProject().getProject(), doc, true);
						
			if (!info.getProjectPaths().isEmpty()) {
				// Run through all of the visible projects and contribute the classpaths (which come from the BeanInfo docs, if they have any).
				IWorkspaceRoot root = info.getJavaProject().getProject().getWorkspace().getRoot();
				Iterator projIter = info.getProjectPaths().entrySet().iterator();
				while (projIter.hasNext()) {
					Map.Entry entry = (Map.Entry) projIter.next();
					if (((Boolean) entry.getValue()).booleanValue()) {
						IResource res = root.findMember((IPath) entry.getKey());
						if (res instanceof IProject && ((IProject) res).isOpen() && BeaninfoNature.hasRuntime((IProject) res))
							contributeClasspathsForProject(controller, (IProject) res, BeaninfoNature.getRuntime((IProject) res)
									.getSearchPath(), false);
					}
				}
			}			
			
			if (!info.getContainerIds().isEmpty()) {
				// Run through all of the visible container ids that are applicable.
				Iterator containerIdItr = info.getContainerIds().values().iterator();
				while (containerIdItr.hasNext()) {
					ContainerPaths containerPaths = (ContainerPaths) containerIdItr.next();
					processBeaninfoEntries(BeaninfoPlugin.getPlugin().getContainerIdBeanInfos(containerPaths.getContainerId(), containerPaths.getVisibleContainerPaths()),
							controller, info.getJavaProject());
				}
				
			}
			
			if (!info.getPluginIds().isEmpty()) {
				// Run through all of the visible plugin ids that are applicable.
				Iterator pluginIdItr = info.getPluginIds().entrySet().iterator();
				while (pluginIdItr.hasNext()) {
					Map.Entry entry = (Map.Entry) pluginIdItr.next();
					if (((Boolean) entry.getValue()).booleanValue()) {
						processBeaninfoEntries(BeaninfoPlugin.getPlugin().getPluginBeanInfos((String) entry.getKey()), controller, info.getJavaProject());
					}
				}
				
			}
			
			if (!info.getContainers().isEmpty()) {
				// Run through all of the visible containers that implement IBeanInfoContributor and ask them for the contributions.
				Iterator containerItr = info.getContainers().entrySet().iterator();
				while (containerItr.hasNext()) {
					Map.Entry entry = (Map.Entry) containerItr.next();
					if (((Boolean) entry.getValue()).booleanValue()) {
						if (entry.getKey() instanceof IBeanInfoContributor)
							processBeaninfoEntries(((IBeanInfoContributor) entry.getKey()).getBeanInfoEntryContributions(info),
									controller, info.getJavaProject());
					}
				}
				
			}			
				
			// And finally run through the explicit contributors.				
			for (int i = 0; i < explicitContributors.length; i++) {
				final IBeanInfoContributor contributor = explicitContributors[i];
				processBeaninfoEntries(contributor.getBeanInfoEntryContributions(info), controller, info.getJavaProject());
				if (contributor instanceof IConfigurationContributor) {
					Platform.run(new ISafeRunnable() {
						public void handleException(Throwable exception) {
							// do nothing. by default platform logs.
						}

						public void run() throws Exception {;
							if (contributor instanceof IConfigurationContributor)
								((IConfigurationContributor) contributor).contributeClasspaths(controller);
						}
					});
				}
			}
			
			// Add the common to the end of the classpath. (Since we are now a jarred plugin, the common is not the plugin jar itself).
			controller.contributeClasspath(BeaninfoPlugin.getPlugin().getBundle(), (IPath) null, IConfigurationContributionController.APPEND_USER_CLASSPATH, false); //$NON-NLS-1$
			
			// Add the beaninfovm.jar and any nls to the end of the classpath.
			controller.contributeClasspath(BeaninfoPlugin.getPlugin().getBundle(), "vm/beaninfovm.jar", IConfigurationContributionController.APPEND_USER_CLASSPATH, true); //$NON-NLS-1$
		}

		private IClasspathEntry get(IClasspathEntry[] array, SearchpathEntry se) {
			for (int i = 0; i < array.length; i++) {
				if (array[i].getEntryKind() == se.getKind() && array[i].getPath().equals(se.getPath()))
					return array[i];
			}
			return null;
		}

		private static final IBeaninfosDocEntry[] EMPTY_ENTRIES = new IBeaninfosDocEntry[0];
		
		/*
		 * Contribute classpaths for the specified project. If doc is passed in, then this is the top level and
		 * all should be added. If no doc, then this is pre-req'd project, and then we will handle exported entries only.
		 */
		protected void contributeClasspathsForProject(
			IConfigurationContributionController controller,
			IProject project,
			BeaninfosDoc doc,
			boolean toplevelProject)
			throws CoreException {
			
			IJavaProject jProject = JavaCore.create(project);
			IClasspathEntry[] rawPath = jProject.getRawClasspath();

			// Search path of this project
			IBeaninfosDocEntry[] entries = (doc != null) ? doc.getSearchpath() : EMPTY_ENTRIES;

			for (int i = 0; i < entries.length; i++) {
				IBeaninfosDocEntry entry = entries[i];
				if (entry instanceof BeaninfoEntry) {
					BeaninfoEntry be = (BeaninfoEntry) entry;
					if (toplevelProject || be.isExported()) {
						// First project or this is an exported beaninfo, so we process it.
						processBeaninfoEntry(be, controller, jProject);
					}
				} else if (nature != null){
					// Just a search path entry. There is no beaninfo jar to pick up.
					// We have a nature, so we process search path.
					SearchpathEntry se = (SearchpathEntry) entry;
					if (!toplevelProject) {
						// We are in a nested project, find the raw classpath entry to see
						// if this entry is exported. Only do it if exported. (Note: exported is only used on non-source. Source are always exported).
						IClasspathEntry cpe = get(rawPath, se);
						if (cpe == null || (cpe.getEntryKind() != IClasspathEntry.CPE_SOURCE && !cpe.isExported())) {
							continue; // Not exist or not exported, so we don't want it here either.
						}
					}

					String pkg = se.getPackage();
					if (pkg != null) {
						// Explicit search path
						if (!computedSearchPath.contains(pkg))
							computedSearchPath.add(pkg);
					} else {
						// We no longer allow this, but just to be on safe side we test for it.
					}
				}
			}
		}

		protected void processBeaninfoEntries(
			BeaninfoEntry[] entries,
			IConfigurationContributionController controller,
			IJavaProject javaProject)
			throws CoreException {
			if (entries != null) {
				for (int i = 0; i < entries.length; i++)
					processBeaninfoEntry(entries[i], controller, javaProject);
			}
		}

		protected void processBeaninfoEntry(
			BeaninfoEntry entry,
			IConfigurationContributionController controller,
			IJavaProject javaProject)
			throws CoreException {
			Object[] cps = entry.getClasspath(javaProject);
			for (int j = 0; j < cps.length; j++) {
				Object cp = cps[j];
				if (cp instanceof IProject)
					controller.contributeProject((IProject) cp);
				else if (cp instanceof String)
					controller.contributeClasspath(ProxyLaunchSupport.convertStringPathToURL((String) cp), IConfigurationContributionController.APPEND_USER_CLASSPATH);
				else if (cp instanceof IPath) {
					IPath path = (IPath) cp;
					Bundle bundle = Platform.getBundle(path.segment(0));
					if (bundle != null)
						controller.contributeClasspath(bundle, path.removeFirstSegments(1), IConfigurationContributionController.APPEND_USER_CLASSPATH, true);
				}
			}

			if (nature != null) {
				// Now add in the package names.
				SearchpathEntry[] sees = entry.getSearchPaths();
				for (int j = 0; j < sees.length; j++) {
					SearchpathEntry searchpathEntry = sees[j];
					if (!computedSearchPath.contains(searchpathEntry.getPackage()))
						computedSearchPath.add(searchpathEntry.getPackage());
				}
			}
		}

		public void contributeToConfiguration(final ILaunchConfigurationWorkingCopy config) {
			for (int i = 0; i < explicitContributors.length; i++) {
				final int ii = i;
				Platform.run(new ISafeRunnable() {
					public void handleException(Throwable exception) {
						// do nothing. by default platform logs.
					}

					public void run() throws Exception {
						IBeanInfoContributor contributor = explicitContributors[ii];
						if (contributor instanceof IConfigurationContributor)
							((IConfigurationContributor) contributor).contributeToConfiguration(config);
					}
				});
			}			
		}

		public void contributeToRegistry(final ProxyFactoryRegistry registry) {
			if (nature != null)
				nature.setProxySearchPath(registry, computedSearchPath);
			for (int i = 0; i < explicitContributors.length; i++) {
				final int ii = i;
				Platform.run(new ISafeRunnable() {
					public void handleException(Throwable exception) {
						// do nothing. by default platform logs.
					}

					public void run() throws Exception {
						IBeanInfoContributor contributor = explicitContributors[ii];
						if (contributor instanceof IConfigurationContributor)
							((IConfigurationContributor) contributor).contributeToRegistry(registry);
					}
				});
			}			
		}
	}


}
