/*******************************************************************************
 * Copyright (c) 2004, 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.proxy.core;

import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.MessageFormat;
import java.util.*;
import java.util.logging.Level;

import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.jobs.IJobManager;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.debug.core.*;
import org.eclipse.jdt.core.*;
import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants;
import org.osgi.framework.Bundle;

import org.eclipse.jem.internal.proxy.core.IConfigurationContributionInfo.ContainerPaths;
import org.eclipse.jem.internal.proxy.core.ProxyPlugin.FoundIDs;
import org.eclipse.jem.util.PerformanceMonitorUtil;
import org.eclipse.jem.util.TimerTests;

 
/**
 * This is the used to launch the proxy registries.
 * This is a static helper class, it is not meant to be instantiated.
 * 
 * @since 1.0.0
 */
public class ProxyLaunchSupport {
	
	// The key for the persisten property is in ProxyPlugin so that it can set it on startup without
	// causing this class to be initialized. We don't want this class initialized until the very last
	// moment when needed. This is because it needs UI to be active when initialized to query some 
	// values and if ProxyPlugin.start() causes this class to initialize, it may be too soon.
	//
	// If a project's persistent property is set with this value, that means there is at least one
	// launch configuration with this project, but none are selected as the default. This is here
	// so that we can check in the object contribution that if not set then don't show the menu
	// item at all. This is to clean up the popup menu so not so cluttered.
	// If the property is trully not set, then there is no default and there are no configurations for it.
	public static final String NOT_SET = "...not..set..";	  //$NON-NLS-1$
		
	public static final String EXPRESSION_TRACING = "/debug/traceexpressions";	// Trace IExpressions. //$NON-NLS-1$
	
	/**
	 * Timer threshold for indicating any expressions that took longer than this.
	 * If not set, then threshold will default to 100ms.
	 * It will only be used if traceexpressions is true.
	 */
	public static final String EXPRESSION_TRACEING_TIMER_THRESHOLD = "/debug/traceexpressionstimethreshold";	 //$NON-NLS-1$
	
	/*
	 * Registry of launch key to LaunchInfo classes.
	 */
	private static Map LAUNCH_INFO = new HashMap(2);

	/**
	 * Public only for access by other launch delegates to set up if they go outside of ProxyLaunchSupport,
	 * e.g. IDE proxy. Must not be used for any purpose.
	 * 
	 * @since 1.0.0
	 */
	public static class LaunchSupportIConfigurationContributionInfo implements IConfigurationContributionInfo {
		
		/**
		 * Construct with no settings. This is to be used by other launch delegates that
		 * don't have a {@link FoundIDs} available to fill in the fields. Those 
		 * delegates must fill the fields themselves.  
		 * 
		 * 
		 * @since 1.2.0
		 */
		public LaunchSupportIConfigurationContributionInfo(IJavaProject javaProject) {
			this.javaProject = javaProject;
		}
		
		public LaunchSupportIConfigurationContributionInfo(IJavaProject javaProject, FoundIDs foundIDs) {
			this(javaProject);
			containerIds = foundIDs.containerIds;
			containers = foundIDs.containers;
			pluginIds = foundIDs.pluginIds;
			projectPaths = foundIDs.projects;
		}
		
		/* (non-Javadoc)
		 * Map of containers (IClasspathContainer) found in classpath (including required projects).
		 * This is for each project found. If there was a container in more than one project with the
		 * id, this set will contain the container from each such project. They are not considered the
		 * same because they come from a different project.
		 * <p>
		 * The key will be the containers, and the value will be a <code>Boolean</code>, where true means it
		 * is visible to the top-level project.
		 * <p>
		 * This is used for determining if a project's container implements the desired contributor.
		 * 
		 * Will be empty if no project sent in to launch configuration.
		 * 
		 * @see org.eclipse.jdt.core.IClasspathContainer
		 * 
		 */
		public Map containers = Collections.EMPTY_MAP;

		
		/* (non-Javadoc)
		 * Map of unique container id strings found in classpath (including required projects).
		 * If a container with the same id was found in more than one project, only one id will
		 * be in this set since they are the same.
		 * <p>
		 * The key will be the container ids, and the value will be ContainerPaths
		 * 
		 * Will be empty if no project sent in to launch configuration.
		 * 
		 */
		public Map containerIds = Collections.EMPTY_MAP;
		
