/*******************************************************************************
 * Copyright (c) 2001, 2004 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
 *******************************************************************************/
package org.eclipse.jem.internal.proxy.core;
/*
 *  $RCSfile: ProxyPlugin.java,v $
 *  $Revision: 1.36 $  $Date: 2004/11/01 21:43:18 $ 
 */


import java.io.*;
import java.net.URL;
import java.util.*;
import java.util.logging.Level;

import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.*;
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.eclipse.osgi.util.ManifestElement;
import org.osgi.framework.*;

import com.ibm.wtp.common.logger.proxy.Logger;
import com.ibm.wtp.logger.proxyrender.EclipseLogger;

/**
 * The plugin class for the org.eclipse.jem.internal.proxy.core plugin.
 */

public class ProxyPlugin extends Plugin {
	
	/**
	 * This interface is for a listener that needs to know if this plugin (ProxyPlugin) is being shutdown. 
	 * It is needed because there are some extensions that get added dynamically that need to know when the
	 * plugin is being shutdown. Can't use new bundle listener for this because it notifies AFTER shutdown.
	 * 
	 * @since 1.0.0
	 */
	public interface IProxyPluginShutdownListener {
		/**
		 * ProxyPlugin is in shutdown.
		 * 
		 * @since 1.0.0
		 */
		public void shutdown();
	}
	
	private static ProxyPlugin PROXY_PLUGIN = null;
		
	// If this is set to true, then in development mode and it will try for proxy jars in directories.
	private boolean devMode;
	
	private ListenerList shutdownListeners;

	public ProxyPlugin() {
		super();
		PROXY_PLUGIN = this;
		devMode = Platform.inDevelopmentMode();  	
	}

	/**
	 * Access the singleton
	 * @return the singleton plugin
	 * 
	 * @since 1.0.0
	 */
	public static ProxyPlugin getPlugin() {
		return PROXY_PLUGIN;
	}
	
	private Logger logger;
	public Logger getLogger() {
		if (logger == null)
			logger = EclipseLogger.getEclipseLogger(this);
		return logger;
	}	

	/**
	 * 
	 * @param pluginDescriptor
	 * @param filenameWithinPlugin
	 * @return
	 * @deprecated see localizeFromPluginDescriptor(Bundle, String) instead.
	 */
	public String localizeFromPluginDescriptor(IPluginDescriptor pluginDescriptor, String filenameWithinPlugin) {
		return localizeFromBundle(Platform.getBundle(pluginDescriptor.getUniqueIdentifier()), filenameWithinPlugin);
	}

	/**
	 * This will take the bundle and file name and make it local and return that
	 * fully qualified. It will look in fragments, but only returns first found. If there can be multiples use
	 * the one for bundles and it fragments.
	 * <p>
	 * If we are in development and it will pick it up from the path
	 * that is listed in the proxy.jars file located in the bundle passed in. This allows development code to be
	 * used in place of the actual runtime jars. If the runtime jars are found,
	 * they will be used.
	 * <p>
	 * For example if looking for file runtime/xyz.jar in bundle abc, then in bundle directory for abc,
	 * there should be a file called proxy.jars. This should only be in development, this file should not
	 * be distributed for production. It would be distributed in the SDK environment when testing is desired.
	 * <p>
	 * The format of the file is:
	 * 	runtimefile=/projectname/builddirectory
	 * <p>
	 * For this to work when the actual jar is not found, the Eclipse must of been started in 
	 * dev mode (i.e. the bundle location will be a project within the developer Eclipse. That way
	 * we can go up one level for the current install location and assume the above projectname
	 * will be found relative to the directory.
	 * <p>
	 * For the above example:
	 * 	runtime/xyz.jar=/xyzproject/bin
	 * <p>
	 * It will return "." if file can't be found. It means nothing but it won't cause jvm to crash.
	 * 
	 * @param bundle
	 * @param filenameWithinBundle
	 * @return the path to the file or <code>"."</code> if not found.
	 * 
	 * @since 1.0.0
	 */
	public String localizeFromBundle(Bundle bundle, String filenameWithinBundle) {
		URL url = urlLocalizeFromBundle(bundle, filenameWithinBundle);
		return url != null ? getFileFromURL(url) : "."; //$NON-NLS-1$
	}
	
	/**
	 * @deprecated see localizeFromPluginDescriptorAndFragments(Bundle, String) instead.
	 */
	public String[] localizeFromPluginDescriptorAndFragments(IPluginDescriptor pluginDescriptor, String filenameWithinPlugin) {
		return localizeFromBundleAndFragments(Platform.getBundle(pluginDescriptor.getUniqueIdentifier()), filenameWithinPlugin);
	}
	

	/**
	 * Just like localizeFromBundle except it will return an array of Strings. It will look for the filename
	 * within the bundle and any fragments of the bundle. If none are found, an empty array will be returned.
	 * <p>
	 * To find the files in the fragments that are in the runtime path (i.e. libraries), it will need to use a suffix,
	 * This is because the JDT will get confused if a runtime jar in a fragment has the same name
	 * as a runtime jar in the main bundle.
	 * NOTE: This is obsolete. JDT no longer has this problem. So we can find libraries in fragments that have the
	 * same file path. 
	 * <p>
	 * So we will use the following search pattern:
	 * <ol>
	 * <li>Find in all of the fragments those that match the name exactly in the same paths if paths are supplied.</li>
	 * <li>Find in all of the fragments, in their runtime path (library stmt), those that match the name 
	 *    but have a suffix the same as the uniqueid of the fragment (preceeded by a period). This is so that it can be easily
	 *    found but yet be unique in the entire list of fragments. For example if looking for "runtime/xyz.jar"
	 *    and we have fragment "a.b.c.d.frag", then in the runtime path we will look for the file
	 *    "runtime/xyz.a.b.c.d.frag.jar". Note: This is obsolete. Still here only for possible old code. Will go 
	 *    away in future.</li>
	 * <p>
	 * If the files in the fragments are not in the fragments library path then it can have the same name. NOTE: Obsolete,
	 * JDT can now handle same name.
	 * <p>
	 * This is useful for nls where the nls for the filename will be in one or more of the fragments of the plugin.
	 * 
	 * @param bundle
	 * @param filenameWithinBundle
	 * @return
	 * 
	 * @since 1.0.0
	 */
	public String[] localizeFromBundleAndFragments(Bundle bundle, String filenameWithinBundle) {
		URL[] urls = urlLocalizeFromBundleAndFragments(bundle, filenameWithinBundle);
		String[] result = new String[urls.length];
		for (int i = 0; i < urls.length; i++) {
			result[i] = getFileFromURL(urls[i]);
		}
		return result;
	}
	
