Bug 312397 - Run Configuration Command Line to Clipboard

Change-Id: I766655f94324002a8e67310e7882c1a63a706c5b
diff --git a/org.eclipse.debug.core/.settings/.api_filters b/org.eclipse.debug.core/.settings/.api_filters
index 985cbd8..2b5e5c4 100644
--- a/org.eclipse.debug.core/.settings/.api_filters
+++ b/org.eclipse.debug.core/.settings/.api_filters
@@ -8,4 +8,12 @@
             </message_arguments>
         </filter>
     </resource>
+    <resource path="core/org/eclipse/debug/core/model/ILaunchConfigurationDelegate.java" type="org.eclipse.debug.core.model.ILaunchConfigurationDelegate">
+        <filter comment="adding default method" id="404000815">
+            <message_arguments>
+                <message_argument value="org.eclipse.debug.core.model.ILaunchConfigurationDelegate"/>
+                <message_argument value="showCommandLine(ILaunchConfiguration, String, ILaunch, IProgressMonitor)"/>
+            </message_arguments>
+        </filter>
+    </resource>
 </component>
diff --git a/org.eclipse.debug.core/META-INF/MANIFEST.MF b/org.eclipse.debug.core/META-INF/MANIFEST.MF
index acec883..930cbe6 100644
--- a/org.eclipse.debug.core/META-INF/MANIFEST.MF
+++ b/org.eclipse.debug.core/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %pluginName
 Bundle-SymbolicName: org.eclipse.debug.core; singleton:=true
-Bundle-Version: 3.12.100.qualifier
+Bundle-Version: 3.13.0.qualifier
 Bundle-ClassPath: .
 Bundle-Activator: org.eclipse.debug.core.DebugPlugin
 Bundle-Vendor: %providerName
diff --git a/org.eclipse.debug.core/core/org/eclipse/debug/core/ILaunchConfigurationType.java b/org.eclipse.debug.core/core/org/eclipse/debug/core/ILaunchConfigurationType.java
index 2f1ad93..40af1c4 100644
--- a/org.eclipse.debug.core/core/org/eclipse/debug/core/ILaunchConfigurationType.java
+++ b/org.eclipse.debug.core/core/org/eclipse/debug/core/ILaunchConfigurationType.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2017 IBM Corporation and others.
+ * Copyright (c) 2000, 2018 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
@@ -354,4 +354,14 @@
 	 * @since 3.12
 	 */
 	boolean supportsPrototypes();
+
+	/**
+	 * Returns whether this type of launch configuration supports showing
+	 * command line.
+	 *
+	 * @return whether this kind of launch configuration supports showing
+	 *         command line
+	 * @since 3.13
+	 */
+	boolean supportsCommandLine();
 }
diff --git a/org.eclipse.debug.core/core/org/eclipse/debug/core/model/ILaunchConfigurationDelegate.java b/org.eclipse.debug.core/core/org/eclipse/debug/core/model/ILaunchConfigurationDelegate.java
index cdf215c..9766fb9 100644
--- a/org.eclipse.debug.core/core/org/eclipse/debug/core/model/ILaunchConfigurationDelegate.java
+++ b/org.eclipse.debug.core/core/org/eclipse/debug/core/model/ILaunchConfigurationDelegate.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * Copyright (c) 2000, 2018 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
@@ -51,4 +51,34 @@
 	 */
 	void launch(ILaunchConfiguration configuration, String mode, ILaunch launch, IProgressMonitor monitor) throws CoreException;
 