		/* (non-Javadoc)
		 * Set of unique plugin id strings found in classpath (including required projects).
		 * If a required plugin with the same id was found in more than one project, only one id will
		 * be in this set since they are the same.
		 * <p>
		 * The key will be the plugin ids, and the value will be a <code>Boolean</code>, where true means it
		 * is visible to the top-level project.
		 * 
		 * Will be empty if no project sent in to launch configuration.
		 */		
		public Map pluginIds = Collections.EMPTY_MAP;;
		
		/* (non-Javadoc)
		 * Map of unique projects found in classpath (including required projects), but not including top-level project.
		 * <p>
		 * The key will be the <code>IPath</code> for the project, and the value will be a <code>Boolean</code>, where true means it
		 * is visible to the top-level project.
		 * 
		 * Will be <code>null</code> if no project sent in to launch configuration.
		 */		
		public Map projectPaths;
		
		/* (non-Javadoc)
		 * Java project for this launch. <code>null</code> if not for a project.
		 */
		public IJavaProject javaProject;
		
		/* (non-Javadoc)
		 * @see org.eclipse.jem.internal.proxy.core.IConfigurationContributionInfo#getContainerIds()
		 */
		public Map getContainerIds() {
			return containerIds;
		}
		/* (non-Javadoc)
		 * @see org.eclipse.jem.internal.proxy.core.IConfigurationContributionInfo#getContainers()
		 */
		public Map getContainers() {
			return containers;
		}
		
		/* (non-Javadoc)
		 * @see org.eclipse.jem.internal.proxy.core.IConfigurationContributionInfo#getJavaProject()
		 */
		public IJavaProject getJavaProject() {
			return javaProject;
		}
		/* (non-Javadoc)
		 * @see org.eclipse.jem.internal.proxy.core.IConfigurationContributionInfo#getPluginIds()
		 */
		public Map getPluginIds() {
			return pluginIds;
		}
		/* (non-Javadoc)
		 * @see org.eclipse.jem.internal.proxy.core.IConfigurationContributionInfo#getProjectPaths()
		 */
		public Map getProjectPaths() {
			return projectPaths;
		}
		
	}
		
	/**
	 * LaunchInfo for a launch. Stored by key and retrievable by the key.
	 * This is only passed to launch delegates. It should not be passed on to
	 * others, though the IConfigurationContributionInfo may be.
	 * 
	 * <p>
	 * This class is not intended to be subclassed by clients.
	 * </p>
	 * 
	 * @see ProxyLaunchSupport#getInfo(String)
	 * @see IConfigurationContributionInfo
	 * @since 1.0.0
	 */
	public static class LaunchInfo {
		/**
		 * Contributors for this launch. It will never be <code>null</code>. It may be empty.
		 */
		public IConfigurationContributor[] contributors;
		
		/**
		 * The registry returned from the launch. The launch needs to set this before it returns.
		 */
		public ProxyFactoryRegistry resultRegistry;
		

		/* (non-Javadoc)
		 * @see org.eclipse.jem.internal.proxy.core.IConfigurationContributionInfo#getJavaProject()
		 */
		public IJavaProject getJavaProject() {
			return configInfo.getJavaProject();
		}		
		
		/**
		 * Return the IConfigurationContributionInfo for this launch.
		 * @return
		 * 
		 * @since 1.0.0
		 */
		public IConfigurationContributionInfo getConfigInfo() {
			return configInfo;
		}
		
		protected IConfigurationContributionInfo configInfo;
		
	}
	
	/**
	 * Start an implementation using the default config for the given project.
	 * <p> 
	 * This will wait for build. If you
	 * know the build has been suspended by your thread, then you must use the other method that takes a waitForThread
	 * boolean, and you must pass in false. Otherwise it will deadlock.
	 * 
	 * @param project The project. It must be a java project, and it cannot be <code>null</code>.
	 * @param vmTitle title for VM. It may be <code>null</code>.
	 * @param aContribs The contributions array. It may be <code>null</code>.
	 * @param pm
	 * @return The created registry.
	 * @throws CoreException
	 * 
	 * @see ProxyLaunchSupport#startImplementation(IProject, String, IConfigurationContributor[], boolean, IProgressMonitor)
	 * @since 1.0.0
	 */
	public static ProxyFactoryRegistry startImplementation(
			IProject project,
			String vmTitle,
			IConfigurationContributor[] aContribs,
			IProgressMonitor pm)
				throws CoreException {
		return startImplementation(project, vmTitle, aContribs, true, pm);
	}
	
