Bug 369524 - 'Installed JREs > Search...' should also find JDKs from
Developer Package
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/jres/MacVMSearch.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/jres/MacVMSearch.java
index 8ba5d4e..be8d04e 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/jres/MacVMSearch.java
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/jres/MacVMSearch.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2007, 2010 IBM Corporation and others.
+ * Copyright (c) 2007, 2012 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
@@ -16,9 +16,7 @@
 import java.util.List;
 
 import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IPath;
 import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.Path;
 import org.eclipse.core.runtime.SubMonitor;
 import org.eclipse.jdt.internal.debug.ui.JDIDebugUIPlugin;
 import org.eclipse.jdt.internal.launching.MacInstalledJREs;
@@ -55,8 +53,7 @@
 			for (int i = 0; i < descriptors.length; i++) {
 				JREDescriptor descriptor = descriptors[i];
 				String name = descriptor.getName();
-				IPath path= new Path(descriptor.getHome().getAbsolutePath());
-				String id= path.segment(path.segmentCount() - 2); // ID is the second last segment in the install path (e.g. 1.5.0)
+				String id= descriptor.getId();
 				try {
 					File home= descriptor.getHome();
 					if (home.exists()) {
diff --git a/org.eclipse.jdt.launching.macosx/macosx/org/eclipse/jdt/internal/launching/macosx/MacOSXVMInstallType.java b/org.eclipse.jdt.launching.macosx/macosx/org/eclipse/jdt/internal/launching/macosx/MacOSXVMInstallType.java
index 3f9212a..0007690 100644
--- a/org.eclipse.jdt.launching.macosx/macosx/org/eclipse/jdt/internal/launching/macosx/MacOSXVMInstallType.java
+++ b/org.eclipse.jdt.launching.macosx/macosx/org/eclipse/jdt/internal/launching/macosx/MacOSXVMInstallType.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * Copyright (c) 2000, 2012 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
@@ -29,46 +29,50 @@
 import org.eclipse.jdt.internal.launching.MacInstalledJREs.JREDescriptor;
 import org.eclipse.jdt.internal.launching.StandardVMType;
 import org.eclipse.jdt.launching.IVMInstall;
+import org.eclipse.jdt.launching.IVMInstallType;
 import org.eclipse.jdt.launching.JavaRuntime;
 import org.eclipse.jdt.launching.VMStandin;
 import org.eclipse.osgi.util.NLS;
 
 /**
- * This plug-ins into the org.eclipse.jdt.launching.vmInstallTypes extension point
+ * This class provides the implementation of the {@link IVMInstallType} for Mac OSX.
+ * 
+ * The default VM locations are outlined below. each VM except for developer VMs provide links in the 
+ * <code>/System/Library/Frameworks/JavaVM.framework/Versions/</code> folder, with a link named 
+ * <code>CurrentJDK</code> that points to the VM you have set using the Java preference tool in the system preferences.
+ * <br><br>
+ * The directory structure for Java VMs prior to Snow Leopard is as follows:
+ * <pre>
+ * /System/Library/Frameworks/JavaVM.framework/Versions/
+ *   1.3.1/
+ *     Classes/
+ *       classes.jar
+ *       ui.jar
+ *     Home/
+ *       src.jar
+ * </pre>
+ * 
+ * The directory structure for developer VMs is:
+ * <pre>
+ * /Library/Java/JavaVirtualMachines/
+ *   1.7.0.jdk/
+ *     Contents/
+ *       Home/
+ *         src.zip
+ * </pre>
+ * 
+ * The directory structure for  Snow Leopard and Lion VMs is:
+ * <pre>
+ * /System/Library/Java/JavaVirtualMachines/
+ *   1.6.0.jdk/
+ *     Contents/
+ *       Home/
+ *         src.zip
+ * </pre>
+ * @see http://developer.apple.com/library/mac/#releasenotes/Java/JavaSnowLeopardUpdate3LeopardUpdate8RN/NewandNoteworthy/NewandNoteworthy.html#//apple_ref/doc/uid/TP40010380-CH4-SW1
  */
 public class MacOSXVMInstallType extends StandardVMType {
 	
-	/*
-	 * The directory structure for Java VMs is as follows:
-	 * 
-	 * 	/System/Library/Frameworks/JavaVM.framework/Versions/
-	 * 		1.3.1
-	 * 			Classes
-	 * 				classes.jar
-	 * 				ui.jar
-	 * 			Home
-	 * 				src.jar
-	 * 		1.4.1
-	 * 			Classes
-	 * 				classes.jar
-	 * 				ui.jar
-	 * 			Home
-	 * 				src.jar
-	 * 		CurrentJDK -> 1.3.1
-	 * 
-	 * New in OSX 10.7 'Lion' JDKs are laid out in the following location:
-	 * 
-	 * /System/Library/Java/JavaVirtualMachines/
-	 * 		1.6.0
-	 * 			/Contents
-	 * 				/Home
-	 * 					classes.jar
-	 * 					ui.jar
-	 * @see http://developer.apple.com/library/mac/#releasenotes/Java/JavaSnowLeopardUpdate3LeopardUpdate8RN/NewandNoteworthy/NewandNoteworthy.html#//apple_ref/doc/uid/TP40010380-CH4-SW1
-	 * for more information
-	 */
-	 
-	
 	/** The OS keeps all the JVM versions in this directory */
 	private static final String JVM_VERSION_LOC= "/System/Library/Frameworks/JavaVM.framework/Versions/";	//$NON-NLS-1$
 	private static final File JVM_VERSIONS_FOLDER= new File(JVM_VERSION_LOC);
@@ -104,8 +108,7 @@
 				JREDescriptor descripor = jres[i];
 				String name = jres[i].getName();
 				File home= descripor.getHome();
-				IPath path= new Path(home.getAbsolutePath());
-				String id= path.segment(path.segmentCount() - 2); // ID is the second last segment in the install path (e.g. 1.5.0)
+				String id= descripor.getId();
 				if (home.exists()) {
 					boolean isDefault= i == 0;
 					IVMInstall install= findVMInstall(id);
@@ -116,10 +119,9 @@
 								? "MacOSXVMType.jvmDefaultName"		//$NON-NLS-1$
 										: "MacOSXVMType.jvmName");				//$NON-NLS-1$
 										vm.setName(MessageFormat.format(format, new Object[] { name } ));
-										vm.setLibraryLocations(getDefaultLibraryLocations(home));
-										vm.setJavadocLocation(getDefaultJavadocLocation(home));
-										
-										install= vm.convertToRealVM();
+						vm.setLibraryLocations(getDefaultLibraryLocations(home));
+						vm.setJavadocLocation(getDefaultJavadocLocation(home));
+						install= vm.convertToRealVM();
 					}
 					if (isDefault) {
 						defaultLocation= home;
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/MacInstalledJREs.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/MacInstalledJREs.java
index c7e7ebf..f39619c 100644
--- a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/MacInstalledJREs.java
+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/MacInstalledJREs.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2010, 2011 IBM Corporation and others.
+ * Copyright (c) 2010, 2012 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
@@ -38,15 +38,22 @@
 	private static final String PLIST_JVM_NAME = "JVMName"; //$NON-NLS-1$
 	/** The plist attribute describing the JRE version */
 	private static final String PLIST_JVM_VERSION = "JVMVersion"; //$NON-NLS-1$
+	/**
+	 * The plist attribute describing the bundle id of the VM
+	 * @since 3.8
+	 */
+	private static final String PLIST_JVM_BUNDLE_ID = "JVMBundleID"; //$NON-NLS-1$
+	
+	static final JREDescriptor[] NO_DESCRIPTORS = new JREDescriptor[0];
 	
 	/**
 	 * Describes an installed JRE on MacOS
 	 */
 	public class JREDescriptor {
-		
 		String fName;
 		File fHome;
 		String fVersion;
+		String fId;
 		
 		/**
 		 * Constructs a new JRE descriptor 
@@ -54,11 +61,13 @@
 		 * @param home Home directory of the JRE
 		 * @param name JRE name
 		 * @param version JRE version
+		 * @param id the computed id of the JRE from the plist output
 		 */
-		public JREDescriptor(File home, String name, String version) {
+		public JREDescriptor(File home, String name, String version, String id) {
 			fHome = home;
 			fName = name;
 			fVersion = version;
+			fId = id;
 		}
 		
 		/**
@@ -88,11 +97,21 @@
 			return fVersion;
 		}
 		
+		/**
+		 * returns the computed id of the descriptor
+		 * 
+		 * @return the descriptor id
+		 * @since 3.8
+		 */
+		public String getId() {
+			return fId;
+		}
+		
 		@Override
 		public boolean equals(Object obj) {
 			if (obj instanceof JREDescriptor) {
 				JREDescriptor jre = (JREDescriptor) obj;
-				return jre.fHome.equals(fHome) && jre.fName.equals(fName) && jre.fVersion.equals(fVersion);
+				return jre.fHome.equals(fHome) && jre.fName.equals(fName) && jre.fVersion.equals(fVersion) && fId.equals(jre.fId);
 			}
 			return false;
 		}
@@ -167,26 +186,33 @@
 						Object name = map.get(PLIST_JVM_NAME);
 						Object version = map.get(PLIST_JVM_VERSION);
 						if (home instanceof String && name instanceof String && version instanceof String) {
-							JREDescriptor descriptor = new JREDescriptor(new File((String)home), (String)name, (String)version);
+							String ver = (String) version;
+							JREDescriptor descriptor = new JREDescriptor(new File((String)home), (String)name, (String)version, computeId(map, ver));
 							if (!jres.contains(descriptor)) { // remove duplicates
 								jres.add(descriptor);	
 							}
-						} else {
-							unexpectedFormat();
-						}
-					} else {
-						unexpectedFormat();
-					}
+						} 
+					} 
 				}
 				return jres.toArray(new JREDescriptor[jres.size()]);
 			}
-			unexpectedFormat();
 		}
-		unexpectedFormat();
-		return null; // previous line will throw an exception
+		return NO_DESCRIPTORS;
 	}
 	
-	private void unexpectedFormat() throws CoreException {
-		throw new CoreException(new Status(IStatus.ERROR, LaunchingPlugin.getUniqueIdentifier(), "Output from java_home not in expected format")); //$NON-NLS-1$
-	}
+	/**
+	 * Tries to compute the descriptor id using the {@link #PLIST_JVM_BUNDLE_ID}. If that is not defined
+	 * we fall back to using the version.
+	 * @param map the map to look up the VM bundle version in
+	 * @param version the current version - fall-back for no VM bundle id defined
+	 * @return the id to use for the {@link JREDescriptor}
+	 * @since 3.8
+	 */
+	String computeId(Map<?, ?> map, String version) {
+		Object o = map.get(PLIST_JVM_BUNDLE_ID);
+		if(o instanceof String) {
+			return (String) o;
+		}
+		return version;
+ 	}
 }