+	/**
+	 * Gets the command line to launch the given configuration in the specified
+	 * mode, contributing debug targets and/or processes to the given launch
+	 * object. The launch object has already been registered with the launch
+	 * manager.
+	 *
+	 * @param configuration the configuration to launch
+	 * @param mode the mode in which to launch, one of the mode constants
+	 *            defined by <code>ILaunchManager</code> - <code>RUN_MODE</code>
+	 *            or <code>DEBUG_MODE</code>.
+	 * @param monitor progress monitor, or <code>null</code> progress monitor,
+	 *            or <code>null</code>. A cancelable progress monitor is
+	 *            provided by the Job framework. It should be noted that the
+	 *            setCanceled(boolean) method should never be called on the
+	 *            provided monitor or the monitor passed to any delegates from
+	 *            this method; due to a limitation in the progress monitor
+	 *            framework using the setCanceled method can cause entire
+	 *            workspace batch jobs to be canceled, as the canceled flag is
+	 *            propagated up the top-level parent monitor. The provided
+	 *            monitor is not guaranteed to have been started.
+	 * @param launch the launch object to contribute processes and debug targets
+	 *            to
+	 * @return the command line string
+	 * @exception CoreException if launching fails
+	 * @since 3.13
+	 */
+	public default String showCommandLine(ILaunchConfiguration configuration, String mode, ILaunch launch, IProgressMonitor monitor) throws CoreException {
+		return ""; //$NON-NLS-1$
+	}
+
 }
diff --git a/org.eclipse.debug.core/core/org/eclipse/debug/internal/core/IConfigurationElementConstants.java b/org.eclipse.debug.core/core/org/eclipse/debug/internal/core/IConfigurationElementConstants.java
index 3118f26..55570ef 100644
--- a/org.eclipse.debug.core/core/org/eclipse/debug/internal/core/IConfigurationElementConstants.java
+++ b/org.eclipse.debug.core/core/org/eclipse/debug/internal/core/IConfigurationElementConstants.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2006, 2017 IBM Corporation and others.
+ * Copyright (c) 2006, 2018 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
@@ -352,4 +352,14 @@
 	 * @since 3.12
 	 */
 	String ALLOW_PROTOTYPES = "allowPrototypes"; //$NON-NLS-1$
+
+	/**
+	 * The allowCommandLine node name for a configuration element
+	 * <p>
+	 * Equal to the word: <code>allowCommandLine</code>
+	 * </p>
+	 *
+	 * @since 3.13
+	 */
+	String ALLOW_COMMANDLINE = "allowCommandLine"; //$NON-NLS-1$
 }
diff --git a/org.eclipse.debug.core/core/org/eclipse/debug/internal/core/LaunchConfigurationType.java b/org.eclipse.debug.core/core/org/eclipse/debug/internal/core/LaunchConfigurationType.java
index df18815..7cad14e 100644
--- a/org.eclipse.debug.core/core/org/eclipse/debug/internal/core/LaunchConfigurationType.java
+++ b/org.eclipse.debug.core/core/org/eclipse/debug/internal/core/LaunchConfigurationType.java
@@ -480,5 +480,16 @@
 		}
 		return false;
 	}
+
+	@Override
+	public boolean supportsCommandLine() {
+		String allowPrototypesString = fElement.getAttribute(IConfigurationElementConstants.ALLOW_COMMANDLINE);
+		if (allowPrototypesString != null) {
+			if (allowPrototypesString.equalsIgnoreCase("true")) { //$NON-NLS-1$
+				return true;
+			}
+		}
+		return false;
+	}
 }
 
diff --git a/org.eclipse.debug.core/pom.xml b/org.eclipse.debug.core/pom.xml
index 1861f98..52228e4 100644
--- a/org.eclipse.debug.core/pom.xml
+++ b/org.eclipse.debug.core/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-  Copyright (c) 2012, 2017 Eclipse Foundation and others.
+  Copyright (c) 2012, 2018 Eclipse Foundation and others.
   All rights reserved. This program and the accompanying materials
   are made available under the terms of the Eclipse Distribution License v1.0
   which accompanies this distribution, and is available at
@@ -18,6 +18,6 @@
   </parent>
   <groupId>org.eclipse.debug</groupId>
   <artifactId>org.eclipse.debug.core</artifactId>
-  <version>3.12.100-SNAPSHOT</version>
+  <version>3.13.0-SNAPSHOT</version>
   <packaging>eclipse-plugin</packaging>
 </project>