	/**
	 * Start an implementation using the default config for the given project.
	 * <p> 
	 * If you know the build has been suspended by your thread, then you must use call this with false for waitForThread. Otherwise it will deadlock.
	 * 
	 * @param project The project. It must be a java project, and it cannot be <code>null</code>.
	 * @param vmTitle title for VM. It may be <code>null</code>.
	 * @param aContribs The contributions array. It may be <code>null</code>.
	 * @param waitForBuild wait for the build. If caller knows that the build has been suspended by this thread, then it must call this with false. Otherwise a deadlock will occur.
	 * @param pm
	 * @return The created registry.
	 * @throws CoreException
	 * 
	 * @since 1.0.0
	 */
	public static ProxyFactoryRegistry startImplementation(
			IProject project,
			String vmTitle,
			IConfigurationContributor[] aContribs,
			boolean waitForBuild, 
			IProgressMonitor pm)
				throws CoreException {
		// First find the appropriate launch configuration to use for this project.
		// The process is:
		//	1) See if the project's persistent property has a setting for "proxyLaunchConfiguration", if it does,
		//		get the configuration of that name and create a working copy of it.
		//	2) If not, then get the "org.eclipse.jem.proxy.LocalProxyLaunchConfigurationType"
		//		and create a new instance working copy.

		IJavaProject javaProject = JavaCore.create(project);
		if (javaProject == null) {
			throw new CoreException(
					new Status(
							IStatus.WARNING,
							ProxyPlugin.getPlugin().getBundle().getSymbolicName(),
							0,
							MessageFormat.format(
									ProxyMessages.Not_Java_Project_WARN_, 
									new Object[] { project.getName()}),
							null));
		}

		// First if specific set.
		String launchName = project.getPersistentProperty(ProxyPlugin.PROPERTY_LAUNCH_CONFIGURATION);
		ILaunchConfiguration config = null;		
		if (launchName != null && !NOT_SET.equals(launchName)) {
			ILaunchConfiguration[] configs = DebugPlugin.getDefault().getLaunchManager().getLaunchConfigurations();
			for (int i = 0; i < configs.length; i++) {
				if (configs[i].getName().equals(launchName)) {
					config = configs[i];
					break;
				}
			}
			if (config == null || !config.getAttribute(IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, "").equals(project.getName())) { //$NON-NLS-1$
				project.setPersistentProperty(ProxyPlugin.PROPERTY_LAUNCH_CONFIGURATION, (String) null);	// Config not found, or for a different project, so no longer the default.
				config = null;
			}
		}
		
		if (config == null) {
			ILaunchConfigurationWorkingCopy configwc = DebugPlugin.getDefault().getLaunchManager().getLaunchConfigurationType(IProxyConstants.LOCAL_LAUNCH_TYPE).newInstance(null, DebugPlugin.getDefault().getLaunchManager().generateUniqueLaunchConfigurationNameFrom("LocalProxy_"+project.getName())); //$NON-NLS-1$
			configwc.setAttribute(IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, project.getName()); 
			config = configwc;
		}
		
		return startImplementation(config, vmTitle, aContribs, waitForBuild, pm);
	}
	
	/**
	 * Launch a registry using the given configuration.
	 * <p> 
	 * This will wait for build. If you
	 * know the build has been suspended by your thread, then you must use the other method that takes a waitForThread
	 * boolean, and you must pass in false. Otherwise it will deadlock.
	 *
	 * @param config 
	 * @param vmTitle title for VM. It may be <code>null</code>.
	 * @param aContribs The contributions array. It may be <code>null</code>.
	 * @param pm
	 * @return The registry from this configuration.
	 * @throws CoreException
	 * 
	 * @see ProxyLaunchSupport#startImplementation(ILaunchConfiguration, String, IConfigurationContributor[], boolean, IProgressMonitor)
	 * @since 1.0.0
	 */
	public static ProxyFactoryRegistry startImplementation(
			ILaunchConfiguration config,
			String vmTitle,
			IConfigurationContributor[] aContribs,
			IProgressMonitor pm)
			throws CoreException {
		return startImplementation(config, vmTitle, aContribs, true, pm);
	}

