Bug 115015 - Installed JRE page needs a "Duplicate" feature.
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/jres/InstalledJREsBlock.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/jres/InstalledJREsBlock.java
index 91c7cd5e..3764c96 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/jres/InstalledJREsBlock.java
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/jres/InstalledJREsBlock.java
@@ -108,6 +108,7 @@
 	private Button fAddButton;
 	private Button fRemoveButton;
 	private Button fEditButton;
+	private Button fCopyButton;
 	private Button fSearchButton;	
 	
 	// column weights
@@ -350,6 +351,13 @@
 			}
 		});
 		
+		fCopyButton = createPushButton(buttons, JREMessages.InstalledJREsBlock_16); 
+		fCopyButton.addListener(SWT.Selection, new Listener() {
+			public void handleEvent(Event evt) {
+				copyVM();
+			}
+		});
+		
 		fRemoveButton= createPushButton(buttons, JREMessages.InstalledJREsBlock_5); 
 		fRemoveButton.addListener(SWT.Selection, new Listener() {
 			public void handleEvent(Event evt) {
@@ -381,6 +389,33 @@
 	}
 	
 	/**
+	 * Adds a duplicate of the selected VM to the block 
+	 * @since 3.2
+	 */
+	protected void copyVM() {
+		IStructuredSelection selection= (IStructuredSelection)fVMList.getSelection();
+		Iterator it = selection.iterator();
+		List newEntries = new ArrayList();
+		while(it.hasNext()){
+			IVMInstall selectedVM = (IVMInstall)it.next();
+			
+			//duplicate & add vm
+			VMStandin standin = new VMStandin(selectedVM, createUniqueId(selectedVM.getVMInstallType()));
+			standin.setName(MessageFormat.format(JREMessages.InstalledJREsBlock_17, new String[]{selectedVM.getName()}));
+
+			AddVMDialog dialog= new AddVMDialog(this, getShell(), JavaRuntime.getVMInstallTypes(), standin);
+			dialog.setTitle(JREMessages.InstalledJREsBlock_18); 
+			if (dialog.open() != Window.OK) {
+				return;
+			}				
+			newEntries.add(standin);
+		}
+		fVMs.addAll(newEntries);
+		fVMList.refresh();
+		fVMList.setSelection(new StructuredSelection(newEntries.toArray()));
+	}
+
+	/**
 	 * Fire current selection
 	 */
 	private void fireSelectionChanged() {
@@ -464,6 +499,7 @@
 	private void enableButtons() {
 		int selectionCount= ((IStructuredSelection)fVMList.getSelection()).size();
 		fEditButton.setEnabled(selectionCount == 1);
+		fCopyButton.setEnabled(selectionCount > 0);
 		fRemoveButton.setEnabled(selectionCount > 0 && selectionCount < fVMList.getTable().getItemCount());
 	}	
 	
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/jres/JREMessages.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/jres/JREMessages.java
index a8b3ef1..c539bc4 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/jres/JREMessages.java
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/jres/JREMessages.java
@@ -38,6 +38,9 @@
 	public static String InstalledJREsBlock_13;
 	public static String InstalledJREsBlock_14;
 	public static String InstalledJREsBlock_15;
+	public static String InstalledJREsBlock_16;
+	public static String InstalledJREsBlock_17;
+	public static String InstalledJREsBlock_18;
 
 	public static String JREsComboBlock_1;
 	public static String JREsComboBlock_2;
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/jres/JREMessages.properties b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/jres/JREMessages.properties
index f0b7114..e65a523 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/jres/JREMessages.properties
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/jres/JREMessages.properties
@@ -33,6 +33,9 @@
 InstalledJREsBlock_13=No JREs found in {0}
 InstalledJREsBlock_14=Found {0} - Searching {1}
 InstalledJREsBlock_15=Installed &JREs:
+InstalledJREsBlock_16=&Copy...
+InstalledJREsBlock_17=Copy of {0}
+InstalledJREsBlock_18=Copy JRE
 
 JREsComboBlock_1=Alternate &JRE:
 JREsComboBlock_10=JRE name not specified for JRE type: {0}
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/VMStandin.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/VMStandin.java
index a1d1a24..cbc6e8c 100644
--- a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/VMStandin.java
+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/VMStandin.java
@@ -50,6 +50,19 @@
 	}
 	
 	/**
+	 * Constructs a copy of the specified VM with the given identifier.
+	 * 
+	 * @param sourceVM
+	 * @param id
+	 * @since 3.2
+	 */
+	public VMStandin(IVMInstall sourceVM, String id) {
+		super(sourceVM.getVMInstallType(), id);
+		init(sourceVM);
+		
+	}
+	
+	/**
 	 * Construct a <code>VMStandin</code> instance based on the specified <code>IVMInstall</code>.
 	 * Changes to this standin will not be reflected in the 'real' VM until <code>convertToRealVM</code>
 	 * is called.
@@ -58,6 +71,16 @@
 	 */
 	public VMStandin(IVMInstall realVM) {
 		this (realVM.getVMInstallType(), realVM.getId());
+		init(realVM);
+	}
+
+	/**
+	 * Initializes the settings of this standin based on the settings in the given
+	 * VM install.
+	 * 
+	 * @param realVM VM to copy settings from
+	 */
+	private void init(IVMInstall realVM) {
 		setName(realVM.getName());
 		setInstallLocation(realVM.getInstallLocation());
 		setLibraryLocations(realVM.getLibraryLocations());