diff --git a/org.eclipse.debug.core/schema/launchConfigurationTypes.exsd b/org.eclipse.debug.core/schema/launchConfigurationTypes.exsd
index aed236e..048c276 100644
--- a/org.eclipse.debug.core/schema/launchConfigurationTypes.exsd
+++ b/org.eclipse.debug.core/schema/launchConfigurationTypes.exsd
@@ -163,6 +163,13 @@
                </documentation>
             </annotation>
          </attribute>
+         <attribute name="allowCommandLine" type="boolean">
+            <annotation>
+               <documentation>
+                  specifies whether this launch configuration type allows command line or not.  Defaults to &lt;code&gt;false&lt;/code&gt; if not specified. This attribute was added in 4.7 release.
+               </documentation>
+            </annotation>
+         </attribute>
       </complexType>
    </element>
 
@@ -248,7 +255,7 @@
          <meta.section type="copyright"/>
       </appinfo>
       <documentation>
-         Copyright (c) 2000, 2005 IBM Corporation and others.&lt;br&gt;
+         Copyright (c) 2000, 2018 IBM Corporation and others.&lt;br&gt;
 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 
diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/launchConfigurations/LaunchConfigurationTabGroupViewer.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/launchConfigurations/LaunchConfigurationTabGroupViewer.java
index d7884c0..45a43f2 100644
--- a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/launchConfigurations/LaunchConfigurationTabGroupViewer.java
+++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/launchConfigurations/LaunchConfigurationTabGroupViewer.java
@@ -143,6 +143,9 @@
 	private Button fApplyButton;
 	private Button fRevertButton;
 
+	Composite buttonComp;
+	private Button fShowCommandLineButton;
+
 	/**
 	 * Whether tabs are currently being disposed or initialized
 	 */
@@ -306,9 +309,20 @@
 		});
 		fOptionsLink.setVisible(false);
 
-		Composite buttonComp = SWTFactory.createComposite(blComp, 2, 1, GridData.HORIZONTAL_ALIGN_END);
+		buttonComp = SWTFactory.createComposite(blComp, 3, 1, GridData.HORIZONTAL_ALIGN_END);
 