	/**
	 * Launch a registry using the given configuration.
	 * <p> 
	 * If you know the build has been suspended by your thread, then you must use you must pass in false for waitForThread. Otherwise it will deadlock.
	 *
	 * @param config
	 * @param vmTitle title for VM. It may be <code>null</code>.
	 * @param aContribs The contributions array. It may be <code>null</code>.
	 * @param waitForBuild wait for the build. If caller knows that the build has been suspended by this thread, then it must call this with false. Otherwise a deadlock will occur.
	 * @param pm
	 * @return The registry from this configuration.
	 * @throws CoreException
	 * 
	 * @since 1.0.0
	 */
	public static ProxyFactoryRegistry startImplementation(
				ILaunchConfiguration config,
				String vmTitle,
				IConfigurationContributor[] aContribs,
				boolean waitForBuild,
				IProgressMonitor pm)
				throws CoreException {

		if (pm == null)
			pm = new NullProgressMonitor();
		String stepId = "Pre-launch VM ( " + vmTitle + " )"; //$NON-NLS-1$ //$NON-NLS-2$
		TimerTests.basicTest.startStep(stepId);
		if (vmTitle.equals("Beaninfo")) //$NON-NLS-1$
			PerformanceMonitorUtil.getMonitor().snapshot(125);
		final ILaunchConfigurationWorkingCopy configwc = config.getWorkingCopy();
		
		pm.beginTask("", 400); //$NON-NLS-1$
		pm.subTask(ProxyMessages.ProxyLaunch);	
		if (waitForBuild) {
			// See if build needed or waiting or inprogress, if so, wait for it to complete. We've
			// decided too difficult to determine if build would affect us or not, so just wait.		
			if (UI_RUNNER != null)
				UI_RUNNER.handleBuild(new SubProgressMonitor(pm, 100));
			else
				runBuild(new SubProgressMonitor(pm, 100));
			
			if (pm.isCanceled())
				return null;
		}
				
		if (aContribs != null) {
			IConfigurationContributor[] newContribs = new IConfigurationContributor[aContribs.length+1];
			System.arraycopy(aContribs, 0, newContribs, 1, aContribs.length);
			newContribs[0] = new ProxyContributor();
			aContribs = newContribs;
		} else
			aContribs = new IConfigurationContributor[] {new ProxyContributor()};

		String launchKey = String.valueOf(System.currentTimeMillis());
		LaunchInfo launchInfo = new LaunchInfo();
		synchronized (ProxyLaunchSupport.class) {
			while (LAUNCH_INFO.containsKey(launchKey)) {
				launchKey += 'a'; // Just add something on to make it unique.
			}
			LAUNCH_INFO.put(launchKey, launchInfo);
		}
		
		String projectName = configwc.getAttribute(IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, (String) null);
		aContribs = fillInLaunchInfo(aContribs, launchInfo, projectName);
		
		try {		
			configwc.setAttribute(IProxyConstants.ATTRIBUTE_LAUNCH_KEY, launchKey);
			if (vmTitle != null && vmTitle.length()>0)
				configwc.setAttribute(IProxyConstants.ATTRIBUTE_VM_TITLE, vmTitle);
			
			if (ATTR_PRIVATE != null)
				configwc.setAttribute(ATTR_PRIVATE, true);			
			
			// Let contributors modify the configuration.
			final IConfigurationContributor[] contribs = aContribs;
			final LaunchInfo linfo = launchInfo;
			for (int i = 0; i < contribs.length; i++) {
				// First run the initialize.
				// Run in safe mode so that anything happens we don't go away.
				final int ii = i;
				SafeRunner.run(new ISafeRunnable() {
					public void handleException(Throwable exception) {
						// Don't need to do anything. Platform.run logs it for me.
					}

					public void run() throws Exception {
						contribs[ii].initialize(linfo.getConfigInfo());
					}
				});

				// Now run the contribute to configuration.
				// Run in safe mode so that anything happens we don't go away.
				SafeRunner.run(new ISafeRunnable() {
					public void handleException(Throwable exception) {
						// Don't need to do anything. Platform.run logs it for me.
					}

					public void run() throws Exception {
						contribs[ii].contributeToConfiguration(configwc);
					}
				});
			}
			pm.worked(100);
			
			configwc.launch(ILaunchManager.RUN_MODE, new SubProgressMonitor(pm, 100));
			
			final ProxyFactoryRegistry reg = launchInfo.resultRegistry;
			if (!pm.isCanceled() && reg == null)
				throw new CoreException(new Status(IStatus.WARNING, ProxyPlugin.getPlugin().getBundle().getSymbolicName(), 0, ProxyMessages.ProxyLaunchSupport_RegistryCouldNotStartForSomeReason_WARN_, null)); 
			if (pm.isCanceled()) {
				if (reg != null)
					reg.terminateRegistry();
				return null;
			}
			
			performExtensionRegistrations((BaseProxyFactoryRegistry) reg, launchInfo);
			
//			TimerTests.basicTest.startStep("contribute to registry");
			for (int i = 0; i < contribs.length; i++) {
				final int ii = i;
				// Run in safe mode so that anything happens we don't go away.
				SafeRunner.run(new ISafeRunnable() {
					public void handleException(Throwable exception) {
						// Don't need to do anything. Platform.run logs it for me.
					}

					public void run() throws Exception {
//						String stepid = "contribute to registry for " + contribs[ii].getClass();
//						TimerTests.basicTest.startStep(stepid);
						contribs[ii].contributeToRegistry(reg);
//						TimerTests.basicTest.stopStep(stepid);
					}
				});
			}
//			TimerTests.basicTest.stopStep("contribute to registry");
		} finally {
			// Clean up and return.
			LAUNCH_INFO.remove(launchKey);
		}	
		
		pm.done();
		if (vmTitle.equals("Beaninfo")) //$NON-NLS-1$
			PerformanceMonitorUtil.getMonitor().snapshot(126);
		TimerTests.basicTest.stopStep(stepId);
		return launchInfo.resultRegistry;
	}
	