	private static String getFileFromURL(URL url) {
		// We need to do this in a device independent way. The URL will always put a leading '/' in the
		// file part of the URL, but on Windows we need to have this '/' removed. Some JRE's don't understand it.
		return new File(url.getFile()).getAbsolutePath();

	}

	/**
	 * Like <code>urlLocalizeFromBundleAndFragments(Bundle, String)</code> except takes a path.
	 * 
	 * @param bundle
	 * @param filenameWithinBundle
	 * @return
	 * 
	 * @see #urlLocalizeFromBundle(Bundle, String)
	 * @since 1.0.0
	 */
	public URL[] urlLocalizeFromBundleAndFragments(Bundle bundle, IPath filenameWithinBundle) {
		Bundle[] fragments = Platform.getFragments(bundle); // See if there are any fragments
		if (fragments == null || fragments.length == 0) {
			URL result = urlLocalizeFromBundle(bundle, filenameWithinBundle);
			return result != null ? new URL[] { result } : new URL[0];
		} else {
			return urlLocalizeBundleAndFragments(bundle, fragments, filenameWithinBundle.toString());
		}
	}
	
	/**
	 * Like <code>localizeFromBundleAndFragments</code> except it returns URL's instead.
	 * @param bundle
	 * @param filenameWithinBundle
	 * @return
	 * 
	 * @see ProxyPlugin#localizeFromBundleAndFragments(Bundle, String)
	 * @since 1.0.0
	 */
	public URL[] urlLocalizeFromBundleAndFragments(Bundle bundle, String filenameWithinBundle) {
		Bundle[] fragments = Platform.getFragments(bundle); // See if there are any fragments
		if (fragments == null || fragments.length == 0) {
			URL result = urlLocalizeFromBundle(bundle, filenameWithinBundle);
			return result != null ? new URL[] { result } : new URL[0];
		} else {
			return urlLocalizeBundleAndFragments(bundle, fragments, filenameWithinBundle);
		}
	}
	
	/**
	 * @param bundle
	 * @param filenameWithinBundle
	 * @param fragments
	 * @return
	 * 
	 * @since 1.0.0
	 */
	private URL[] urlLocalizeBundleAndFragments(Bundle bundle, Bundle[] fragments, String filenameWithinBundle) {
		ArrayList urls = new ArrayList(fragments.length + 1);
		URL url = urlLocalizeFromBundleOnly(bundle, filenameWithinBundle);
		if (url != null)
			urls.add(url);
		for (int i = 0; i < fragments.length; i++) {
			Bundle fragment = fragments[i];
			url =  urlLocalizeFromBundleOnly(fragment, filenameWithinBundle);
			if (url != null)
				urls.add(url);
			// Also, look through the libraries of the fragment to see if one matches the special path.				
			// This is where one of the runtime libraries has the fragment id in it. 
			//  (As for why we are doing this, look at the comment for localizeFromPluginDescriptorAndFragments, but this is obsolete).
			String classpath = (String) fragment.getHeaders().get(Constants.BUNDLE_CLASSPATH);
			try {
				ManifestElement[] classpaths = ManifestElement.parseHeader(Constants.BUNDLE_CLASSPATH, classpath);
				if (classpaths != null && classpaths.length > 0) {
					int extndx = filenameWithinBundle.lastIndexOf('.');
					String libFile = null;
					if (extndx != -1)
						libFile =
							filenameWithinBundle.substring(0, extndx)
								+ '.'
								+ fragment.getSymbolicName()
								+ filenameWithinBundle.substring(extndx);
					else
						libFile = filenameWithinBundle + '.' + fragment.getSymbolicName();
					for (int j = 0; j < classpaths.length; j++) {
						IPath cp = new Path(classpaths[j].getValue());
						// The last segment should be the file name. That is the name we are looking for.
						if (libFile.equals(cp.lastSegment())) {
							url = urlLocalizeFromBundleOnly(fragment, classpaths[j].getValue());
							// Though the actual classpath entry is the file we are looking for.
							if (url != null)
								urls.add(url);
							break;
						}
					}
				}
			} catch (BundleException e) {
				getLogger().log(e, Level.INFO);
			}
		}
		return (URL[]) urls.toArray(new URL[urls.size()]);
	}

	private static final String PROXYJARS = "proxy.jars";	//$NON-NLS-1$
	private static final IPath PROXYJARS_PATH = new Path(PROXYJARS); 
	
	/**
	 * @see ProxyPlugin#localizeFromBundle(Bundle, String)
	 * 
	 * This is just a helper to return a url instead.
	 * 
	 * @param bundle
	 * @param filenameWithinBundle
	 * @return
	 * 
	 * @since 1.0.0
	 */
	public URL urlLocalizeFromBundle(Bundle bundle, String filenameWithinBundle) {
		return urlLocalizeFromBundle(bundle, new Path(filenameWithinBundle));
	}
	