-		fRevertButton = SWTFactory.createPushButton(buttonComp, LaunchConfigurationsMessages.LaunchConfigurationDialog_Revert_2, null, GridData.HORIZONTAL_ALIGN_END);
+		fShowCommandLineButton = SWTFactory.createPushButton(buttonComp,
+				LaunchConfigurationsMessages.LaunchConfigurationDialog_ShowCommandLine, null,
+				GridData.HORIZONTAL_ALIGN_BEGINNING);
+		fShowCommandLineButton.addSelectionListener(new SelectionAdapter() {
+			@Override
+			public void widgetSelected(SelectionEvent evt) {
+				handleShowCommandLinePressed();
+			}
+		});
+
+		fRevertButton = SWTFactory.createPushButton(buttonComp,
+				LaunchConfigurationsMessages.LaunchConfigurationDialog_Revert_2, null, GridData.HORIZONTAL_ALIGN_END);
 		fRevertButton.addSelectionListener(new SelectionAdapter() {
 			@Override
 			public void widgetSelected(SelectionEvent evt) {
@@ -801,6 +815,11 @@
 		fTabPlaceHolder.layout(true, true);
 	}
 
+	private void updateShowCommandLineVisibility(boolean visible) {
+		if (fShowCommandLineButton != null) {
+			fShowCommandLineButton.setVisible(visible);
+		}
+	}
     /**
      * sets the current widget focus to the 'Name' widget
      */
@@ -829,6 +848,12 @@
 		}
 		// show the name area
 		updateVisibleControls(true);
+		if (type.supportsCommandLine()) {
+			updateShowCommandLineVisibility(true);
+		}
+		else {
+			updateShowCommandLineVisibility(false);
+		}
 
 		// Retrieve the current tab group.  If there is none, clean up and leave
 		ILaunchConfigurationTabGroup tabGroup = getTabGroup();
@@ -1525,6 +1550,19 @@
 	}
 
 	/**
+	 * Dialog to Show the Command line
+	 */
+	protected void handleShowCommandLinePressed() {
+		ShowCommandLineDialog dialog = new ShowCommandLineDialog(getShell(),
+				LaunchConfigurationsMessages.LaunchConfigurationDialog_ShowCommandLine_Title, null, null, 0,
+				new String[] { LaunchConfigurationsMessages.LaunchConfigurationDialog_ShowCommandLine_Copy,
+						IDialogConstants.CANCEL_LABEL },
+				0,
+				fOriginal);
+		dialog.open();
+	}
+
+	/**
 	 * Show an error dialog on the given exception.
 	 *
 	 * @param exception the exception to display
diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/launchConfigurations/LaunchConfigurationsMessages.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/launchConfigurations/LaunchConfigurationsMessages.java
index a64e0bd..3414bbb 100644
--- a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/launchConfigurations/LaunchConfigurationsMessages.java
+++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/launchConfigurations/LaunchConfigurationsMessages.java
@@ -104,6 +104,9 @@
 	public static String LaunchConfigurationsDialog_Error_1;
 	public static String LaunchConfigurationsDialog_Warning_2;
 	public static String LaunchConfigurationsDialog_Information_3;
+	public static String LaunchConfigurationDialog_ShowCommandLine;
+	public static String LaunchConfigurationDialog_ShowCommandLine_Title;
+	public static String LaunchConfigurationDialog_ShowCommandLine_Copy;
 	public static String LaunchConfigurationSelectionDialog_0;
 	public static String LaunchConfigurationSelectionDialog_1;
 	public static String LaunchConfigurationSelectionDialog_deleteButtonLabel;
diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/launchConfigurations/LaunchConfigurationsMessages.properties b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/launchConfigurations/LaunchConfigurationsMessages.properties
index 887c4a1..b48e01d 100644
--- a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/launchConfigurations/LaunchConfigurationsMessages.properties
+++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/launchConfigurations/LaunchConfigurationsMessages.properties
@@ -115,6 +115,9 @@
 LaunchConfigurationsDialog_Error_1=Error
 LaunchConfigurationsDialog_Warning_2=Warning
 LaunchConfigurationsDialog_Information_3=Information
+LaunchConfigurationDialog_ShowCommandLine=Sho&w Command Line
+LaunchConfigurationDialog_ShowCommandLine_Title=Command Line
+LaunchConfigurationDialog_ShowCommandLine_Copy=C&opy
 LaunchConfigurationsDialog_0=New launch configuration
 LaunchConfigurationsDialog_1=Delete selected launch configuration(s)
 LaunchConfigurationsDialog_2=New launch configuration prototype
diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/launchConfigurations/ShowCommandLineDialog.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/launchConfigurations/ShowCommandLineDialog.java
new file mode 100644
index 0000000..fc3a3b4
--- /dev/null
+++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/launchConfigurations/ShowCommandLineDialog.java
@@ -0,0 +1,140 @@
+/*******************************************************************************
+ * Copyright (c) 2018 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.debug.internal.ui.launchConfigurations;
+
+import java.util.Set;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.debug.core.ILaunch;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.debug.core.ILaunchDelegate;
+import org.eclipse.debug.core.ILaunchManager;
+import org.eclipse.debug.core.Launch;
+import org.eclipse.debug.core.model.ILaunchConfigurationDelegate;
+import org.eclipse.debug.core.model.ILaunchConfigurationDelegate2;
+import org.eclipse.debug.internal.core.DebugCoreMessages;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.dnd.Clipboard;
+import org.eclipse.swt.dnd.TextTransfer;
+import org.eclipse.swt.dnd.Transfer;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+
+import com.ibm.icu.text.MessageFormat;
+
+/**
+ * Allows the user to specify to see and copy the command line to be executed
+ * for the launch.
+ * 
+ * @since 3.13
+ */
+public class ShowCommandLineDialog extends MessageDialog {
+	Text fModuleArgumentsText;
+	ILaunchConfiguration flaunchConfiguration;
+
+
+	public ShowCommandLineDialog(Shell parentShell, String dialogTitle, Image dialogTitleImage, String dialogMessage, int dialogImageType, String[] dialogButtonLabels, int defaultIndex, ILaunchConfiguration config) {
+		super(parentShell, dialogTitle, dialogTitleImage, dialogMessage, dialogImageType, dialogButtonLabels, defaultIndex);
+		flaunchConfiguration = config;
+	}
+
+	@Override
+	protected Control createCustomArea(Composite parent) {
+		Composite comp = new Composite(parent, SWT.NONE);
+		comp.setLayout(new GridLayout());
+		Font font = parent.getFont();
+
+		Group group = new Group(comp, SWT.NONE);
+		GridLayout topLayout = new GridLayout();
+		group.setLayout(topLayout);
+		GridData gd = new GridData(GridData.FILL_BOTH);
+		gd.heightHint = convertHeightInCharsToPixels(15);
+		gd.widthHint = convertWidthInCharsToPixels(50);
+		group.setLayoutData(gd);
+		group.setFont(font);
+
+
+		// Label description = new Label(group, SWT.WRAP);
+		// description.setText(ActionMessages.Override_Dependencies_label1);
+		fModuleArgumentsText = new Text(group, SWT.MULTI | SWT.WRAP | SWT.BORDER | SWT.V_SCROLL);
+		gd = new GridData(GridData.FILL_BOTH);
+		gd.heightHint = convertHeightInCharsToPixels(10);
+		gd.widthHint = convertWidthInCharsToPixels(60);
+		fModuleArgumentsText.setLayoutData(gd);
+
+		String command = "Could not retrieve the command"; //$NON-NLS-1$
+		try {
+			Set<String> modes = flaunchConfiguration.getModes();
+			modes.add(ILaunchManager.RUN_MODE);
+			ILaunchDelegate[] delegates = flaunchConfiguration.getType().getDelegates(modes);
+			if (delegates.length ==1) {
+				ILaunchConfigurationDelegate delegate = delegates[0].getDelegate();
+				ILaunchConfigurationDelegate2 delegate2;
+				ILaunch launch = null;
+				if (delegate instanceof ILaunchConfigurationDelegate2) {
+					delegate2 = (ILaunchConfigurationDelegate2) delegate;
+					if (delegate2 != null) {
+						launch = delegate2.getLaunch(flaunchConfiguration, ILaunchManager.RUN_MODE);
+					}
+					if (launch == null) {
+						launch = new Launch(flaunchConfiguration, ILaunchManager.RUN_MODE, null);
+					} else {
+						// ensure the launch mode is valid
+						if (!ILaunchManager.RUN_MODE.equals(launch.getLaunchMode())) {
+							IStatus status = new Status(IStatus.ERROR, DebugPlugin.getUniqueIdentifier(),
+									DebugPlugin.ERROR, MessageFormat.format(DebugCoreMessages.LaunchConfiguration_14,
+											ILaunchManager.RUN_MODE, launch.getLaunchMode()),
+									null);
+							throw new CoreException(status);
+						}
+					}
+				}
+				command = delegate.showCommandLine(flaunchConfiguration, ILaunchManager.RUN_MODE, launch, null);
+			}
+		} catch (CoreException e) {
+			e.printStackTrace();
+		}
+		fModuleArgumentsText.setText(command);
+		fModuleArgumentsText.setEditable(false);
+
+		return comp;
+	}
+
+	@Override
+	protected void buttonPressed(int buttonId) {
+		if (buttonId == OK) {
+			Clipboard clipboard = new Clipboard(null);
+			try {
+				TextTransfer textTransfer = TextTransfer.getInstance();
+				Transfer[] transfers = new Transfer[] { textTransfer };
+				Object[] data = new Object[] { fModuleArgumentsText.getText() };
+				clipboard.setContents(data, transfers);
+			} finally {
+				clipboard.dispose();
+			}
+		}
+		super.buttonPressed(buttonId);
+	}
+
+
+
+}