	/**
	 * Create a default IConfigurationContributionInfo for the given project. This is useful info even when not launching a
	 * vm.
	 * 
	 * @param javaProject
	 * @return new contrib info.
	 * @throws JavaModelException
	 * 
	 * @since 1.1.0
	 */
	public static IConfigurationContributionInfo createDefaultConfigurationContributionInfo(IJavaProject javaProject) throws JavaModelException {
		LaunchSupportIConfigurationContributionInfo configInfo = new LaunchSupportIConfigurationContributionInfo(javaProject,
				ProxyPlugin.getPlugin().getIDsFound(javaProject));
		return configInfo;

	}
	
	/**
	 * Use in calling {@link ProxyLaunchSupport#fillInLaunchInfo(IConfigurationContributor[], LaunchInfo, String)} for the configuration
	 * contributors array if there are no incoming contributors.
	 * 
	 * @since 1.1.0
	 */
	public static final IConfigurationContributor[] EMPTY_CONFIG_CONTRIBUTORS = new IConfigurationContributor[0];
	/**
	 * Fill in the launch info config info and contribs. The contribs sent in may be expanded due to extension
	 * points and a new one created. Either the expanded copy or the original (if no change) will be stored in
	 * the launchinfo and returned from this call.
	 * 
	 * @param aContribs this should never be <code>null</code>. Pass in {@link ProxyLaunchSupport#EMPTY_CONFIG_CONTRIBUTORS} in that case.
	 * @param launchInfo
	 * @param projectName
	 * @return a modified aContribs if any change was made to it.  This will never be <code>null</code>. It will return an empty list if aContribs was null and no changes were made.
	 * @throws JavaModelException
	 * @throws CoreException
	 * 
	 * @since 1.0.0
	 */
	public static IConfigurationContributor[] fillInLaunchInfo(IConfigurationContributor[] aContribs, LaunchInfo launchInfo, String projectName) throws JavaModelException, CoreException {
		if (projectName != null) {
			projectName = projectName.trim();
			if (projectName.length() > 0) {
				IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName);
				IJavaProject javaProject = JavaCore.create(project);
				if (javaProject != null && javaProject.exists()) {
					launchInfo.configInfo = createDefaultConfigurationContributionInfo(javaProject);
					if (!launchInfo.configInfo.getContainerIds().isEmpty() || !launchInfo.configInfo.getContainers().isEmpty() || !launchInfo.configInfo.getPluginIds().isEmpty()) {
						List computedContributors = new ArrayList(launchInfo.configInfo.getContainerIds().size()+launchInfo.configInfo.getContainers().size()+launchInfo.configInfo.getPluginIds().size());
						// Note: We don't care about the visibility business here. For contributors to proxy it means
						// some classes in the projects/plugins/etc. need configuration whether they are visible or not.
						// This is because even though not visible, some other visible class may instantiate it. So it
						// needs the configuration.
						// First handle explicit classpath containers that implement IConfigurationContributor
						for (Iterator iter = launchInfo.configInfo.getContainers().keySet().iterator(); iter.hasNext();) {
							IClasspathContainer container = (IClasspathContainer) iter.next();
							if (container instanceof IConfigurationContributor)
								computedContributors.add(container);
						}
						
						// Second add in contributors that exist for a container id.
						for (Iterator iter = launchInfo.configInfo.getContainerIds().values().iterator(); iter.hasNext();) {
							ContainerPaths paths = (ContainerPaths) iter.next();
							IConfigurationElement[] contributors = ProxyPlugin.getPlugin().getContainerConfigurations(paths.getContainerId(), paths.getAllPaths());
							if (contributors != null)
								for (int i = 0; i < contributors.length; i++) {
									Object contributor = contributors[i].createExecutableExtension(ProxyPlugin.PI_CLASS);
									if (contributor instanceof IConfigurationContributor)
										computedContributors.add(contributor);
								}
						}
						
						// Finally add in contributors that exist for a plugin id.
						for (Iterator iter = launchInfo.configInfo.getPluginIds().keySet().iterator(); iter.hasNext();) {
							String pluginId = (String) iter.next();
							IConfigurationElement[] contributors = ProxyPlugin.getPlugin().getPluginConfigurations(pluginId);
							if (contributors != null)
								for (int i = 0; i < contributors.length; i++) {
									Object contributor = contributors[i].createExecutableExtension(ProxyPlugin.PI_CLASS);
									if (contributor instanceof IConfigurationContributor)
										computedContributors.add(contributor);
								}
						}
						
						// Now turn into array
						if (!computedContributors.isEmpty()) {
							IConfigurationContributor[] newContribs = new IConfigurationContributor[aContribs.length
									+ computedContributors.size()];
							System.arraycopy(aContribs, 0, newContribs, 0, aContribs.length);
							IConfigurationContributor[] cContribs = (IConfigurationContributor[]) computedContributors
									.toArray(new IConfigurationContributor[computedContributors.size()]);
							System.arraycopy(cContribs, 0, newContribs, aContribs.length, cContribs.length);
							aContribs = newContribs;
						}
					}
				}
			}
		}
		
