Bug 113909 - Extension point for installing a JRE
diff --git a/org.eclipse.jdt.debug.tests/test plugin/org/eclipse/jdt/debug/testplugin/AnalyzerJ2SE14x.java b/org.eclipse.jdt.debug.tests/test plugin/org/eclipse/jdt/debug/testplugin/AnalyzerJ2SE14x.java
index fc68095..dd418b1 100644
--- a/org.eclipse.jdt.debug.tests/test plugin/org/eclipse/jdt/debug/testplugin/AnalyzerJ2SE14x.java
+++ b/org.eclipse.jdt.debug.tests/test plugin/org/eclipse/jdt/debug/testplugin/AnalyzerJ2SE14x.java
@@ -14,7 +14,7 @@
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.jdt.launching.IVMInstall;
 import org.eclipse.jdt.launching.IVMInstall2;
-import org.eclipse.jdt.launching.environments.ExecutionEnvironments;
+import org.eclipse.jdt.launching.JavaRuntime;
 import org.eclipse.jdt.launching.environments.IExecutionEnvironment;
 import org.eclipse.jdt.launching.environments.IExecutionEnvironmentAnalyzerDelegate;
 
@@ -35,7 +35,7 @@
 			IVMInstall2 vm2 = (IVMInstall2) vm;
 			String javaVersion = vm2.getJavaVersion();
 			if (javaVersion.startsWith("1.4")) {
-				return new IExecutionEnvironment[] { ExecutionEnvironments
+				return new IExecutionEnvironment[] { JavaRuntime.getExecutionEnvironmentsManager()
 						.getEnvironment("org.eclipse.jdt.debug.tests.environment.j2se14x") };
 			}
 		}
diff --git a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/core/ExecutionEnvironmentTests.java b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/core/ExecutionEnvironmentTests.java
index d42a0c5..c97362b 100644
--- a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/core/ExecutionEnvironmentTests.java
+++ b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/core/ExecutionEnvironmentTests.java
@@ -10,13 +10,11 @@
  *******************************************************************************/
 package org.eclipse.jdt.debug.tests.core;
 
-import org.eclipse.core.runtime.NullProgressMonitor;
 import org.eclipse.jdt.debug.tests.AbstractDebugTest;
 import org.eclipse.jdt.launching.IVMInstall;
 import org.eclipse.jdt.launching.JavaRuntime;
-import org.eclipse.jdt.launching.environments.ExecutionEnvironments;
 import org.eclipse.jdt.launching.environments.IExecutionEnvironment;
