package org.eclipse.jem.internal.beaninfo.core;
/*******************************************************************************
 * Copyright (c)  2001, 2003 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials 
 * are made available under the terms of the Common Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/cpl-v10.html
 * 
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
/*
 *  $RCSfile: BeaninfoNature.java,v $
 *  $Revision: 1.1 $  $Date: 2004/03/22 23:49:10 $ 
 */

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

import org.apache.xerces.jaxp.DocumentBuilderFactoryImpl;
import org.apache.xml.serialize.*;
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.jdt.core.*;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.InputSource;

import org.eclipse.jem.internal.beaninfo.adapters.*;
import org.eclipse.jem.internal.java.adapters.JavaXMIFactoryImpl;
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 com.ibm.wtp.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");
	public static final QualifiedName BEANINFO_CONTRIBUTORS_SESSION_KEY = new QualifiedName(BeaninfoPlugin.PI_BEANINFO_PLUGINID, "BEANINFO_CONTRIBUTORS");

	private ResourceTracker resourceTracker;
	// This class listens for changes to the beaninfo paths file, and if changed it marks all stale
	// so the next time anything is needed it will recycle the vm. It will also listen about to close or
	// about to delete of the project so that it can cleanup.
	private class ResourceTracker implements IResourceChangeListener{
		public void resourceChanged(IResourceChangeEvent e) {
			// About to close or delete the project and it is ours, so we need to cleanup.
			if (e.getType() == IResourceChangeEvent.PRE_CLOSE || e.getType() == IResourceChangeEvent.PRE_DELETE) {
				// Performance: It has been noted that dres.equals(...) can be slow with the number
				// of visits done. Checking just the last segment (getName()) first before checking
				// the entire resource provides faster testing. If the last segment is not equal,
				// then the entire resource could not be equal.
				IResource eventResource = e.getResource();
				if (eventResource.getName().equals(getProject().getName()) && eventResource.equals(getProject())) {
					cleanup(false);
					return;
				}
			}
			// Note: the BeaninfoModelSynchronizer takes care of both .classpath and .beaninfoconfig changes
			// in this project and any required projects.
		}
	}

	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 {
		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(
						BeaninfoPlugin.getPlugin().getDescriptor().getResourceString(BeaninfoProperties.INTROSPECTFAILED),
						new Object[] { project.getName(), "Invalid project"}),
					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);
	}

	/**
	 * Return a new ResourceSet that is linked correctly to this Beaninfo Nature.
	 * 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.
	 * 
	 * The resourceset will have a context assigned to it.
	 * 
	 * 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.
	 */
	public ResourceSet 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, JavaXMIFactoryImpl.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 (JavaXMIFactoryImpl.SCHEME.equals(uri.scheme()))
					return getResourceSet().getResource(uri, true);
				else
					return null;
			}
		});
		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.
	 */
	protected void cleanup(boolean clearResults) {
		getProject().getWorkspace().removeResourceChangeListener(resourceTracker);
		resourceTracker = null;
		fSynchronizer.stopSynchronizer(clearResults);
		Init.cleanup(javaRSet, clearResults);
		if (fRegistry != null)
			fRegistry.terminateRegistry();

		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) {
		fProject = project;

		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();
				JavaXMIFactoryImpl.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();
				}
			});
			fSynchronizer =
				new BeaninfoModelSynchronizer(
					(BeaninfoAdapterFactory) EcoreUtil.getAdapterFactory(javaRSet.getAdapterFactories(), IIntrospectionAdapter.ADAPTER_KEY),
					JavaCore.create(javaNature.getProject()));
			resourceTracker = new ResourceTracker();
			project.getWorkspace().addResourceChangeListener(resourceTracker);
		} catch (CoreException e) {
			BeaninfoPlugin.getPlugin().getLogger().log(e.getStatus());
		}
	}

	/**
	 * Get the registry, creating it if necessary.
	 */
	public ProxyFactoryRegistry getRegistry() {
		return getRegistry(new NullProgressMonitor());
	}

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

	public synchronized ProxyFactoryRegistry getRegistry(IProgressMonitor pm) {
		if (fRegistry == null) {
			try {
				ConfigurationContributor configurationContributor =  (ConfigurationContributor) getConfigurationContributor();
				configurationContributor.setNature(this);
				fRegistry = ProxyLaunchSupport.startImplementation(fProject, "Beaninfo", //$NON-NLS-1$
					new IConfigurationContributor[] { configurationContributor}, pm);
				fRegistry.addRegistryListener(registryListener);
			} catch (CoreException e) {
				BeaninfoPlugin.getPlugin().getLogger().log(e.getStatus());
			}
		}
		return fRegistry;
	}
	
	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.
					DocumentBuilderFactoryImpl bldrFactory = new DocumentBuilderFactoryImpl();
					Document doc = bldrFactory.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));
		}
		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 {
				DocumentBuilderFactoryImpl bldrFactory = new DocumentBuilderFactoryImpl();
				Document doc = bldrFactory.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
				OutputFormat format = new OutputFormat(doc); //Serialize DOM
				format.setIndenting(true);
				StringWriter strWriter = new StringWriter();
				Serializer serial = SerializerFactory.getSerializerFactory(format.getMethod()).makeSerializer(strWriter, format);
				serial.asDOMSerializer().serialize(doc.getDocumentElement());
				property = strWriter.toString();
			} catch (Exception e) {
			}
		}

		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.
		}
		
		private static final String PI_CLASS = "class";
		
		/* (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) {
					// 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.
					
					// Save it for override processing. That happens over and over later after all config processing is done.
					info.getJavaProject().getProject().setSessionProperty(CONFIG_INFO_SESSION_KEY, info);
					
					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().entrySet().iterator();
						while (containerIdItr.hasNext()) {
							Map.Entry entry = (Map.Entry) containerIdItr.next();
							if (((Boolean) entry.getValue()).booleanValue()) {
								IConfigurationElement[] contributors = BeaninfoPlugin.getPlugin().getContainerIdContributors(
										(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);
									}
								}
							}
}
						}						
					}
					
					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).
					explicitContributors = (IBeanInfoContributor[]) contributorsList.toArray(new IBeanInfoContributor[contributorsList.size()]);
					info.getJavaProject().getProject().setSessionProperty(BEANINFO_CONTRIBUTORS_SESSION_KEY, explicitContributors);
				} else {
					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().entrySet().iterator();
				while (containerIdItr.hasNext()) {
					Map.Entry entry = (Map.Entry) containerIdItr.next();
					if (((Boolean) entry.getValue()).booleanValue()) {
						processBeaninfoEntries(BeaninfoPlugin.getPlugin().getContainerIdBeanInfos((String) entry.getKey()),
								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 beaninfovm.jar and any nls to the end of the classpath.
			controller.contributeClasspath(BeaninfoPlugin.getPlugin().getDescriptor(), "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 {
			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((String) cp, IConfigurationContributionController.APPEND_USER_CLASSPATH);
				else if (cp instanceof IPath) {
					IPath path = (IPath) cp;
					IPluginDescriptor pd = Platform.getPluginRegistry().getPluginDescriptor(path.segment(0));
					if (pd != null)
						controller.contributeClasspath(pd, path.removeFirstSegments(1).toString(), 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);
					}
				});
			}			
		}
	}


}