	/**
	 * @see ProxyPlugin#localizeFromBundle(bundle, String)
	 * 
	 * This is just a helper to return a url instead.
	 * 
	 * @param bundle
	 * @param filenameWithinBundle
	 * @return
	 * 
	 * @since 1.0.0
	 */
	public URL urlLocalizeFromBundle(Bundle bundle, IPath filenameWithinBundle) {					
		try {
			URL pvm = Platform.find(bundle, filenameWithinBundle);
			pvm = verifyFound(pvm);
			if (pvm != null)
				return pvm;
		} catch (IOException e) {
		}

		return findDev(bundle, filenameWithinBundle.toString());
	}

	protected URL urlLocalizeFromBundleOnly(Bundle bundle, String filenameWithinBundle) {
		try {
			URL pvm = bundle.getEntry(filenameWithinBundle);
			pvm = verifyFound(pvm);
			if (pvm != null)
				return pvm;
		} catch (IOException e) {
		}

		return findDev(bundle, filenameWithinBundle);
	}
	
	private URL verifyFound(URL pvm) throws IOException {
		if (pvm != null)
			pvm = Platform.asLocalURL(pvm);
		if (devMode) {
			// Need to test if found in devmode. Otherwise we will just assume it is found. If not found on remote and moved to cache, an IOException would be thrown.
			if (pvm != null) {
				InputStream ios = null;
				try {
					ios = pvm.openStream();
					if (ios != null)
						return pvm; // Found it, so return it.
				} finally {
					if (ios != null)
						ios.close();
				}
			}
		} else
			return pvm;
		return null;
	}
	
	private URL findDev(Bundle bundle, String filenameWithinBundle) {
		if (devMode) {
			// Got this far and in dev mode means it wasn't found, so we'll try for development style.
			// It is assumed that in dev mode, we are running with the IDE as local and any 
			// build outputs will be local so local file protocol will be returned
			// from Platform.resolve(). We won't be running in dev mode with our entireplugin being in a jar,
			// or on a separate system.
			try {
				URL pvm = Platform.find(bundle, PROXYJARS_PATH);
				if (pvm != null) {
					InputStream ios = null;
					try {
						ios = pvm.openStream();
						Properties props = new Properties();
						props.load(ios);
						String pathString = props.getProperty(filenameWithinBundle.toString());
						if (pathString != null) {
							URL url = Platform.resolve(bundle.getEntry("/"));	// It is assumed that if in debug mode, then this plugin is an imported plugin within the developement workspace.
							if (url.getProtocol().equals("file")) {
								File file = new File(url.getFile()).getParentFile();	// This gets us to workspace root of development workspace.
								file = new File(file, pathString);
								return file.toURL();
							}
						}
					} finally {
						if (ios != null)
							ios.close();
					}
				}
			} catch (IOException e) {
			}
		}
		
		return null;

	}
	
	/**
	 * A helper to order the plugins into pre-req order. 
	 * If A eventually depends on B, then B will be ahead of A in the
	 * list of plugins. (I.e. B is a pre-req somewhere of A).
	 *  
	 * @param bundlesToOrder - Bundles of interest. The results will have these in thiee correct order.
	 * @return An array of the Bundlers in there order from no prereqs in set to the leaves.
	 * 
	 * @since 1.0.0
	 */
	public static Bundle[] orderPlugins(final Set bundlesToOrder) {
		Map prereqsMap = new HashMap(bundlesToOrder.size()*3);
		int ndx = bundlesToOrder.size();
		Bundle[] result = new Bundle[ndx];
		Map dependents = getDependentCounts(false, bundlesToOrder, prereqsMap);	// We want the inactive ones too. That way have complete order. They can be ignored later if necessary.
		// keep iterating until all have been visited. This will actually find them in reverse order from what we
		// want, i.e. it will find the leaves first. So we will build result array in reverse order.
		while (!dependents.isEmpty()) {
			// loop over the dependents list.  For each entry, if there are no dependents, visit
			// the bundle and remove it from the list.  Make a copy of the keys so we don't end up
			// with concurrent accesses (since we are deleting the values as we go)
			Iterator ib = dependents.entrySet().iterator();
			while (ib.hasNext()) {
				Map.Entry entry = (Map.Entry) ib.next();
				Bundle bundle = (Bundle) entry.getKey() ;
				int[] count = (int[]) entry.getValue();
				if (count != null && count[0] <= 0) {
					if (bundlesToOrder.contains(bundle)) {
						result[--ndx] = bundle;
						if (ndx == 0)
							return result;	// We've ordered all that we care about. Anything left over is unimportant.
					}
					ib.remove();
					// decrement the dependent count for all of the prerequisites.
					List requires = getPrereqs(bundle, prereqsMap);
					for (int j = 0; j < requires.size(); j++) {
						Bundle prereq = (Bundle) requires.get(j);
						int[] countPrereq = (int[]) dependents.get(prereq);
						if (countPrereq != null)
							--countPrereq[0];
					}
				}
			}
		}		
		return result;
	}
	
	/**
	 * Get all of the prereqs for this bundle, all of the way down to the root.
	 * They will be in top-down depth-first order. There won't be duplicates. They will show up
	 * only once the first time they are found.
	 * 
	 * @param bundle
	 * @return list of all pre-reqs.
	 * 
	 * @since 1.0.0
	 */
	public static List getAllPrereqs(Bundle bundle) {
		List prereqs = new ArrayList();
		getAllPrereqs(bundle, prereqs, new HashMap());
		return prereqs;
	}
	
	private static void getAllPrereqs(Bundle bundle, List prereqs, Map prereqsMap) {
		List prs = getPrereqs(bundle, prereqsMap);
		for (int i = 0; i < prs.size(); i++) {
			Bundle pre = (Bundle) prs.get(i);
			if (prereqsMap.containsKey(pre))
				continue;	// Already processed this one once.
			prereqs.add(pre);	// Add to the list of pre-reqs accumulated so far.
			getAllPrereqs(pre, prereqs, prereqsMap);
		}
	}
	
