/*******************************************************************************
 * Copyright (c) 2001, 2005 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;
/*
 *  $RCSfile: ProxyPlugin.java,v $
 *  $Revision: 1.53 $  $Date: 2005/08/24 20:39:05 $ 
 */


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.service.resolver.BundleSpecification;
import org.osgi.framework.*;

import org.eclipse.jem.util.logger.proxy.Logger;
import org.eclipse.jem.util.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;
	public static final String PREFERENCES_VM_NOVERIFY_KEY = "JEM_PREFERENCES_VM_NOVERIFY_KEY"; // Key for NOVERIFY option of VM //$NON-NLS-1$
	public static final String PDE_NATURE_ID = "org.eclipse.pde.PluginNature" ; //$NON-NLS-1$
		
	// 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;
	}	

	/**
	 * 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 localizeFromBundleOnly(Bundle bundle, String filenameWithinBundle) {
		URL url = urlLocalizeFromBundleOnly(bundle, filenameWithinBundle);
		return url != null ? getFileFromURL(url) : "."; //$NON-NLS-1$
	}
	public String localizeFromBundleAndFragments(Bundle bundle, String filenameWithinBundle) {
		URL url = urlLocalizeFromBundleAndFragments(bundle, filenameWithinBundle);
		return url != null ? getFileFromURL(url) : "."; //$NON-NLS-1$
	}
	
	/**
	 * 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[] localizeAllFromBundleAndFragments(Bundle bundle, String filenameWithinBundle) {
		URL[] urls = urlLocalizeAllFromBundleAndFragments(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();

	}

	public URL urlLocalizeFromBundleAndFragments(Bundle bundle, String filenameWithinBundle) {
		return urlLocalizeFromBundleAndFragments(bundle, new Path(filenameWithinBundle));
	}
	public URL urlLocalizeFromBundleAndFragments(Bundle bundle, IPath filenameWithinBundle) {
		try {
			URL pvm = Platform.find(bundle, filenameWithinBundle);
			if (pvm != null)
				return Platform.asLocalURL(pvm);
		} catch (IOException e) {
		}
		if (devMode) {
			URL[] urls = findDevAllFromBundleAndFragments(bundle, filenameWithinBundle.toString());
			if (urls.length > 0)
				return urls[0];
			else
				return null;
		} else
			return null;
	}
	
	/**
	 * 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[] urlLocalizeAllFromBundleAndFragments(Bundle bundle, String filenameWithinBundle) {
		return urlLocalizeAllBundleAndFragments(bundle, Platform.getFragments(bundle), filenameWithinBundle);
	}
	public URL[] urlLocalizeAllFromBundleAndFragments(Bundle bundle, IPath filenameWithinBundle) {
		return urlLocalizeAllBundleAndFragments(bundle, Platform.getFragments(bundle), filenameWithinBundle.toString());
	}
	
	/**
	 * @param bundle
	 * @param filenameWithinBundle
	 * @param fragments
	 * @return
	 * 
	 * @since 1.0.0
	 */
	private URL[] urlLocalizeAllBundleAndFragments(Bundle bundle, Bundle[] fragments, String filenameWithinBundle) {

		ArrayList urls = new ArrayList((fragments == null ? 0 : fragments.length) + 1);
		URL url = internalUrlLocalizeFromBundleOnly(bundle, filenameWithinBundle);
		if (url != null)
			urls.add(url);
		if (fragments != null) {
			for (int i = 0; i < fragments.length; i++) {
				Bundle fragment = fragments[i];
				url = internalUrlLocalizeFromBundleOnly(fragment, filenameWithinBundle);
				if (url != null)
					urls.add(url);
			}
		}
		return (URL[]) urls.toArray(new URL[urls.size()]);
	}

	private static final String PROXYJARS = "proxy.jars";	//$NON-NLS-1$
	
	/**
	 * @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 urlLocalizeFromBundleOnly(Bundle bundle, String filenameWithinBundle) {
		// If the filenameWithinBundle begins with one of these special characters,
		// it might be in a fragment.
		if (filenameWithinBundle.charAt(0) == '$'
				&& (filenameWithinBundle.regionMatches(true, 0, "$nl$", 0, "$nl$".length()) //$NON-NLS-1$ //$NON-NLS-2$
						|| filenameWithinBundle.regionMatches(true, 0, "$os$", 0, "$os$".length()) || filenameWithinBundle.regionMatches(true, 0, //$NON-NLS-1$ //$NON-NLS-2$
						"$ws$", 0, "$ws$".length()))) //$NON-NLS-1$ //$NON-NLS-2$
			return urlLocalizeFromBundleAndFragments(bundle, filenameWithinBundle);
		try {
			URL pvm = new URL(bundle.getEntry("/"), filenameWithinBundle); //$NON-NLS-1$
			pvm = verifyFound(Platform.asLocalURL(pvm));
			if (pvm != null)
				return pvm;
		} catch (IOException e) {
		}
		return findDev(bundle, filenameWithinBundle);

	}
	
	protected URL internalUrlLocalizeFromBundleOnly(Bundle bundle, String filenameWithinBundle) {
		try {
			URL pvm = bundle.getEntry(filenameWithinBundle);
			if (pvm != null)
				return Platform.asLocalURL(pvm);
		} catch (IOException e) {
		}
		return findDev(bundle, filenameWithinBundle);		
		
	}	
	
	private URL verifyFound(URL pvm) throws IOException {
		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;
	}

	/**
	 * @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 urlLocalizeFromBundleOnly(Bundle bundle, IPath filenameWithinBundle) {					
		return urlLocalizeFromBundleOnly(bundle, filenameWithinBundle.toString());
	}
	
	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 = bundle.getEntry(PROXYJARS);
				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. //$NON-NLS-1$
							if (url.getProtocol().equals("file")) { //$NON-NLS-1$
								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;

	}
	private URL[] findDevAllFromBundleAndFragments(Bundle bundle, String filenameWithinBundle) {
		Bundle [] fragments = Platform.getFragments(bundle);
		ArrayList urls = new ArrayList((fragments == null ? 0 : fragments.length) + 1);
		URL url = findDev(bundle, filenameWithinBundle);
		if (url != null)
			urls.add(url);
		if (fragments != null) {
			for (int i = 0; i < fragments.length; i++) {
				Bundle fragment = fragments[i];
				url = findDev(fragment, filenameWithinBundle);
				if (url != null)
					urls.add(url);
			}
		}
		return (URL[]) urls.toArray(new URL[urls.size()]);
	}	
	/**
	 * 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.
					Bundle[] requires = getPrereqs(bundle, prereqsMap);
					for (int j = 0; j < requires.length; j++) {
						Bundle prereq = requires[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) {
		Bundle[] prs = getPrereqs(bundle, prereqsMap);
		for (int i = 0; i < prs.length; i++) {
			Bundle pre = prs[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 Bundle[] getPrereqs(Bundle bundle, Map prereqsMap) {
		Bundle[] prereqs = (Bundle[]) prereqsMap.get(bundle);
		if (prereqs == null) {
			prereqs = getPrereqs(bundle);
			prereqsMap.put(bundle, prereqs);
		}
		return prereqs;
	}
	
	public static Bundle[] getPrereqs(Bundle bundle) {
		Bundle[] l = (Bundle[]) pluginRequiredMap.get(bundle.getSymbolicName());
		if (l == null) {
			BundleSpecification specs[] = Platform.getPlatformAdmin().getState(false).getBundle(bundle.getBundleId()).getRequiredBundles();
			ArrayList bundles = new ArrayList(specs.length);
			for (int i = 0; i < specs.length; i++) {
				Bundle b = Platform.getBundle(specs[i].getName());
				if (b != null)
					bundles.add(b);
			}
			l = (Bundle[]) bundles.toArray(new Bundle[bundles.size()]);
			pluginRequiredMap.put(bundle.getSymbolicName(), l);
		}
		return l;
	}
	
	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;			
				Bundle[] requires = getPrereqs(bundle, prereqsMap);
				for (int j = 0; j < requires.length; j++) {
					Bundle prereq = requires[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.ProxyPlugin_CleanupDefaultProxyLaunchConfigurations) { 
		{
			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, "")); //$NON-NLS-1$
				}

				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;
				}
			}
		});
		getPluginPreferences().setDefault(PREFERENCES_VM_NOVERIFY_KEY, true);
	}
	

	/* (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_EXTENSION_REGISTRATION_EXTENSION_POINT = "org.eclipse.jem.proxy.extensions"; //$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$
	public static final String PI_REGISTRY_TYPE = "registryType";	//$NON-NLS-1$
	public static final Map pluginRequiredMap = new HashMap(50);
	
	/*
	 * 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;
	
	/*
	 * Map of container id's to their ordered array of extension config elements.
	 */
	protected Map containerToExtensions = null;
	/*
	 * Map of plugin id's to their ordered array of contribution config elements.
	 */
	protected Map pluginToExtension = 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);
	}

	/**
	 * Return the plugin ordered array of configuration elements for the given container, or <code>null</code> if not contributed.
	 * 
	 * @param containerid
	 * @return Array of extension registration elements or <code>null</code> if this container has no contributions.
	 * 
	 * @since 1.0.0
	 */
	public synchronized IConfigurationElement[] getContainerExtensions(String containerid) {
		if (containerToExtensions == null)
			processProxyExtensionExtensionPoint();
		return (IConfigurationElement[]) containerToExtensions.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[] getPluginExtensions(String pluginid) {
		if (pluginToExtension == null)
			processProxyExtensionExtensionPoint();
		return (IConfigurationElement[]) pluginToExtension.get(pluginid);
	}

	protected synchronized void processProxyContributionExtensionPoint() {
		ContributorExtensionPointInfo info = processContributionExtensionPoint(PI_CONFIGURATION_CONTRIBUTION_EXTENSION_POINT);
		containerToContributions = info.containerToContributions;
		pluginToContributions = info.pluginToContributions;
	}
	
	protected synchronized void processProxyExtensionExtensionPoint() {
		ContributorExtensionPointInfo info = processContributionExtensionPoint(PI_EXTENSION_REGISTRATION_EXTENSION_POINT);
		containerToExtensions = info.containerToContributions;
		pluginToExtension = 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.
		// If it is the first time, we are about to find out many inter-dependencies
		// notify the cache on a start/end of a transaction so that updates (if new
		// dependencies) are updated only once
		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))) //$NON-NLS-1$
						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) {
		try {
			// To prevent unnecessary loading of the PDE plugin, find the plugins only if this project is a PDE plugin project.
			if (isPDEProject(project)) {
				IPDEProcessForPlugin pdeprocess = getPDEProcessForPlugin();
				if (pdeprocess != null)
					pdeprocess.findPlugins(project, pluginIds, visible, first); // expand the plugins for this project, if any.
			}
		} catch (CoreException e) {
		}
	}

	/**
	 * 
	 * @param project
	 * 
	 * @return true if this is a Plugin project or false if not
	 * @throws CoreException
	 * 
	 * @since 1.1.0
	 */
	public static boolean isPDEProject(IJavaProject project) throws CoreException {
		return project.getProject().hasNature(PDE_NATURE_ID);
	}


	/*
	 * 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) { //$NON-NLS-1$
				try {
					Class classPDEProcess = Class.forName("org.eclipse.jem.internal.proxy.core.PDEProcessForPlugin"); //$NON-NLS-1$
					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(); //$NON-NLS-1$
		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(); //$NON-NLS-1$
				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$ $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"); //$NON-NLS-1$
		
		// 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"); //$NON-NLS-1$
		for (int i = 0; i < ces.length; i++) {
			IPath srcsrch = new Path(ces[i].getAttributeAsIs("path")).append(srcPath); //$NON-NLS-1$
			Bundle srcBundle = Platform.getBundle(ces[i].getDeclaringExtension().getNamespace());
			URL srcUrl = Platform.find(srcBundle, srcsrch);
			if (srcUrl != null) {
				return srcUrl;
			}
		}
		return null;
	}
}