		launchInfo.contributors = aContribs;
		return aContribs;
	}
	
	/**
	 * Execute the extension registrations that are valid for this type of registry and the launchinfo paths.
	 * <p>
	 * This is meant to be called only by registry implementations that do not launch through a launch configration after the registry is created but
	 * before the {@link IConfigurationContributor#contributeToRegistry(ProxyFactoryRegistry)} is called. This will be called automatically
	 * by registries that used a launch configuration to launch.
	 * 
	 * @param baseRegistry
	 * @param launchInfo
	 * @throws CoreException 
	 * 
	 * @since 1.1.0
	 */
	public static void performExtensionRegistrations(final BaseProxyFactoryRegistry baseRegistry, LaunchInfo launchInfo) throws CoreException {
		IConfigurationContributionInfo configInfo = launchInfo.configInfo;
		if (configInfo != null && (!configInfo.getContainerIds().isEmpty() || !configInfo.getPluginIds().isEmpty())) {
			String registryID = baseRegistry.getRegistryTypeID();
			// Note: We don't care about the visibility business here. For contributors to proxy it means
			// some classes in the projects/plugins/etc. need configuration whether they are visible or not.
			// This is because even though not visible, some other visible class may instantiate it. So it
			// needs the configuration.
			
			// First call registrations that exist for a container id.
			for (Iterator iter = configInfo.getContainerIds().values().iterator(); iter.hasNext();) {
				ContainerPaths paths = (ContainerPaths) iter.next();
				IConfigurationElement[] contributors = ProxyPlugin.getPlugin().getContainerExtensions(paths.getContainerId(), paths.getAllPaths());
				if (contributors != null)
					for (int i = 0; i < contributors.length; i++) {
						if (registryID.equals(contributors[i].getAttribute(ProxyPlugin.PI_REGISTRY_TYPE))) {
							try {
								final IExtensionRegistration contributor = (IExtensionRegistration) contributors[i].createExecutableExtension(ProxyPlugin.PI_CLASS);
								SafeRunner.run(new ISafeRunnable() {
								
									public void run() throws Exception {
										contributor.register(baseRegistry);
									}
								
									public void handleException(Throwable exception) {
										// Don't need to do anything, Platform logs it for me.
									}
								
								});
							} catch (ClassCastException e) {
								// If not right class, just ignore it.
							}
						}
					}
			}
			
			// Finally add in contributors that exist for a plugin id.
			for (Iterator iter = configInfo.getPluginIds().keySet().iterator(); iter.hasNext();) {
				String pluginId = (String) iter.next();
				IConfigurationElement[] contributors = ProxyPlugin.getPlugin().getPluginExtensions(pluginId);
				if (contributors != null)
					for (int i = 0; i < contributors.length; i++) {
						if (registryID.equals(contributors[i].getAttribute(ProxyPlugin.PI_REGISTRY_TYPE))) {
							try {
								final IExtensionRegistration contributor = (IExtensionRegistration) contributors[i].createExecutableExtension(ProxyPlugin.PI_CLASS);
								SafeRunner.run(new ISafeRunnable() {
								
									public void run() throws Exception {
										contributor.register(baseRegistry);
									}
								
									public void handleException(Throwable exception) {
										// Don't need to do anything, Platform logs it for me.
									}
								
								});
							} catch (ClassCastException e) {
								// If not right class, just ignore it.
							}
						}
					}
			}
	}
}


	/*
	 * Run the build. If the original launch was in the UI thread, this will
	 * be called under control of an IProgressService so that it is in a separate
	 * thread and the UI will remain responsive (in that either a busy cursor comes
	 * up or eventually a progress dialog).
	 * If the pm is canceled, this will just return, but the caller must check if the pm is canceled.
	 * 
	 * <package-protected> so that only the UI handler will access it.
	 */
	static void runBuild(IProgressMonitor pm) throws CoreException {
		boolean autobuilding = ResourcesPlugin.getWorkspace().isAutoBuilding();
		if (!autobuilding) {
			try {
				// We are not autobuilding. So kick off a build right here and
				// wait for it. (If we already within a build on this thread, then this
				// will return immediately without building. We will take that risk. If
				// some other thread is building, we will wait for it finish before we
				// can get it and do our build.
				ResourcesPlugin.getWorkspace().build(IncrementalProjectBuilder.INCREMENTAL_BUILD, pm); 
			} catch (OperationCanceledException e) {
				// The pm is already marked canceled, so caller can check that instead.
			} 
		} else {
			pm.beginTask("", 200); //$NON-NLS-1$
			IJobManager jobManager = Job.getJobManager();
			Job currentJob = jobManager.currentJob();
			if (currentJob == null || (!currentJob.belongsTo(ResourcesPlugin.FAMILY_AUTO_BUILD) && !currentJob.belongsTo(ResourcesPlugin.FAMILY_MANUAL_BUILD))) { 
				if (jobManager.find(ResourcesPlugin.FAMILY_AUTO_BUILD).length > 0 || jobManager.find(ResourcesPlugin.FAMILY_MANUAL_BUILD).length >0) {
					// We are not within a build job. If we were, then we don't do the build. We will take
					// that risk. The problem is that if within the build, we can't wait for it to finish because
					// we would stop the thread and so the build would not complete.
					pm.subTask(ProxyMessages.ProxyWaitForBuild); 
					try {
						while (true) {
							try {
								jobManager.join(ResourcesPlugin.FAMILY_AUTO_BUILD, new SubProgressMonitor(pm, 100));
								jobManager.join(ResourcesPlugin.FAMILY_MANUAL_BUILD, new SubProgressMonitor(pm, 100));
								break;
							} catch (InterruptedException e) {
							}
						}
					} catch (OperationCanceledException e) {
					}
				}
			} 
			pm.done();
		}
	}
	
	
	/*
	 * This prevents the launch from being shown. However these constants are in UI component, and we don't
	 * want to pre-req that. So we will get them reflectively instead.
	 * public but only so that launch delegate can get to it.
	 */
	public static String ATTR_PRIVATE;
	private static IUIRunner UI_RUNNER = null;

	static {
		ATTR_PRIVATE = null;
		try {
			// See if we have a UI bundle and it is active. If it exists but is not active,
			// then we won't do anything. If we were running a UI application, it should already
			// of been active before we got here.
			Bundle uiBundle = Platform.getBundle("org.eclipse.ui");	//$NON-NLS-1$
			if (uiBundle != null && uiBundle.getState() == Bundle.ACTIVE) {
				try {
					// We have a UI bundle, so we can load our UIRunner class and it will load fine.
					UI_RUNNER = (IUIRunner) Class.forName("org.eclipse.jem.internal.proxy.core.UIRunner").newInstance(); //$NON-NLS-1$
				} catch (InstantiationException e1) {
					ProxyPlugin.getPlugin().getLogger().log(e1, Level.WARNING);
				}
				
				// So that we can run headless (w/o ui), need to do class forName for debugui contants
				Bundle debuguiBundle = Platform.getBundle("org.eclipse.debug.ui"); //$NON-NLS-1$
				if (debuguiBundle != null && debuguiBundle.getState() == Bundle.ACTIVE) {
					Class debugUIConstants = debuguiBundle.loadClass("org.eclipse.debug.ui.IDebugUIConstants"); //$NON-NLS-1$
					ATTR_PRIVATE = (String) debugUIConstants.getField("ATTR_PRIVATE").get(null); //$NON-NLS-1$
				}
			}			
		} catch (SecurityException e) {
		} catch (ClassNotFoundException e) {
		} catch (NoSuchFieldException e) {
		} catch (IllegalArgumentException e) {
		} catch (IllegalAccessException e) {
		}
	}	

	/* (non-Javadoc)
	 * Only referenced by launch delegates. public because they are in other packages,
	 * or even external developers packages. Not meant to be generally available.
	 * 
	 * This is needed because we can't pass the generic info into a launch configuration
	 * because a launch configuration can't take objects. Only can take strings and numbers.  
	 */
	public static synchronized LaunchInfo getInfo(String key) {
		return (LaunchInfo) LAUNCH_INFO.get(key);
	}
	
	/**
	 * Convert the string path into a valid url.
	 * @param path
	 * @return the url or <code>null</code> if not convertable (i.e. not well-formed).
	 * 
	 * @since 1.0.0
	 */
	public static URL convertStringPathToURL(String path) {
		try {
			return path != null ? new File(path).toURL() : null;
		} catch (MalformedURLException e) {
			return null;
		}
	}

	/**
	 * Convert the string paths into a valid urls.
	 * 
	 * @param paths
	 * @return the urls or <code>null</code> if paths is null. Any path not convertable (i.e. not well-formed) will not be in the final list.
	 * So this means the result length may be smaller than the paths length.
	 * 
	 * @since 1.0.0
	 */
	public static URL[] convertStringPathsToURL(String[] paths) {
		if (paths != null) {
			URL[] result = new URL[paths.length];
			int nextURL = 0;
			for (int i = 0; i < paths.length; i++) {
				URL url = convertStringPathToURL(paths[i]);
				if (url != null)
					result[nextURL++] = url;   
			}
			if (nextURL == 0)
				return null;	// None were found.
			
			if (nextURL != result.length) {
				URL[] nr = new URL[nextURL];
				System.arraycopy(result, 0, nr, 0, nr.length);
				result = nr;
			}
			return result;
		} else
			return null;
	}

	/**
	 * Convert the urls to string array. It is assumed the urls are in file protocol. It handles platform and JDK reqts. too.
	 * @param urls
	 * @return string paths or <code>null</code> if urls is <code>null</code>. Any <code>null</code> entry of urls will result in 
	 * a corresponding <code>null</code> in the strings.
	 * 
	 * @since 1.0.0
	 */
	public static String[] convertURLsToStrings(URL[] urls) {
		if (urls != null) {
			String[] strings = new String[urls.length];
			for (int i = 0; i < urls.length; i++) {
				// [132378] There is a problem with IBM JDK's. They can't handle the getFile() from a URL in the java lib path on Windows.
				// That is because the normalized format of a file url on windows is "file:/D:/asdfasf". But IBM JDKs can't handle the
				// leading slash. Sun JDKs do.
				URL url = urls[i];
				if (url != null) {
					strings[i] = url.getFile();
					if(strings[i].startsWith("/") && Platform.getOS().equals(Platform.OS_WIN32)) //$NON-NLS-1$
						strings[i] = strings[i].substring(1);
				}
			}
			return strings;
		} else
			return null;
	}

	/* (non-Javadoc)
	 * Local contributor used to make sure that certain jars are in the path.
	 * 
	 * @since 1.0.0
	 */
	static class ProxyContributor extends ConfigurationContributorAdapter {
		public void contributeClasspaths(IConfigurationContributionController controller) {
			// Add the required jars to the end of the classpath. (We want proxyCommon and initParser (+ initParser NLS), but they are in the runtime of the proxy bundle (which is jarred up), so we contribute the bundle instead.
			controller.contributeClasspath(ProxyPlugin.getPlugin().getBundle(), (IPath) null, IConfigurationContributionController.APPEND_USER_CLASSPATH, true);	//$NON-NLS-1$
		}
	}
	
}