	private static List getPrereqs(Bundle bundle, Map prereqsMap) {
		List prereqs = (List) prereqsMap.get(bundle);
		if (prereqs == null) {
			prereqs = getPrereqs(bundle);
			prereqsMap.put(bundle, prereqs);
		}
		return prereqs;
	}
	
	/**
	 * Get the immediate pre-req'ed bundles for this bundle. 
	 * 
	 * @param bundle
	 * @return the prereq'ed bundles.
	 * 
	 * @since 1.0.0
	 */
	public static List getPrereqs(Bundle bundle) {
		List requires = null; 
		try {
			String requiresList = (String) bundle.getHeaders().get(Constants.REQUIRE_BUNDLE);
			ManifestElement[] requiresElements = ManifestElement.parseHeader(Constants.REQUIRE_BUNDLE, requiresList);
			if (requiresElements != null) {
				for (int i = 0; i < requiresElements.length; i++) {
					Bundle b = Platform.getBundle(requiresElements[i].getValue());
					if (b != null) {
						if (requires == null)
							requires = new ArrayList(2);
						requires.add(b);
					}
				}
			}
			// Now for each fragment, get the dependents of the fragment.
			Bundle[] fragments = Platform.getFragments(bundle);
			if (fragments != null) {
				if (requires == null)
					requires = new ArrayList(fragments.length);				
				for (int i = 0; i < fragments.length; i++) {
					requires.addAll(getPrereqs(fragments[i]));
				}
			}
		} catch (BundleException e) {
			ProxyPlugin.getPlugin().getLogger().log(e, Level.INFO);
		}
		return requires == null ? Collections.EMPTY_LIST : requires;
	}
	
	private static Map getDependentCounts(boolean activeOnly, Set startingSet, Map prereqsMap) {
		Map dependents = new HashMap(startingSet.size());
		// build a table of all dependent counts.  The table is keyed by descriptor and
		// the value the integer number of dependent plugins.
		List processNow = new ArrayList(startingSet);
		List processNext = new ArrayList(processNow.size());
		if (!processNow.isEmpty()) {
			// Go through the first time from the starting set to get an entry into the list.
			// If there is an entry, then it won't be marked for processNext. Only new entries
			// are added to processNext in the following loop.
			int pnSize = processNow.size();
			for (int i = 0; i < pnSize; i++) {
				Bundle bundle = (Bundle) processNow.get(i);
				if (activeOnly && bundle.getState() != Bundle.ACTIVE)
					continue;
				// ensure there is an entry for this descriptor (otherwise it will not be visited)
				int[] entry = (int[]) dependents.get(bundle);
				if (entry == null)
					dependents.put(bundle, new int[1]);
			}
		}
		
		// Now process the processNow to find the requireds, increment them, and add to processNext if never found before.
		while (!processNow.isEmpty()) {
			processNext.clear();
			int pnSize = processNow.size();
			for (int i = 0; i < pnSize; i++) {
				Bundle bundle = (Bundle) processNow.get(i);
				if (activeOnly && bundle.getState() != Bundle.ACTIVE)
					continue;			
				List requires = getPrereqs(bundle, prereqsMap);
				for (int j = 0; j < requires.size(); j++) {
					Bundle prereq = (Bundle) requires.get(j);
					if (prereq == null || activeOnly
							&& bundle.getState() != Bundle.ACTIVE)
						continue;
					int[] entry = (int[]) dependents.get(prereq);
					if (entry == null) {
						dependents.put(prereq, new int[]{1});
						processNext.add(prereq); // Never processed before, so we add it to the next process loop.
					} else
						++entry[0];
				}
			}
			
			// Now swap the lists so that we processNext will be now and visa-versa.
			List t = processNext;
			processNext = processNow;
			processNow = t;
		}
		return dependents;
	}
		
	/**
	 * Add a shutdown listener
	 * @param listener
	 * 
	 * @since 1.0.0
	 */
	public void addProxyShutdownListener(IProxyPluginShutdownListener listener) {
		if (shutdownListeners == null)
			shutdownListeners = new ListenerList();
		shutdownListeners.add(listener);
	}

	/**
	 * Remove a shutdown listener
	 * @param listener
	 * 
	 * @since 1.0.0
	 */
	public void removeProxyShutdownListener(IProxyPluginShutdownListener listener) {
		if (shutdownListeners != null)
			shutdownListeners.remove(listener);
	}
	
	private ILaunchConfigurationListener launchListener = new ILaunchConfigurationListener() {
		public void launchConfigurationAdded(ILaunchConfiguration configuration) {
			try {
				if (!configuration.isWorkingCopy() && IProxyConstants.ID_PROXY_LAUNCH_GROUP.equals(configuration.getCategory()))
					startCleanupJob();
			} catch (Exception e) {
			}
		}

		public void launchConfigurationChanged(ILaunchConfiguration configuration) {
			try {
				if (!configuration.isWorkingCopy() && IProxyConstants.ID_PROXY_LAUNCH_GROUP.equals(configuration.getCategory()))
					startCleanupJob();
			} catch (Exception e) {
			}
		}

		public void launchConfigurationRemoved(ILaunchConfiguration configuration) {
			try {
				// On delete you can't tell the category or anything because all of that info has already removed.
				if (!configuration.isWorkingCopy())
					startCleanupJob();
			} catch (Exception e) {
			}
		}
	};
	
