/*******************************************************************************
 * Copyright (c) 2004 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials 
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
/*
 *  $RCSfile: ProxyLaunchSupport.java,v $
 *  $Revision: 1.27 $  $Date: 2005/06/21 19:36:48 $ 
 */
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.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 {
		/* (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 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 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;
				Platform.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.
				Platform.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.
				Platform.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();
		configInfo.javaProject = javaProject;
		configInfo.containerIds = new HashMap(5);
		configInfo.containers = new HashMap(5);
		configInfo.pluginIds = new HashMap(5);
		configInfo.projectPaths = new HashMap(5);
		ProxyPlugin.getPlugin().getIDsFound(javaProject, configInfo.containerIds, configInfo.containers, configInfo.pluginIds, configInfo.projectPaths);
		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().keySet().iterator(); iter.hasNext();) {
							String containerid = (String) iter.next();
							IConfigurationElement[] contributors = ProxyPlugin.getPlugin().getContainerConfigurations(containerid);
							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().keySet().iterator(); iter.hasNext();) {
				String containerid = (String) iter.next();
				IConfigurationElement[] contributors = ProxyPlugin.getPlugin().getContainerExtensions(containerid);
				if (contributors != null)
					for (int i = 0; i < contributors.length; i++) {
						if (registryID.equals(contributors[i].getAttributeAsIs(ProxyPlugin.PI_REGISTRY_TYPE))) {
							try {
								final IExtensionRegistration contributor = (IExtensionRegistration) contributors[i].createExecutableExtension(ProxyPlugin.PI_CLASS);
								Platform.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].getAttributeAsIs(ProxyPlugin.PI_REGISTRY_TYPE))) {
							try {
								final IExtensionRegistration contributor = (IExtensionRegistration) contributors[i].createExecutableExtension(ProxyPlugin.PI_CLASS);
								Platform.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 = Platform.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. 
	 * @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++) {
				strings[i] = urls[i] != null ? urls[i].getFile() : null;
			}
			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.
			controller.contributeClasspath(ProxyPlugin.getPlugin().getBundle(), "proxycommon.jar", IConfigurationContributionController.APPEND_USER_CLASSPATH, false);	//$NON-NLS-1$
			controller.contributeClasspath(ProxyPlugin.getPlugin().getBundle(), "initparser.jar", IConfigurationContributionController.APPEND_USER_CLASSPATH, true);	//$NON-NLS-1$			
		}
	}
	
}
