Bug 310789: Optimize the update of projects JRE container when the VM has changed
https://bugs.eclipse.org/bugs/show_bug.cgi?id=310789
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/JREContainerInitializer.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/JREContainerInitializer.java
index 77cdad0..8c74989 100644
--- a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/JREContainerInitializer.java
+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/JREContainerInitializer.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * Copyright (c) 2000, 2010 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
@@ -80,6 +80,45 @@
 	}
 	
 	/**
+	 * Sets the specified class path container for all of the given projects.
+	 *  
+	 * @param containerPath JRE container path
+	 * @param projects projects set the container on
+	 * @throws CoreException on failure
+	 */
+	public void initialize(IPath containerPath, IJavaProject[] projects) throws CoreException {
+		int size = containerPath.segmentCount();
+		if (size > 0) {
+			if (containerPath.segment(0).equals(JavaRuntime.JRE_CONTAINER)) {
+				int length = projects.length;
+				IVMInstall vm = resolveVM(containerPath);
+				IClasspathContainer[] containers = new JREContainer[length];
+				if (vm != null) {
+					if (JREContainer.DEBUG_JRE_CONTAINER) {
+						System.out.println("\tResolved VM: " + vm.getName()); //$NON-NLS-1$
+					}
+					for (int i=0; i<length; i++) {
+						containers[i] = new JREContainer(vm, containerPath, projects[i]);
+					}
+				} else {
+					if (JREContainer.DEBUG_JRE_CONTAINER) {
+						System.out.println("\t*** FAILED RESOLVE VM ***"); //$NON-NLS-1$
+					}
+				}
+				JavaCore.setClasspathContainer(containerPath, projects, containers, null);
+			} else {
+				if (JREContainer.DEBUG_JRE_CONTAINER) {
+					System.out.println("\t*** INVALID JRE CONTAINER PATH ***"); //$NON-NLS-1$
+				}	
+			}
+		} else {
+			if (JREContainer.DEBUG_JRE_CONTAINER) {
+				System.out.println("\t*** NO SEGMENTS IN CONTAINER PATH ***"); //$NON-NLS-1$
+			}
+		}
+	}
+	
+	/**
 	 * Returns the VM install associated with the container path, or <code>null</code>
 	 * if it does not exist.
 	 */
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/LaunchingPlugin.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/LaunchingPlugin.java
index c26abac..5dd9665 100644
--- a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/LaunchingPlugin.java
+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/LaunchingPlugin.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * Copyright (c) 2000, 2010 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
@@ -272,7 +272,9 @@
 			monitor.worked(1);
 														
 			// re-bind all container entries
-			for (int i = 0; i < projects.length; i++) {
+			int length = projects.length;
+			Map projectsMap = new HashMap();
+			for (int i = 0; i < length; i++) {
 				IJavaProject project = projects[i];
 				IClasspathEntry[] entries = project.getRawClasspath();
 				boolean replace = false;
@@ -292,10 +294,14 @@
 										newBinding = renamed;
 									}
 								}
-								JREContainerInitializer initializer = new JREContainerInitializer();
 								if (newBinding == null){
 									// re-bind old path
-									initializer.initialize(reference, project);
+									// @see bug 310789 - batch updates by common container paths
+									List projectsList = (List) projectsMap.get(reference);
+									if (projectsList == null) {
+										projectsMap.put(reference, projectsList = new ArrayList(length));
+									}
+									projectsList.add(project);
 								} else {
 									// replace old class path entry with a new one
 									IClasspathEntry newEntry = JavaCore.newContainerEntry(newBinding, entry.isExported());
@@ -313,7 +319,16 @@
 				}
 				monitor.worked(1);
 			}
-
+			Iterator references = projectsMap.keySet().iterator();
+			while (references.hasNext()) {
+				IPath reference = (IPath) references.next();
+				List projectsList = (List) projectsMap.get(reference);
+				IJavaProject[] referenceProjects = new IJavaProject[projectsList.size()];
+				projectsList.toArray(referenceProjects);
+				// re-bind old path
+				JREContainerInitializer initializer = new JREContainerInitializer();
+				initializer.initialize(reference, referenceProjects);
+			}
 		}
 
 	}