	private Job cleanupJob = new Job(ProxyMessages.getString("ProxyPlugin.CleanupDefaultProxyLaunchConfigurations")) { //$NON-NLS-1$
		{
			setSystem(true);	// So it doesn't show up in progress monitor. No need to interrupt user.
			setPriority(Job.SHORT);	// A quick running job.
		}
		protected IStatus run(IProgressMonitor monitor) {
			synchronized (this) {
				if (monitor.isCanceled())
					return Status.CANCEL_STATUS;
			}
			// all we want to do is find out if any launch configurations (from proxy launch group) exist for
			// a project. If they don't, then unset the project's property. If they do, and the property is not
			// set, then set it to NOT_SET to indicate not set, but there are some configs for it.
			// We just gather the project names that have launch configurations.
			try {
				Set projectNames = new HashSet();
				ILaunchConfiguration[] configs = DebugPlugin.getDefault().getLaunchManager().getLaunchConfigurations();
				for (int i = 0; i < configs.length; i++) {
					if (IProxyConstants.ID_PROXY_LAUNCH_GROUP.equals(configs[i].getCategory())
						&& (ProxyLaunchSupport.ATTR_PRIVATE == null || !configs[i].getAttribute(ProxyLaunchSupport.ATTR_PRIVATE, false)))
						projectNames.add(configs[i].getAttribute(IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, ""));
				}

				IJavaModel model = JavaCore.create(ResourcesPlugin.getWorkspace().getRoot());
				IJavaElement[] children = model.getChildren();
				int cancelCount = 10;
				for (int j = 0; j < children.length; j++) {
					if (children[j].getElementType() == IJavaElement.JAVA_PROJECT) {
						if (--cancelCount <= 0)
							synchronized (this) {
								cancelCount = 10;	// Rest for next set of ten.
								// Checking on every 10 projects because they may be many projects, while only few configs.
								// This way it will stop sooner.
								if (monitor.isCanceled())
									return Status.CANCEL_STATUS;
							}						
						IProject p = ((IJavaProject) children[j]).getProject();
						if (projectNames.contains(p.getName())) {
							// This project has a launch config. If it has a setting, then do nothing, else need to put on not set. 
							if (p.getPersistentProperty(ProxyPlugin.PROPERTY_LAUNCH_CONFIGURATION) == null)
								p.getProject().setPersistentProperty(
									ProxyPlugin.PROPERTY_LAUNCH_CONFIGURATION,
									ProxyLaunchSupport.NOT_SET);
						} else {
							// This project has no launch configs. Remove any setting if it exists.
							p.setPersistentProperty(ProxyPlugin.PROPERTY_LAUNCH_CONFIGURATION, (String) null);
						}
					}
				}
				return Status.OK_STATUS;
			} catch (CoreException e) {
				return e.getStatus();
			}
		}
	};
	
	private void startCleanupJob() {
		cleanupJob.cancel();	// Stop what we are doing.
		cleanupJob.schedule(1000l);	// Schedule to start in one second.
	}

	
	/* (non-Javadoc)
	 * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
	 */
	public void start(final BundleContext context) throws Exception {
		super.start(context);
		DebugPlugin.getDefault().getLaunchManager().addLaunchConfigurationListener(launchListener);
		context.addBundleListener(new BundleListener() {
			public void bundleChanged(BundleEvent event) {
				if (event.getBundle() != ProxyPlugin.this.getBundle())
					return;	// Not of interest to us.
				switch (event.getType()) {
					case BundleEvent.STARTED:
						context.removeBundleListener(this);	// Since we don't care anymore
						startCleanupJob();
						break;
					case BundleEvent.STOPPED:
					case BundleEvent.UNINSTALLED:
					case BundleEvent.UNRESOLVED:
						context.removeBundleListener(this);	// We stopped before we started, so remove ourselves.
						break;
				}
			}
		});
	}
	

	/* (non-Javadoc)
	 * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
	 */
	public void stop(BundleContext context) throws Exception {
		// Handle case where debug plugin shuts down before we do since order not guarenteed.
		if (DebugPlugin.getDefault() != null)
			DebugPlugin.getDefault().getLaunchManager().removeLaunchConfigurationListener(launchListener);
		cleanupJob.cancel();	// Stop what we are doing.		
		if (shutdownListeners != null) {
			Object[] listeners = shutdownListeners.getListeners();
			for (int i = 0; i < listeners.length; i++) {
				((IProxyPluginShutdownListener) listeners[i]).shutdown();
			}
		}		
		super.stop(context);
	}
	
	public static final String PI_CONFIGURATION_CONTRIBUTION_EXTENSION_POINT = "org.eclipse.jem.proxy.contributors"; //$NON-NLS-1$
	public static final String PI_CONTAINER = "container"; //$NON-NLS-1$
	public static final String PI_PLUGIN = "plugin"; //$NON-NLS-1$
	public static final String PI_CLASS = "class"; //$NON-NLS-1$
	
	/*
	 * Map of container id's to their ordered array of contribution config elements.
	 */
	protected Map containerToContributions = null;
	/*
	 * Map of plugin id's to their ordered array of contribution config elements.
	 */
	protected Map pluginToContributions = null;

	/**
	 * These are public only so that jem.ui can access this constant. Not meant to be accessed by others.
	 */
	public static final QualifiedName PROPERTY_LAUNCH_CONFIGURATION = new QualifiedName("org.eclipse.jem.proxy", "proxyLaunchConfiguration"); //$NON-NLS-1$ //$NON-NLS-2$
	
	/**
	 * Return the plugin ordered array of configuration elements for the given container, or <code>null</code> if not contributed.
	 * 
	 * @param containerid
	 * @return Array of configuration elements or <code>null</code> if this container has no contributions.
	 * 
	 * @since 1.0.0
	 */
	public synchronized IConfigurationElement[] getContainerConfigurations(String containerid) {
		if (containerToContributions == null)
			processProxyContributionExtensionPoint();
		return (IConfigurationElement[]) containerToContributions.get(containerid);
	}

	/**
	 * Return the plugin ordered array of configuration elements for the given plugin, or <code>null</code> if not contributed.
	 * 
	 * @param pluginid
	 * @return Array of configuration elements or <code>null</code> if this plugin has no contributions.
	 * 
	 * @since 1.0.0
	 */
	public synchronized IConfigurationElement[] getPluginConfigurations(String pluginid) {
		if (pluginToContributions == null)
			processProxyContributionExtensionPoint();
		return (IConfigurationElement[]) pluginToContributions.get(pluginid);
	}
	