-import org.eclipse.jdt.launching.environments.IExecutionEnvironmentAnalyzer;
+import org.eclipse.jdt.launching.environments.IExecutionEnvironmentsManager;
 
 /**
  * Tests for execution environments
@@ -28,7 +26,7 @@
 	}
 	
 	public void testGetEnvironments() throws Exception {
-		IExecutionEnvironment[] executionEnvironments = ExecutionEnvironments.getExecutionEnvironments();
+		IExecutionEnvironment[] executionEnvironments = JavaRuntime.getExecutionEnvironmentsManager().getExecutionEnvironments();
 		assertTrue("Should be at least one environment", executionEnvironments.length > 0);
 		for (int i = 0; i < executionEnvironments.length; i++) {
 			IExecutionEnvironment environment = executionEnvironments[i];
@@ -39,21 +37,15 @@
 		assertTrue("Did not find test environment org.eclipse.jdt.debug.tests.environment.j2se14x", false);
 	}
 	
-	public void testGetAnalyzers() throws Exception {
-		IExecutionEnvironmentAnalyzer[] analyzers = ExecutionEnvironments.getAnalyzers();
-		assertTrue("Should be at least one analyzer", analyzers.length > 0);
-	}	
-	
 	public void testAnalyze() throws Exception {
 		IVMInstall vm = JavaRuntime.getDefaultVMInstall();
-		IExecutionEnvironment[] environments = ExecutionEnvironments.analyze(vm, new NullProgressMonitor());
+		IExecutionEnvironmentsManager manager = JavaRuntime.getExecutionEnvironmentsManager();
+		
+		IExecutionEnvironment[] environments = manager.getEnvironments(vm);
 		assertTrue("Should be at least one environmet", environments.length > 0);
 		
-		environments = ExecutionEnvironments.getEnvironments(vm);
-		assertTrue("Should be at least one environmet", environments.length > 0);
-		
-		IExecutionEnvironment environment = ExecutionEnvironments.getEnvironment("org.eclipse.jdt.debug.tests.environment.j2se14x");
-		IVMInstall[] installs = ExecutionEnvironments.getVMInstalls(environment);
+		IExecutionEnvironment environment = manager.getEnvironment("org.eclipse.jdt.debug.tests.environment.j2se14x");
+		IVMInstall[] installs = manager.getVMInstalls(environment);
 		assertTrue("Should be at least one vm install for the environment", installs.length > 0);
 		for (int i = 0; i < installs.length; i++) {
 			IVMInstall install = installs[i];
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/environments/Analyzer.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/environments/Analyzer.java
index 478338a..4d4b0c1 100644
--- a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/environments/Analyzer.java
+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/environments/Analyzer.java
@@ -15,7 +15,6 @@
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.jdt.launching.IVMInstall;
 import org.eclipse.jdt.launching.environments.IExecutionEnvironment;
-import org.eclipse.jdt.launching.environments.IExecutionEnvironmentAnalyzer;
 import org.eclipse.jdt.launching.environments.IExecutionEnvironmentAnalyzerDelegate;
 
 /**
@@ -24,7 +23,7 @@
  * @since 3.2
  *
  */
