/*******************************************************************************
 * Copyright (c) 2001, 2006 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;
/*


 */

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) {
			prematureRegistryTerminate();
			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 synchronized 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);

		projectCleaned();
		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;
	}
	
	private static final long NO_PREMATURE_TERMINATE_TIME = -1;
	private int registryPrematureTerminateCount;
	private long registryLastPrematureTerminateTime = NO_PREMATURE_TERMINATE_TIME;
	
	/*
	 * 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.
		}

		// Test to see if we have terminated too many times within the last 10 minutes. If we have then don't try again.
		synchronized(this) {
			if (registryLastPrematureTerminateTime != NO_PREMATURE_TERMINATE_TIME) {
				long lastPrematureTerminateInterval = System.currentTimeMillis() - registryLastPrematureTerminateTime;
				// Don't try again within 1 sec of last premature terminate. It will still be bad.
				// Of if there have been more than 3 and it has been 10 mins since the last try.
				if (lastPrematureTerminateInterval < 3*1000 || (registryPrematureTerminateCount > 3 && lastPrematureTerminateInterval < 10 * 60 * 1000))
					return;
			}			
		}
		
		ProxyFactoryRegistry registry = null;
		try {
			ConfigurationContributor configurationContributor = (ConfigurationContributor) getConfigurationContributor();
			configurationContributor.setNature(this);
			registry = ProxyLaunchSupport.startImplementation(fProject, "Beaninfo", //$NON-NLS-1$
					new IConfigurationContributor[] { configurationContributor}, false, new SubProgressMonitor(pm, 100));
			synchronized(this) {
				if (!isRegistryCreated()) {
					projectCleaned();
					registry.addRegistryListener(registryListener);
					fRegistry = registry;
				} else {
					// It was created while we were creating. So use the current one. Terminate the one just created. Not needed.
					registry.terminateRegistry(false);
				}
			}
		} catch (CoreException e) {
			BeaninfoPlugin.getPlugin().getLogger().log(e.getStatus());
		} finally {
			if (registry == null) {
				// It didn't create. Treat as premature terminate.
				prematureRegistryTerminate();
			}
			pm.done();
		}
	}

	/**
	 * Called by others in package (BeaninfoCacheController) to let know a clean has occured.
	 * 
	 * TODO this should be package-protected but until in same package as cache controller it is public.
	 * @since 1.2.0
	 */
	public synchronized void projectCleaned() {
		// On a clean we will reset the counters.
		registryPrematureTerminateCount = 0;
		registryLastPrematureTerminateTime = NO_PREMATURE_TERMINATE_TIME;
	}
	
	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 void prematureRegistryTerminate() {
		synchronized(BeaninfoNature.this) {
			registryPrematureTerminateCount++;
			registryLastPrematureTerminateTime = System.currentTimeMillis();
		}
	}

	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) {
					SafeRunner.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;
				SafeRunner.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;
				SafeRunner.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);
					}
				});
			}			
		}
	}


}