	protected synchronized void processProxyContributionExtensionPoint() {
		ContributorExtensionPointInfo info = processContributionExtensionPoint(PI_CONFIGURATION_CONTRIBUTION_EXTENSION_POINT);
		containerToContributions = info.containerToContributions;
		pluginToContributions = info.pluginToContributions;
	}
	
	/**
	 * Result form processContributionExtensionPoint.
	 * 
	 * @see ProxyPlugin#processContributionExtensionPoint(String)
	 * @since 1.0.0
	 */
	public static class ContributorExtensionPointInfo {
		/**
		 * Map of container ids (String) to contributions (IConfigurationElement[]) that was found with that id. For each container,
		 * the contributions will be listed in plugin prereq order.
		 */
		public Map containerToContributions;
		
		/**
		 * Map of plugin ids (String) to contributions (IConfigurationElement[]) that was found with that id. For each plugin,
		 * the contributions will be listed in plugin prereq order.
		 */
		public Map pluginToContributions;
	}

	/**
	 * Process the extension point looking contributors. It will find entries that have the "container" or "plugin" attributes
	 * set on them.
	 * 
	 * @param extensionPoint fully-qualified extension point id, including plugin id of the extension point.
	 * @return the contributor info record.
	 * 
	 * @since 1.0.0
	 */
	public static ContributorExtensionPointInfo processContributionExtensionPoint(String extensionPoint) {	
		// We are processing this once because it is accessed often (once per vm per project).
		// This can add up so we get it together once here.
		IExtensionPoint extp = Platform.getExtensionRegistry().getExtensionPoint(extensionPoint);
		ContributorExtensionPointInfo result = new ContributorExtensionPointInfo();
		if (extp == null) {
			result.containerToContributions = Collections.EMPTY_MAP;
			result.pluginToContributions = Collections.EMPTY_MAP;
			return result;
		}
		
		IExtension[] extensions = extp.getExtensions();
		// Need to be in plugin order so that first ones processed have no dependencies on others.
		HashMap bundlesToExtensions = new HashMap(extensions.length);
		for (int i = 0; i < extensions.length; i++) {
			Bundle bundle = Platform.getBundle(extensions[i].getNamespace());
			IExtension[] ext = (IExtension[]) bundlesToExtensions.get(bundle);
			if (ext == null)
				bundlesToExtensions.put(bundle, new IExtension[] {extensions[i]});
			else {
				// More than one extension defined in this plugin.
				IExtension[] newExt = new IExtension[ext.length + 1];
				System.arraycopy(ext, 0, newExt, 0, ext.length);
				newExt[newExt.length-1] = extensions[i];
				bundlesToExtensions.put(bundle, newExt);
			}
		}
		
		// Now order them so we process in required order.
		Bundle[] ordered = ProxyPlugin.orderPlugins(bundlesToExtensions.keySet());
		result.containerToContributions = new HashMap(ordered.length);
		result.pluginToContributions = new HashMap(ordered.length);
		for (int i = 0; i < ordered.length; i++) {
			IExtension[] exts = (IExtension[]) bundlesToExtensions.get(ordered[i]);
			for (int j = 0; j < exts.length; j++) {
				IConfigurationElement[] configs = exts[j].getConfigurationElements();
				// Technically we expect the config elements to have a name of "contributor", but since that
				// is all that can be there, we will ignore it. The content is what is important.
				for (int k = 0; k < configs.length; k++) {
					String container = configs[k].getAttributeAsIs(PI_CONTAINER);
					if (container != null) {
						List contributions = (List) result.containerToContributions.get(container);
						if (contributions == null) {
							contributions = new ArrayList(1);
							result.containerToContributions.put(container, contributions);
						}
						contributions.add(configs[k]);
					}
					String plugin = configs[k].getAttributeAsIs(PI_PLUGIN);
					if (plugin != null) {
						List contributions = (List) result.pluginToContributions.get(plugin);
						if (contributions == null) {
							contributions = new ArrayList(1);
							result.pluginToContributions.put(plugin, contributions);
						}
						contributions.add(configs[k]);
					}
				}
			} 
		}
		
		// Now go through and turn all of the contribution lists into arrays.
		for (Iterator iter = result.containerToContributions.entrySet().iterator(); iter.hasNext();) {
			Map.Entry entry = (Map.Entry) iter.next();
			entry.setValue(((List) entry.getValue()).toArray(new IConfigurationElement[((List) entry.getValue()).size()]));
		}
		for (Iterator iter = result.pluginToContributions.entrySet().iterator(); iter.hasNext();) {
			Map.Entry entry = (Map.Entry) iter.next();
			entry.setValue(((List) entry.getValue()).toArray(new IConfigurationElement[((List) entry.getValue()).size()]));
		}

		return result;
	}
	
	/**
	 * For the given java project, return the maps of container paths and plugins found. The keys will be of type as specified for the parms
	 * while the value will be Boolean, true if it was visible, and false if it wasn't.
	 * For example if <code>/SWT_CONTAINER/subpath1</code> is found in the projects path (or from required projects), then
	 * the container id will be added to the map. They come from the raw classpath entries of the projects.
	 *
	 * @param jproject
	 * @param containerIds This map will be filled in with container ids as keys (type is <code>java.lang.String</code>) that are found in the projects build path. The value will be a Boolean, true if this container id was visible to the project (i.e. was in the project or was exported from a required project).
	 * @param containers This map will be filled in with classpath containers as keys found in the projects build path. The value will be a Boolean as in container ids map.
	 * @param pluginIds This map will be filled in with plugin ids as keys (type is <code>java.lang.String</code>) that are found in the projects build path. The value will be a Boolean as in container ids map.
	 * @param projects This map will be filled in with project paths (except the top project) as keys (type is <code>org.eclipse.core.runtime.IPath</code>) that are found in the projects build path. The value will be a Boolean as in container ids map.
	 * 
	 * @since 1.0.0
	 */
	public void getIDsFound(IJavaProject jproject, Map containerIds, Map containers, Map pluginIds, Map projects) throws JavaModelException {		
		IPath projectPath = jproject.getProject().getFullPath();
		projects.put(projectPath, Boolean.TRUE);		
		expandProject(projectPath, containerIds, containers, pluginIds, projects, true, true);
		projects.remove(projectPath);	// Don't need to include itself now, was needed for testing so if ciruclar we don't get into a loop.
	}
	