-class Analyzer implements IExecutionEnvironmentAnalyzer {
+class Analyzer implements IExecutionEnvironmentAnalyzerDelegate {
 	
 	private IConfigurationElement fElement;
 	
@@ -54,8 +53,9 @@
 		return fDelegate;
 	}
 
-	/* (non-Javadoc)
-	 * @see org.eclipse.jdt.launching.environments.IExecutionEnvironmentAnalyzer#getId()
+	/**
+	 * Returns the id of this delegate
+	 * @return id
 	 */
 	public String getId() {
 		return fElement.getAttribute("id"); //$NON-NLS-1$
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/environments/Environments.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/environments/Environments.java
deleted file mode 100644
index f91dd89..0000000
--- a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/environments/Environments.java
+++ /dev/null
@@ -1,177 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 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.jdt.internal.launching.environments;
-
-import java.text.MessageFormat;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IConfigurationElement;
-import org.eclipse.core.runtime.IExtensionPoint;
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.Platform;
-import org.eclipse.jdt.internal.launching.LaunchingPlugin;
-import org.eclipse.jdt.launching.IVMInstall;
-import org.eclipse.jdt.launching.JavaRuntime;
-import org.eclipse.jdt.launching.environments.IExecutionEnvironment;
-import org.eclipse.jdt.launching.environments.IExecutionEnvironmentAnalyzer;
-
-/**
- * Utility class for execution environments.
- * 
- * @since 3.2
- */
-public class Environments {
-	
-	/**
-	 * Map of environments keyed by id
-	 */
-	private static Map fEnvironments = null;
-	
-	/**
-	 * Map of analyzers keyed by id
-	 */
-	private static Map fAnalyzers = null;
-	
-	/**
-	 * Map of vm installs to lists of compatible environments
-	 */
-	private static Map fCompatibleEnvironments = null;
-	
-	/**
-	 * Returns all registered execution environments.
-	 * 
-	 * @return all registered execution environments
-	 */
-	public synchronized static IExecutionEnvironment[] getExecutionEnvironments() {
-		initialize();
-		Collection environments = fEnvironments.values();
-		return (IExecutionEnvironment[]) environments.toArray(new IExecutionEnvironment[environments.size()]);
-	}
-	
-	/**
-	 * Returns the execution environment associated with the given
-	 * identifier or <code>null</code> if none.
-	 * 
-	 * @param id execution environment identifier 
-	 * @return execution environment or <code>null</code>
-	 */
-	public synchronized static IExecutionEnvironment getEnvironment(String id) {
-		initialize();
-		return (IExecutionEnvironment) fEnvironments.get(id);
-	}
-	
-	/**
-	 * Returns the exeuctuion environments associated with the specified
-	 * vm install, possibly an empty collection.
-	 * 
-	 * @param vm vm install
-	 * @return exeuctuion environments associated with the specified
-	 * vm install, possibly an empty collection
-	 */
-	public synchronized static IExecutionEnvironment[] getEnvironments(IVMInstall vm) {
-		List environments = (List) fCompatibleEnvironments.get(vm);
-		if (environments == null) {
-			return new IExecutionEnvironment[0];
-		}
-		return (IExecutionEnvironment[]) environments.toArray(new IExecutionEnvironment[environments.size()]);
-	}
-
-	/**
-	 * Returns the vm installs that are compatible with the given 
-	 * execution environment, possibly an empty collection.
-	 * 
-	 * @param environment execution environment
-	 * @return vm installs that are compatible with the given 
-	 * execution environment, possibly an empty collection
-	 */
-	public synchronized static IVMInstall[] getVMInstalls(IExecutionEnvironment environment) {
-		initialize();
-		List vms = new ArrayList();
-		Iterator iterator = fCompatibleEnvironments.entrySet().iterator();
-		while (iterator.hasNext()) {
-			Map.Entry entry = (Entry) iterator.next();
-			if (((List)entry.getValue()).contains(environment)) {
-				vms.add(entry.getKey());
-			}
-		}
-		return (IVMInstall[]) vms.toArray(new IVMInstall[vms.size()]);
-	}
-	
-	/**
-	 * Returns all registered exeuction environment analyzers.
-	 * 
-	 * @return all registered exeuction environment analyzers
-	 */
-	public synchronized static IExecutionEnvironmentAnalyzer[] getAnalyzers() { 
-		initialize();
-		Collection collection = fAnalyzers.values();
-		return (IExecutionEnvironmentAnalyzer[]) collection.toArray(new IExecutionEnvironmentAnalyzer[collection.size()]);
-	}	
-	
-	private synchronized static void initialize() {
-		if (fEnvironments == null) {
-			IExtensionPoint extensionPoint = Platform.getExtensionRegistry().getExtensionPoint(LaunchingPlugin.ID_PLUGIN, JavaRuntime.EXTENSION_POINT_EXECUTION_ENVIRONMENTS);
-			IConfigurationElement[] configs= extensionPoint.getConfigurationElements();
-			fEnvironments = new HashMap(configs.length);
-			fAnalyzers = new HashMap(configs.length);
-			for (int i = 0; i < configs.length; i++) {
-				IConfigurationElement element = configs[i];
-				String name = element.getName();
-				if (name.equals("environment")) { //$NON-NLS-1$
-					String id = element.getAttribute("id"); //$NON-NLS-1$
-					if (id == null) {
-						LaunchingPlugin.log(MessageFormat.format(EnvironmentMessages.Environments_0, new String[]{element.getNamespace()}));
-					} else {
-						fEnvironments.put(id, new ExecutionEnvironment(element));
-					}
-				} else if (name.equals("analyzer")) { //$NON-NLS-1$
-					String id = element.getAttribute("id"); //$NON-NLS-1$
-					if (id == null) {
-						LaunchingPlugin.log(MessageFormat.format(EnvironmentMessages.Environments_1, new String[]{element.getNamespace()}));
-					} else {
-						fAnalyzers.put(id, new Analyzer(element));
-					}
-				}
-			}
-			// TODO: restore compatibilities from disk
-			fCompatibleEnvironments = new HashMap();
-		}
-	}
-	
-	/**
-	 * Recomputes the environments compatible with the given vm install.
-	 * 
-	 * @param vm
-	 * @param monitor
-	 * @return
-	 * @throws CoreException
-	 */
-	public synchronized static IExecutionEnvironment[] analyze(IVMInstall vm, IProgressMonitor monitor) throws CoreException {
-		IExecutionEnvironmentAnalyzer[] analyzers = getAnalyzers();
-		List environmentList = new ArrayList();
-		for (int i = 0; i < analyzers.length; i++) {
-			IExecutionEnvironmentAnalyzer analyzer = analyzers[i];
-			IExecutionEnvironment[] environments = analyzer.analyze(vm, monitor);
-			for (int j = 0; j < environments.length; j++) {
-				environmentList.add(environments[j]);
-			}
-		}
-		fCompatibleEnvironments.put(vm, environmentList);
-		return (IExecutionEnvironment[]) environmentList.toArray(new IExecutionEnvironment[environmentList.size()]);
-	}
-}
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/environments/EnvironmentsManager.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/environments/EnvironmentsManager.java
new file mode 100644
index 0000000..2ca38e1
--- /dev/null
+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/environments/EnvironmentsManager.java
@@ -0,0 +1,258 @@
+/*******************************************************************************
+ * Copyright (c) 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.jdt.internal.launching.environments;
+
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtensionPoint;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.jdt.internal.launching.LaunchingPlugin;
+import org.eclipse.jdt.launching.IVMInstall;
+import org.eclipse.jdt.launching.IVMInstallChangedListener;
+import org.eclipse.jdt.launching.IVMInstallType;
+import org.eclipse.jdt.launching.JavaRuntime;
+import org.eclipse.jdt.launching.PropertyChangeEvent;
+import org.eclipse.jdt.launching.environments.IExecutionEnvironment;
+import org.eclipse.jdt.launching.environments.IExecutionEnvironmentsManager;
+
+/**
+ * Utility class for execution environments.
+ * 
+ * @since 3.2
+ */
+public class EnvironmentsManager implements IExecutionEnvironmentsManager, IVMInstallChangedListener {
+	
+	private static EnvironmentsManager fgManager = null;
+	
+	/**
+	 * Map of environments keyed by id
+	 */
+	private Map fEnvironments = null;
+	
+	/**
+	 * Map of analyzers keyed by id
+	 */
+	private Map fAnalyzers = null;
+	
+	/**
+	 * Map of vm installs to lists of compatible environments
+	 */
+	private Map fCompatibleEnvironments = null;
+	
+	/**
+	 * Returns the singleton environments manager.
+	 * 
+	 * @return environments manager
+	 */
+	public static EnvironmentsManager getDefault() {
+		if (fgManager == null) {
+			fgManager = new EnvironmentsManager();
+		}
+		return fgManager;
+	}
+	
+	/**
+	 * Constructs the new manager.
+	 */
+	private EnvironmentsManager() {
+		JavaRuntime.addVMInstallChangedListener(this);
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.launching.environments.IExecutionEnvironmentsManager#getExecutionEnvironments()
+	 */
+	public synchronized IExecutionEnvironment[] getExecutionEnvironments() {
+		initializeExtensions();
+		Collection environments = fEnvironments.values();
+		return (IExecutionEnvironment[]) environments.toArray(new IExecutionEnvironment[environments.size()]);
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.launching.environments.IExecutionEnvironmentsManager#getEnvironment(java.lang.String)
+	 */
+	public synchronized IExecutionEnvironment getEnvironment(String id) {
+		initializeExtensions();
+		return (IExecutionEnvironment) fEnvironments.get(id);
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.launching.environments.IExecutionEnvironmentsManager#getEnvironments(org.eclipse.jdt.launching.IVMInstall)
+	 */
+	public synchronized IExecutionEnvironment[] getEnvironments(IVMInstall vm) {
+		initializeCompatibilities();
+		List environments = (List) fCompatibleEnvironments.get(vm);
+		if (environments == null) {
+			return new IExecutionEnvironment[0];
+		}
+		return (IExecutionEnvironment[]) environments.toArray(new IExecutionEnvironment[environments.size()]);
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.launching.environments.IExecutionEnvironmentsManager#getVMInstalls(org.eclipse.jdt.launching.environments.IExecutionEnvironment)
+	 */
+	public synchronized IVMInstall[] getVMInstalls(IExecutionEnvironment environment) {
+		initializeCompatibilities();
+		List vms = new ArrayList();
+		Iterator iterator = fCompatibleEnvironments.entrySet().iterator();
+		while (iterator.hasNext()) {
+			Map.Entry entry = (Entry) iterator.next();
+			if (((List)entry.getValue()).contains(environment)) {
+				vms.add(entry.getKey());
+			}
+		}
+		return (IVMInstall[]) vms.toArray(new IVMInstall[vms.size()]);
+	}
+	
+	/**
+	 * Returns all registered analyzers 
+	 * 
+	 * @return
+	 */
+	public synchronized Analyzer[] getAnalyzers() { 
+		initializeExtensions();
+		Collection collection = fAnalyzers.values();
+		return (Analyzer[]) collection.toArray(new Analyzer[collection.size()]);
+	}	
+	
+	private synchronized void initializeExtensions() {
+		if (fEnvironments == null) {
+			IExtensionPoint extensionPoint = Platform.getExtensionRegistry().getExtensionPoint(LaunchingPlugin.ID_PLUGIN, JavaRuntime.EXTENSION_POINT_EXECUTION_ENVIRONMENTS);
+			IConfigurationElement[] configs= extensionPoint.getConfigurationElements();
+			fEnvironments = new HashMap(configs.length);
+			fAnalyzers = new HashMap(configs.length);
+			for (int i = 0; i < configs.length; i++) {
+				IConfigurationElement element = configs[i];
+				String name = element.getName();
+				if (name.equals("environment")) { //$NON-NLS-1$
+					String id = element.getAttribute("id"); //$NON-NLS-1$
+					if (id == null) {
+						LaunchingPlugin.log(MessageFormat.format(EnvironmentMessages.Environments_0, new String[]{element.getNamespace()}));
+					} else {
+						fEnvironments.put(id, new ExecutionEnvironment(element));
+					}
+				} else if (name.equals("analyzer")) { //$NON-NLS-1$
+					String id = element.getAttribute("id"); //$NON-NLS-1$
+					if (id == null) {
+						LaunchingPlugin.log(MessageFormat.format(EnvironmentMessages.Environments_1, new String[]{element.getNamespace()}));
+					} else {
+						fAnalyzers.put(id, new Analyzer(element));
+					}
+				}
+			}
+		}
+	}
+	
+	/**
+	 * Initializes the cache of JRE/EE compatibilities. Returns whether the cache was
+	 * built from scratch.
+	 * 
+	 * @return whether the compatibilites were built from scratch
+	 */
+	private synchronized boolean initializeCompatibilities() {
+		initializeExtensions();
+		if (fCompatibleEnvironments == null) {
+			fCompatibleEnvironments = new HashMap();
+			// TODO: restore from preference
+			// build from scratch
+			IVMInstallType[] installTypes = JavaRuntime.getVMInstallTypes();
+			for (int i = 0; i < installTypes.length; i++) {
+				IVMInstallType type = installTypes[i];
+				IVMInstall[] installs = type.getVMInstalls();
+				for (int j = 0; j < installs.length; j++) {
+					IVMInstall install = installs[j];
+					try {
+						// TODO: progress reporting?
+						List list = analyze(install, new NullProgressMonitor());
+						fCompatibleEnvironments.put(install, list);
+					} catch (CoreException e) {
+						LaunchingPlugin.log(e);
+					}
+				}
+			}
+			return true;
+		}
+		return false;
+	}
+	
+	/**
+	 * Analyzes and returns execution environments for the given vm install.
+	 * 
+	 * @param vm
+	 * @param monitor
+	 * @return execution environments for the given vm install
+	 * @throws CoreException
+	 */
+	private List analyze(IVMInstall vm, IProgressMonitor monitor) throws CoreException {
+		Analyzer[] analyzers = getAnalyzers();
+		List environmentList = new ArrayList();
+		for (int i = 0; i < analyzers.length; i++) {
+			Analyzer analyzer = analyzers[i];
+			IExecutionEnvironment[] environments = analyzer.analyze(vm, monitor);
+			for (int j = 0; j < environments.length; j++) {
+				environmentList.add(environments[j]);
+			}
+		}	
+		return environmentList;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.launching.IVMInstallChangedListener#defaultVMInstallChanged(org.eclipse.jdt.launching.IVMInstall, org.eclipse.jdt.launching.IVMInstall)
+	 */
+	public void defaultVMInstallChanged(IVMInstall previous, IVMInstall current) {
+		// TODO Auto-generated method stub
+		
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.launching.IVMInstallChangedListener#vmChanged(org.eclipse.jdt.launching.PropertyChangeEvent)
+	 */
+	public synchronized void vmChanged(PropertyChangeEvent event) {
+		if (fCompatibleEnvironments != null) {
+			IVMInstall vm = (IVMInstall) event.getSource();
+			vmRemoved(vm);
+			vmAdded(vm);
+		}
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.launching.IVMInstallChangedListener#vmAdded(org.eclipse.jdt.launching.IVMInstall)
+	 */
+	public synchronized void vmAdded(IVMInstall vm) {
+		try {
+			// TODO: progress?
+			List list = analyze(vm, new NullProgressMonitor());
+			fCompatibleEnvironments.put(vm, list);
+		} catch (CoreException e) {
+			LaunchingPlugin.log(e);
+		}
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.launching.IVMInstallChangedListener#vmRemoved(org.eclipse.jdt.launching.IVMInstall)
+	 */
+	public synchronized void vmRemoved(IVMInstall vm) {
+		if (fCompatibleEnvironments != null) {
+			fCompatibleEnvironments.remove(vm);
+		}
+	}
+	
+}
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/JavaRuntime.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/JavaRuntime.java
index f556b98..d33f922 100644
--- a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/JavaRuntime.java
+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/JavaRuntime.java
@@ -70,6 +70,8 @@
 import org.eclipse.jdt.internal.launching.SocketAttachConnector;
 import org.eclipse.jdt.internal.launching.VMDefinitionsContainer;
 import org.eclipse.jdt.internal.launching.VariableClasspathEntry;
+import org.eclipse.jdt.internal.launching.environments.EnvironmentsManager;
+import org.eclipse.jdt.launching.environments.IExecutionEnvironmentsManager;
 import org.w3c.dom.Element;
 import org.w3c.dom.Node;
 import org.w3c.dom.NodeList;
@@ -2114,5 +2116,15 @@
 		}
 		return null;
 	}
+	
+	/**
+	 * Returns the execution environments manager.
+	 * 
+	 * @return execution environments manager
+	 * @since 3.2
+	 */
+	public static IExecutionEnvironmentsManager getExecutionEnvironmentsManager() {
+		return EnvironmentsManager.getDefault();
+	}
 
 }
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/environments/ExecutionEnvironments.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/environments/ExecutionEnvironments.java
deleted file mode 100644
index c7b9bfc..0000000
--- a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/environments/ExecutionEnvironments.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 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.jdt.launching.environments;
-
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.jdt.internal.launching.environments.Environments;
-import org.eclipse.jdt.launching.IVMInstall;
-
-/**
- * Utility class for execution environments.
- * 
- * @since 3.2
- */
-public class ExecutionEnvironments {
-	
-	/**
-	 * Returns all registered execution environments.
-	 * 
-	 * @return all registered execution environments
-	 */
-	public static IExecutionEnvironment[] getExecutionEnvironments() {
-		return Environments.getExecutionEnvironments();
-	}
-	
-	/**
-	 * Returns the execution environment associated with the given
-	 * identifier or <code>null</code> if none.
-	 * 
-	 * @param id execution environment identifier 
-	 * @return execution environment or <code>null</code>
-	 */
-	public static IExecutionEnvironment getEnvironment(String id) {
-		return Environments.getEnvironment(id);
-	}
-	
-	/**
-	 * Returns the exeuctuion environments associated with the specified
-	 * vm install, possibly an empty collection.
-	 * 
-	 * @param vm vm install
-	 * @return exeuctuion environments associated with the specified
-	 * vm install, possibly an empty collection
-	 */
-	public static IExecutionEnvironment[] getEnvironments(IVMInstall vm) {
-		return Environments.getEnvironments(vm);
-	}
-
-	/**
-	 * Returns the vm installs that are compatible with the given 
-	 * execution environment, possibly an empty collection.
-	 * 
-	 * @param environment execution environment
-	 * @return vm installs that are compatible with the given 
-	 * execution environment, possibly an empty collection
-	 */
-	public static IVMInstall[] getVMInstalls(IExecutionEnvironment environment) {
-		return Environments.getVMInstalls(environment);
-	}
-	
-	/**
-	 * Returns all registered exeuction environment analyzers.
-	 * 
-	 * @return all registered exeuction environment analyzers
-	 */
-	public static IExecutionEnvironmentAnalyzer[] getAnalyzers() { 
-		return Environments.getAnalyzers();
-	}
-	
-	/**
-	 * Recomputes the environments compatible with the given vm install.
-	 * 
-	 * @param vm
-	 * @param monitor
-	 * @return
-	 * @throws CoreException
-	 */
-	public static IExecutionEnvironment[] analyze(IVMInstall vm, IProgressMonitor monitor) throws CoreException {
-		return Environments.analyze(vm, monitor);
-	}	
-	
-}
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/environments/IExecutionEnvironmentAnalyzer.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/environments/IExecutionEnvironmentAnalyzer.java
deleted file mode 100644
index e0f1018..0000000
--- a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/environments/IExecutionEnvironmentAnalyzer.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 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.jdt.launching.environments;
-
-
-/**
- * Analyzes vm installs for compatibility with execution environments.
- *
- * @since 3.2
- * @see IExecutionEnvironmentAnalyzerDelegate
- */
-public interface IExecutionEnvironmentAnalyzer extends IExecutionEnvironmentAnalyzerDelegate {
-	
-	/**
-	 * Returns the unique identifier for this analyzer.
-	 * 
-	 * @return analyzer identifier
-	 */
-	public String getId();
-
-}
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/environments/IExecutionEnvironmentsManager.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/environments/IExecutionEnvironmentsManager.java
new file mode 100644
index 0000000..f814075
--- /dev/null
+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/environments/IExecutionEnvironmentsManager.java
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * Copyright (c) 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.jdt.launching.environments;
+
+import org.eclipse.jdt.launching.IVMInstall;
+
+/**
+ * Manager for execution environments. The singleton manager is available
+ * via <code>JavaRuntime.getExecutionEnvironmentsManager()</code>.
+ * 
+ * @since 3.2
+ */
+public interface IExecutionEnvironmentsManager {
+
+	/**
+	 * Returns all registered execution environments.
+	 * 
+	 * @return all registered execution environments
+	 */
+	public IExecutionEnvironment[] getExecutionEnvironments();
+	
+	/**
+	 * Returns the execution environment associated with the given
+	 * identifier or <code>null</code> if none.
+	 * 
+	 * @param id execution environment identifier 
+	 * @return execution environment or <code>null</code>
+	 */
+	public IExecutionEnvironment getEnvironment(String id);
+	
+	/**
+	 * Returns the exeuctuion environments associated with the specified
+	 * vm install, possibly an empty collection.
+	 * 
+	 * @param vm vm install
+	 * @return exeuctuion environments associated with the specified
+	 * vm install, possibly an empty collection
+	 */
+	public IExecutionEnvironment[] getEnvironments(IVMInstall vm);
+
+	/**
+	 * Returns the vm installs that are compatible with the given 
+	 * execution environment, possibly an empty collection.
+	 * 
+	 * @param environment execution environment
+	 * @return vm installs that are compatible with the given 
+	 * execution environment, possibly an empty collection
+	 */
+	public IVMInstall[] getVMInstalls(IExecutionEnvironment environment);
+		
+}