	/*
	 * The passed in visible flag tells if this project is visible and its contents are visible if they are exported.
	 * Only exception is if first is true, then all contents are visible to the top level project.
	 */
	private void expandProject(IPath projectPath, Map containerIds, Map containers, Map pluginIds, Map projects, boolean visible, boolean first) throws JavaModelException {
		IResource res = ResourcesPlugin.getWorkspace().getRoot().findMember(projectPath.lastSegment());
		if (res == null)
			return;	// Not exist so don't delve into it.
		IJavaProject project = (IJavaProject)JavaCore.create(res);
		if (project == null || !project.exists() || !project.getProject().isOpen())
			return;	// Not exist as a java project or not open, so don't delve into it.

		IClasspathEntry[] entries = project.getRawClasspath();
		for (int i = 0; i < entries.length; i++) {
			IClasspathEntry entry = entries[i];
			Boolean currentFlag = null;	// Current setting value.
			boolean newFlag;	// The new setting value. 
			switch (entry.getEntryKind()) {
				case IClasspathEntry.CPE_PROJECT:
					// Force true if already true, or this is the first project, or this project is visible and the entry is exported. These override a previous false.
					currentFlag = (Boolean) projects.get(entry.getPath());
					newFlag = (currentFlag != null && currentFlag.booleanValue()) || first || (visible && entry.isExported());
					if (currentFlag == null || currentFlag.booleanValue() != newFlag)
						projects.put(entry.getPath(),  newFlag ? Boolean.TRUE : Boolean.FALSE );
					if (currentFlag == null)
						expandProject(entry.getPath(), containerIds, containers, pluginIds, projects, visible && entry.isExported(), false);
					break;
				case IClasspathEntry.CPE_CONTAINER:
					if (!first && "org.eclipse.jdt.launching.JRE_CONTAINER".equals(entry.getPath().segment(0)))
						break;	// The first project determines the JRE, so any subsequent ones can be ignored.
					currentFlag = (Boolean) containerIds.get(entry.getPath().segment(0));
					newFlag = (currentFlag != null && currentFlag.booleanValue()) || first || (visible && entry.isExported());					
					if (currentFlag == null || currentFlag.booleanValue() != newFlag)					
						containerIds.put(entry.getPath().segment(0), newFlag ? Boolean.TRUE : Boolean.FALSE );					

					IClasspathContainer container = JavaCore.getClasspathContainer(entry.getPath(), project);
					// Force true if already true, or this is the first project, or this project is visible and the entry is exported. These override a previous false.
					currentFlag = (Boolean) containers.get(container);
					newFlag = (currentFlag != null && currentFlag.booleanValue()) || first || (visible && entry.isExported());
					if (currentFlag == null || currentFlag.booleanValue() != newFlag)					
						containers.put(container,  newFlag ? Boolean.TRUE : Boolean.FALSE );
					break;
				case IClasspathEntry.CPE_VARIABLE:
					// We only care about JRE_LIB. If we have that, then we will treat it as JRE_CONTAINER. Only
					// care about first project too, because the first project is the one that determines the JRE type.
					if (first && "JRE_LIB".equals(entry.getPath().segment(0))) { //$NON-NLS-1$
						currentFlag = (Boolean) containerIds.get("org.eclipse.jdt.launching.JRE_CONTAINER");	//$NON-NLS-1$
						if (currentFlag == null || !currentFlag.booleanValue())						
							containerIds.put("org.eclipse.jdt.launching.JRE_CONTAINER", Boolean.TRUE); //$NON-NLS-1$
					}
					break;
				default:
					break;
			}
		}		
		
		findPlugins(pluginIds, visible, first, project);
	}
	
	/**
	 * Find the plugins that the given project references, either directly or indirectly.
	 * <p>
	 * The map will be of plugin ids to a Boolean. If the boolean is <code>BooleanTRUE</code>,
	 * then the plugin is visible to the given project. the visible and first flags
	 * will modify this. If first is true, then all direct plugins will be visible,
	 * else only exported plugins will be visible. If visible is false and first is false, then it doesn't matter, all of the
	 * plugins will not be visible. 
	 * <p>
	 * Visible means that classes in the plugin can be referenced directly from code. Not visible
	 * means that they can only be referenced from some other plugin in the list. In other words,
	 * visible ones can be directly referenced, but invisible ones can only be referenced from
	 * plugins that can see it.
	 * <p>
	 * For most uses, first and visible should be true. Then it will treat the project as the toplevel
	 * project and will return true for those that are visible to it, either directly or indirectly.
	 * These flags were added for more special cases where may be calling on a project that is deeper
	 * down in the classpath were visibilty has already been decided.
	 * <p>
	 * Note: PDE must be installed for this to return anything, otherwise it will leave
	 * the map alone.
	 * 
	 * @param pluginIds map of pluginIds->Boolean(TRUE is visible)
	 * @param visible <code>true</code> means this project is visible, so any plugins visible to it will be visible, else none will be visible.
	 * @param first <code>true</code> if this is the top project of interest. This means that all plugins within the project are visible. Else only exported projects will be visible.
	 * @param project project to start looking from
	 * 
	 * @since 1.0.2
	 */
	public void findPlugins(Map pluginIds, boolean visible, boolean first, IJavaProject project) {
		IPDEProcessForPlugin pdeprocess = getPDEProcessForPlugin();
		if (pdeprocess != null)
			pdeprocess.findPlugins(project, pluginIds, visible, first);	// expand the plugins for this project, if any.
	}

	/*
	 * Interface for processing Plugins. Used when PDE plugin is present in the installation. 
	 * 
	 * @since 1.0.2
	 */
	interface IPDEProcessForPlugin {

		/*
		 * Go through the project and find all of the plugins it references, either directly or through
		 * the referenced plugins, and mark them as visible or not.
		 */
		public abstract void findPlugins(IJavaProject project, Map pluginIds, boolean visible, boolean first);
	}
	
	/*
	 * Try to get the pde process for plugin. If already tried once and not found, then forget it.
	 * <package-protected> because PDEContributeClasspath needs it too.
	 */
	private IPDEProcessForPlugin pdeProcessForPlugin;
	private boolean triedPDEProcess;
	IPDEProcessForPlugin getPDEProcessForPlugin() {
		if (!triedPDEProcess) {
			triedPDEProcess = true;
			if (Platform.getBundle("org.eclipse.pde.core") != null) {
				try {
					Class classPDEProcess = Class.forName("org.eclipse.jem.internal.proxy.core.PDEProcessForPlugin");
					pdeProcessForPlugin = (IPDEProcessForPlugin) classPDEProcess.newInstance();
				} catch (ClassNotFoundException e) {
					// Not found, do nothing.
				} catch (InstantiationException e) {
					getLogger().log(e, Level.WARNING);
				} catch (IllegalAccessException e) {
					getLogger().log(e, Level.WARNING);
				}
			}
		}
		return pdeProcessForPlugin;
	}
	
	/**
	 * This tries to find a jar in the bundle specified, and the attached source using the
	 * PDE source location extension point. The jar must exist for source to be attachable.
	 * The source must be in the standard PDE source plugin. I.e. it must be in a directory
	 * of the name "bundlename_bundleversion", and in the same path from there as in the
	 * jar, plus the name must be "jarnamesrc.zip".
	 * <p>
	 * The returned URL's will not be Platform.resolve(). They will be in form returned from
	 * Platform.find().
	 * 
	 * @param bundle bundle to search, will search fragments too.
	 * @param filepath filepath from the root of the bundle/fragment where the jar will be found. 
	 * @return two URL's. [0] is the URL to the jar, <code>null</code> if not found, [2] is the URL to the source zip, <code>null</code> if not found.
	 * 
	 * @since 1.0.0
	 */
	public URL[] findPluginJarAndAttachedSource(Bundle bundle, IPath filepath) {
		// This is a bit kludgy, but the algorithm is to find the file first, and then get the root url of the bundle/fragment
		// that matches the found file. This will be used to calculate the name of the directory under the source. From there
		// all of the source extensions will be searched for the source zip file.
		// This is assuming that find returns a url where the file part of the url is a standard path and doesn't have
		// things like special chars to indicate within a jar. That would appear when it is resolved, but I think that the
		// unresolved ones from find are typically "jarbundle://nnn/path" or something like that. This is a gray area.
		URL jarURL = Platform.find(bundle, filepath);
		if (jarURL == null)
			return new URL[2];
		
		// Found it, so let's try to find which bundle/fragment it was found in.
		String jarString = jarURL.toExternalForm();
		// First the bundle itself.
		String installLoc = bundle.getEntry("/").toExternalForm();
		URL sourceURL = null;
		if (jarString.startsWith(installLoc))
			sourceURL = getSrcFrom(bundle, installLoc, jarString);
		else {
			// Now look in the fragments.
			Bundle[] frags = Platform.getFragments(bundle);
			for (int i = 0; i < frags.length; i++) {
				installLoc = frags[i].getEntry("/").toExternalForm();
				if (jarString.startsWith(installLoc)) {
					sourceURL = getSrcFrom(frags[i], installLoc, jarString);
					break;
				}
			}
		}
		return new URL[] {jarURL, sourceURL};
	}
	
	private URL getSrcFrom(Bundle bundle, String installLoc, String jarString) {
		// format of path in a PDE source plugin is (under the "src" directory from the extension point),
		// "bundlename_bundleversion/pathOfJar/jarnamesrc.zip". However there is no way to know
		// which extension has the source in it, so we need to search them all.
		
		IPath srcPath = new Path(bundle.getSymbolicName()+"_"+ (String) bundle.getHeaders("").get(Constants.BUNDLE_VERSION)); //$NON-NLS-1$ $NON-NLS-2$
		srcPath = srcPath.append(new Path(jarString.substring(installLoc.length())));
		if (srcPath.segmentCount() < 2)
			return null;	// Something is not right. No jar name.
		srcPath = srcPath.removeFileExtension();	// Remove the .jar.
		String jarName = srcPath.lastSegment();	// This should be the jar name.
		srcPath = srcPath.removeLastSegments(1).append(jarName+"src.zip");
		
		// Now look through all of the src extensions. Can't tell if the extension is from a fragment or a bundle, so we need to
		// use Platform.find() to look in the bundle and fragment. So we may get a dup search if there is a fragment source 
		// (for example platform source and win32 platform source (which is a fragment of platform source).
		IConfigurationElement[] ces = Platform.getExtensionRegistry().getConfigurationElementsFor("org.eclipse.pde.core.source");
		for (int i = 0; i < ces.length; i++) {
			IPath srcsrch = new Path(ces[i].getAttributeAsIs("path")).append(srcPath);
			Bundle srcBundle = Platform.getBundle(ces[i].getDeclaringExtension().getNamespace());
			URL srcUrl = Platform.find(srcBundle, srcsrch);
			if (srcUrl != null) {
				return srcUrl;
			}
		}
		return null;
	}
}
