Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeff Johnston2017-02-09 23:43:05 +0000
committerJeff Johnston2017-10-22 09:38:51 +0000
commitc96d126b86382356caec9b8ee961e37b84313f6b (patch)
treef48f38e68d303c6d8c7d9f1b30d22f3c8ea3c59e
parent4c1a6e0ccd90da71cb6d2e7cacfc284a07b180b8 (diff)
downloadorg.eclipse.cdt-c96d126b86382356caec9b8ee961e37b84313f6b.tar.gz
org.eclipse.cdt-c96d126b86382356caec9b8ee961e37b84313f6b.tar.xz
org.eclipse.cdt-c96d126b86382356caec9b8ee961e37b84313f6b.zip
Bug 513589 - Add support to build CDT projects in a Docker Container
- add IOptionalBuildObjectPropertiesContainer interface to use for objects that supply optional build properties - add new IOptionalBuildProperties interface that defines optional build properties donated by external plug-ins - add new - change IConfiguration to an IOptionalBuildObjectPropertiesContainer - change IManagedProject to be an IOptionalBuildObjectPropertiesContainer - fix ProcessClosure to ensure that readers are not null before accessing them - fix Container launch delegate to look at project optional build properties for active configuration to fetch connection and image info and use said info to find a matching launch or create a new one - have Container launch delegate use the image name as part of the launch config name - have Container launch short-cut also use the project's optional build properties for the active config to get connection and image information before any defaulting - change AutotoolsNewMarkerGenerator to store the command launcher as an ICommandLauncher - add new CommandLauncherFactory extension to cdt.core that allows plug-ins to specify a CommandLauncherFactory that will return an ICommandLauncher based on the project - add macros for new extension to CCorePlugin - add new CommandLauncherManager class that loads CommandLauncherFactory extensions and is used to give an ICommandLauncher wrapper that will go through the list of CommandLauncherFactory extensions until one returns non-null ICommandLauncher - add code to RemoteCommandLauncher so it will use the CommandLauncherManager to get the local launcher - also change RemoteCommandLauncher to check at execution time whether the command is local and in that case use the local command launcher - add new ICommandLauncherFactory interface - add new ContainerCommandLauncher to launch - add new ContainerCommandLauncherFactory class for returning a ContainerCommandLauncher instance to launch commands in a Docker Container - change MakeBuilder to use CommandLauncherManager to get its ICommandLauncher - change CommandBuilder to use CommandLauncherManager too - ditto for Builder and AbstractBuiltinSpecsDetector and ExternalToolInvoker - change Configuration to load/store optional build properties as well as return the properties to get/set - ditto for MultiConfiguration - change ManagedProject to implement IOptionalBuildOptionProperties interface - ditto for ProjectType - create new OptionalBuildProperties class to store optional build properties for a configuration - bump cdt.docker.launcher to 1.1.0 - use CommandLauncherFactory extension to define ContainerCommandLauncherFactory - add optional ContainerPropertyTab which allows the end-user to optionally choose to build a C/C++ project in a Container and specify the connection/image to use - in LanguageSettingsSerializableSettings class, call the CommandLauncherManager getLanguageSettingEntries method to get the massaged language setting entries based on the current list - in LanguageSettingsProviderSerializer, try and get the pooled entries using the cfg description so that it will have the project and can use the CommandLauncherManager to get entries from image - in ContainerCommandLauncherFactory move cached headers under a HEADERS directory in the plug-in area - create a sub-directory for the connection and a sub-directory for the image based on cleansed names - store the real names of the connection and image to use later in the DockerHeaderPreferencePage - modify LanguageSettingsEntriesTab to force the horizontal scroll bar to appear (this is a bug in SWT SashForm support and the fix here isn't quite correct, but is better) - add new DockerHeaderPreferencePage that allows user to remove cached headers from images - change C/C++ Docker preferences to be titled: Docker Container - fix LanguageSettingsWorkspaceProvider.getSettingEntries method to use the CommandLauncherManager so entries will be transformed to use cached headers - add BaseDatabindingModel class - add DataVolumeModel class to model a volume mount - add ContainerPropertyVolumes model to model volume specification and selected volumes - add properties to ContainerCommandLauncher to represent volumes and selected volumes for a configuration - add ContainerDataVolumeDialog for specifying a volume mount by the end-user - add a null detector for cfgDescription in LanguageSettingsSerializableProvider - fix AutotoolsNewMakeGenerator.getWinOSType to not specify "." for working dir - fix GCCBuiltinSpecsDetectorCygwin to not map paths to Cygwin if the current configuration is enabled for container build - add logic to ContainerCommandLauncher to look for Windows file formats and change them to unix format and map any "." working dir to be /tmp - fix ContainerLauncherConfigurationDelegate similarly - fix AbstractBuiltinSpecsDetector to pass in the current configuration description when getting the CommandLauncher since the current configuration may not be the active configuration - change ContainerPropertyTab to add Elf and GNU Elf binary parsers when build in Container is chosen so that output executables are treated as Binaries by the CDT project - add documentationl for the ContainerPropertyTab in Build Settings and the Data Volume dialog pop-up it brings up - change CommandBuilder to accept a project as an argument to its constructor and to pass this as an argument to the CommandLauncherManager - have StepBuilder pass project when creating a CommandBuilder Change-Id: Ia78488b93056e6ec7ca83a6c87b3a9d2b9424943
-rw-r--r--build/org.eclipse.cdt.autotools.core/src/org/eclipse/cdt/internal/autotools/core/AutotoolsNewMakeGenerator.java6
-rw-r--r--build/org.eclipse.cdt.autotools.tests/src/org/eclipse/cdt/autotools/tests/ProjectTools.java5
-rw-r--r--build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/core/MakeBuilder.java4
-rw-r--r--build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig2/DefaultRunSIProvider.java4
-rw-r--r--build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/buildproperties/IOptionalBuildProperties.java30
-rw-r--r--build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/IBuildObjectPropertiesContainer.java1
-rw-r--r--build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/IConfiguration.java6
-rw-r--r--build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/IManagedProject.java6
-rw-r--r--build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/IOptionalBuildObjectPropertiesContainer.java21
-rw-r--r--build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/IProjectType.java2
-rw-r--r--build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/buildmodel/CommandBuilder.java10
-rw-r--r--build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/buildmodel/StepBuilder.java6
-rw-r--r--build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/Builder.java4
-rw-r--r--build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/Configuration.java43
-rw-r--r--build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/ManagedProject.java28
-rw-r--r--build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/MultiConfiguration.java9
-rw-r--r--build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/OptionalBuildProperties.java104
-rw-r--r--build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/ProjectType.java24
-rw-r--r--build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/language/settings/providers/GCCBuiltinSpecsDetectorCygwin.java16
-rw-r--r--build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/language/settings/providers/AbstractBuiltinSpecsDetector.java7
-rw-r--r--build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/language/settings/providers/GCCBuiltinSpecsDetector.java2
-rw-r--r--build/org.eclipse.cdt.managedbuilder.ui.tests/src/org/eclipse/cdt/managedbuilder/ui/tests/util/TestConfiguration.java8
-rw-r--r--build/org.eclipse.cdt.managedbuilder.ui.tests/src/org/eclipse/cdt/managedbuilder/ui/tests/util/TestProjectType.java3
-rw-r--r--codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/internal/externaltool/ExternalToolInvoker.java4
-rw-r--r--core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/testplugin/CModelMock.java4
-rw-r--r--core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/language/settings/providers/LanguageSettingsSerializableProvider.java8
-rw-r--r--core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/language/settings/providers/LanguageSettingsProvidersSerializer.java9
-rw-r--r--core/org.eclipse.cdt.core/plugin.xml1
-rw-r--r--core/org.eclipse.cdt.core/schema/CommandLauncherFactory.exsd128
-rw-r--r--core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CCorePlugin.java11
-rw-r--r--core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CommandLauncherManager.java288
-rw-r--r--core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/ICommandLauncherFactory.java54
-rw-r--r--core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/ProcessClosure.java16
-rw-r--r--core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/language/settings/providers/LanguageSettingsEntriesTab.java11
-rw-r--r--doc/org.eclipse.cdt.doc.user/images/prop_container.pngbin0 -> 41949 bytes
-rw-r--r--doc/org.eclipse.cdt.doc.user/images/prop_datavolumes.pngbin0 -> 22638 bytes
-rw-r--r--doc/org.eclipse.cdt.doc.user/reference/cdt_u_prop_build.htm1
-rw-r--r--doc/org.eclipse.cdt.doc.user/reference/cdt_u_prop_build_settings_artifact.htm1
-rw-r--r--doc/org.eclipse.cdt.doc.user/reference/cdt_u_prop_build_settings_binparser.htm1
-rw-r--r--doc/org.eclipse.cdt.doc.user/reference/cdt_u_prop_build_settings_container.htm166
-rw-r--r--doc/org.eclipse.cdt.doc.user/reference/cdt_u_prop_build_settings_errparser.htm1
-rw-r--r--doc/org.eclipse.cdt.doc.user/reference/cdt_u_prop_build_settings_steps.htm1
-rw-r--r--doc/org.eclipse.cdt.doc.user/reference/cdt_u_prop_build_settings_tool.htm1
-rw-r--r--doc/org.eclipse.cdt.doc.user/reference/cdt_u_prop_data_volumes.htm149
-rw-r--r--doc/org.eclipse.cdt.doc.user/reference/cdt_u_properties.htm1
-rw-r--r--launch/org.eclipse.cdt.docker.launcher/META-INF/MANIFEST.MF11
-rw-r--r--launch/org.eclipse.cdt.docker.launcher/icons/error_obj.gifbin0 -> 339 bytes
-rw-r--r--launch/org.eclipse.cdt.docker.launcher/icons/file_obj.gifbin0 -> 349 bytes
-rw-r--r--launch/org.eclipse.cdt.docker.launcher/icons/folder_closed.gifbin0 -> 219 bytes
-rw-r--r--launch/org.eclipse.cdt.docker.launcher/icons/warning_obj.gifbin0 -> 337 bytes
-rw-r--r--launch/org.eclipse.cdt.docker.launcher/plugin.properties10
-rw-r--r--launch/org.eclipse.cdt.docker.launcher/plugin.xml27
-rw-r--r--launch/org.eclipse.cdt.docker.launcher/src/org/eclipse/cdt/docker/launcher/ContainerCommandLauncherFactory.java265
-rw-r--r--launch/org.eclipse.cdt.docker.launcher/src/org/eclipse/cdt/internal/docker/launcher/BaseDatabindingModel.java44
-rw-r--r--launch/org.eclipse.cdt.docker.launcher/src/org/eclipse/cdt/internal/docker/launcher/ContainerCommandLauncher.java429
-rw-r--r--launch/org.eclipse.cdt.docker.launcher/src/org/eclipse/cdt/internal/docker/launcher/ContainerDataVolumeDialog.java466
-rw-r--r--launch/org.eclipse.cdt.docker.launcher/src/org/eclipse/cdt/internal/docker/launcher/ContainerLaunchConfigurationDelegate.java67
-rw-r--r--launch/org.eclipse.cdt.docker.launcher/src/org/eclipse/cdt/internal/docker/launcher/ContainerPropertyTab.java1053
-rw-r--r--launch/org.eclipse.cdt.docker.launcher/src/org/eclipse/cdt/internal/docker/launcher/ContainerPropertyVolumesModel.java142
-rw-r--r--launch/org.eclipse.cdt.docker.launcher/src/org/eclipse/cdt/internal/docker/launcher/ContainerTab.java7
-rw-r--r--launch/org.eclipse.cdt.docker.launcher/src/org/eclipse/cdt/internal/docker/launcher/DataVolumeModel.java347
-rw-r--r--launch/org.eclipse.cdt.docker.launcher/src/org/eclipse/cdt/internal/docker/launcher/LaunchShortcut.java102
-rw-r--r--launch/org.eclipse.cdt.docker.launcher/src/org/eclipse/cdt/internal/docker/launcher/Messages.java15
-rw-r--r--launch/org.eclipse.cdt.docker.launcher/src/org/eclipse/cdt/internal/docker/launcher/SWTImagesFactory.java13
-rw-r--r--launch/org.eclipse.cdt.docker.launcher/src/org/eclipse/cdt/internal/docker/launcher/messages.properties15
-rw-r--r--launch/org.eclipse.cdt.docker.launcher/src/org/eclipse/cdt/internal/docker/launcher/ui/preferences/DockerHeaderPreferencePage.java356
-rw-r--r--remote/org.eclipse.cdt.remote.core/src/org/eclipse/cdt/remote/core/RemoteCommandLauncher.java35
67 files changed, 4543 insertions, 66 deletions
diff --git a/build/org.eclipse.cdt.autotools.core/src/org/eclipse/cdt/internal/autotools/core/AutotoolsNewMakeGenerator.java b/build/org.eclipse.cdt.autotools.core/src/org/eclipse/cdt/internal/autotools/core/AutotoolsNewMakeGenerator.java
index 813fd3b4b5..b94eab734e 100644
--- a/build/org.eclipse.cdt.autotools.core/src/org/eclipse/cdt/internal/autotools/core/AutotoolsNewMakeGenerator.java
+++ b/build/org.eclipse.cdt.autotools.core/src/org/eclipse/cdt/internal/autotools/core/AutotoolsNewMakeGenerator.java
@@ -893,7 +893,7 @@ public class AutotoolsNewMakeGenerator extends MarkerGenerator {
consoleOutStream.flush();
// Get a launcher for the config command
- RemoteCommandLauncher launcher = new RemoteCommandLauncher();
+ ICommandLauncher launcher = new RemoteCommandLauncher();
launcher.setProject(project);
// Set the environment
IEnvironmentVariable variables[] =
@@ -1042,7 +1042,7 @@ public class AutotoolsNewMakeGenerator extends MarkerGenerator {
new Path(SHELL_COMMAND), //$NON-NLS-1$
new String[] { "-c", "echo $OSTYPE" }, //$NON-NLS-1$ //$NON-NLS-2$
env,
- new Path("."), //$NON-NLS-1$
+ buildLocation,
SubMonitor.convert(monitor));
if (launcher.waitAndRead(out, out) == ICommandLauncher.OK)
winOSType = out.toString().trim();
@@ -1207,7 +1207,7 @@ public class AutotoolsNewMakeGenerator extends MarkerGenerator {
consoleOutStream.flush();
// Get a launcher for the config command
- RemoteCommandLauncher launcher = new RemoteCommandLauncher();
+ ICommandLauncher launcher = new RemoteCommandLauncher();
launcher.setProject(project);
// Set the environment
IEnvironmentVariable variables[] =
diff --git a/build/org.eclipse.cdt.autotools.tests/src/org/eclipse/cdt/autotools/tests/ProjectTools.java b/build/org.eclipse.cdt.autotools.tests/src/org/eclipse/cdt/autotools/tests/ProjectTools.java
index ad5aad0d3b..8cbe618ac7 100644
--- a/build/org.eclipse.cdt.autotools.tests/src/org/eclipse/cdt/autotools/tests/ProjectTools.java
+++ b/build/org.eclipse.cdt.autotools.tests/src/org/eclipse/cdt/autotools/tests/ProjectTools.java
@@ -18,6 +18,8 @@ import java.util.zip.ZipFile;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.CommandLauncher;
+import org.eclipse.cdt.core.CommandLauncherManager;
+import org.eclipse.cdt.core.ICommandLauncher;
import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
import org.eclipse.cdt.internal.autotools.core.configure.AutotoolsConfigurationManager;
import org.eclipse.cdt.internal.autotools.core.configure.IAConfiguration;
@@ -129,7 +131,8 @@ public class ProjectTools {
*/
public static boolean markExecutable(IProject project, String filePath) {
// Get a launcher for the config command
- CommandLauncher launcher = new CommandLauncher();
+ ICommandLauncher launcher = CommandLauncherManager.getInstance().getCommandLauncher();
+ launcher.setProject(project);
OutputStream stdout = new ByteArrayOutputStream();
OutputStream stderr = new ByteArrayOutputStream();
diff --git a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/core/MakeBuilder.java b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/core/MakeBuilder.java
index 4d9b9ad51c..50a9e61e5e 100644
--- a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/core/MakeBuilder.java
+++ b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/core/MakeBuilder.java
@@ -23,7 +23,7 @@ import java.util.List;
import java.util.Map;
import org.eclipse.cdt.core.CCorePlugin;
-import org.eclipse.cdt.core.CommandLauncher;
+import org.eclipse.cdt.core.CommandLauncherManager;
import org.eclipse.cdt.core.ErrorParserManager;
import org.eclipse.cdt.core.ICommandLauncher;
import org.eclipse.cdt.core.IConsoleParser;
@@ -180,7 +180,7 @@ public class MakeBuilder extends ACBuilder {
console.start(project);
// Prepare launch parameters for BuildRunnerHelper
- ICommandLauncher launcher = new CommandLauncher();
+ ICommandLauncher launcher = CommandLauncherManager.getInstance().getCommandLauncher();
String[] targets = getTargets(kind, info);
if (targets.length != 0 && targets[targets.length - 1].equals(info.getCleanBuildTarget()))
diff --git a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig2/DefaultRunSIProvider.java b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig2/DefaultRunSIProvider.java
index cd8b03563b..8a2c47fab1 100644
--- a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig2/DefaultRunSIProvider.java
+++ b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig2/DefaultRunSIProvider.java
@@ -19,7 +19,7 @@ import java.util.List;
import java.util.Properties;
import org.eclipse.cdt.core.CCorePlugin;
-import org.eclipse.cdt.core.CommandLauncher;
+import org.eclipse.cdt.core.CommandLauncherManager;
import org.eclipse.cdt.core.ErrorParserManager;
import org.eclipse.cdt.core.ICommandLauncher;
import org.eclipse.cdt.core.IConsoleParser;
@@ -120,7 +120,7 @@ public class DefaultRunSIProvider implements IExternalScannerInfoProvider {
}
console.start(project);
- ICommandLauncher launcher = new CommandLauncher();
+ ICommandLauncher launcher = CommandLauncherManager.getInstance().getCommandLauncher();
launcher.setProject(project);
IPath program = getCommandToLaunch();
diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/buildproperties/IOptionalBuildProperties.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/buildproperties/IOptionalBuildProperties.java
new file mode 100644
index 0000000000..23043aed06
--- /dev/null
+++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/buildproperties/IOptionalBuildProperties.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Red Hat Inc. 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:
+ * Red Hat Inc. - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.managedbuilder.buildproperties;
+
+/**
+ * @noextend This class is not intended to be subclassed by clients.
+ * @noimplement This interface is not intended to be implemented by clients.
+ * @since 8.5
+ */
+public interface IOptionalBuildProperties extends Cloneable {
+ String[] getProperties();
+
+ String getProperty(String id);
+
+ void setProperty(String propertyId, String propertyValue);
+
+ void removeProperty(String id);
+
+ void clear();
+
+ Object clone();
+} \ No newline at end of file
diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/IBuildObjectPropertiesContainer.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/IBuildObjectPropertiesContainer.java
index 3bc55876f6..a3704a24f0 100644
--- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/IBuildObjectPropertiesContainer.java
+++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/IBuildObjectPropertiesContainer.java
@@ -10,7 +10,6 @@
*******************************************************************************/
package org.eclipse.cdt.managedbuilder.core;
-
/**
* @noextend This class is not intended to be subclassed by clients.
* @noimplement This interface is not intended to be implemented by clients.
diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/IConfiguration.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/IConfiguration.java
index f04149faef..81d1f28bbb 100644
--- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/IConfiguration.java
+++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/IConfiguration.java
@@ -36,7 +36,7 @@ import org.eclipse.core.runtime.IPath;
* @noextend This class is not intended to be subclassed by clients.
* @noimplement This interface is not intended to be implemented by clients.
*/
-public interface IConfiguration extends IBuildObject, IBuildObjectPropertiesContainer {
+public interface IConfiguration extends IBuildObject, IBuildObjectPropertiesContainer, IOptionalBuildObjectPropertiesContainer {
public static final String ARTIFACT_NAME = "artifactName"; //$NON-NLS-1$
public static final String CLEAN_COMMAND = "cleanCommand"; //$NON-NLS-1$
public static final String PREBUILD_STEP = "prebuildStep"; //$NON-NLS-1$
@@ -54,6 +54,10 @@ public interface IConfiguration extends IBuildObject, IBuildObjectPropertiesCont
public static final String DESCRIPTION = "description"; //$NON-NLS-1$
public static final String BUILD_PROPERTIES = "buildProperties"; //$NON-NLS-1$
+ /**
+ * @since 8.5
+ */
+ public static final String OPTIONAL_BUILD_PROPERTIES = "optionalBuildProperties"; //$NON-NLS-1$
public static final String BUILD_ARTEFACT_TYPE = "buildArtefactType"; //$NON-NLS-1$
public static final String IS_SYSTEM = "isSystem"; //$NON-NLS-1$
diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/IManagedProject.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/IManagedProject.java
index e0d527e939..8e5a0d7857 100644
--- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/IManagedProject.java
+++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/IManagedProject.java
@@ -38,10 +38,14 @@ import org.eclipse.core.resources.IResource;
* @noextend This class is not intended to be subclassed by clients.
* @noimplement This interface is not intended to be implemented by clients.
*/
-public interface IManagedProject extends IBuildObject, IBuildObjectPropertiesContainer {
+public interface IManagedProject extends IBuildObject, IBuildObjectPropertiesContainer, IOptionalBuildObjectPropertiesContainer {
public static final String MANAGED_PROJECT_ELEMENT_NAME = "project"; //$NON-NLS-1$
public static final String PROJECTTYPE = "projectType"; //$NON-NLS-1$
public static final String BUILD_PROPERTIES = "buildProperties"; //$NON-NLS-1$
+ /**
+ * @since 8.5
+ */
+ public static final String OPTIONAL_BUILD_PROPERTIES = "optionalBuildProperties"; //$NON-NLS-1$
public static final String BUILD_ARTEFACT_TYPE = "buildArtefactType"; //$NON-NLS-1$
diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/IOptionalBuildObjectPropertiesContainer.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/IOptionalBuildObjectPropertiesContainer.java
new file mode 100644
index 0000000000..68cfa186bc
--- /dev/null
+++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/IOptionalBuildObjectPropertiesContainer.java
@@ -0,0 +1,21 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Red Hat Inc 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:
+ * Red Hat Inc. - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.managedbuilder.core;
+
+import org.eclipse.cdt.managedbuilder.buildproperties.IOptionalBuildProperties;
+
+/**
+ * @since 8.5
+ */
+public interface IOptionalBuildObjectPropertiesContainer {
+ IOptionalBuildProperties getOptionalBuildProperties();
+
+}
diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/IProjectType.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/IProjectType.java
index 1eea850c35..6d810e7110 100644
--- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/IProjectType.java
+++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/IProjectType.java
@@ -44,7 +44,7 @@ import org.eclipse.cdt.managedbuilder.macros.IProjectBuildMacroSupplier;
* @noextend This class is not intended to be subclassed by clients.
* @noimplement This interface is not intended to be implemented by clients.
*/
-public interface IProjectType extends IBuildObject, IBuildObjectPropertiesContainer {
+public interface IProjectType extends IBuildObject, IBuildObjectPropertiesContainer, IOptionalBuildObjectPropertiesContainer {
public static final String PROJECTTYPE_ELEMENT_NAME = "projectType"; //$NON-NLS-1$
public static final String SUPERCLASS = "superClass"; //$NON-NLS-1$
public static final String IS_ABSTRACT = "isAbstract"; //$NON-NLS-1$
diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/buildmodel/CommandBuilder.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/buildmodel/CommandBuilder.java
index 4fe8091783..9f7c979b64 100644
--- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/buildmodel/CommandBuilder.java
+++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/buildmodel/CommandBuilder.java
@@ -18,11 +18,12 @@ import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
-import org.eclipse.cdt.core.CommandLauncher;
+import org.eclipse.cdt.core.CommandLauncherManager;
import org.eclipse.cdt.core.ICommandLauncher;
import org.eclipse.cdt.managedbuilder.buildmodel.IBuildCommand;
import org.eclipse.cdt.managedbuilder.core.ManagedBuilderCorePlugin;
import org.eclipse.cdt.managedbuilder.internal.core.ManagedMakeMessages;
+import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
@@ -47,6 +48,8 @@ public class CommandBuilder implements IBuildModelBuilder {
private Process fProcess;
private String fErrMsg;
+ private IProject fProject;
+
protected class OutputStreamWrapper extends OutputStream {
private OutputStream fOut;
@@ -80,8 +83,9 @@ public class CommandBuilder implements IBuildModelBuilder {
}
- public CommandBuilder(IBuildCommand cmd, IResourceRebuildStateContainer cr){
+ public CommandBuilder(IBuildCommand cmd, IResourceRebuildStateContainer cr, IProject project){
fCmd = cmd;
+ fProject = project;
}
protected OutputStream wrap(OutputStream out){
@@ -143,7 +147,7 @@ public class CommandBuilder implements IBuildModelBuilder {
}
protected ICommandLauncher createLauncher() {
- return new CommandLauncher();
+ return CommandLauncherManager.getInstance().getCommandLauncher(fProject);
}
public String getErrMsg() {
diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/buildmodel/StepBuilder.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/buildmodel/StepBuilder.java
index 9773bec0aa..b40ae1ccc6 100644
--- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/buildmodel/StepBuilder.java
+++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/buildmodel/StepBuilder.java
@@ -17,7 +17,9 @@ import org.eclipse.cdt.managedbuilder.buildmodel.IBuildCommand;
import org.eclipse.cdt.managedbuilder.buildmodel.IBuildDescription;
import org.eclipse.cdt.managedbuilder.buildmodel.IBuildResource;
import org.eclipse.cdt.managedbuilder.buildmodel.IBuildStep;
+import org.eclipse.cdt.managedbuilder.core.IConfiguration;
import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
@@ -223,8 +225,10 @@ public class StepBuilder implements IBuildModelBuilder {
fCommandBuilders = new CommandBuilder[0];
else {
fCommandBuilders = new CommandBuilder[cmds.length];
+ IConfiguration cfg = fStep.getBuildDescription().getConfiguration();
+ IProject project = (IProject)cfg.getOwner();
for(int i = 0; i < cmds.length; i++){
- fCommandBuilders[i] = new CommandBuilder(cmds[i], fRebuildStateContainer);
+ fCommandBuilders[i] = new CommandBuilder(cmds[i], fRebuildStateContainer, project);
}
}
}
diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/Builder.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/Builder.java
index 2b61d3e6ca..aa3427dce5 100644
--- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/Builder.java
+++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/Builder.java
@@ -25,7 +25,7 @@ import java.util.SortedMap;
import java.util.StringTokenizer;
import org.eclipse.cdt.core.CCorePlugin;
-import org.eclipse.cdt.core.CommandLauncher;
+import org.eclipse.cdt.core.CommandLauncherManager;
import org.eclipse.cdt.core.ErrorParserManager;
import org.eclipse.cdt.core.ICommandLauncher;
import org.eclipse.cdt.core.cdtvariables.CdtVariableException;
@@ -2858,7 +2858,7 @@ public class Builder extends HoldsOptions implements IBuilder, IMatchKeyProvider
return getSuperClass().getCommandLauncher();
else if(fCommandLauncher == null) // catch all for backwards compatibility
- fCommandLauncher = new CommandLauncher();
+ fCommandLauncher = CommandLauncherManager.getInstance().getCommandLauncher();
return fCommandLauncher;
}
diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/Configuration.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/Configuration.java
index bba687d816..03f14a6256 100644
--- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/Configuration.java
+++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/Configuration.java
@@ -45,6 +45,7 @@ import org.eclipse.cdt.internal.core.SafeStringInterner;
import org.eclipse.cdt.managedbuilder.buildproperties.IBuildProperty;
import org.eclipse.cdt.managedbuilder.buildproperties.IBuildPropertyType;
import org.eclipse.cdt.managedbuilder.buildproperties.IBuildPropertyValue;
+import org.eclipse.cdt.managedbuilder.buildproperties.IOptionalBuildProperties;
import org.eclipse.cdt.managedbuilder.core.BuildException;
import org.eclipse.cdt.managedbuilder.core.IBuildObject;
import org.eclipse.cdt.managedbuilder.core.IBuildObjectProperties;
@@ -114,6 +115,7 @@ public class Configuration extends BuildObject implements IConfiguration, IBuild
private String description;
private ICSourceEntry[] sourceEntries;
private BuildObjectProperties buildProperties;
+ private OptionalBuildProperties optionalBuildProperties;
private boolean isTest;
private SupportedProperties supportedProperties;
@@ -261,6 +263,10 @@ public class Configuration extends BuildObject implements IConfiguration, IBuild
if(props != null)
buildProperties = new BuildObjectProperties(props, this, this);
+ String optionalProps = SafeStringInterner.safeIntern(element.getAttribute(OPTIONAL_BUILD_PROPERTIES));
+ if(optionalProps != null)
+ optionalBuildProperties = new OptionalBuildProperties(optionalProps);
+
String artType = SafeStringInterner.safeIntern(element.getAttribute(BUILD_ARTEFACT_TYPE));
if(artType != null){
if(buildProperties == null)
@@ -482,6 +488,9 @@ public class Configuration extends BuildObject implements IConfiguration, IBuild
if(baseCfg.buildProperties != null)
this.buildProperties = new BuildObjectProperties(baseCfg.buildProperties, this, this);
+ if (baseCfg.optionalBuildProperties != null)
+ this.optionalBuildProperties = new OptionalBuildProperties(baseCfg.optionalBuildProperties);
+
// set managedBuildRevision
setManagedBuildRevision(baseCfg.getManagedBuildRevision());
@@ -625,6 +634,10 @@ public class Configuration extends BuildObject implements IConfiguration, IBuild
if(cloneConfig.buildProperties != null) {
this.buildProperties = new BuildObjectProperties(cloneConfig.buildProperties, this, this);
}
+
+ if (cloneConfig.optionalBuildProperties != null) {
+ this.optionalBuildProperties = new OptionalBuildProperties(cloneConfig.optionalBuildProperties);
+ }
this.description = cloneConfig.getDescription();
@@ -819,6 +832,10 @@ public class Configuration extends BuildObject implements IConfiguration, IBuild
if(props != null)
buildProperties = new BuildObjectProperties(props, this, this);
+ String optionalProps = element.getAttribute(OPTIONAL_BUILD_PROPERTIES);
+ if (optionalProps != null)
+ optionalBuildProperties = new OptionalBuildProperties(optionalProps);
+
String artType = SafeStringInterner.safeIntern(element.getAttribute(BUILD_ARTEFACT_TYPE));
if(artType != null){
if(buildProperties == null)
@@ -908,6 +925,10 @@ public class Configuration extends BuildObject implements IConfiguration, IBuild
}
}
+ if(optionalBuildProperties != null){
+ element.setAttribute(OPTIONAL_BUILD_PROPERTIES, optionalBuildProperties.toString());
+ }
+
if (parent != null)
element.setAttribute(IConfiguration.PARENT, parent.getId());
@@ -2398,6 +2419,18 @@ public class Configuration extends BuildObject implements IConfiguration, IBuild
return buildProperties;
}
+ @Override
+ public IOptionalBuildProperties getOptionalBuildProperties() {
+ if (optionalBuildProperties == null){
+ OptionalBuildProperties parentProps = findOptionalBuildProperties();
+ if(parentProps != null)
+ optionalBuildProperties = new OptionalBuildProperties(parentProps);
+ else
+ optionalBuildProperties = new OptionalBuildProperties();
+ }
+ return optionalBuildProperties;
+ }
+
private BuildObjectProperties findBuildProperties(){
if(buildProperties == null){
if(parent != null){
@@ -2407,6 +2440,16 @@ public class Configuration extends BuildObject implements IConfiguration, IBuild
}
return buildProperties;
}
+
+ private OptionalBuildProperties findOptionalBuildProperties(){
+ if (optionalBuildProperties == null){
+ if (parent != null){
+ return ((Configuration)parent).findOptionalBuildProperties();
+ }
+ return null;
+ }
+ return optionalBuildProperties;
+ }
public boolean supportsType(IBuildPropertyType type) {
return supportsType(type.getId());
diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/ManagedProject.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/ManagedProject.java
index 22bbaa7cde..68d59d2f27 100644
--- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/ManagedProject.java
+++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/ManagedProject.java
@@ -24,6 +24,7 @@ import org.eclipse.cdt.core.settings.model.ICStorageElement;
import org.eclipse.cdt.internal.core.cdtvariables.StorableCdtVariables;
import org.eclipse.cdt.managedbuilder.buildproperties.IBuildPropertyType;
import org.eclipse.cdt.managedbuilder.buildproperties.IBuildPropertyValue;
+import org.eclipse.cdt.managedbuilder.buildproperties.IOptionalBuildProperties;
import org.eclipse.cdt.managedbuilder.core.IBuildObject;
import org.eclipse.cdt.managedbuilder.core.IBuildObjectProperties;
import org.eclipse.cdt.managedbuilder.core.IBuildPropertiesRestriction;
@@ -57,6 +58,7 @@ public class ManagedProject extends BuildObject implements IManagedProject, IBui
// private StorableEnvironment userDefinedEnvironment;
private BuildObjectProperties buildProperties;
+ private OptionalBuildProperties optionalBuildProperties;
/*
* C O N S T R U C T O R S
@@ -191,6 +193,10 @@ public class ManagedProject extends BuildObject implements IManagedProject, IBui
String props = element.getAttribute(BUILD_PROPERTIES);
if(props != null && props.length() != 0)
buildProperties = new BuildObjectProperties(props, this, this);
+
+ String optionalProps = element.getAttribute(OPTIONAL_BUILD_PROPERTIES);
+ if (optionalProps != null && optionalProps.length() != 0)
+ optionalBuildProperties = new OptionalBuildProperties(optionalProps);
String artType = element.getAttribute(BUILD_ARTEFACT_TYPE);
if(artType != null){
@@ -576,6 +582,18 @@ public class ManagedProject extends BuildObject implements IManagedProject, IBui
return buildProperties;
}
+ @Override
+ public IOptionalBuildProperties getOptionalBuildProperties() {
+ if(optionalBuildProperties == null){
+ OptionalBuildProperties parentProps = findOptionalBuildProperties();
+ if(parentProps != null)
+ optionalBuildProperties = new OptionalBuildProperties(parentProps);
+ else
+ optionalBuildProperties = new OptionalBuildProperties();
+ }
+ return optionalBuildProperties;
+ }
+
private BuildObjectProperties findBuildProperties(){
if(buildProperties == null){
if(projectType != null){
@@ -586,6 +604,16 @@ public class ManagedProject extends BuildObject implements IManagedProject, IBui
return buildProperties;
}
+ private OptionalBuildProperties findOptionalBuildProperties(){
+ if(optionalBuildProperties == null){
+ if(projectType != null){
+ return ((ProjectType)projectType).findOptionalBuildProperties();
+ }
+ return null;
+ }
+ return optionalBuildProperties;
+ }
+
@Override
public void propertiesChanged() {
IConfiguration cfgs[] = getConfigurations();
diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/MultiConfiguration.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/MultiConfiguration.java
index f3e9bda6d7..0a7b5a0e4b 100644
--- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/MultiConfiguration.java
+++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/MultiConfiguration.java
@@ -22,6 +22,7 @@ import org.eclipse.cdt.core.settings.model.extension.CBuildData;
import org.eclipse.cdt.core.settings.model.extension.CConfigurationData;
import org.eclipse.cdt.managedbuilder.buildproperties.IBuildProperty;
import org.eclipse.cdt.managedbuilder.buildproperties.IBuildPropertyValue;
+import org.eclipse.cdt.managedbuilder.buildproperties.IOptionalBuildProperties;
import org.eclipse.cdt.managedbuilder.core.BuildException;
import org.eclipse.cdt.managedbuilder.core.IBuildObjectProperties;
import org.eclipse.cdt.managedbuilder.core.IBuilder;
@@ -1204,6 +1205,14 @@ public class MultiConfiguration extends MultiItemsHolder implements
return curr().getBuildProperties();
}
+ /* (non-Javadoc)
+ * @see org.eclipse.cdt.managedbuilder.core.IBuildObjectPropertiesContainer#getOptionalBuildProperties()
+ */
+ @Override
+ public IOptionalBuildProperties getOptionalBuildProperties() {
+ return curr().getOptionalBuildProperties();
+ }
+
@Override
public boolean getParallelDef() {
for (IConfiguration cfg : fCfgs) {
diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/OptionalBuildProperties.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/OptionalBuildProperties.java
new file mode 100644
index 0000000000..8ec750feba
--- /dev/null
+++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/OptionalBuildProperties.java
@@ -0,0 +1,104 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Red Hat Inc. 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
+ *
+ * Red Hat Inc. - initial contribution
+ *******************************************************************************/
+package org.eclipse.cdt.managedbuilder.internal.core;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.StringTokenizer;
+
+import org.eclipse.cdt.internal.core.SafeStringInterner;
+import org.eclipse.cdt.managedbuilder.buildproperties.IOptionalBuildProperties;
+
+public class OptionalBuildProperties implements IOptionalBuildProperties {
+
+ public static final String PROPERTY_VALUE_SEPARATOR = "="; //$NON-NLS-1$
+ public static final String PROPERTIES_SEPARATOR = ","; //$NON-NLS-1$
+
+ private Map<String, String> fProperties = new HashMap<>();
+
+ public OptionalBuildProperties() {
+ }
+
+ public OptionalBuildProperties(String properties) {
+ StringTokenizer t = new StringTokenizer(properties, PROPERTIES_SEPARATOR);
+ while(t.hasMoreTokens()){
+ String property = t.nextToken();
+ int index = property.indexOf(PROPERTY_VALUE_SEPARATOR);
+ String id, value;
+ if(index != -1){
+ id = SafeStringInterner.safeIntern(property.substring(0, index));
+ value = SafeStringInterner.safeIntern(property.substring(index + 1));
+ } else {
+ id = SafeStringInterner.safeIntern(property);
+ value = null;
+ }
+ fProperties.put(id, value);
+ }
+ }
+
+ public OptionalBuildProperties(OptionalBuildProperties properties) {
+ fProperties.putAll(properties.fProperties);
+ }
+
+ @Override
+ public String getProperty(String id) {
+ return fProperties.get(id);
+ }
+
+ @Override
+ public void setProperty(String id, String value) {
+ fProperties.put(id, value);
+ }
+
+ @Override
+ public String[] getProperties(){
+ return fProperties.values().toArray(new String[fProperties.size()]);
+ }
+
+ @Override
+ public void removeProperty(String id) {
+ fProperties.remove(id);
+ }
+
+ @Override
+ public String toString(){
+ int size = fProperties.size();
+ Set<Entry<String,String>> entries = fProperties.entrySet();
+ if(size == 0)
+ return ""; //$NON-NLS-1$
+
+ StringBuilder buf = new StringBuilder();
+ Iterator<Entry<String,String>> iterator = entries.iterator();
+ Entry<String,String> entry = iterator.next();
+ buf.append(entry.getKey() + PROPERTY_VALUE_SEPARATOR + entry.getValue());
+
+ while (iterator.hasNext()) {
+ buf.append(PROPERTIES_SEPARATOR);
+ entry = iterator.next();
+ buf.append(entry.getKey() + PROPERTY_VALUE_SEPARATOR + entry.getValue());
+ }
+ return buf.toString();
+ }
+
+ @Override
+ public Object clone() {
+ return new OptionalBuildProperties(this);
+ }
+
+ @Override
+ public void clear() {
+ fProperties.clear();
+ }
+
+
+}
diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/ProjectType.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/ProjectType.java
index 780b7f374e..c95d833b50 100644
--- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/ProjectType.java
+++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/ProjectType.java
@@ -22,6 +22,7 @@ import org.eclipse.cdt.internal.core.SafeStringInterner;
import org.eclipse.cdt.managedbuilder.buildproperties.IBuildProperty;
import org.eclipse.cdt.managedbuilder.buildproperties.IBuildPropertyType;
import org.eclipse.cdt.managedbuilder.buildproperties.IBuildPropertyValue;
+import org.eclipse.cdt.managedbuilder.buildproperties.IOptionalBuildProperties;
import org.eclipse.cdt.managedbuilder.core.IBuildObjectProperties;
import org.eclipse.cdt.managedbuilder.core.IBuildPropertiesRestriction;
import org.eclipse.cdt.managedbuilder.core.IConfiguration;
@@ -66,6 +67,7 @@ public class ProjectType extends BuildObject implements IProjectType, IBuildProp
private IProjectBuildMacroSupplier buildMacroSupplier = null;
BuildObjectProperties buildProperties;
+ OptionalBuildProperties optionalBuildProperties;
// Miscellaneous
@@ -708,6 +710,28 @@ public class ProjectType extends BuildObject implements IProjectType, IBuildProp
}
@Override
+ public IOptionalBuildProperties getOptionalBuildProperties() {
+ if(optionalBuildProperties == null){
+ OptionalBuildProperties parentProps = findOptionalBuildProperties();
+ if(parentProps != null)
+ optionalBuildProperties = new OptionalBuildProperties(parentProps);
+ else
+ optionalBuildProperties = new OptionalBuildProperties();
+ }
+ return optionalBuildProperties;
+ }
+
+ OptionalBuildProperties findOptionalBuildProperties(){
+ if(optionalBuildProperties == null){
+ if(superClass != null){
+ return ((ProjectType)superClass).findOptionalBuildProperties();
+ }
+ return null;
+ }
+ return optionalBuildProperties;
+ }
+
+ @Override
public void propertiesChanged() {
List<Configuration> list = getConfigurationList();
for(int i = 0; i < list.size(); i++){
diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/language/settings/providers/GCCBuiltinSpecsDetectorCygwin.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/language/settings/providers/GCCBuiltinSpecsDetectorCygwin.java
index d2a4b86ed7..1c63fd73c8 100644
--- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/language/settings/providers/GCCBuiltinSpecsDetectorCygwin.java
+++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/language/settings/providers/GCCBuiltinSpecsDetectorCygwin.java
@@ -12,11 +12,17 @@
package org.eclipse.cdt.managedbuilder.internal.language.settings.providers;
import java.net.URI;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
import org.eclipse.cdt.core.EFSExtensionProvider;
import org.eclipse.cdt.internal.core.Cygwin;
+import org.eclipse.cdt.managedbuilder.buildproperties.IOptionalBuildProperties;
+import org.eclipse.cdt.managedbuilder.core.IConfiguration;
+import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager;
import org.eclipse.cdt.managedbuilder.core.ManagedBuilderCorePlugin;
import org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuiltinSpecsDetector;
+import org.eclipse.core.runtime.Platform;
/**
* Class to detect built-in compiler settings for Cygwin toolchain.
@@ -26,6 +32,7 @@ public class GCCBuiltinSpecsDetectorCygwin extends GCCBuiltinSpecsDetector {
// ID must match the tool-chain definition in org.eclipse.cdt.managedbuilder.core.buildDefinitions extension point
private static final String GCC_TOOLCHAIN_ID_CYGWIN = "cdt.managedbuild.toolchain.gnu.cygwin.base"; //$NON-NLS-1$
private static final String ENV_PATH = "PATH"; //$NON-NLS-1$
+ public static final String CONTAINER_ENABLEMENT_PROPERTY = "org.eclipse.cdt.docker.launcher.containerbuild.property.enablement"; //$NON-NLS-1$
/**
* EFSExtensionProvider for Cygwin translations
@@ -46,7 +53,14 @@ public class GCCBuiltinSpecsDetectorCygwin extends GCCBuiltinSpecsDetector {
String windowsPath = null;
try {
String cygwinPath = getPathFromURI(locationURI);
- windowsPath = Cygwin.cygwinToWindowsPath(cygwinPath, envPathValue);
+ IConfiguration cfg = ManagedBuildManager.getConfigurationForDescription(currentCfgDescription);
+ if (cfg != null) {
+ IOptionalBuildProperties bp = cfg.getOptionalBuildProperties();
+ String ep = bp.getProperty(CONTAINER_ENABLEMENT_PROPERTY);
+ if (ep == null || !Boolean.parseBoolean(ep)) {
+ windowsPath = Cygwin.cygwinToWindowsPath(cygwinPath, envPathValue);
+ }
+ }
} catch (Exception e) {
ManagedBuilderCorePlugin.log(e);
}
diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/language/settings/providers/AbstractBuiltinSpecsDetector.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/language/settings/providers/AbstractBuiltinSpecsDetector.java
index 3ed6c14997..ca31fcc4d6 100644
--- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/language/settings/providers/AbstractBuiltinSpecsDetector.java
+++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/language/settings/providers/AbstractBuiltinSpecsDetector.java
@@ -26,7 +26,7 @@ import java.util.Map.Entry;
import java.util.Set;
import org.eclipse.cdt.core.CCorePlugin;
-import org.eclipse.cdt.core.CommandLauncher;
+import org.eclipse.cdt.core.CommandLauncherManager;
import org.eclipse.cdt.core.ErrorParserManager;
import org.eclipse.cdt.core.ICommandLauncher;
import org.eclipse.cdt.core.IConsoleParser;
@@ -542,6 +542,7 @@ public abstract class AbstractBuiltinSpecsDetector extends AbstractLanguageSetti
boolean isChanged = false;
List<String> languageIds = getLanguageScope();
+
if (languageIds != null) {
monitor.beginTask(ManagedMakeMessages.getResourceString("AbstractBuiltinSpecsDetector.ScannerDiscoveryTaskTitle"), //$NON-NLS-1$
TICKS_REMOVE_MARKERS + languageIds.size()*TICKS_RUN_FOR_ONE_LANGUAGE + TICKS_SERIALIZATION);
@@ -656,7 +657,7 @@ public abstract class AbstractBuiltinSpecsDetector extends AbstractLanguageSetti
}
console.start(currentProject);
- ICommandLauncher launcher = new CommandLauncher();
+ ICommandLauncher launcher = CommandLauncherManager.getInstance().getCommandLauncher(currentCfgDescription);
launcher.setProject(currentProject);
IPath program = new Path(""); //$NON-NLS-1$
@@ -765,7 +766,7 @@ public abstract class AbstractBuiltinSpecsDetector extends AbstractLanguageSetti
// so collect them to save later when output finishes
if (entries != null) {
for (ICLanguageSettingEntry entry : entries) {
- if (!detectedSettingEntries.contains(entry)) {
+ if (detectedSettingEntries != null && !detectedSettingEntries.contains(entry)) {
detectedSettingEntries.add(entry);
}
}
diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/language/settings/providers/GCCBuiltinSpecsDetector.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/language/settings/providers/GCCBuiltinSpecsDetector.java
index 163e22a088..d07d225b8c 100644
--- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/language/settings/providers/GCCBuiltinSpecsDetector.java
+++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/language/settings/providers/GCCBuiltinSpecsDetector.java
@@ -74,7 +74,7 @@ public class GCCBuiltinSpecsDetector extends ToolchainBuiltinSpecsDetector imple
@Override
protected List<String> parseOptions(String line) {
line = line.trim();
-
+
// contribution of -dD option
if (line.startsWith("#define")) {
return makeList(line);
diff --git a/build/org.eclipse.cdt.managedbuilder.ui.tests/src/org/eclipse/cdt/managedbuilder/ui/tests/util/TestConfiguration.java b/build/org.eclipse.cdt.managedbuilder.ui.tests/src/org/eclipse/cdt/managedbuilder/ui/tests/util/TestConfiguration.java
index 6bb61e8299..d3c139e359 100644
--- a/build/org.eclipse.cdt.managedbuilder.ui.tests/src/org/eclipse/cdt/managedbuilder/ui/tests/util/TestConfiguration.java
+++ b/build/org.eclipse.cdt.managedbuilder.ui.tests/src/org/eclipse/cdt/managedbuilder/ui/tests/util/TestConfiguration.java
@@ -14,6 +14,7 @@ import org.eclipse.cdt.core.settings.model.ICSourceEntry;
import org.eclipse.cdt.core.settings.model.extension.CBuildData;
import org.eclipse.cdt.core.settings.model.extension.CConfigurationData;
import org.eclipse.cdt.managedbuilder.buildproperties.IBuildPropertyValue;
+import org.eclipse.cdt.managedbuilder.buildproperties.IOptionalBuildProperties;
import org.eclipse.cdt.managedbuilder.core.BuildException;
import org.eclipse.cdt.managedbuilder.core.IBuildObjectProperties;
import org.eclipse.cdt.managedbuilder.core.IBuilder;
@@ -632,6 +633,13 @@ public class TestConfiguration implements IConfiguration {
// TODO Auto-generated method stub
return null;
}
+
+ @Override
+ public IOptionalBuildProperties getOptionalBuildProperties() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
@Override
public IResource getOwner() { return null; }
diff --git a/build/org.eclipse.cdt.managedbuilder.ui.tests/src/org/eclipse/cdt/managedbuilder/ui/tests/util/TestProjectType.java b/build/org.eclipse.cdt.managedbuilder.ui.tests/src/org/eclipse/cdt/managedbuilder/ui/tests/util/TestProjectType.java
index d22f0878a6..0727d3bdc7 100644
--- a/build/org.eclipse.cdt.managedbuilder.ui.tests/src/org/eclipse/cdt/managedbuilder/ui/tests/util/TestProjectType.java
+++ b/build/org.eclipse.cdt.managedbuilder.ui.tests/src/org/eclipse/cdt/managedbuilder/ui/tests/util/TestProjectType.java
@@ -11,6 +11,7 @@
package org.eclipse.cdt.managedbuilder.ui.tests.util;
import org.eclipse.cdt.managedbuilder.buildproperties.IBuildPropertyValue;
+import org.eclipse.cdt.managedbuilder.buildproperties.IOptionalBuildProperties;
import org.eclipse.cdt.managedbuilder.core.IBuildObjectProperties;
import org.eclipse.cdt.managedbuilder.core.IConfiguration;
import org.eclipse.cdt.managedbuilder.core.IConfigurationNameProvider;
@@ -76,6 +77,8 @@ public class TestProjectType implements IProjectType {
public void setVersion(Version version) {}
@Override
public IBuildObjectProperties getBuildProperties() { return null; }
+ @Override
+ public IOptionalBuildProperties getOptionalBuildProperties() { return null; }
@Override
public IBuildPropertyValue getBuildArtefactType() {
diff --git a/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/internal/externaltool/ExternalToolInvoker.java b/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/internal/externaltool/ExternalToolInvoker.java
index 8343815c42..4e02aa476f 100644
--- a/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/internal/externaltool/ExternalToolInvoker.java
+++ b/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/internal/externaltool/ExternalToolInvoker.java
@@ -18,7 +18,7 @@ import org.eclipse.cdt.codan.core.cxx.externaltool.ConfigurationSettings;
import org.eclipse.cdt.codan.core.cxx.externaltool.InvocationFailure;
import org.eclipse.cdt.codan.core.cxx.externaltool.InvocationParameters;
import org.eclipse.cdt.core.CCorePlugin;
-import org.eclipse.cdt.core.CommandLauncher;
+import org.eclipse.cdt.core.CommandLauncherManager;
import org.eclipse.cdt.core.ICommandLauncher;
import org.eclipse.cdt.core.IConsoleParser;
import org.eclipse.cdt.core.resources.IConsole;
@@ -85,7 +85,7 @@ public class ExternalToolInvoker {
final OutputStream out = sniffer.getOutputStream();
final OutputStream err = sniffer.getErrorStream();
try {
- ICommandLauncher launcher = new CommandLauncher();
+ ICommandLauncher launcher = CommandLauncherManager.getInstance().getCommandLauncher();
launcher.showCommand(true);
launcher.setProject(project);
Process p = launcher.execute(commandPath, commandArgs, commandEnv, workingDirectory, new SubProgressMonitor(monitor, 50));
diff --git a/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/testplugin/CModelMock.java b/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/testplugin/CModelMock.java
index a6c0a5d255..db644fd1d6 100644
--- a/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/testplugin/CModelMock.java
+++ b/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/testplugin/CModelMock.java
@@ -221,9 +221,11 @@ public class CModelMock {
*/
public static class DummyCConfigurationDescription implements ICConfigurationDescription {
private String id;
+ private ICProjectDescription projectDescription;
public DummyCConfigurationDescription(String id) {
this.id = id;
+ this.projectDescription = new DummyCProjectDescription();
}
@Override
@@ -302,7 +304,7 @@ public class CModelMock {
@Override
public ICProjectDescription getProjectDescription() {
- return null;
+ return projectDescription;
}
@Override
diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/language/settings/providers/LanguageSettingsSerializableProvider.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/language/settings/providers/LanguageSettingsSerializableProvider.java
index 839f80e4c6..f14594d452 100644
--- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/language/settings/providers/LanguageSettingsSerializableProvider.java
+++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/language/settings/providers/LanguageSettingsSerializableProvider.java
@@ -17,6 +17,7 @@ import java.util.Map;
import java.util.Map.Entry;
import org.eclipse.cdt.core.CCorePlugin;
+import org.eclipse.cdt.core.CommandLauncherManager;
import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
import org.eclipse.cdt.core.settings.model.ICLanguageSettingEntry;
import org.eclipse.cdt.internal.core.XmlUtil;
@@ -146,6 +147,9 @@ public class LanguageSettingsSerializableProvider extends LanguageSettingsBasePr
List<? extends ICLanguageSettingEntry> entries) {
String rcProjectPath = rc!=null ? rc.getProjectRelativePath().toString() : null;
fStorage.setSettingEntries(rcProjectPath, languageId, entries);
+ if (cfgDescription != null) {
+ CommandLauncherManager.getInstance().setLanguageSettingEntries(cfgDescription.getProjectDescription().getProject(), entries);
+ }
}
/**
@@ -167,6 +171,10 @@ public class LanguageSettingsSerializableProvider extends LanguageSettingsBasePr
entries = fStorage.getSettingEntries(rcProjectPath, null);
}
}
+
+ if (cfgDescription != null) {
+ entries = CommandLauncherManager.getInstance().getLanguageSettingEntries(cfgDescription.getProjectDescription().getProject(), entries);
+ }
return entries;
}
diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/language/settings/providers/LanguageSettingsProvidersSerializer.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/language/settings/providers/LanguageSettingsProvidersSerializer.java
index 1338d2b704..cbb1001c69 100644
--- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/language/settings/providers/LanguageSettingsProvidersSerializer.java
+++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/language/settings/providers/LanguageSettingsProvidersSerializer.java
@@ -20,6 +20,7 @@ import java.util.Map;
import java.util.Set;
import org.eclipse.cdt.core.CCorePlugin;
+import org.eclipse.cdt.core.CommandLauncherManager;
import org.eclipse.cdt.core.language.settings.providers.ICListenerAgent;
import org.eclipse.cdt.core.language.settings.providers.ILanguageSettingsBroadcastingProvider;
import org.eclipse.cdt.core.language.settings.providers.ILanguageSettingsChangeEvent;
@@ -178,6 +179,10 @@ public class LanguageSettingsProvidersSerializer {
public List<ICLanguageSettingEntry> getSettingEntries(ICConfigurationDescription cfgDescription, IResource rc, String languageId) {
ILanguageSettingsProvider rawProvider = getRawProvider();
List<ICLanguageSettingEntry> entries = rawProvider!=null ? rawProvider.getSettingEntries(cfgDescription, rc, languageId) : null;
+ if (cfgDescription != null) {
+ IProject project = cfgDescription.getProjectDescription().getProject();
+ entries = CommandLauncherManager.getInstance().getLanguageSettingEntries(project, entries);
+ }
return entries;
}
@@ -1456,6 +1461,10 @@ public class LanguageSettingsProvidersSerializer {
return getSettingEntriesUpResourceTree(provider, cfgDescription, parentFolder, languageId);
}
// if out of parent resources - get default entries
+ entries = getSettingEntriesPooled(provider, cfgDescription, null, languageId);
+ if (entries != null) {
+ return entries;
+ }
entries = getSettingEntriesPooled(provider, null, null, languageId);
if (entries != null) {
return entries;
diff --git a/core/org.eclipse.cdt.core/plugin.xml b/core/org.eclipse.cdt.core/plugin.xml
index 81354a3bcb..086b08d5ef 100644
--- a/core/org.eclipse.cdt.core/plugin.xml
+++ b/core/org.eclipse.cdt.core/plugin.xml
@@ -692,6 +692,7 @@
<extension-point id="ProblemMarkerFilter" name="%problemMarkerFilter.name" schema="schema/ProblemMarkerFilter.exsd"/>
<extension-point id="buildConfigProvider" name="buildConfigProvider" schema="schema/buildConfigProvider.exsd"/>
<extension-point id="toolChainProvider" name="Tool Chain Provider" schema="schema/toolChainProvider.exsd"/>
+ <extension-point id="CommandLauncherFactory" name="CommandLauncherFactory" schema="schema/CommandLauncherFactory.exsd"/>
<extension
point="org.eclipse.cdt.core.templateProcessTypes">
diff --git a/core/org.eclipse.cdt.core/schema/CommandLauncherFactory.exsd b/core/org.eclipse.cdt.core/schema/CommandLauncherFactory.exsd
new file mode 100644
index 0000000000..a4b0564eb1
--- /dev/null
+++ b/core/org.eclipse.cdt.core/schema/CommandLauncherFactory.exsd
@@ -0,0 +1,128 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Schema file written by PDE -->
+<schema targetNamespace="org.eclipse.cdt.core" xmlns="http://www.w3.org/2001/XMLSchema">
+<annotation>
+ <appInfo>
+ <meta.schema plugin="org.eclipse.cdt.core" id="CommandLauncherFactory" name="CommandLauncherFactory"/>
+ </appInfo>
+ <documentation>
+ This extension point is used to contribute a Command Launcher factory to CDT. A Command Launcher factory creates a Command Launcher for running commands.
+ </documentation>
+ </annotation>
+
+ <element name="extension">
+ <annotation>
+ <appInfo>
+ <meta.element />
+ </appInfo>
+ </annotation>
+ <complexType>
+ <sequence minOccurs="1" maxOccurs="unbounded">
+ <element ref="factory"/>
+ </sequence>
+ <attribute name="point" type="string" use="required">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="id" type="string">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="name" type="string">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ <appInfo>
+ <meta.attribute translatable="true"/>
+ </appInfo>
+ </annotation>
+ </attribute>
+ </complexType>
+ </element>
+
+ <element name="factory">
+ <complexType>
+ <attribute name="id" type="string">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="priority" type="string" use="default" value="0">
+ <annotation>
+ <documentation>
+ Integer priority of factory. Default is 0. Use higher values if you want to override an existing factory.
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="class" type="string">
+ <annotation>
+ <documentation>
+ Command Launcher factory class that implements org.eclipse.cdt.core.ICommandLauncherFactory.
+ </documentation>
+ <appInfo>
+ <meta.attribute kind="java" basedOn=":org.eclipse.cdt.core.ICommandLauncherFactory"/>
+ </appInfo>
+ </annotation>
+ </attribute>
+ </complexType>
+ </element>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="since"/>
+ </appInfo>
+ <documentation>
+ CDT 9.4.0
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="examples"/>
+ </appInfo>
+ <documentation>
+ [Enter extension point usage example here.]
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="apiinfo"/>
+ </appInfo>
+ <documentation>
+ Plug-ins that want to extend this extension point must implement &lt;samp&gt;org.eclipse.cdt.core.ICommandLauncherFactory&lt;/samp&gt; interface.
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="implementation"/>
+ </appInfo>
+ <documentation>
+ [Enter information about supplied implementation of this extension point.]
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="copyright"/>
+ </appInfo>
+ <documentation>
+ Copyright (c) 2017 Red Hat Inc. and others.&lt;br/&gt;
+All rights reserved. This program and the accompanying materials&lt;br/&gt;
+are made available under the terms of the Eclipse Public License v1.0&lt;br/&gt;
+which accompanies this distribution, and is available at&lt;br/&gt;
+http://www.eclipse.org/legal/epl-v10.html&lt;br/&gt;
+ </documentation>
+ </annotation>
+
+</schema>
diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CCorePlugin.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CCorePlugin.java
index b639dee57c..ab980ee987 100644
--- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CCorePlugin.java
+++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CCorePlugin.java
@@ -156,6 +156,17 @@ public class CCorePlugin extends Plugin {
*/
public static final String ERROR_PARSER_UNIQ_ID = PLUGIN_ID + "." + ERROR_PARSER_SIMPLE_ID; //$NON-NLS-1$
+ /**
+ * Name of the extension point for contributing a Command Launcher factory
+ * @since 6.3
+ */
+ public static final String COMMAND_LAUNCHER_FACTORY_SIMPLE_ID = "CommandLauncherFactory"; //$NON-NLS-1$
+ /**
+ * Full unique name of the extension point for contributing a Command Launcher factory
+ * @since 6.3
+ */
+ public static final String COMMAND_LAUNCHER_FACTORY_UNIQ_ID = PLUGIN_ID + "." + COMMAND_LAUNCHER_FACTORY_SIMPLE_ID; //$NON-NLS-1$
+
// default store for pathentry
public static final String DEFAULT_PATHENTRY_STORE_ID = PLUGIN_ID + ".cdtPathEntryStore"; //$NON-NLS-1$
diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CommandLauncherManager.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CommandLauncherManager.java
new file mode 100644
index 0000000000..ad70f104cc
--- /dev/null
+++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CommandLauncherManager.java
@@ -0,0 +1,288 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Red Hat Inc. 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:
+ * Red Hat Inc. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.core;
+
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
+import org.eclipse.cdt.core.settings.model.ICLanguageSettingEntry;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtension;
+import org.eclipse.core.runtime.IExtensionPoint;
+import org.eclipse.core.runtime.IExtensionRegistry;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.Platform;
+
+/**
+ * @since 6.3
+ */
+public class CommandLauncherManager {
+
+ private static CommandLauncherManager instance;
+
+ private List<ICommandLauncherFactory> factories = new ArrayList<>();
+ private Map<ICommandLauncherFactory, Integer> priorityMapping = new HashMap<>();
+
+ private CommandLauncherManager() {
+ loadCommandLauncherFactoryExtensions();
+ }
+
+ public static synchronized CommandLauncherManager getInstance() {
+ if (instance == null) {
+ instance = new CommandLauncherManager();
+ }
+ return instance;
+ }
+
+ public ICommandLauncher getCommandLauncher() {
+ return new CommandLauncherWrapper(this);
+ }
+
+
+ private class CommandLauncherWrapper implements ICommandLauncher {
+
+ private ICommandLauncher launcher;
+ private IProject fProject;
+ private boolean fShowCommand;
+ private String fErrorMessage;
+ private CommandLauncherManager manager;
+
+ public CommandLauncherWrapper(CommandLauncherManager manager) {
+ this.manager = manager;
+ }
+
+ @Override
+ public void setProject(IProject project) {
+ if (launcher != null) {
+ launcher.setProject(project);
+ } else {
+ fProject = project;
+ }
+ }
+
+ @Override
+ public IProject getProject() {
+ if (launcher != null) {
+ return launcher.getProject();
+ }
+ return fProject;
+ }
+
+ @Override
+ public void showCommand(boolean show) {
+ if (launcher != null) {
+ launcher.showCommand(show);
+ } else {
+ fShowCommand = show;
+ }
+ }
+
+ @Override
+ public String getErrorMessage() {
+ if (launcher != null) {
+ return launcher.getErrorMessage();
+ }
+ return fErrorMessage;
+ }
+
+ @Override
+ public void setErrorMessage(String error) {
+ if (launcher != null) {
+ launcher.setErrorMessage(error);
+ } else {
+ fErrorMessage = error;
+ }
+ }
+
+ @Override
+ public String[] getCommandArgs() {
+ if (launcher != null) {
+ return launcher.getCommandArgs();
+ }
+ return new String[0];
+ }
+
+ @Override
+ public Properties getEnvironment() {
+ if (launcher != null) {
+ return launcher.getEnvironment();
+ }
+ return null;
+ }
+
+ @Override
+ public String getCommandLine() {
+ if (launcher != null) {
+ return launcher.getCommandLine();
+ }
+ return null;
+ }
+
+ @Override
+ public Process execute(IPath commandPath, String[] args, String[] env, IPath workingDirectory,
+ IProgressMonitor monitor) throws CoreException {
+ if (launcher == null) {
+ launcher = manager.getCommandLauncher(fProject);
+ launcher.setProject(fProject);
+ launcher.showCommand(fShowCommand);
+ launcher.setErrorMessage(fErrorMessage);
+ }
+ return launcher.execute(commandPath, args, env, workingDirectory, monitor);
+ }
+
+ @SuppressWarnings("deprecation")
+ @Override
+ public int waitAndRead(OutputStream out, OutputStream err) {
+ if (launcher != null) {
+ return launcher.waitAndRead(out, err);
+ }
+ return 0;
+ }
+
+ @Override
+ public int waitAndRead(OutputStream output, OutputStream err, IProgressMonitor monitor) {
+ if (launcher != null) {
+ return launcher.waitAndRead(output, err, monitor);
+ }
+ return 0;
+ }
+
+ }
+
+
+ /**
+ * Get a command launcher.
+ *
+ * @param project - IProject to determine launcher for.
+ * @return an ICommandLauncher for running commands
+ */
+ public ICommandLauncher getCommandLauncher(IProject project) {
+ // loop through list of factories and return launcher returned with
+ // highest priority
+ int highestPriority = -1;
+ ICommandLauncher bestLauncher = null;
+ for (ICommandLauncherFactory factory : factories) {
+ ICommandLauncher launcher = factory.getCommandLauncher(project);
+ if (launcher != null) {
+ if (priorityMapping.get(factory) > highestPriority) {
+ bestLauncher = launcher;
+ }
+ }
+ }
+ if (bestLauncher != null) {
+ return bestLauncher;
+ }
+ // default to local CommandLauncher
+ return new CommandLauncher();
+ }
+
+ /**
+ * Get a command launcher.
+ *
+ * @param cfgd - ICConfigurationDescription to get command launcher for.
+ * @return an ICommandLauncher for running commands
+ */
+ public ICommandLauncher getCommandLauncher(ICConfigurationDescription cfgd) {
+ // loop through list of factories and return launcher returned with
+ // highest priority
+ int highestPriority = -1;
+ ICommandLauncher bestLauncher = null;
+ for (ICommandLauncherFactory factory : factories) {
+ ICommandLauncher launcher = factory.getCommandLauncher(cfgd);
+ if (launcher != null) {
+ if (priorityMapping.get(factory) > highestPriority) {
+ bestLauncher = launcher;
+ }
+ }
+ }
+ if (bestLauncher != null) {
+ return bestLauncher;
+ }
+ // default to local CommandLauncher
+ return new CommandLauncher();
+ }
+
+ /**
+ * Load command launcher factory contributed extensions from extension registry.
+ *
+ */
+ private void loadCommandLauncherFactoryExtensions() {
+ IExtensionRegistry registry = Platform.getExtensionRegistry();
+ IExtensionPoint extension = registry.getExtensionPoint(CCorePlugin.PLUGIN_ID, CCorePlugin.COMMAND_LAUNCHER_FACTORY_SIMPLE_ID);
+ if (extension != null) {
+ IExtension[] extensions = extension.getExtensions();
+ for (IExtension ext : extensions) {
+ try {
+ IConfigurationElement element[] = ext.getConfigurationElements();
+ for (IConfigurationElement element2 : element) {
+ if (element2.getName().equalsIgnoreCase("factory")) { //$NON-NLS-1$
+ ICommandLauncherFactory factory = (ICommandLauncherFactory) element2.createExecutableExtension("class"); //$NON-NLS-1$
+ String priorityAttr = element2.getAttribute("priority"); //$NON-NLS-1$
+ int priority = Integer.valueOf(0);
+ if (priorityAttr != null) {
+ try {
+ priority = Integer.valueOf(priorityAttr);
+ } catch (NumberFormatException e) {
+ CCorePlugin.log(e);
+ }
+ }
+ factories.add(factory);
+ priorityMapping.put(factory, priority);
+ }
+ }
+ } catch (Exception e) {
+ CCorePlugin.log("Cannot load CommandLauncherFactory extension " + ext.getUniqueIdentifier(), e); //$NON-NLS-1$
+ }
+ }
+ }
+ }
+
+ private ICommandLauncherFactory getBestFactory(IProject project) {
+ // loop through list of factories and return launcher returned with
+ // highest priority
+ int highestPriority = -1;
+ ICommandLauncherFactory bestLauncherFactory = null;
+ for (ICommandLauncherFactory factory : factories) {
+ ICommandLauncher launcher = factory.getCommandLauncher(project);
+ if (launcher != null) {
+ if (priorityMapping.get(factory) > highestPriority) {
+ bestLauncherFactory = factory;
+ }
+ }
+ }
+ return bestLauncherFactory;
+ }
+
+ public void setLanguageSettingEntries(IProject project, List<? extends ICLanguageSettingEntry> entries) {
+ ICommandLauncherFactory factory = getBestFactory(project);
+ if (factory != null) {
+ factory.registerLanguageSettingEntries(project, entries);
+ }
+ }
+
+ public List<ICLanguageSettingEntry> getLanguageSettingEntries(IProject project, List<ICLanguageSettingEntry> entries) {
+ List<ICLanguageSettingEntry> verifiedEntries = entries;
+ ICommandLauncherFactory factory = getBestFactory(project);
+ if (factory != null) {
+ verifiedEntries = factory.verifyLanguageSettingEntries(project, entries);
+ }
+ return verifiedEntries;
+ }
+
+}
diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/ICommandLauncherFactory.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/ICommandLauncherFactory.java
new file mode 100644
index 0000000000..7da2397e78
--- /dev/null
+++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/ICommandLauncherFactory.java
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Red Hat Inc. 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:
+ * Red Hat Inc. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.core;
+
+import java.util.List;
+
+import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
+import org.eclipse.cdt.core.settings.model.ICLanguageSettingEntry;
+import org.eclipse.core.resources.IProject;
+
+/**
+ * @since 6.3
+ */
+public interface ICommandLauncherFactory {
+
+ /**
+ * Get a Command Launcher for a project (based on active configuration)
+ * @param project - IProject to get command launcher for
+ * @return ICommandLauncher
+ */
+ public ICommandLauncher getCommandLauncher(IProject project);
+
+ /**
+ * Get a Command Launcher for a build configuration descriptor
+ * @param cfgd - ICConfigurationDescription to get command launcher for
+ * @return ICommandLauncher
+ */
+ public ICommandLauncher getCommandLauncher(ICConfigurationDescription cfgd);
+
+ /**
+ * Register language setting entries for a project
+ * @param project - IProject used in obtaining language setting entries
+ * @param entries - List of language setting entries
+ */
+ public void registerLanguageSettingEntries(IProject project, List<? extends ICLanguageSettingEntry> entries);
+
+ /**
+ * Verify language setting entries for a project and change any entries that
+ * have been copied to a local location
+ * @param project - IProject used in obtaining language setting entries
+ * @param entries - List of language setting entries
+ * @return modified List of language setting entries
+ */
+ public List<ICLanguageSettingEntry> verifyLanguageSettingEntries(IProject project, List<ICLanguageSettingEntry> entries);
+
+}
diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/ProcessClosure.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/ProcessClosure.java
index 771cb6e4b0..668457e1d7 100644
--- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/ProcessClosure.java
+++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/ProcessClosure.java
@@ -217,14 +217,18 @@ public class ProcessClosure {
fProcess.destroy();
fProcess = null;
}
- if (!fOutputReader.finished()) {
- fOutputReader.waitFor();
+ if (fOutputReader != null) {
+ if (!fOutputReader.finished()) {
+ fOutputReader.waitFor();
+ }
+ fOutputReader.close();
}
- if (!fErrorReader.finished()) {
- fErrorReader.waitFor();
+ if (fErrorReader != null) {
+ if (!fErrorReader.finished()) {
+ fErrorReader.waitFor();
+ }
+ fErrorReader.close();
}
- fOutputReader.close();
- fErrorReader.close();
fOutputReader = null;
fErrorReader = null;
}
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/language/settings/providers/LanguageSettingsEntriesTab.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/language/settings/providers/LanguageSettingsEntriesTab.java
index 91851f784b..a7c5be0c70 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/language/settings/providers/LanguageSettingsEntriesTab.java
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/language/settings/providers/LanguageSettingsEntriesTab.java
@@ -28,6 +28,7 @@ import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.layout.PixelConverter;
import org.eclipse.jface.viewers.IDecoration;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.TreeViewer;
@@ -39,6 +40,7 @@ import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
@@ -375,7 +377,7 @@ public class LanguageSettingsEntriesTab extends AbstractCPropertyTab {
*/
private void createTreeForEntries(Composite parent) {
treeEntries = new Tree(parent, SWT.BORDER | SWT.SINGLE | SWT.H_SCROLL | SWT.V_SCROLL);
- treeEntries.setLayoutData(new GridData(GridData.FILL_VERTICAL));
+ treeEntries.setLayoutData(new GridData(GridData.FILL_VERTICAL | GridData.GRAB_HORIZONTAL));
treeEntries.setHeaderVisible(true);
treeEntries.setLinesVisible(true);
@@ -383,13 +385,14 @@ public class LanguageSettingsEntriesTab extends AbstractCPropertyTab {
treeEntries.addPaintListener(new PaintListener() {
@Override
public void paintControl(PaintEvent e) {
- int x = treeEntries.getClientArea().width;
- if (treeCol.getWidth() != x)
- treeCol.setWidth(x);
+ Point p = treeEntries.computeSize(SWT.DEFAULT, SWT.DEFAULT);
+ if (treeCol.getWidth() != p.x)
+ treeCol.setWidth(p.x);
}
});
treeCol.setText(Messages.LanguageSettingsProviderTab_SettingEntries);
+
treeCol.setWidth(200);
treeCol.setResizable(false);
treeCol.setToolTipText(Messages.LanguageSettingsProviderTab_SettingEntriesTooltip);
diff --git a/doc/org.eclipse.cdt.doc.user/images/prop_container.png b/doc/org.eclipse.cdt.doc.user/images/prop_container.png
new file mode 100644
index 0000000000..e6e47bbf8b
--- /dev/null
+++ b/doc/org.eclipse.cdt.doc.user/images/prop_container.png
Binary files differ
diff --git a/doc/org.eclipse.cdt.doc.user/images/prop_datavolumes.png b/doc/org.eclipse.cdt.doc.user/images/prop_datavolumes.png
new file mode 100644
index 0000000000..1dea453d4b
--- /dev/null
+++ b/doc/org.eclipse.cdt.doc.user/images/prop_datavolumes.png
Binary files differ
diff --git a/doc/org.eclipse.cdt.doc.user/reference/cdt_u_prop_build.htm b/doc/org.eclipse.cdt.doc.user/reference/cdt_u_prop_build.htm
index e446b5934f..5e7b923b63 100644
--- a/doc/org.eclipse.cdt.doc.user/reference/cdt_u_prop_build.htm
+++ b/doc/org.eclipse.cdt.doc.user/reference/cdt_u_prop_build.htm
@@ -178,6 +178,7 @@ and, moreover, change the visibility of other property pages.
<li>Settings page
<ul>
<li><a href="cdt_u_prop_build_settings_tool.htm"> Tool Settings tab</a>
+ <li><a href="cdt_u_prop_build_settings_container.htm">Container Settings tab</a>
<li><a href="cdt_u_prop_build_settings_steps.htm"> Build Steps tab</a>
<li><a href="cdt_u_prop_build_settings_artifact.htm"> Build Artifact tab</a>
<li><a href="cdt_u_prop_build_settings_binparser.htm">Binary Parsers tab</a>
diff --git a/doc/org.eclipse.cdt.doc.user/reference/cdt_u_prop_build_settings_artifact.htm b/doc/org.eclipse.cdt.doc.user/reference/cdt_u_prop_build_settings_artifact.htm
index 94b36ef1be..9a1f7ea59d 100644
--- a/doc/org.eclipse.cdt.doc.user/reference/cdt_u_prop_build_settings_artifact.htm
+++ b/doc/org.eclipse.cdt.doc.user/reference/cdt_u_prop_build_settings_artifact.htm
@@ -75,6 +75,7 @@
<li>Settings page
<ul>
<li><a href="cdt_u_prop_build_settings_tool.htm"> Tool Settings tab</a>
+ <li><a href="cdt_u_prop_build_settings_container.htm">Container Settings tab</a>
<li><a href="cdt_u_prop_build_settings_steps.htm"> Build Steps tab</a>
<li><a href="cdt_u_prop_build_settings_artifact.htm"> Build Artifact tab</a>
<li><a href="cdt_u_prop_build_settings_binparser.htm">Binary Parsers tab</a>
diff --git a/doc/org.eclipse.cdt.doc.user/reference/cdt_u_prop_build_settings_binparser.htm b/doc/org.eclipse.cdt.doc.user/reference/cdt_u_prop_build_settings_binparser.htm
index 2fc03874ca..06f58a92e1 100644
--- a/doc/org.eclipse.cdt.doc.user/reference/cdt_u_prop_build_settings_binparser.htm
+++ b/doc/org.eclipse.cdt.doc.user/reference/cdt_u_prop_build_settings_binparser.htm
@@ -85,6 +85,7 @@ symbols of the object file using the C/C++ Projects view.</p>
<li>Settings page
<ul>
<li><a href="cdt_u_prop_build_settings_tool.htm"> Tool Settings tab</a>
+ <li><a href="cdt_u_prop_build_settings_container.htm">Container Settings tab</a>
<li><a href="cdt_u_prop_build_settings_steps.htm"> Build Steps tab</a>
<li><a href="cdt_u_prop_build_settings_artifact.htm"> Build Artifact tab</a>
<li><a href="cdt_u_prop_build_settings_binparser.htm">Binary Parsers tab</a>
diff --git a/doc/org.eclipse.cdt.doc.user/reference/cdt_u_prop_build_settings_container.htm b/doc/org.eclipse.cdt.doc.user/reference/cdt_u_prop_build_settings_container.htm
new file mode 100644
index 0000000000..983542a1a9
--- /dev/null
+++ b/doc/org.eclipse.cdt.doc.user/reference/cdt_u_prop_build_settings_container.htm
@@ -0,0 +1,166 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html lang="en">
+<head>
+ <meta http-equiv="Content-Language" content="en-us">
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <title>C/C++ Project Properties, Build, Settings, Container Settings</title>
+ <link rel="stylesheet" type="text/css" href="../help.css">
+</head>
+<body>
+<div role="main"><h1>C/C++ Project Properties, Build, Settings, Container Settings</h1>
+<p>Use the <strong>Container Settings</strong> properties tab to
+specify options for building the project in a Docker Container. This properties tab is
+provided with the optional Docker C/C++ Launch feature. By default,
+project configurations will build locally, however, if you want to have a particular
+configuration build the project in a Container, use the enablement check-box.
+After enabling building in a Container, you need to select an active Docker Connection and
+a down-loaded Image in that Connection to run the build in. The Image must have whatever
+tools are necessary to perform the build already installed. Docker Images will be linux-based so the build
+will use linux appropriate toolsets and create a linux-compatible executable.</p>
+<p>By default, the C/C++ project and all dependent project contents will be mounted
+into the Container where the build is occurring. This allows the build to find project source and
+header files. If additional host directories are needed to
+build the project (e.g. a local header file directory that is not part of an
+installed package in the Docker Image), such directories can be added to the Data Volumes table and they
+will be mounted in the Container before the build occurs. If the Docker daemon is running locally, this
+will be a simple mount. If the Docker daemon is remote,
+mounting will involve automatically copying the directory contents over to the Container since system mounting cannot
+occur across machines.</p>
+<p>To accommodate indexing, build-specs discovery will be performed in the Docker Container. Directories found
+by specs detection will be copied locally for use by the indexer. This copying process also occurs for any
+header file directories discovered while building. The
+header files are stored within the workspace and are only uploaded once per Docker Image. These header files
+can be removed from the Preferences page if, for example, the project no longer needs to build/index for that
+particular Docker Image.</p>
+
+<p><img img="" src="../images/prop_container.png"
+ alt="C/C++ Project Properties, Build, Settings, Container Settings"></p>
+
+
+<table cellpadding="5" cellspacing="0" border="1" width="600px" bordercolor="#DDDDDD" >
+ <caption><strong>Container settings options</strong></caption>
+ <colgroup>
+ <col width="30%" valign="top" >
+ <col width="70%" valign="top" >
+ </colgroup>
+ <tbody>
+ <tr style="text-align:center;">
+ <th id="group"><strong>Group</strong></th>
+ <th id="description"><strong>Description</strong></th>
+ </tr>
+ <tr>
+ <td headers="group"><strong>Configuration</strong></td>
+ <td headers="description"><a href="cdt_u_prop_all.htm">Click here for a description.</a></td>
+ </tr>
+ <tr>
+ <td headers="group"><strong>Manage Configurations...</strong></td>
+ <td headers="description"><a href="cdt_u_prop_all.htm">Click here for a description.</a></td>
+ </tr>
+ <tr>
+ <td headers="group"><strong>Build inside Docker Image</strong> (check-box)</td>
+ <td headers="description">Enables the build to occur inside a Container.</td>
+ </tr>
+ <tr>
+ <td headers="group"><strong>Connection</strong></td>
+ <td headers="description">Pull-down that contains a list of known Docker daemon connections to run the build in if enablement button is checked.</td>
+ </tr>
+ <tr>
+ <td headers="group"><strong>Image</strong></td>
+ <td headers="description">Pull-down that contains Docker Image names to use to create the Container the build will run in. This list is enabled by
+ a Docker Connection selection and the enablement check-box.</td>
+ </tr>
+ <tr>
+ <td headers="group"><strong>Data Volumes</strong></td>
+ <td headers="description">Optional list of directories to mount into the Container prior to building. By default, the C/C++ project and any refererenced
+ projects are mounted automatically in the Container. Directories can be added, edited, or removed using the buttons to the
+ right of the list.</td>
+ </tr>
+ <tr>
+ <td headers="group"><strong>Add...</strong></td>
+ <td headers="description">Button to bring up the <a href="cdt_u_prop_data_volumes.htm">Data Volume</a> dialog for specifying a
+ data volume to mount in the Docker Container. This usually involves selecting a directory from the local system. Once finished,
+ the mount will be shown in the Data Volumes list.</td>
+ </tr>
+ <tr>
+ <td headers="group"><strong>Edit...</strong></td>
+ <td headers="description">Button to edit the currently selected data volume in the Data Volumes list.</td>
+ </tr>
+ <tr>
+ <td headers="group"><strong>Remove</strong></td>
+ <td headers="description">Button to remove the currently selected data volume(s) in the Data Volumes list.</td>
+ </tr>
+ </tbody>
+</table>
+<br>
+<p><strong>Available for:</strong> CDT projects.</p>
+
+<p><img src="../images/ngtasks.gif" alt="Related tasks"
+ width="143" height="21">
+<br>
+</p>
+
+
+<p style="margin-top: 0pt; margin-bottom: 0pt;"><img
+ src="../images/ngref.gif" alt="Related reference" width="143"
+ height="21"><br>
+
+
+<ul>
+<li><a href="cdt_u_prop_resource.htm">Project Properties, Resource page</a>
+<li><a href="cdt_u_prop_builders.htm">Project Properties, Builders page</a>
+<li><a href="cdt_u_prop_all.htm">Project Properties, common C/C++ Configurations handling</a>
+ <ul style="list-style-type: disc">
+ <li><a href="cdt_u_prop_manage_dialog.htm">Manage Configurations dialog</a>
+ <li><a href="cdt_u_prop_manage_newdialog.htm">Create Configuration dialog</a>
+ <li><a href="cdt_u_prop_manage_rendialog.htm">Rename Configuration dialog</a>
+ </ul>
+<li><a href="cdt_u_prop_build.htm">Project Properties, C/C++ Build category</a>
+ <ul style="list-style-type: disc">
+ <li><a href="cdt_u_prop_build_discovery.htm">Discovery options page</a>
+ <li><a href="cdt_u_prop_build_environment.htm">Environment page</a>
+ <li>Settings page
+ <ul>
+ <li><a href="cdt_u_prop_build_settings_tool.htm"> Tool Settings tab</a>
+ <li><a href="cdt_u_prop_build_settings_container.htm">ContainerSettings tab</a>
+ <li><a href="cdt_u_prop_build_settings_steps.htm"> Build Steps tab</a>
+ <li><a href="cdt_u_prop_build_settings_artifact.htm"> Build Artifact tab</a>
+ <li><a href="cdt_u_prop_build_settings_binparser.htm">Binary Parsers tab</a>
+ <li><a href="cdt_u_prop_build_settings_errparser.htm">Error Parsers tab</a>
+ </ul>
+ <li><a href="cdt_u_prop_build_toolchain.htm">Tool chain editor page</a>
+ <li><a href="cdt_u_prop_build_variables.htm">Variables page</a>
+ </ul>
+<li>Project Properties, <a href="cdt_u_prop_general.htm">C/C++ General category</a>
+ <ul style="list-style-type: disc">
+ <li><a href="cdt_u_prop_general_doc.htm">Documentation page</a>
+ <li><a href="cdt_u_prop_general_exp.htm">Export Settings page</a>
+ <!--ul>
+ <li><a href="cdt_u_prop_general_exp_inc.htm">Includes tab</a>
+ <li><a href="cdt_u_prop_general_exp_sym.htm">Symbols tab</a>
+ <li><a href="cdt_u_prop_general_exp_lib.htm">Libraries tab</a>
+ <li><a href="cdt_u_prop_general_exp_libpath.htm">Libraries path tab</a>
+ </ul-->
+ <li><a href="cdt_u_prop_general_typ.htm">File Types page</a>
+ <li><a href="cdt_u_prop_general_idx.htm">Indexer page</a>
+ <li><a href="cdt_u_prop_general_lng.htm">Language Mapping page</a>
+ <li>Paths and Symbols page
+ <ul>
+ <li><a href="cdt_u_prop_general_pns_inc.htm">Includes tab</a>
+ <li><a href="cdt_u_prop_general_pns_sym.htm">Symbols tab</a>
+ <li><a href="cdt_u_prop_general_pns_lib.htm">Libraries tab</a>
+ <li><a href="cdt_u_prop_general_pns_libpath.htm">Libraries path tab</a>
+ <li><a href="cdt_u_prop_general_pns_src.htm">Source Location tab</a>
+ <li><a href="cdt_u_prop_general_pns_out.htm">Output Location tab</a>
+ <li><a href="cdt_u_prop_general_pns_ref.htm">References tab</a>
+ <li><a href="cdt_u_prop_general_pns_hier.htm">Data Hierarchy tab</a>
+ </ul>
+ </ul>
+<li><a href="cdt_u_prop_ref.htm">C/C++ Project Properties, Project References page</a>
+<li><a href="cdt_u_prop_rundebug.htm">C/C++ Project Properties, Run/Debug Settings page</a>
+</ul>
+</p>
+<hr >
+<p><img src="../images/intl_07.gif" ALT="Intel Copyright Statement" ></p>
+
+</div></body>
+</html>
diff --git a/doc/org.eclipse.cdt.doc.user/reference/cdt_u_prop_build_settings_errparser.htm b/doc/org.eclipse.cdt.doc.user/reference/cdt_u_prop_build_settings_errparser.htm
index 566c8c5447..9de52de687 100644
--- a/doc/org.eclipse.cdt.doc.user/reference/cdt_u_prop_build_settings_errparser.htm
+++ b/doc/org.eclipse.cdt.doc.user/reference/cdt_u_prop_build_settings_errparser.htm
@@ -88,6 +88,7 @@ build output log.</p>
<li>Settings page
<ul>
<li><a href="cdt_u_prop_build_settings_tool.htm"> Tool Settings tab</a>
+ <li><a href="cdt_u_prop_build_settings_container.htm">Container Settings tab</a>
<li><a href="cdt_u_prop_build_settings_steps.htm"> Build Steps tab</a>
<li><a href="cdt_u_prop_build_settings_artifact.htm"> Build Artifact tab</a>
<li><a href="cdt_u_prop_build_settings_binparser.htm">Binary Parsers tab</a>
diff --git a/doc/org.eclipse.cdt.doc.user/reference/cdt_u_prop_build_settings_steps.htm b/doc/org.eclipse.cdt.doc.user/reference/cdt_u_prop_build_settings_steps.htm
index 39c3a44e90..3ed28ad752 100644
--- a/doc/org.eclipse.cdt.doc.user/reference/cdt_u_prop_build_settings_steps.htm
+++ b/doc/org.eclipse.cdt.doc.user/reference/cdt_u_prop_build_settings_steps.htm
@@ -99,6 +99,7 @@ including pre-build or post-build steps.<br>
<li>Settings page
<ul>
<li><a href="cdt_u_prop_build_settings_tool.htm"> Tool Settings tab</a>
+ <li><a href="cdt_u_prop_build_settings_container.htm">Container Settings tab</a>
<li><a href="cdt_u_prop_build_settings_steps.htm"> Build Steps tab</a>
<li><a href="cdt_u_prop_build_settings_artifact.htm"> Build Artifact tab</a>
<li><a href="cdt_u_prop_build_settings_binparser.htm">Binary Parsers tab</a>
diff --git a/doc/org.eclipse.cdt.doc.user/reference/cdt_u_prop_build_settings_tool.htm b/doc/org.eclipse.cdt.doc.user/reference/cdt_u_prop_build_settings_tool.htm
index 7d0a6d548a..d999fa31f0 100644
--- a/doc/org.eclipse.cdt.doc.user/reference/cdt_u_prop_build_settings_tool.htm
+++ b/doc/org.eclipse.cdt.doc.user/reference/cdt_u_prop_build_settings_tool.htm
@@ -65,6 +65,7 @@ Use the <strong>Tool Settings</strong> properties tab to customize the tools and
<li>Settings page
<ul>
<li><a href="cdt_u_prop_build_settings_tool.htm"> Tool Settings tab</a>
+ <li><a href="cdt_u_prop_build_settings_container.htm">Container Settings tab</a>
<li><a href="cdt_u_prop_build_settings_steps.htm"> Build Steps tab</a>
<li><a href="cdt_u_prop_build_settings_artifact.htm"> Build Artifact tab</a>
<li><a href="cdt_u_prop_build_settings_binparser.htm">Binary Parsers tab</a>
diff --git a/doc/org.eclipse.cdt.doc.user/reference/cdt_u_prop_data_volumes.htm b/doc/org.eclipse.cdt.doc.user/reference/cdt_u_prop_data_volumes.htm
new file mode 100644
index 0000000000..8515ae8e1e
--- /dev/null
+++ b/doc/org.eclipse.cdt.doc.user/reference/cdt_u_prop_data_volumes.htm
@@ -0,0 +1,149 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html lang="en">
+<head>
+ <meta http-equiv="Content-Language" content="en-us">
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <title>C/C++ Project Properties, Build, Settings, Data Volume Dialog</title>
+ <link rel="stylesheet" type="text/css" href="../help.css">
+</head>
+<body>
+<div role="main"><h1>C/C++ Project Properties, Build, Settings, Data Volume Dialog</h1>
+<p>The <strong>Data Volume</strong> dialog is brought up when a user selects the
+Add... button from the Container Settings Data Volumes table. Like the properties tab,
+this dialog is only available if the optional Docker C/C++ Launch feature is installed.</p>
+<p>Data volumes can be specified from the local file system, another Container, or created
+as empty, in the Docker Container where the build will be performed.</p>
+
+<p><img img="" src="../images/prop_datavolumes.png"
+ alt="C/C++ Project Properties, Build, Settings, Data Volume Dialog"></p>
+
+
+<table cellpadding="5" cellspacing="0" border="1" width="600px" bordercolor="#DDDDDD" >
+ <caption><strong>Data Volume Dialog</strong></caption>
+ <colgroup>
+ <col width="30%" valign="top" >
+ <col width="70%" valign="top" >
+ </colgroup>
+ <tbody>
+ <tr style="text-align:center;">
+ <th id="group"><strong>Group</strong></th>
+ <th id="description"><strong>Description</strong></th>
+ </tr>
+ <tr>
+ <td headers="group"><strong>Container path</strong></td>
+ <td headers="description">This defines the path that the data volume will be mounted as within the Docker Container.</td>
+ </tr>
+ <tr>
+ <td headers="group"><strong>No external mount</strong></td>
+ <td headers="description">Use this option to create a new empty directory in the Docker Container that is not mounted
+ to any external directory.</td>
+ </tr>
+ <tr>
+ <td headers="group"><strong>Mount a host directory or host file</strong></td>
+ <td headers="description">Use this to specify a local system path that will be mounted in the Docker Container with
+ the given Container path.</td>
+ </tr>
+ <tr>
+ <td headers="group"><strong>Path</strong></td>
+ <td headers="description">This is the local path of the directory or file to mount in the Docker Container. This
+ can be specified manually or via the Directory/File buttons.</td>
+ </tr>
+ <tr>
+ <td headers="group"><strong>Directory</strong></td>
+ <td headers="description">Use this button to bring up a local directory browser to fill in the Path text field
+ when mounting a local directory in the Docker Container.</td>
+ </tr>
+ <tr>
+ <td headers="group"><strong>File</strong></td>
+ <td headers="description">Use this button to bring up a local file browser to fill in the Path text field
+ when mounting a local file in the Docker Container.</td>
+ </tr>
+ <tr>
+ <td headers="group"><strong>Read-only access</strong></td>
+ <td headers="description">Check this button if mounting a local directory or file and you do not wish the
+ Container to modify it.</td>
+ </tr>
+ <tr>
+ <td headers="group"><strong>Mount a data volume container</strong></td>
+ <td headers="description">Check this button if mounting the volumes of another Container.</td>
+ </tr>
+ <tr>
+ <td headers="group"><strong>Container</strong></td>
+ <td headers="description">This is a pull-down containing actively running Containers to use data volumes from if
+ the option above is chosen.</td>
+ </tr>
+ </tbody>
+</table>
+<br>
+<p><strong>Available for:</strong> CDT projects.</p>
+
+<p><img src="../images/ngtasks.gif" alt="Related tasks"
+ width="143" height="21">
+<br>
+</p>
+
+
+<p style="margin-top: 0pt; margin-bottom: 0pt;"><img
+ src="../images/ngref.gif" alt="Related reference" width="143"
+ height="21"><br>
+
+
+<ul>
+<li><a href="cdt_u_prop_resource.htm">Project Properties, Resource page</a>
+<li><a href="cdt_u_prop_builders.htm">Project Properties, Builders page</a>
+<li><a href="cdt_u_prop_all.htm">Project Properties, common C/C++ Configurations handling</a>
+ <ul style="list-style-type: disc">
+ <li><a href="cdt_u_prop_manage_dialog.htm">Manage Configurations dialog</a>
+ <li><a href="cdt_u_prop_manage_newdialog.htm">Create Configuration dialog</a>
+ <li><a href="cdt_u_prop_manage_rendialog.htm">Rename Configuration dialog</a>
+ </ul>
+<li><a href="cdt_u_prop_build.htm">Project Properties, C/C++ Build category</a>
+ <ul style="list-style-type: disc">
+ <li><a href="cdt_u_prop_build_discovery.htm">Discovery options page</a>
+ <li><a href="cdt_u_prop_build_environment.htm">Environment page</a>
+ <li>Settings page
+ <ul>
+ <li><a href="cdt_u_prop_build_settings_tool.htm"> Tool Settings tab</a>
+ <li><a href="cdt_u_prop_build_settings_container.htm">ContainerSettings tab</a>
+ <li><a href="cdt_u_prop_build_settings_steps.htm"> Build Steps tab</a>
+ <li><a href="cdt_u_prop_build_settings_artifact.htm"> Build Artifact tab</a>
+ <li><a href="cdt_u_prop_build_settings_binparser.htm">Binary Parsers tab</a>
+ <li><a href="cdt_u_prop_build_settings_errparser.htm">Error Parsers tab</a>
+ </ul>
+ <li><a href="cdt_u_prop_build_toolchain.htm">Tool chain editor page</a>
+ <li><a href="cdt_u_prop_build_variables.htm">Variables page</a>
+ </ul>
+<li>Project Properties, <a href="cdt_u_prop_general.htm">C/C++ General category</a>
+ <ul style="list-style-type: disc">
+ <li><a href="cdt_u_prop_general_doc.htm">Documentation page</a>
+ <li><a href="cdt_u_prop_general_exp.htm">Export Settings page</a>
+ <!--ul>
+ <li><a href="cdt_u_prop_general_exp_inc.htm">Includes tab</a>
+ <li><a href="cdt_u_prop_general_exp_sym.htm">Symbols tab</a>
+ <li><a href="cdt_u_prop_general_exp_lib.htm">Libraries tab</a>
+ <li><a href="cdt_u_prop_general_exp_libpath.htm">Libraries path tab</a>
+ </ul-->
+ <li><a href="cdt_u_prop_general_typ.htm">File Types page</a>
+ <li><a href="cdt_u_prop_general_idx.htm">Indexer page</a>
+ <li><a href="cdt_u_prop_general_lng.htm">Language Mapping page</a>
+ <li>Paths and Symbols page
+ <ul>
+ <li><a href="cdt_u_prop_general_pns_inc.htm">Includes tab</a>
+ <li><a href="cdt_u_prop_general_pns_sym.htm">Symbols tab</a>
+ <li><a href="cdt_u_prop_general_pns_lib.htm">Libraries tab</a>
+ <li><a href="cdt_u_prop_general_pns_libpath.htm">Libraries path tab</a>
+ <li><a href="cdt_u_prop_general_pns_src.htm">Source Location tab</a>
+ <li><a href="cdt_u_prop_general_pns_out.htm">Output Location tab</a>
+ <li><a href="cdt_u_prop_general_pns_ref.htm">References tab</a>
+ <li><a href="cdt_u_prop_general_pns_hier.htm">Data Hierarchy tab</a>
+ </ul>
+ </ul>
+<li><a href="cdt_u_prop_ref.htm">C/C++ Project Properties, Project References page</a>
+<li><a href="cdt_u_prop_rundebug.htm">C/C++ Project Properties, Run/Debug Settings page</a>
+</ul>
+</p>
+<hr >
+<p><img src="../images/intl_07.gif" ALT="Intel Copyright Statement" ></p>
+
+</div></body>
+</html>
diff --git a/doc/org.eclipse.cdt.doc.user/reference/cdt_u_properties.htm b/doc/org.eclipse.cdt.doc.user/reference/cdt_u_properties.htm
index 06b57c2385..23611f6a4c 100644
--- a/doc/org.eclipse.cdt.doc.user/reference/cdt_u_properties.htm
+++ b/doc/org.eclipse.cdt.doc.user/reference/cdt_u_properties.htm
@@ -39,6 +39,7 @@ To select object properties, right click on object in view and select <strong>Pr
<li>Settings page
<ul>
<li><a href="cdt_u_prop_build_settings_tool.htm"> Tool Settings tab</a>
+ <li><a href="cdt_u_prop_build_settings_container.htm">Container Settings tab</a>
<li><a href="cdt_u_prop_build_settings_steps.htm"> Build Steps tab</a>
<li><a href="cdt_u_prop_build_settings_artifact.htm"> Build Artifact tab</a>
<li><a href="cdt_u_prop_build_settings_binparser.htm">Binary Parsers tab</a>
diff --git a/launch/org.eclipse.cdt.docker.launcher/META-INF/MANIFEST.MF b/launch/org.eclipse.cdt.docker.launcher/META-INF/MANIFEST.MF
index c24f2f4939..8eb9ae3603 100644
--- a/launch/org.eclipse.cdt.docker.launcher/META-INF/MANIFEST.MF
+++ b/launch/org.eclipse.cdt.docker.launcher/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %Plugin.name
Bundle-SymbolicName: org.eclipse.cdt.docker.launcher;singleton:=true
-Bundle-Version: 1.0.0.qualifier
+Bundle-Version: 1.1.0.qualifier
Bundle-Activator: org.eclipse.cdt.docker.launcher.DockerLaunchUIPlugin
Bundle-Vendor: %Plugin.vendor
Bundle-Localization: plugin
@@ -20,7 +20,14 @@ Require-Bundle: org.eclipse.ui,
org.eclipse.cdt.debug.ui;bundle-version="7.5.0",
org.eclipse.cdt.dsf.gdb;bundle-version="4.6.0",
org.eclipse.cdt.dsf.gdb.ui;bundle-version="2.4.0",
- org.eclipse.core.variables
+ org.eclipse.core.variables,
+ org.eclipse.cdt.managedbuilder.ui,
+ org.eclipse.cdt.managedbuilder.core,
+ org.eclipse.core.databinding.observable,
+ org.eclipse.core.databinding.beans,
+ org.eclipse.jface.databinding,
+ org.eclipse.core.databinding;bundle-version="1.6.0",
+ org.eclipse.core.databinding.property;bundle-version="1.6.0"
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Bundle-ActivationPolicy: lazy
Export-Package: org.eclipse.cdt.docker.launcher;x-internal:=true,
diff --git a/launch/org.eclipse.cdt.docker.launcher/icons/error_obj.gif b/launch/org.eclipse.cdt.docker.launcher/icons/error_obj.gif
new file mode 100644
index 0000000000..0bc60689c6
--- /dev/null
+++ b/launch/org.eclipse.cdt.docker.launcher/icons/error_obj.gif
Binary files differ
diff --git a/launch/org.eclipse.cdt.docker.launcher/icons/file_obj.gif b/launch/org.eclipse.cdt.docker.launcher/icons/file_obj.gif
new file mode 100644
index 0000000000..efa7a38014
--- /dev/null
+++ b/launch/org.eclipse.cdt.docker.launcher/icons/file_obj.gif
Binary files differ
diff --git a/launch/org.eclipse.cdt.docker.launcher/icons/folder_closed.gif b/launch/org.eclipse.cdt.docker.launcher/icons/folder_closed.gif
new file mode 100644
index 0000000000..42e027c933
--- /dev/null
+++ b/launch/org.eclipse.cdt.docker.launcher/icons/folder_closed.gif
Binary files differ
diff --git a/launch/org.eclipse.cdt.docker.launcher/icons/warning_obj.gif b/launch/org.eclipse.cdt.docker.launcher/icons/warning_obj.gif
new file mode 100644
index 0000000000..1e5f5eb367
--- /dev/null
+++ b/launch/org.eclipse.cdt.docker.launcher/icons/warning_obj.gif
Binary files differ
diff --git a/launch/org.eclipse.cdt.docker.launcher/plugin.properties b/launch/org.eclipse.cdt.docker.launcher/plugin.properties
index 0669aa80aa..245288bb62 100644
--- a/launch/org.eclipse.cdt.docker.launcher/plugin.properties
+++ b/launch/org.eclipse.cdt.docker.launcher/plugin.properties
@@ -1,5 +1,5 @@
###############################################################################
-# Copyright (c) 2015 Red Hat Inc. and others.
+# Copyright (c) 2015,2017 Red Hat Inc. 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
@@ -15,4 +15,10 @@ Delegate.desc=This launcher runs C/C++ applications in a specified Docker Contai
must be set-up to supply the C/C++ application what it needs to run.
LaunchConfigurationType.name=C/C++ Container Launcher
Shortcut.label=C/C++ Container Application
-DockerLaunchPreferencePage.name=Docker Container Launch
+DockerLaunchPreferencePage.name=Docker Container
+DockerHeaderPreferencePage.name=Cached Headers
+ContainerCommandLauncherFactory.name=Container Command Launcher Factory
+Container.settings=Container Settings
+ContainerBuild.property.enablement=Container Build Enablement
+ContainerBuild.property.connection=Container Build Connection
+ContainerBuild.property.image=Container Build Image
diff --git a/launch/org.eclipse.cdt.docker.launcher/plugin.xml b/launch/org.eclipse.cdt.docker.launcher/plugin.xml
index a8e0a2cdb8..a9c3f67e10 100644
--- a/launch/org.eclipse.cdt.docker.launcher/plugin.xml
+++ b/launch/org.eclipse.cdt.docker.launcher/plugin.xml
@@ -65,6 +65,12 @@
id="org.eclipse.cdt.docker.launcher.page1"
name="%DockerLaunchPreferencePage.name">
</page>
+ <page
+ category="org.eclipse.cdt.docker.launcher.page1"
+ class="org.eclipse.cdt.internal.docker.launcher.ui.preferences.DockerHeaderPreferencePage"
+ id="org.eclipse.cdt.docker.launcher.page2"
+ name="%DockerHeaderPreferencePage.name">
+ </page>
</extension>
<extension
point="org.eclipse.debug.ui.launchConfigurationTabGroups">
@@ -88,5 +94,24 @@
id="org.eclipse.cdt.docker.launcher.launchConfigurationTypeImage1">
</launchConfigurationTypeImage>
</extension>
-
+ <extension
+ id="CommandLauncherFactories"
+ name="%ContainerCommandLauncherFactory.name"
+ point="org.eclipse.cdt.core.CommandLauncherFactory">
+ <factory
+ id="ContainerCommandLauncherFactory"
+ class="org.eclipse.cdt.docker.launcher.ContainerCommandLauncherFactory">
+ </factory>
+ </extension>
+ <extension
+ point="org.eclipse.cdt.ui.cPropertyTab">
+ <tab
+ class="org.eclipse.cdt.internal.docker.launcher.ContainerPropertyTab"
+ icon="icons/repository-middle.gif"
+ name="%Container.settings"
+ parent="org.eclipse.cdt.managedbuilder.ui.properties.Page_BuildSettings"
+ weight="020">
+ </tab>
+ </extension>
+
</plugin>
diff --git a/launch/org.eclipse.cdt.docker.launcher/src/org/eclipse/cdt/docker/launcher/ContainerCommandLauncherFactory.java b/launch/org.eclipse.cdt.docker.launcher/src/org/eclipse/cdt/docker/launcher/ContainerCommandLauncherFactory.java
new file mode 100644
index 0000000000..271f173beb
--- /dev/null
+++ b/launch/org.eclipse.cdt.docker.launcher/src/org/eclipse/cdt/docker/launcher/ContainerCommandLauncherFactory.java
@@ -0,0 +1,265 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Red Hat Inc. 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:
+ * Red Hat Inc. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.docker.launcher;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+import org.eclipse.cdt.core.ICommandLauncher;
+import org.eclipse.cdt.core.ICommandLauncherFactory;
+import org.eclipse.cdt.core.model.CoreModel;
+import org.eclipse.cdt.core.settings.model.CIncludePathEntry;
+import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
+import org.eclipse.cdt.core.settings.model.ICIncludePathEntry;
+import org.eclipse.cdt.core.settings.model.ICLanguageSettingEntry;
+import org.eclipse.cdt.internal.docker.launcher.ContainerCommandLauncher;
+import org.eclipse.cdt.internal.docker.launcher.Messages;
+import org.eclipse.cdt.managedbuilder.buildproperties.IOptionalBuildProperties;
+import org.eclipse.cdt.managedbuilder.core.IConfiguration;
+import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.linuxtools.docker.ui.launch.ContainerLauncher;
+
+public class ContainerCommandLauncherFactory
+ implements ICommandLauncherFactory {
+
+ @Override
+ public ICommandLauncher getCommandLauncher(IProject project) {
+ // check if container build enablement has been checked
+ ICConfigurationDescription cfgd = CoreModel.getDefault()
+ .getProjectDescription(project)
+ .getActiveConfiguration();
+ IConfiguration cfg = ManagedBuildManager
+ .getConfigurationForDescription(cfgd);
+ // TODO: figure out why this occurs
+ if (cfg == null) {
+ return null;
+ }
+ IOptionalBuildProperties props = cfg.getOptionalBuildProperties();
+ if (props != null) {
+ String enablementProperty = props.getProperty(
+ ContainerCommandLauncher.CONTAINER_BUILD_ENABLED);
+ if (enablementProperty != null) {
+ boolean enableContainer = Boolean
+ .parseBoolean(enablementProperty);
+ // enablement has occurred, we can return a
+ // ContainerCommandLauncher
+ if (enableContainer) {
+ return new ContainerCommandLauncher();
+ }
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public ICommandLauncher getCommandLauncher(
+ ICConfigurationDescription cfgd) {
+ // check if container build enablement has been checked
+ IConfiguration cfg = ManagedBuildManager
+ .getConfigurationForDescription(cfgd);
+ // TODO: figure out why this occurs
+ if (cfg == null) {
+ return null;
+ }
+ IOptionalBuildProperties props = cfg.getOptionalBuildProperties();
+ if (props != null) {
+ String enablementProperty = props.getProperty(
+ ContainerCommandLauncher.CONTAINER_BUILD_ENABLED);
+ if (enablementProperty != null) {
+ boolean enableContainer = Boolean
+ .parseBoolean(enablementProperty);
+ // enablement has occurred, we can return a
+ // ContainerCommandLauncher
+ if (enableContainer) {
+ return new ContainerCommandLauncher();
+ }
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public void registerLanguageSettingEntries(IProject project,
+ List<? extends ICLanguageSettingEntry> langEntries) {
+ @SuppressWarnings("unchecked")
+ List<ICLanguageSettingEntry> entries = (List<ICLanguageSettingEntry>) langEntries;
+ ICConfigurationDescription cfgd = CoreModel.getDefault()
+ .getProjectDescription(project).getActiveConfiguration();
+ IConfiguration cfg = ManagedBuildManager
+ .getConfigurationForDescription(cfgd);
+ IOptionalBuildProperties props = cfg.getOptionalBuildProperties();
+ if (props != null) {
+ String enablementProperty = props.getProperty(
+ ContainerCommandLauncher.CONTAINER_BUILD_ENABLED);
+ if (enablementProperty != null) {
+ boolean enableContainer = Boolean
+ .parseBoolean(enablementProperty);
+ if (enableContainer) {
+ String connectionName = props.getProperty(
+ ContainerCommandLauncher.CONNECTION_ID);
+ String imageName = props
+ .getProperty(ContainerCommandLauncher.IMAGE_ID);
+ if (connectionName == null || connectionName.isEmpty()
+ || imageName == null || imageName.isEmpty()) {
+ DockerLaunchUIPlugin.logErrorMessage(
+ Messages.ContainerCommandLauncher_invalid_values);
+ return;
+ }
+ ContainerLauncher launcher = new ContainerLauncher();
+ List<String> paths = new ArrayList<>();
+ for (ICLanguageSettingEntry entry : entries) {
+ if (entry instanceof ICIncludePathEntry) {
+ paths.add(entry.getValue());
+ }
+ }
+ if (paths.size() > 0) {
+ // Create a directory to put the header files for
+ // the image. Use the connection name to form
+ // the directory name as the connection may be
+ // connected to a different repo using the same
+ // image name.
+ IPath pluginPath = Platform.getStateLocation(Platform
+ .getBundle(DockerLaunchUIPlugin.PLUGIN_ID))
+ .append("HEADERS"); //$NON-NLS-1$
+ pluginPath.toFile().mkdir();
+ pluginPath = pluginPath
+ .append(getCleanName(connectionName));
+ pluginPath.toFile().mkdir();
+ // To allow the user to later manage the headers, store
+ // the
+ // real connection name in a file.
+ IPath connectionNamePath = pluginPath.append(".name"); //$NON-NLS-1$
+ File f = connectionNamePath.toFile();
+ try {
+ f.createNewFile();
+ try (FileWriter writer = new FileWriter(f);
+ BufferedWriter bufferedWriter = new BufferedWriter(
+ writer);) {
+ bufferedWriter.write(connectionName);
+ bufferedWriter.newLine();
+ } catch (IOException e) {
+ DockerLaunchUIPlugin.log(e);
+ return;
+ }
+ pluginPath = pluginPath
+ .append(getCleanName(imageName));
+ pluginPath.toFile().mkdir();
+ // To allow the user to later manage the headers,
+ // store the
+ // real image name in a file.
+ IPath imageNamePath = pluginPath.append(".name"); //$NON-NLS-1$
+ f = imageNamePath.toFile();
+ f.createNewFile();
+ try (FileWriter writer = new FileWriter(f);
+ BufferedWriter bufferedWriter = new BufferedWriter(
+ writer);) {
+ bufferedWriter.write(imageName);
+ bufferedWriter.newLine();
+ } catch (IOException e) {
+ DockerLaunchUIPlugin.log(e);
+ return;
+ }
+ } catch (IOException e) {
+ DockerLaunchUIPlugin.log(e);
+ return;
+ }
+ IPath hostDir = pluginPath;
+ @SuppressWarnings("unused")
+ int status = launcher.fetchContainerDirs(connectionName,
+ imageName,
+ paths, hostDir);
+ }
+ }
+ }
+ }
+
+ }
+
+ @Override
+ public List<ICLanguageSettingEntry> verifyLanguageSettingEntries(
+ IProject project, List<ICLanguageSettingEntry> entries) {
+ if (entries == null) {
+ return null;
+ }
+ ICConfigurationDescription cfgd = CoreModel.getDefault()
+ .getProjectDescription(project).getActiveConfiguration();
+ IConfiguration cfg = ManagedBuildManager
+ .getConfigurationForDescription(cfgd);
+ IOptionalBuildProperties props = cfg.getOptionalBuildProperties();
+ if (props != null) {
+ String enablementProperty = props.getProperty(
+ ContainerCommandLauncher.CONTAINER_BUILD_ENABLED);
+ if (enablementProperty != null) {
+ boolean enableContainer = Boolean
+ .parseBoolean(enablementProperty);
+ if (enableContainer) {
+ String connectionName = props.getProperty(
+ ContainerCommandLauncher.CONNECTION_ID);
+ String imageName = props
+ .getProperty(ContainerCommandLauncher.IMAGE_ID);
+ if (connectionName == null || connectionName.isEmpty()
+ || imageName == null || imageName.isEmpty()) {
+ DockerLaunchUIPlugin.logErrorMessage(
+ Messages.ContainerCommandLauncher_invalid_values);
+ return entries;
+ }
+
+ ContainerLauncher launcher = new ContainerLauncher();
+ Set<String> copiedVolumes = launcher
+ .getCopiedVolumes(connectionName, imageName);
+ List<ICLanguageSettingEntry> newEntries = new ArrayList<>();
+ IPath pluginPath = Platform.getStateLocation(
+ Platform.getBundle(DockerLaunchUIPlugin.PLUGIN_ID));
+ IPath hostDir = pluginPath.append("HEADERS") //$NON-NLS-1$
+ .append(getCleanName(connectionName))
+ .append(getCleanName(imageName));
+
+ for (ICLanguageSettingEntry entry : entries) {
+ if (entry instanceof ICIncludePathEntry) {
+ if (copiedVolumes
+ .contains(((ICIncludePathEntry) entry)
+ .getName().toString())) {
+ // //$NON-NLS-2$
+ IPath newPath = hostDir.append(entry.getName());
+ CIncludePathEntry newEntry = new CIncludePathEntry(
+ newPath.toString(),
+ entry.getFlags());
+ newEntries.add(newEntry);
+ continue;
+ } else {
+ newEntries.add(entry);
+ }
+ } else {
+ newEntries.add(entry);
+ }
+ }
+ return newEntries;
+ }
+ }
+ }
+ return entries;
+ }
+
+ private String getCleanName(String name) {
+ String cleanName = name.replace("unix:///", "unix_"); //$NON-NLS-1$ //$NON-NLS-2$
+ cleanName = cleanName.replace("tcp://", "tcp_"); //$NON-NLS-1$ //$NON-NLS-2$
+ return cleanName.replaceAll("[:/.]", "_"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+}
diff --git a/launch/org.eclipse.cdt.docker.launcher/src/org/eclipse/cdt/internal/docker/launcher/BaseDatabindingModel.java b/launch/org.eclipse.cdt.docker.launcher/src/org/eclipse/cdt/internal/docker/launcher/BaseDatabindingModel.java
new file mode 100644
index 0000000000..b17d89701a
--- /dev/null
+++ b/launch/org.eclipse.cdt.docker.launcher/src/org/eclipse/cdt/internal/docker/launcher/BaseDatabindingModel.java
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright (c) 2014, 2015 Red Hat.
+ * 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:
+ * Red Hat - Initial Contribution
+ *******************************************************************************/
+
+package org.eclipse.cdt.internal.docker.launcher;
+
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
+
+/**
+ * Base class for all model classes that need Databinding support
+ *
+ */
+public abstract class BaseDatabindingModel {
+
+ private PropertyChangeSupport changeSupport = new PropertyChangeSupport(this);
+
+ public void addPropertyChangeListener(PropertyChangeListener listener) {
+ changeSupport.addPropertyChangeListener(listener);
+ }
+
+ public void removePropertyChangeListener(PropertyChangeListener listener) {
+ changeSupport.removePropertyChangeListener(listener);
+ }
+
+ public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) {
+ changeSupport.addPropertyChangeListener(propertyName, listener);
+ }
+
+ public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) {
+ changeSupport.removePropertyChangeListener(propertyName, listener);
+ }
+
+ protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) {
+ changeSupport.firePropertyChange(propertyName, oldValue, newValue);
+ }
+}
diff --git a/launch/org.eclipse.cdt.docker.launcher/src/org/eclipse/cdt/internal/docker/launcher/ContainerCommandLauncher.java b/launch/org.eclipse.cdt.docker.launcher/src/org/eclipse/cdt/internal/docker/launcher/ContainerCommandLauncher.java
new file mode 100644
index 0000000000..79db65bd63
--- /dev/null
+++ b/launch/org.eclipse.cdt.docker.launcher/src/org/eclipse/cdt/internal/docker/launcher/ContainerCommandLauncher.java
@@ -0,0 +1,429 @@
+package org.eclipse.cdt.internal.docker.launcher;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import org.eclipse.cdt.core.ICommandLauncher;
+import org.eclipse.cdt.core.model.CoreModel;
+import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
+import org.eclipse.cdt.docker.launcher.DockerLaunchUIPlugin;
+import org.eclipse.cdt.internal.core.ProcessClosure;
+import org.eclipse.cdt.managedbuilder.buildproperties.IOptionalBuildProperties;
+import org.eclipse.cdt.managedbuilder.core.IConfiguration;
+import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager;
+import org.eclipse.core.resources.IProject;
+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.Platform;
+import org.eclipse.core.runtime.preferences.InstanceScope;
+import org.eclipse.core.variables.VariablesPlugin;
+import org.eclipse.linuxtools.docker.ui.launch.ContainerLauncher;
+import org.eclipse.linuxtools.docker.ui.launch.IErrorMessageHolder;
+import org.eclipse.linuxtools.internal.docker.ui.launch.ContainerCommandProcess;
+import org.eclipse.osgi.util.NLS;
+import org.osgi.service.prefs.Preferences;
+
+@SuppressWarnings("restriction")
+public class ContainerCommandLauncher
+ implements ICommandLauncher, IErrorMessageHolder {
+
+ public final static String CONTAINER_BUILD_ENABLED = DockerLaunchUIPlugin.PLUGIN_ID
+ + ".containerbuild.property.enablement"; //$NON-NLS-1$
+ public final static String CONNECTION_ID = DockerLaunchUIPlugin.PLUGIN_ID
+ + ".containerbuild.property.connection"; //$NON-NLS-1$
+ public final static String IMAGE_ID = DockerLaunchUIPlugin.PLUGIN_ID
+ + ".containerbuild.property.image"; //$NON-NLS-1$
+ public final static String VOLUMES_ID = DockerLaunchUIPlugin.PLUGIN_ID
+ + ".containerbuild.property.volumes"; //$NON-NLS-1$
+ public final static String SELECTED_VOLUMES_ID = DockerLaunchUIPlugin.PLUGIN_ID
+ + ".containerbuild.property.selectedvolumes"; //$NON-NLS-1$
+
+ public final static String VOLUME_SEPARATOR_REGEX = "[|]"; //$NON-NLS-1$
+
+ private IProject fProject;
+ private Process fProcess;
+ private boolean fShowCommand;
+ private String fErrorMessage;
+ private Properties fEnvironment;
+
+ private String[] commandArgs;
+ private String fImageName = ""; //$NON-NLS-1$
+
+ public final static int COMMAND_CANCELED = ICommandLauncher.COMMAND_CANCELED;
+ public final static int ILLEGAL_COMMAND = ICommandLauncher.ILLEGAL_COMMAND;
+ public final static int OK = ICommandLauncher.OK;
+
+ private static final String NEWLINE = System.getProperty("line.separator", //$NON-NLS-1$
+ "\n"); //$NON-NLS-1$
+
+ /**
+ * The number of milliseconds to pause between polling.
+ */
+ protected static final long DELAY = 50L;
+
+ @Override
+ public void setProject(IProject project) {
+ this.fProject = project;
+ }
+
+ @Override
+ public IProject getProject() {
+ return fProject;
+ }
+
+ private String getImageName() {
+ return fImageName;
+ }
+
+ private void setImageName(String imageName) {
+ fImageName = imageName;
+ }
+
+ @Override
+ public void showCommand(boolean show) {
+ this.fShowCommand = show;
+ }
+
+ @Override
+ public String getErrorMessage() {
+ return fErrorMessage;
+ }
+
+ @Override
+ public void setErrorMessage(String error) {
+ fErrorMessage = error;
+ }
+
+ @Override
+ public String[] getCommandArgs() {
+ return commandArgs;
+ }
+
+ @Override
+ public Properties getEnvironment() {
+ return fEnvironment;
+ }
+
+ @Override
+ public String getCommandLine() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public Process execute(IPath commandPath, String[] args, String[] env,
+ IPath workingDirectory, IProgressMonitor monitor)
+ throws CoreException {
+
+ HashMap<String, String> labels = new HashMap<>();
+ labels.put("org.eclipse.cdt.container-command", ""); //$NON-NLS-1$ //$NON-NLS-2$
+ String projectName = fProject.getName();
+ labels.put("org.eclipse.cdt.project-name", projectName); //$NON-NLS-1$
+
+ List<String> additionalDirs = new ArrayList<>();
+
+ //
+ IPath projectLocation = fProject.getLocation();
+ String projectPath = projectLocation.toPortableString();
+ if (projectLocation.getDevice() != null) {
+ projectPath = "/" + projectPath.replace(':', '/'); //$NON-NLS-1$
+ }
+ additionalDirs.add(projectPath);
+
+ ArrayList<String> commandSegments = new ArrayList<>();
+
+ StringBuilder b = new StringBuilder();
+ String commandString = commandPath.toPortableString();
+ if (commandPath.getDevice() != null) {
+ commandString = "/" + commandString.replace(':', '/'); //$NON-NLS-1$
+ }
+ b.append(commandString);
+ commandSegments.add(commandString);
+ for (String arg : args) {
+ b.append(" "); //$NON-NLS-1$
+ String realArg = VariablesPlugin.getDefault()
+ .getStringVariableManager().performStringSubstitution(arg);
+ if (Platform.getOS().equals(Platform.OS_WIN32)) {
+ // check if file exists and if so, add an additional directory
+ IPath p = new Path(realArg);
+ if (p.isValidPath(realArg) && p.getDevice() != null) {
+ File f = p.toFile();
+ String modifiedArg = realArg;
+ // if the directory of the arg as a file exists, we mount it
+ // and modify the argument to be unix-style
+ if (f.isFile()) {
+ f = f.getParentFile();
+ modifiedArg = "/" //$NON-NLS-1$
+ + p.toPortableString().replace(':', '/');
+ p = p.removeLastSegments(1);
+ }
+ if (f != null && f.exists()) {
+ additionalDirs.add(
+ "/" + p.toPortableString().replace(':', '/')); //$NON-NLS-1$
+ realArg = modifiedArg;
+ }
+ }
+ } else if (realArg.startsWith("/")) { //$NON-NLS-1$
+ // check if file directory exists and if so, add an additional
+ // directory
+ IPath p = new Path(realArg);
+ if (p.isValidPath(realArg)) {
+ File f = p.toFile();
+ if (f.isFile()) {
+ f = f.getParentFile();
+ }
+ if (f != null && f.exists()) {
+ additionalDirs.add(f.getAbsolutePath());
+ }
+ }
+ }
+ b.append(realArg);
+ commandSegments.add(realArg);
+ }
+
+ commandArgs = commandSegments.toArray(new String[0]);
+
+ String commandDir = commandPath.removeLastSegments(1).toString();
+ if (commandDir.isEmpty()) {
+ commandDir = null;
+ } else if (commandPath.getDevice() != null) {
+ commandDir = "/" + commandDir.replace(':', '/'); //$NON-NLS-1$
+ }
+
+ IProject[] referencedProjects = fProject.getReferencedProjects();
+ for (IProject referencedProject : referencedProjects) {
+ String referencedProjectPath = referencedProject.getLocation()
+ .toPortableString();
+ if (referencedProject.getLocation().getDevice() != null) {
+ referencedProjectPath = "/" //$NON-NLS-1$
+ + referencedProjectPath.replace(':', '/');
+ }
+ additionalDirs
+ .add(referencedProjectPath);
+ }
+
+ String command = b.toString();
+
+ String workingDir = workingDirectory.makeAbsolute().toPortableString();
+ if (workingDirectory.toPortableString().equals(".")) { //$NON-NLS-1$
+ workingDir = "/tmp"; //$NON-NLS-1$
+ } else if (workingDirectory.getDevice() != null) {
+ workingDir = "/" + workingDir.replace(':', '/'); //$NON-NLS-1$
+ }
+ parseEnvironment(env);
+ Map<String, String> origEnv = null;
+
+ boolean supportStdin = false;
+
+ boolean privilegedMode = false;
+
+ ContainerLauncher launcher = new ContainerLauncher();
+
+ Preferences prefs = InstanceScope.INSTANCE
+ .getNode(DockerLaunchUIPlugin.PLUGIN_ID);
+
+ boolean keepContainer = prefs.getBoolean(
+ PreferenceConstants.KEEP_CONTAINER_AFTER_LAUNCH, false);
+
+ ICConfigurationDescription cfgd = CoreModel.getDefault()
+ .getProjectDescription(fProject).getActiveConfiguration();
+ IConfiguration cfg = ManagedBuildManager
+ .getConfigurationForDescription(cfgd);
+ if (cfg == null) {
+ return null;
+ }
+ IOptionalBuildProperties props = cfg.getOptionalBuildProperties();
+
+ // Add any specified volumes to additional dir list
+ String selectedVolumeString = props.getProperty(SELECTED_VOLUMES_ID);
+ if (selectedVolumeString != null && !selectedVolumeString.isEmpty()) {
+ String[] selectedVolumes = selectedVolumeString
+ .split(VOLUME_SEPARATOR_REGEX);
+ if (Platform.getOS().equals(Platform.OS_WIN32)) {
+ for (String selectedVolume : selectedVolumes) {
+ IPath path = new Path(selectedVolume);
+ String selectedPath = path.toPortableString();
+ if (path.getDevice() != null) {
+ selectedPath = "/" + selectedPath.replace(':', '/'); //$NON-NLS-1$
+ }
+ additionalDirs.add(selectedPath);
+ }
+ } else {
+ additionalDirs.addAll(Arrays.asList(selectedVolumes));
+ }
+ }
+
+ String connectionName = props
+ .getProperty(ContainerCommandLauncher.CONNECTION_ID);
+ if (connectionName == null) {
+ return null;
+ }
+ String imageName = props
+ .getProperty(ContainerCommandLauncher.IMAGE_ID);
+ if (imageName == null) {
+ return null;
+ }
+ setImageName(imageName);
+
+ fProcess = launcher.runCommand(connectionName, imageName, fProject,
+ this,
+ command,
+ commandDir,
+ workingDir,
+ additionalDirs,
+ origEnv, fEnvironment, supportStdin, privilegedMode,
+ labels, keepContainer);
+
+ return fProcess;
+ }
+
+ /**
+ * Parse array of "ENV=value" pairs to Properties.
+ */
+ private void parseEnvironment(String[] env) {
+ fEnvironment = null;
+ if (env != null) {
+ fEnvironment = new Properties();
+ for (String envStr : env) {
+ // Split "ENV=value" and put in Properties
+ int pos = envStr.indexOf('='); // $NON-NLS-1$
+ if (pos < 0)
+ pos = envStr.length();
+ String key = envStr.substring(0, pos);
+ String value = envStr.substring(pos + 1);
+ fEnvironment.put(key, value);
+ }
+ }
+ }
+
+ @Override
+ public int waitAndRead(OutputStream out, OutputStream err) {
+ printImageHeader(out);
+
+ if (fShowCommand) {
+ printCommandLine(out);
+ }
+
+ if (fProcess == null) {
+ return ILLEGAL_COMMAND;
+ }
+ ProcessClosure closure = new ProcessClosure(fProcess, out, err);
+ closure.runBlocking(); // a blocking call
+ return OK;
+ }
+
+ @Override
+ public int waitAndRead(OutputStream output, OutputStream err,
+ IProgressMonitor monitor) {
+ printImageHeader(output);
+
+ if (fShowCommand) {
+ printCommandLine(output);
+ }
+
+ if (fProcess == null) {
+ return ILLEGAL_COMMAND;
+ }
+
+ ProcessClosure closure = new ProcessClosure(fProcess, output, err);
+ closure.runNonBlocking();
+ Runnable watchProcess = () -> {
+ try {
+ fProcess.waitFor();
+ } catch (InterruptedException e) {
+ // ignore
+ }
+ closure.terminate();
+ };
+ Thread t = new Thread(watchProcess);
+ t.start();
+ while (!monitor.isCanceled() && closure.isAlive()) {
+ try {
+ Thread.sleep(DELAY);
+ } catch (InterruptedException ie) {
+ break;
+ }
+ }
+ try {
+ t.join(500);
+ } catch (InterruptedException e1) {
+ // ignore
+ }
+ int state = OK;
+
+ // Operation canceled by the user, terminate abnormally.
+ if (monitor.isCanceled()) {
+ closure.terminate();
+ state = COMMAND_CANCELED;
+ setErrorMessage(Messages.CommandLauncher_CommandCancelled);
+ }
+ try {
+ fProcess.waitFor();
+ } catch (InterruptedException e) {
+ // ignore
+ }
+
+ monitor.done();
+ return state;
+ }
+
+ protected void printImageHeader(OutputStream os) {
+ if (os != null) {
+ try {
+ os.write(NLS
+ .bind(Messages.ContainerCommandLauncher_image_msg,
+ ((ContainerCommandProcess) fProcess).getImage())
+ .getBytes());
+ os.write(NEWLINE.getBytes());
+ os.flush();
+ } catch (IOException e) {
+ // ignore
+ }
+ }
+ }
+
+ protected void printCommandLine(OutputStream os) {
+ if (os != null) {
+ try {
+ os.write(getCommandLineQuoted(getCommandArgs(), true)
+ .getBytes());
+ os.flush();
+ } catch (IOException e) {
+ // ignore;
+ }
+ }
+ }
+
+ @SuppressWarnings("nls")
+ private String getCommandLineQuoted(String[] commandArgs, boolean quote) {
+ StringBuilder buf = new StringBuilder();
+ if (commandArgs != null) {
+ for (String commandArg : commandArgs) {
+ if (quote && (commandArg.contains(" ")
+ || commandArg.contains("\"")
+ || commandArg.contains("\\"))) {
+ commandArg = '"' + commandArg.replaceAll("\\\\", "\\\\\\\\")
+ .replaceAll("\"", "\\\\\"") + '"';
+ }
+ buf.append(commandArg);
+ buf.append(' ');
+ }
+ buf.append(NEWLINE);
+ }
+ return buf.toString();
+ }
+
+ protected String getCommandLine(String[] commandArgs) {
+ return getCommandLineQuoted(commandArgs, false);
+ }
+
+}
diff --git a/launch/org.eclipse.cdt.docker.launcher/src/org/eclipse/cdt/internal/docker/launcher/ContainerDataVolumeDialog.java b/launch/org.eclipse.cdt.docker.launcher/src/org/eclipse/cdt/internal/docker/launcher/ContainerDataVolumeDialog.java
new file mode 100644
index 0000000000..8e8af909e8
--- /dev/null
+++ b/launch/org.eclipse.cdt.docker.launcher/src/org/eclipse/cdt/internal/docker/launcher/ContainerDataVolumeDialog.java
@@ -0,0 +1,466 @@
+/*******************************************************************************
+ * Copyright (c) 2015, 2016 Red Hat Inc. 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:
+ * Red Hat - Initial Contribution
+ *******************************************************************************/
+
+package org.eclipse.cdt.internal.docker.launcher;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.cdt.internal.docker.launcher.ContainerPropertyVolumesModel.MountType;
+import org.eclipse.core.databinding.Binding;
+import org.eclipse.core.databinding.DataBindingContext;
+import org.eclipse.core.databinding.UpdateValueStrategy;
+import org.eclipse.core.databinding.beans.BeanProperties;
+import org.eclipse.core.databinding.observable.IChangeListener;
+import org.eclipse.core.databinding.observable.value.IObservableValue;
+import org.eclipse.core.databinding.validation.ValidationStatus;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jface.databinding.swt.ISWTObservableValue;
+import org.eclipse.jface.databinding.swt.WidgetProperties;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.fieldassist.ComboContentAdapter;
+import org.eclipse.jface.fieldassist.ContentProposal;
+import org.eclipse.jface.fieldassist.ContentProposalAdapter;
+import org.eclipse.jface.fieldassist.ControlDecoration;
+import org.eclipse.jface.fieldassist.IContentProposal;
+import org.eclipse.jface.fieldassist.IContentProposalProvider;
+import org.eclipse.jface.layout.GridDataFactory;
+import org.eclipse.jface.layout.GridLayoutFactory;
+import org.eclipse.jface.viewers.ArrayContentProvider;
+import org.eclipse.jface.viewers.ComboViewer;
+import org.eclipse.linuxtools.docker.core.IDockerConnection;
+import org.eclipse.linuxtools.docker.core.IDockerContainer;
+import org.eclipse.linuxtools.docker.core.IDockerContainerInfo;
+import org.eclipse.linuxtools.internal.docker.ui.wizards.WizardMessages;
+import org.eclipse.linuxtools.internal.docker.ui.wizards.WizardUtils;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.DirectoryDialog;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.FileDialog;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+
+/**
+ * @author xcoulon
+ *
+ */
+public class ContainerDataVolumeDialog extends Dialog {
+
+ private final DataVolumeModel model;
+
+ private final DataBindingContext dbc = new DataBindingContext();
+
+ private final List<String> containerNames;
+
+ private final IDockerConnection connection;
+
+ public ContainerDataVolumeDialog(final Shell parentShell,
+ final IDockerConnection connection,
+ final DataVolumeModel selectedDataVolume) {
+ super(parentShell);
+ this.connection = connection;
+ this.model = new DataVolumeModel(selectedDataVolume);
+ this.containerNames = WizardUtils.getContainerNames(connection);
+ }
+
+ public ContainerDataVolumeDialog(final Shell parentShell,
+ final IDockerConnection connection) {
+ super(parentShell);
+ this.connection = connection;
+ this.model = new DataVolumeModel();
+ this.containerNames = WizardUtils.getContainerNames(connection);
+ }
+
+ public DataVolumeModel getDataVolume() {
+ return model;
+ }
+
+ @Override
+ protected void configureShell(final Shell shell) {
+ super.configureShell(shell);
+ setShellStyle(getShellStyle() | SWT.RESIZE);
+ shell.setText(
+ WizardMessages.getString("ContainerDataVolumeDialog.title")); //$NON-NLS-1$
+ }
+
+ /**
+ * Disable the 'OK' button by default
+ */
+ @Override
+ protected Button createButton(Composite parent, int id, String label,
+ boolean defaultButton) {
+ final Button button = super.createButton(parent, id, label,
+ defaultButton);
+ if (id == IDialogConstants.OK_ID) {
+ button.setEnabled(false);
+ }
+ return button;
+ }
+
+ @Override
+ protected Point getInitialSize() {
+ return new Point(450, super.getInitialSize().y);
+ }
+
+ @Override
+ protected Control createDialogArea(final Composite parent) {
+ final Composite container = new Composite(parent, SWT.NONE);
+ final int COLUMNS = 3;
+ GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).span(1, 1)
+ .grab(true, true).applyTo(container);
+ GridLayoutFactory.fillDefaults().margins(10, 10).numColumns(COLUMNS)
+ .applyTo(container);
+
+ // Container path
+ final Label containerPathLabel = new Label(container, SWT.NONE);
+ containerPathLabel.setText(WizardMessages
+ .getString("ContainerDataVolumeDialog.containerPathLabel")); //$NON-NLS-1$
+ GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER)
+ .grab(false, false).applyTo(containerPathLabel);
+ final Text containerPathText = new Text(container, SWT.BORDER);
+ GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER)
+ .grab(true, false).applyTo(containerPathText);
+ final IObservableValue containerPathObservable = BeanProperties
+ .value(DataVolumeModel.class, DataVolumeModel.CONTAINER_PATH)
+ .observe(model);
+ dbc.bindValue(
+ WidgetProperties.text(SWT.Modify).observe(containerPathText),
+ containerPathObservable);
+ // mount type
+ final Label explanationLabel = new Label(container, SWT.NONE);
+ explanationLabel.setText(WizardMessages
+ .getString("ContainerDataVolumeDialog.explanationLabel")); //$NON-NLS-1$
+ GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER)
+ .span(COLUMNS, 1).grab(true, false).applyTo(explanationLabel);
+ final int INDENT = 20;
+ // No mount
+ final Button noMountButton = new Button(container, SWT.RADIO);
+ noMountButton.setText(WizardMessages
+ .getString("ContainerDataVolumeDialog.noMountButton")); //$NON-NLS-1$
+ GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER)
+ .indent(INDENT, 0).span(COLUMNS, 1).grab(true, false)
+ .applyTo(noMountButton);
+ bindButton(noMountButton, MountType.NONE);
+ // File System mount
+ final Button fileSystemMountButton = new Button(container, SWT.RADIO);
+ fileSystemMountButton.setText(WizardMessages
+ .getString("ContainerDataVolumeDialog.fileSystemMountButton")); //$NON-NLS-1$
+ GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER)
+ .indent(INDENT, 0).span(COLUMNS, 1).grab(true, false)
+ .applyTo(fileSystemMountButton);
+ final Label hostPathLabel = new Label(container, SWT.NONE);
+ hostPathLabel.setText(WizardMessages
+ .getString("ContainerDataVolumeDialog.hostPathLabel")); //$NON-NLS-1$
+ GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER)
+ .indent(2 * INDENT, SWT.DEFAULT).grab(false, false)
+ .applyTo(hostPathLabel);
+ final Text hostPathText = new Text(container, SWT.BORDER);
+ GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER)
+ .grab(true, false).applyTo(hostPathText);
+ final IObservableValue hostPathObservable = BeanProperties
+ .value(DataVolumeModel.class, DataVolumeModel.HOST_PATH_MOUNT)
+ .observe(model);
+ dbc.bindValue(WidgetProperties.text(SWT.Modify).observe(hostPathText),
+ hostPathObservable);
+ // browse for directory
+ final Button hostPathDirectoryButton = new Button(container, SWT.NONE);
+ hostPathDirectoryButton.setText(WizardMessages
+ .getString("ContainerDataVolumeDialog.directoryButton")); //$NON-NLS-1$
+ GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER)
+ .grab(false, false).applyTo(hostPathDirectoryButton);
+ hostPathDirectoryButton.addSelectionListener(onHostDirectoryPath());
+ GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER)
+ .grab(false, false).applyTo(new Label(container, SWT.NONE));
+ // optional read-only access
+ final Button readOnlyButton = new Button(container, SWT.CHECK);
+ readOnlyButton.setText(WizardMessages
+ .getString("ContainerDataVolumeDialog.readOnlyButton")); //$NON-NLS-1$
+ readOnlyButton.setToolTipText(WizardMessages
+ .getString("ContainerDataVolumeDialog.readOnlyButtonTooltip")); //$NON-NLS-1$
+ GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER)
+ .span(COLUMNS - 2, 1).grab(true, false).applyTo(readOnlyButton);
+ final ISWTObservableValue readOnlyButtonObservable = WidgetProperties
+ .selection().observe(readOnlyButton);
+ dbc.bindValue(readOnlyButtonObservable,
+ BeanProperties
+ .value(DataVolumeModel.class,
+ DataVolumeModel.READ_ONLY_VOLUME)
+ .observe(model));
+ // browse for file
+ final Button hostPathFileButton = new Button(container, SWT.NONE);
+ hostPathFileButton.setText(WizardMessages
+ .getString("ContainerDataVolumeDialog.fileButton")); //$NON-NLS-1$
+ GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER)
+ .grab(false, false).applyTo(hostPathFileButton);
+ hostPathFileButton.addSelectionListener(onHostFilePath());
+ bindButton(fileSystemMountButton, MountType.HOST_FILE_SYSTEM,
+ hostPathText, hostPathDirectoryButton, hostPathFileButton,
+ readOnlyButton);
+
+ // Container mount
+ final Button containerMountButton = new Button(container, SWT.RADIO);
+ containerMountButton.setText(WizardMessages
+ .getString("ContainerDataVolumeDialog.containerMountButton")); //$NON-NLS-1$
+ GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER)
+ .indent(INDENT, 0).span(COLUMNS, 1).grab(true, false)
+ .applyTo(containerMountButton);
+ final Label containerSelectionLabel = new Label(container, SWT.NONE);
+ containerSelectionLabel.setText(WizardMessages.getString(
+ "ContainerDataVolumeDialog.containerSelectionLabel")); //$NON-NLS-1$
+ GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER)
+ .indent(2 * INDENT, SWT.DEFAULT)
+ .applyTo(containerSelectionLabel);
+ final Combo containerSelectionCombo = new Combo(container, SWT.BORDER);
+ GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER)
+ .grab(true, false).span(1, 1).applyTo(containerSelectionCombo);
+ new ControlDecoration(containerSelectionCombo, SWT.TOP | SWT.LEFT);
+ GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER)
+ .grab(false, false).applyTo(new Label(container, SWT.NONE));
+ bindButton(containerMountButton, MountType.CONTAINER,
+ containerSelectionCombo);
+ final ComboViewer containerSelectionComboViewer = new ComboViewer(
+ containerSelectionCombo);
+ containerSelectionComboViewer
+ .setContentProvider(new ArrayContentProvider());
+ containerSelectionComboViewer.setInput(this.containerNames);
+ final IObservableValue selectedContainerObservable = BeanProperties
+ .value(DataVolumeModel.class, DataVolumeModel.CONTAINER_MOUNT)
+ .observe(model);
+ dbc.bindValue(
+ WidgetProperties.selection().observe(containerSelectionCombo),
+ selectedContainerObservable);
+ new ContentProposalAdapter(containerSelectionCombo,
+ new ComboContentAdapter() {
+ @Override
+ public void insertControlContents(Control control,
+ String text, int cursorPosition) {
+ final Combo combo = (Combo) control;
+ final Point selection = combo.getSelection();
+ combo.setText(text);
+ selection.x = text.length();
+ selection.y = selection.x;
+ combo.setSelection(selection);
+ }
+ }, getContainerNameContentProposalProvider(
+ containerSelectionCombo),
+ null, null);
+
+ // error message
+ final Composite errorContainer = new Composite(container, SWT.NONE);
+ GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL)
+ .span(COLUMNS, 1).grab(true, true).applyTo(errorContainer);
+ GridLayoutFactory.fillDefaults().margins(6, 6).numColumns(2)
+ .applyTo(errorContainer);
+
+ final Label errorMessageIcon = new Label(errorContainer, SWT.NONE);
+ GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER)
+ .hint(20, SWT.DEFAULT)
+ .applyTo(errorMessageIcon);
+ final Label errorMessageLabel = new Label(errorContainer, SWT.NONE);
+ GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER)
+ .grab(true, false)
+ .applyTo(errorMessageLabel);
+ setupValidationSupport(errorMessageIcon, errorMessageLabel);
+ return container;
+ }
+
+ private void setupValidationSupport(final Label errorMessageIcon,
+ final Label errorMessageLabel) {
+ for (@SuppressWarnings("unchecked")
+ Iterator<Binding> iterator = dbc.getBindings().iterator(); iterator
+ .hasNext();) {
+ final Binding binding = iterator.next();
+ binding.getModel().addChangeListener(onDataVolumeSettingsChanged(
+ errorMessageIcon, errorMessageLabel));
+ }
+ }
+
+ /**
+ * Binds the given {@link MountType} to the given {@link Button} when it is
+ * selected, and set the enablement of the associated {@link Control} at the
+ * same time (ie: the {@link Control} are only enabled when the given
+ * {@link Button} is selected.
+ *
+ * @param button
+ * the {@link Button} to bind
+ * @param mountType
+ * the {@link MountType} to bind to the {@link Button}
+ * @param controls
+ * the {@link Control}s to enable or disable when the Button is
+ * selected/unselected.
+ * @return
+ */
+ private Binding bindButton(final Button button, final MountType mountType,
+ final Control... controls) {
+ return dbc.bindValue(WidgetProperties.selection().observe(button),
+ BeanProperties.value(DataVolumeModel.class,
+ DataVolumeModel.MOUNT_TYPE).observe(model),
+ new UpdateValueStrategy() {
+ @Override
+ public Object convert(Object value) {
+ if (value.equals(Boolean.TRUE)) {
+ setEnabled(controls, true);
+ return mountType;
+ }
+ setEnabled(controls, false);
+ return null;
+ }
+
+ private void setEnabled(final Control[] controls,
+ final boolean enabled) {
+ for (Control control : controls) {
+ control.setEnabled(enabled);
+ }
+ }
+ }, new UpdateValueStrategy() {
+ @Override
+ public Object convert(final Object value) {
+ if (mountType.equals(value)) {
+ button.setEnabled(true);
+ }
+ return mountType.equals(value);
+ }
+ });
+ }
+
+ private SelectionListener onHostDirectoryPath() {
+ return SelectionListener.widgetSelectedAdapter(e -> {
+ final DirectoryDialog directoryDialog = new DirectoryDialog(
+ getShell());
+ final String selectedPath = directoryDialog.open();
+ if (selectedPath != null) {
+ model.setHostPathMount(selectedPath);
+ }
+ });
+ }
+
+ private SelectionListener onHostFilePath() {
+ return SelectionListener.widgetSelectedAdapter(e -> {
+ final FileDialog fileDialog = new FileDialog(getShell());
+ final String selectedPath = fileDialog.open();
+ if (selectedPath != null) {
+ model.setHostPathMount(selectedPath);
+ }
+ });
+ }
+
+ /**
+ * Creates an {@link IContentProposalProvider} to propose
+ * {@link IDockerContainer} names based on the current text.
+ *
+ * @param items
+ * @return
+ */
+ private IContentProposalProvider getContainerNameContentProposalProvider(
+ final Combo containerSelectionCombo) {
+ return (contents, position) -> {
+ final List<IContentProposal> proposals = new ArrayList<>();
+ for (String containerName : containerSelectionCombo.getItems()) {
+ if (containerName.contains(contents)) {
+ proposals.add(new ContentProposal(containerName,
+ containerName, containerName, position));
+ }
+ }
+ return proposals.toArray(new IContentProposal[0]);
+ };
+ }
+
+ private IChangeListener onDataVolumeSettingsChanged(
+ final Label errorMessageIcon, final Label errorMessageLabel) {
+
+ return event -> {
+ // skip if dialog has been closed
+ if (Display.getCurrent() == null || getShell().isDisposed()) {
+ return;
+ }
+ final IStatus status = validateInput();
+ Display.getCurrent().syncExec(() -> {
+ if (status.isOK()) {
+ errorMessageIcon.setVisible(false);
+ errorMessageLabel.setVisible(false);
+ setOkButtonEnabled(true);
+ } else if (status.matches(IStatus.WARNING)) {
+ errorMessageIcon.setVisible(true);
+ errorMessageIcon.setImage(
+ SWTImagesFactory.DESC_WARNING.createImage());
+ errorMessageLabel.setVisible(true);
+ errorMessageLabel.setText(status.getMessage());
+ setOkButtonEnabled(true);
+ } else if (status.matches(IStatus.ERROR)) {
+ if (status.getMessage() != null
+ && !status.getMessage().isEmpty()) {
+ errorMessageIcon.setVisible(true);
+ errorMessageIcon.setImage(
+ SWTImagesFactory.DESC_ERROR.createImage());
+ errorMessageLabel.setVisible(true);
+ errorMessageLabel.setText(status.getMessage());
+ }
+ setOkButtonEnabled(false);
+ }
+ });
+ };
+ }
+
+ private IStatus validateInput() {
+ final String containerPath = model.getContainerPath();
+ final MountType mountType = model.getMountType();
+ final String hostPath = model.getHostPathMount();
+ if (containerPath == null || containerPath.isEmpty()) {
+ return ValidationStatus.error(null);
+ } else if (mountType == null) {
+ return ValidationStatus.error(null);
+ } else if (mountType == MountType.HOST_FILE_SYSTEM
+ && (hostPath == null || hostPath.isEmpty())) {
+ return ValidationStatus.error(null);
+ } else if (mountType == MountType.HOST_FILE_SYSTEM
+ && !new File(hostPath).exists()) {
+ return ValidationStatus
+ .warning("The specified path does not exist on the host."); //$NON-NLS-1$
+ } else if (mountType == MountType.CONTAINER) {
+ final IDockerContainer container = WizardUtils
+ .getContainer(connection, model.getContainerMount());
+ if (container == null) {
+ // just make sure that the dialog cannot complete
+ return ValidationStatus.error(null);
+ }
+ final IDockerContainerInfo selectedContainerInfo = container.info();
+ if (selectedContainerInfo != null
+ && selectedContainerInfo.volumes() != null
+ && !selectedContainerInfo.volumes()
+ .containsKey(model.getContainerPath())) {
+ return ValidationStatus
+ .warning(WizardMessages.getFormattedString(
+ "ContainerDataVolumeDialog.volumeWarning", //$NON-NLS-1$
+ model.getContainerPath()));
+ }
+ }
+ return ValidationStatus.ok();
+ }
+
+ private void setOkButtonEnabled(final boolean enabled) {
+ final Button okButton = getButton(IDialogConstants.OK_ID);
+ // skip if 'OK' button does not exist yet.
+ if (okButton != null) {
+ okButton.setEnabled(enabled);
+ }
+ }
+
+}
diff --git a/launch/org.eclipse.cdt.docker.launcher/src/org/eclipse/cdt/internal/docker/launcher/ContainerLaunchConfigurationDelegate.java b/launch/org.eclipse.cdt.docker.launcher/src/org/eclipse/cdt/internal/docker/launcher/ContainerLaunchConfigurationDelegate.java
index ae11435556..096db2fbed 100644
--- a/launch/org.eclipse.cdt.docker.launcher/src/org/eclipse/cdt/internal/docker/launcher/ContainerLaunchConfigurationDelegate.java
+++ b/launch/org.eclipse.cdt.docker.launcher/src/org/eclipse/cdt/internal/docker/launcher/ContainerLaunchConfigurationDelegate.java
@@ -10,6 +10,7 @@
*******************************************************************************/
package org.eclipse.cdt.internal.docker.launcher;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
@@ -80,7 +81,8 @@ public class ContainerLaunchConfigurationDelegate extends GdbLaunchDelegate
@Override
public void newOutput(String output) {
- if (output.contains(Messages.Gdbserver_up)) {
+ if (output.contains(Messages.Gdbserver_up)
+ || output.contains("gdbserver:")) { //$NON-NLS-1$
started = true;
}
@@ -137,10 +139,16 @@ public class ContainerLaunchConfigurationDelegate extends GdbLaunchDelegate
labels.put("org.eclipse.cdt.project-name", projectName); //$NON-NLS-1$
if (mode.equals(ILaunchManager.RUN_MODE)) {
String commandDir = commandPath.removeLastSegments(1)
- .toString();
+ .toPortableString();
+ String commandString = commandPath.toPortableString();
+
+ if (commandPath.getDevice() != null) {
+ commandDir = "/" + commandDir.replace(':', '/'); //$NON-NLS-1$
+ commandString = "/" + commandString.replace(':', '/'); //$NON-NLS-1$
+ }
StringBuilder b = new StringBuilder();
- b.append(commandPath.toString().trim());
+ b.append(commandString);
String arguments = getProgramArguments(configuration);
if (arguments.trim().length() > 0) {
@@ -154,6 +162,13 @@ public class ContainerLaunchConfigurationDelegate extends GdbLaunchDelegate
.getAttribute(
ICDTLaunchConfigurationConstants.ATTR_WORKING_DIRECTORY,
(String) null);
+ if (workingDir != null) {
+ IPath workingPath = new Path(workingDir);
+ if (workingPath.getDevice() != null) {
+ workingDir = "/" + workingPath.toPortableString() //$NON-NLS-1$
+ .replace(':', '/');
+ }
+ }
Map<String, String> envMap = configuration.getAttribute(
ILaunchManager.ATTR_ENVIRONMENT_VARIABLES,
(Map<String, String>) null);
@@ -168,6 +183,18 @@ public class ContainerLaunchConfigurationDelegate extends GdbLaunchDelegate
List<String> additionalDirs = configuration.getAttribute(
ILaunchConstants.ATTR_ADDITIONAL_DIRS,
(List<String>) null);
+ if (additionalDirs != null) {
+ List<String> dirs = new ArrayList<>();
+ for (String additionalDir : additionalDirs) {
+ IPath path = new Path(additionalDir);
+ String dir = path.toPortableString();
+ if (path.getDevice() != null) {
+ dir = "/" + dir.replace(':', '/');
+ }
+ dirs.add(dir);
+ }
+ additionalDirs = dirs;
+ }
String image = configuration.getAttribute(
ILaunchConstants.ATTR_IMAGE, (String) null);
String connectionUri = configuration.getAttribute(
@@ -196,11 +223,18 @@ public class ContainerLaunchConfigurationDelegate extends GdbLaunchDelegate
String gdbserverCommand = configuration.getAttribute(
ILaunchConstants.ATTR_GDBSERVER_COMMAND,
ILaunchConstants.ATTR_GDBSERVER_COMMAND_DEFAULT);
- String commandArguments = ":" + gdbserverPortNumber + " " //$NON-NLS-1$ //$NON-NLS-2$
- + spaceEscapify(commandPath.toString());
+ String commandString = commandPath.toPortableString();
String commandDir = commandPath.removeLastSegments(1)
- .toString();
+ .toPortableString();
+
+ if (commandPath.getDevice() != null) {
+ commandDir = "/" + commandDir.replace(':', '/'); //$NON-NLS-1$
+ commandString = "/" + commandString.replace(':', '/'); //$NON-NLS-1$
+ }
+
+ String commandArguments = ":" + gdbserverPortNumber + " " //$NON-NLS-1$ //$NON-NLS-2$
+ + spaceEscapify(commandString);
StringBuilder b = new StringBuilder();
@@ -217,6 +251,14 @@ public class ContainerLaunchConfigurationDelegate extends GdbLaunchDelegate
.getAttribute(
ICDTLaunchConfigurationConstants.ATTR_WORKING_DIRECTORY,
(String) null);
+ if (workingDir != null) {
+ IPath workingPath = new Path(workingDir);
+ if (workingPath.getDevice() != null) {
+ workingDir = "/" + workingPath.toPortableString() //$NON-NLS-1$
+ .replace(':', '/');
+ }
+ }
+
Map<String, String> envMap = configuration.getAttribute(
ILaunchManager.ATTR_ENVIRONMENT_VARIABLES,
(Map<String, String>) null);
@@ -231,6 +273,19 @@ public class ContainerLaunchConfigurationDelegate extends GdbLaunchDelegate
List<String> additionalDirs = configuration.getAttribute(
ILaunchConstants.ATTR_ADDITIONAL_DIRS,
(List<String>) null);
+ if (additionalDirs != null) {
+ List<String> dirs = new ArrayList<>();
+ for (String additionalDir : additionalDirs) {
+ IPath path = new Path(additionalDir);
+ String dir = path.toPortableString();
+ if (path.getDevice() != null) {
+ dir = "/" + dir.replace(':', '/');
+ }
+ dirs.add(dir);
+ }
+ additionalDirs = dirs;
+ }
+
String image = configuration.getAttribute(
ILaunchConstants.ATTR_IMAGE, (String) null);
String connectionUri = configuration.getAttribute(
diff --git a/launch/org.eclipse.cdt.docker.launcher/src/org/eclipse/cdt/internal/docker/launcher/ContainerPropertyTab.java b/launch/org.eclipse.cdt.docker.launcher/src/org/eclipse/cdt/internal/docker/launcher/ContainerPropertyTab.java
new file mode 100644
index 0000000000..cb892ea452
--- /dev/null
+++ b/launch/org.eclipse.cdt.docker.launcher/src/org/eclipse/cdt/internal/docker/launcher/ContainerPropertyTab.java
@@ -0,0 +1,1053 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Red Hat Inc. 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:
+ * Red Hat Inc. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.internal.docker.launcher;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.cdt.core.language.settings.providers.ILanguageSettingsProvider;
+import org.eclipse.cdt.core.language.settings.providers.ILanguageSettingsProvidersKeeper;
+import org.eclipse.cdt.core.model.CoreModelUtil;
+import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
+import org.eclipse.cdt.core.settings.model.ICMultiConfigDescription;
+import org.eclipse.cdt.core.settings.model.ICResourceDescription;
+import org.eclipse.cdt.core.settings.model.ICTargetPlatformSetting;
+import org.eclipse.cdt.internal.docker.launcher.ContainerPropertyVolumesModel.MountType;
+import org.eclipse.cdt.managedbuilder.buildproperties.IOptionalBuildProperties;
+import org.eclipse.cdt.managedbuilder.core.IConfiguration;
+import org.eclipse.cdt.managedbuilder.core.IMultiConfiguration;
+import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager;
+import org.eclipse.cdt.managedbuilder.internal.core.Configuration;
+import org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuiltinSpecsDetector;
+import org.eclipse.cdt.managedbuilder.ui.properties.AbstractCBuildPropertyTab;
+import org.eclipse.core.databinding.DataBindingContext;
+import org.eclipse.core.databinding.beans.BeanProperties;
+import org.eclipse.core.databinding.beans.IBeanValueProperty;
+import org.eclipse.core.databinding.observable.list.IObservableList;
+import org.eclipse.core.databinding.observable.map.IObservableMap;
+import org.eclipse.core.databinding.property.Properties;
+import org.eclipse.jface.databinding.viewers.ObservableListContentProvider;
+import org.eclipse.jface.databinding.viewers.ObservableMapLabelProvider;
+import org.eclipse.jface.databinding.viewers.ViewerSupport;
+import org.eclipse.jface.databinding.viewers.ViewersObservables;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.layout.GridDataFactory;
+import org.eclipse.jface.layout.GridLayoutFactory;
+import org.eclipse.jface.viewers.CheckboxTableViewer;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.StructuredViewer;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.TableViewerColumn;
+import org.eclipse.linuxtools.docker.core.DockerConnectionManager;
+import org.eclipse.linuxtools.docker.core.IDockerConnection;
+import org.eclipse.linuxtools.docker.core.IDockerConnectionManagerListener;
+import org.eclipse.linuxtools.docker.core.IDockerImage;
+import org.eclipse.linuxtools.docker.core.IDockerImageListener;
+import org.eclipse.linuxtools.internal.docker.ui.wizards.WizardMessages;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.events.VerifyEvent;
+import org.eclipse.swt.events.VerifyListener;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+
+@SuppressWarnings("restriction")
+public class ContainerPropertyTab extends AbstractCBuildPropertyTab
+ implements IDockerConnectionManagerListener, IDockerImageListener {
+
+ public final static String VOLUME_SEPARATOR = "|"; //$NON-NLS-1$
+
+ private final static String GNU_ELF_PARSER_ID = "org.eclipse.cdt.core.GNU_ELF"; //$NON-NLS-1$
+ private final static String ELF_PARSER_ID = "org.eclipse.cdt.core.ELF"; //$NON-NLS-1$
+
+ private Combo imageCombo;
+ private Combo connectionSelector;
+ private Button enableButton;
+ private Button addButton;
+ private IDockerConnection connection;
+ private IDockerConnection[] connections;
+ private IDockerImageListener containerTab;
+
+ private String connectionName;
+ private String connectionUri = ""; //$NON-NLS-1$
+
+ private boolean initialEnabled;
+ private String initialConnection;
+ private String initialImageId;
+ private String initialVolumes;
+ private String initialSelectedVolumes;
+
+ private boolean multiChange;
+
+ private List<IDockerImage> displayedImages = new ArrayList<>();
+
+ private IConfiguration iCfg;
+ private ICConfigurationDescription iCfgd;
+
+ private final DataBindingContext dbc = new DataBindingContext();
+ private final ContainerPropertyVolumesModel model;
+
+ private ModifyListener connectionModifyListener = new ModifyListener() {
+
+ @Override
+ public void modifyText(ModifyEvent e) {
+ int index = connectionSelector.getSelectionIndex();
+ if (index < 0) {
+ connection = null;
+ connectionName = "";
+ return;
+ }
+ if (connection != null)
+ connection.removeImageListener(containerTab);
+ connection = connections[index];
+ connectionUri = connection.getUri();
+ if (!connectionName.equals(connection.getName())) {
+ imageCombo.setText("");
+ initialImageId = null;
+ refreshImages();
+ setVolumeControlsEnabled(new Button[] { addButton }, false);
+ }
+ connectionName = connection.getName();
+ setConnection(connectionUri);
+ model.setConnection(connection);
+ }
+
+ };
+
+ public ContainerPropertyTab() {
+ this.containerTab = this;
+ this.model = new ContainerPropertyVolumesModel(
+ (IDockerConnection) null);
+ }
+
+ @Override
+ public void createControls(Composite parent) {
+ super.createControls(parent);
+
+ usercomp.setLayout(new GridLayout(5, false));
+ usercomp.setFont(parent.getFont());
+ GridData gd = new GridData(GridData.FILL_HORIZONTAL);
+ gd.horizontalSpan = 1;
+
+ usercomp.setLayoutData(gd);
+
+ enableButton = new Button(usercomp, SWT.CHECK);
+ enableButton.setText(Messages.ContainerPropertyTab_Enable_Msg);
+
+ iCfg = getCfg();
+ iCfgd = getResDesc().getConfiguration();
+
+ gd = new GridData(GridData.FILL_HORIZONTAL);
+ gd.horizontalSpan = 5;
+ enableButton.setLayoutData(gd);
+
+ Label connectionSelectorLabel = new Label(usercomp, SWT.NULL);
+ connectionSelectorLabel
+ .setText(Messages.ContainerTab_Connection_Selector_Label);
+ gd = new GridData(GridData.FILL_HORIZONTAL);
+ gd.horizontalSpan = 1;
+ gd.grabExcessHorizontalSpace = false;
+ connectionSelectorLabel.setLayoutData(gd);
+
+ connectionSelector = new Combo(usercomp, SWT.BORDER | SWT.READ_ONLY);
+ initializeConnectionSelector();
+ connectionSelector.addModifyListener(connectionModifyListener);
+ // Following is a kludge so that on Linux the Combo is read-only but
+ // has a white background.
+ connectionSelector.addVerifyListener(new VerifyListener() {
+ @Override
+ public void verifyText(VerifyEvent e) {
+ e.doit = false;
+ }
+ });
+ gd = new GridData(GridData.FILL_HORIZONTAL);
+ gd.horizontalSpan = 3;
+ gd.grabExcessHorizontalSpace = true;
+ connectionSelector.setLayoutData(gd);
+
+ Label label1 = new Label(usercomp, SWT.NULL);
+ gd = new GridData();
+ gd.horizontalSpan = 1;
+ gd.grabExcessHorizontalSpace = false;
+ label1.setLayoutData(gd);
+
+ Label imageSelectorLabel = new Label(usercomp, SWT.NULL);
+ imageSelectorLabel.setText(Messages.ContainerTab_Image_Selector_Label);
+ gd = new GridData(GridData.FILL_HORIZONTAL);
+ gd.horizontalSpan = 1;
+ connectionSelectorLabel.setLayoutData(gd);
+
+ imageCombo = new Combo(usercomp, SWT.DROP_DOWN);
+ gd = new GridData(GridData.FILL_HORIZONTAL);
+ gd.horizontalSpan = 3;
+ gd.grabExcessHorizontalSpace = true;
+ imageCombo.setLayoutData(gd);
+
+ Label label2 = new Label(usercomp, SWT.NULL);
+ gd = new GridData();
+ gd.horizontalSpan = 1;
+ gd.grabExcessHorizontalSpace = false;
+ label2.setLayoutData(gd);
+
+ initializeImageCombo();
+
+ imageCombo.addSelectionListener(new SelectionListener() {
+
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ setImageId(imageCombo.getText());
+ model.setSelectedImage(
+ displayedImages.get(imageCombo.getSelectionIndex()));
+ }
+
+ @Override
+ public void widgetDefaultSelected(SelectionEvent e) {
+ }
+
+ });
+
+ initializeEnablementButton();
+ enableButton.addSelectionListener(new SelectionListener() {
+
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ setControlsEnabled(enableButton.getSelection());
+ setEnablement(enableButton.getSelection());
+ }
+
+ @Override
+ public void widgetDefaultSelected(SelectionEvent e) {
+ // ignore
+ }
+
+ });
+
+ createVolumeSettingsContainer(usercomp);
+ }
+
+ private void createVolumeSettingsContainer(final Composite container) {
+ final Label volumesLabel = new Label(container, SWT.NONE);
+ volumesLabel.setText(WizardMessages
+ .getString("ImageRunResourceVolVarPage.dataVolumesLabel")); //$NON-NLS-1$
+ GridDataFactory.fillDefaults().grab(false, false).applyTo(volumesLabel);
+ final CheckboxTableViewer dataVolumesTableViewer = createVolumesTable(
+ container);
+ GridDataFactory.fillDefaults().align(SWT.FILL, SWT.TOP)
+ .grab(true, false).hint(400, 200)
+ .applyTo(dataVolumesTableViewer.getTable());
+ // buttons
+ final Composite buttonsContainers = new Composite(container, SWT.NONE);
+ GridDataFactory.fillDefaults().align(SWT.FILL, SWT.TOP)
+ .grab(false, false).applyTo(buttonsContainers);
+ GridLayoutFactory.fillDefaults().numColumns(1).margins(0, 0)
+ .spacing(SWT.DEFAULT, 0).applyTo(buttonsContainers);
+
+ addButton = new Button(buttonsContainers, SWT.NONE);
+ GridDataFactory.fillDefaults().align(SWT.FILL, SWT.TOP)
+ .grab(true, false).applyTo(addButton);
+ addButton.setText(WizardMessages
+ .getString("ImageRunResourceVolVarPage.addButton")); //$NON-NLS-1$
+ addButton.addSelectionListener(onAddDataVolume(dataVolumesTableViewer));
+ if (imageCombo.getText() != null && !imageCombo.getText().equals("")) {
+ setVolumeControlsEnabled(new Button[] { addButton }, true);
+ }
+ final Button editButton = new Button(buttonsContainers, SWT.NONE);
+ GridDataFactory.fillDefaults().align(SWT.FILL, SWT.TOP)
+ .grab(true, false).applyTo(editButton);
+ editButton.setText(WizardMessages
+ .getString("ImageRunResourceVolVarPage.editButton")); //$NON-NLS-1$
+ editButton
+ .addSelectionListener(onEditDataVolume(dataVolumesTableViewer));
+ editButton.setEnabled(false);
+ final Button removeButton = new Button(buttonsContainers, SWT.NONE);
+ GridDataFactory.fillDefaults().align(SWT.FILL, SWT.TOP)
+ .grab(true, false).applyTo(removeButton);
+ removeButton.setText(WizardMessages
+ .getString("ImageRunResourceVolVarPage.removeButton")); //$NON-NLS-1$
+ removeButton.addSelectionListener(
+ onRemoveDataVolumes(dataVolumesTableViewer));
+ removeButton.setEnabled(false);
+ // update table content when selected image changes
+ bind(dataVolumesTableViewer, model.getDataVolumes(),
+ BeanProperties.values(DataVolumeModel.class,
+ DataVolumeModel.CONTAINER_PATH, DataVolumeModel.MOUNT,
+ DataVolumeModel.READ_ONLY_VOLUME));
+ dbc.bindSet(
+ ViewersObservables.observeCheckedElements(
+ dataVolumesTableViewer, DataVolumeModel.class),
+ BeanProperties.set(
+ ContainerPropertyVolumesModel.SELECTED_DATA_VOLUMES)
+ .observe(model));
+ // disable the edit and removeButton if the table is empty
+ dataVolumesTableViewer.addSelectionChangedListener(
+ onSelectionChanged(editButton, removeButton));
+
+ initializeVolumesTable();
+ }
+
+ /**
+ * Same as
+ * {@link ViewerSupport#bind(StructuredViewer, IObservableList, org.eclipse.core.databinding.property.value.IValueProperty[])
+ * but with a custom LabelProvider, DataVolumesLabelProvider
+ *
+ * @param viewer
+ * @param input
+ * @param labelProperties
+ */
+ private void bind(final StructuredViewer viewer,
+ final IObservableList input,
+ final IBeanValueProperty[] labelProperties) {
+ final ObservableListContentProvider contentProvider = new ObservableListContentProvider();
+ if (viewer.getInput() != null) {
+ viewer.setInput(null);
+ }
+ viewer.setContentProvider(contentProvider);
+ viewer.setLabelProvider(
+ new DataVolumesLabelProvider(Properties.observeEach(
+ contentProvider.getKnownElements(), labelProperties)));
+ if (input != null) {
+ viewer.setInput(input);
+ }
+
+ }
+
+ private ISelectionChangedListener onSelectionChanged(
+ final Button... targetButtons) {
+ return e -> {
+ if (e.getSelection().isEmpty()) {
+ setVolumeControlsEnabled(targetButtons, false);
+ } else {
+ setVolumeControlsEnabled(targetButtons, true);
+ }
+ };
+ }
+
+ private static void setVolumeControlsEnabled(final Control[] controls,
+ final boolean enabled) {
+ for (Control control : controls) {
+ if (control != null) {
+ control.setEnabled(enabled);
+ }
+ }
+ }
+
+ private SelectionListener onAddDataVolume(
+ final CheckboxTableViewer dataVolumesTableViewer) {
+ return SelectionListener.widgetSelectedAdapter(e -> {
+ final ContainerDataVolumeDialog dialog = new ContainerDataVolumeDialog(
+ Display.getDefault().getActiveShell(),
+ model.getConnection());
+ dialog.create();
+ if (dialog.open() == IDialogConstants.OK_ID) {
+ final DataVolumeModel dataVolume = dialog.getDataVolume();
+ dataVolume.setSelected(true);
+ model.getDataVolumes().add(dataVolume);
+ model.getSelectedDataVolumes().add(dataVolume);
+ dataVolumesTableViewer.setChecked(dataVolume, true);
+ setVolumes();
+ }
+ });
+ }
+
+ private SelectionListener onEditDataVolume(
+ final CheckboxTableViewer dataVolumesTableViewer) {
+ return SelectionListener.widgetSelectedAdapter(e -> {
+ final IStructuredSelection selection = (IStructuredSelection) dataVolumesTableViewer
+ .getSelection();
+ if (selection.isEmpty()) {
+ return;
+ }
+ final DataVolumeModel selectedDataVolume = (DataVolumeModel) selection
+ .getFirstElement();
+ final ContainerDataVolumeDialog dialog = new ContainerDataVolumeDialog(
+ Display.getDefault().getActiveShell(),
+ model.getConnection(), selectedDataVolume);
+ dialog.create();
+ if (dialog.open() == IDialogConstants.OK_ID) {
+ final DataVolumeModel dialogDataVolume = dialog.getDataVolume();
+ selectedDataVolume.setContainerMount(
+ dialogDataVolume.getContainerMount());
+ selectedDataVolume
+ .setMountType(dialogDataVolume.getMountType());
+ selectedDataVolume
+ .setHostPathMount(dialogDataVolume.getHostPathMount());
+ selectedDataVolume.setContainerMount(
+ dialogDataVolume.getContainerMount());
+ selectedDataVolume.setReadOnly(dialogDataVolume.isReadOnly());
+ model.getSelectedDataVolumes().add(selectedDataVolume);
+ dataVolumesTableViewer.setChecked(selectedDataVolume, true);
+ setVolumes();
+ }
+ });
+ }
+
+ private SelectionListener onRemoveDataVolumes(
+ final TableViewer dataVolumesTableViewer) {
+ return SelectionListener.widgetSelectedAdapter(e -> {
+ final IStructuredSelection selection = dataVolumesTableViewer
+ .getStructuredSelection();
+ for (@SuppressWarnings("unchecked")
+ Iterator<DataVolumeModel> iterator = selection.iterator(); iterator
+ .hasNext();) {
+ final DataVolumeModel volume = iterator.next();
+ model.removeDataVolume(volume);
+ model.getSelectedDataVolumes().remove(volume);
+ }
+ setVolumes();
+ });
+ }
+
+ private CheckboxTableViewer createVolumesTable(final Composite container) {
+ final Table table = new Table(container, SWT.CHECK | SWT.BORDER
+ | SWT.FULL_SELECTION | SWT.V_SCROLL | SWT.H_SCROLL);
+ final CheckboxTableViewer tableViewer = new CheckboxTableViewer(table);
+ table.setHeaderVisible(true);
+ table.setLinesVisible(true);
+ dbc.bindSet(
+ ViewersObservables.observeCheckedElements(tableViewer,
+ DataVolumeModel.class),
+ BeanProperties.set(
+ ContainerPropertyVolumesModel.SELECTED_DATA_VOLUMES)
+ .observe(model));
+ addTableViewerColumn(tableViewer,
+ WizardMessages.getString(
+ "ImageRunResourceVolVarPage.containerPathColumn"), //$NON-NLS-1$
+ 180);
+ addTableViewerColumn(tableViewer,
+ WizardMessages
+ .getString("ImageRunResourceVolVarPage.mountColumn"), //$NON-NLS-1$
+ 180);
+ addTableViewerColumn(tableViewer,
+ WizardMessages
+ .getString("ImageRunResourceVolVarPage.readonlyColumn"), //$NON-NLS-1$
+ 60);
+ return tableViewer;
+ }
+
+ private TableViewerColumn addTableViewerColumn(
+ final TableViewer tableViewer,
+ final String title, final int width) {
+ final TableViewerColumn viewerColumn = new TableViewerColumn(
+ tableViewer, SWT.NONE);
+ final TableColumn column = viewerColumn.getColumn();
+ if (title != null) {
+ column.setText(title);
+ }
+ column.setWidth(width);
+ return viewerColumn;
+ }
+
+ private static final class DataVolumesLabelProvider
+ extends ObservableMapLabelProvider {
+
+ private Image CONTAINER_IMAGE = SWTImagesFactory.DESC_CONTAINER
+ .createImage();
+ private Image FOLDER_CLOSED_IMAGE = SWTImagesFactory.DESC_FOLDER_CLOSED
+ .createImage();
+ private Image FILE_IMAGE = SWTImagesFactory.DESC_FILE.createImage();
+
+ public DataVolumesLabelProvider(final IObservableMap[] attributeMaps) {
+ super(attributeMaps);
+ }
+
+ @Override
+ public void dispose() {
+ CONTAINER_IMAGE.dispose();
+ FOLDER_CLOSED_IMAGE.dispose();
+ FILE_IMAGE.dispose();
+ super.dispose();
+ }
+
+ @Override
+ public Image getColumnImage(Object element, int columnIndex) {
+ final DataVolumeModel dataVolume = ((DataVolumeModel) element);
+ if (dataVolume.getMountType() != null && columnIndex == 1) {
+ switch (dataVolume.getMountType()) {
+ case CONTAINER:
+ return CONTAINER_IMAGE;
+ case HOST_FILE_SYSTEM:
+ final File hostFile = new File(dataVolume.getMount());
+ if (!hostFile.exists() || hostFile.isDirectory()) {
+ return FOLDER_CLOSED_IMAGE;
+ } else {
+ return FILE_IMAGE;
+ }
+ default:
+ return null;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public String getColumnText(Object element, int columnIndex) {
+ final DataVolumeModel dataVolume = ((DataVolumeModel) element);
+ switch (columnIndex) {
+ case 0:
+ return dataVolume.getContainerPath();
+ case 1:
+ return dataVolume.getMount();
+ case 2:
+ if (dataVolume.getMountType() != MountType.HOST_FILE_SYSTEM) {
+ return null;
+ } else if (dataVolume.isReadOnly()) {
+ return WizardMessages
+ .getString("ImageRunResourceVolVarPage.true"); //$NON-NLS-1$
+ }
+ return WizardMessages
+ .getString("ImageRunResourceVolVarPage.false"); //$NON-NLS-1$
+ default:
+ return null;
+ }
+ }
+ }
+
+ private void setVolumes() {
+ StringBuffer buffer = new StringBuffer();
+ String separator = ""; //$NON-NLS-1$
+ for (DataVolumeModel volume : model.getDataVolumes()) {
+ buffer.append(separator);
+ buffer.append(volume.toString());
+ separator = VOLUME_SEPARATOR;
+ }
+ StringBuffer selectedBuffer = new StringBuffer();
+ separator = ""; //$NON-NLS-1$
+ for (DataVolumeModel volume : model.getSelectedDataVolumes()) {
+ selectedBuffer.append(separator);
+ selectedBuffer.append(volume.toString());
+ separator = VOLUME_SEPARATOR;
+ }
+ if (iCfg instanceof IMultiConfiguration) {
+ IConfiguration[] cfs = (IConfiguration[]) ((IMultiConfiguration) iCfg)
+ .getItems();
+ for (int i = 0; i < cfs.length; i++) {
+ IConfiguration cfg = cfs[i];
+ IOptionalBuildProperties p = cfg.getOptionalBuildProperties();
+ p.setProperty(ContainerCommandLauncher.VOLUMES_ID,
+ buffer.toString());
+ p.setProperty(ContainerCommandLauncher.SELECTED_VOLUMES_ID,
+ selectedBuffer.toString());
+ }
+ } else {
+ IOptionalBuildProperties p = iCfg.getOptionalBuildProperties();
+ p.setProperty(ContainerCommandLauncher.VOLUMES_ID,
+ buffer.toString());
+ p.setProperty(ContainerCommandLauncher.SELECTED_VOLUMES_ID,
+ selectedBuffer.toString());
+ }
+ }
+
+ private void setEnablement(boolean enabled) {
+ if (iCfg instanceof IMultiConfiguration) {
+ IConfiguration[] cfs = (IConfiguration[]) ((IMultiConfiguration) iCfg)
+ .getItems();
+ for (int i = 0; i < cfs.length; i++) {
+ IConfiguration cfg = cfs[i];
+ IOptionalBuildProperties p = cfg.getOptionalBuildProperties();
+ p.setProperty(ContainerCommandLauncher.CONTAINER_BUILD_ENABLED,
+ Boolean.toString(enableButton.getSelection()));
+ }
+ } else {
+ IOptionalBuildProperties p = iCfg.getOptionalBuildProperties();
+ p.setProperty(ContainerCommandLauncher.CONTAINER_BUILD_ENABLED,
+ Boolean.toString(enableButton.getSelection()));
+ }
+ // if enabled, make sure we have ELF binary parsers specified
+ if (enabled) {
+ String[] ids = CoreModelUtil
+ .getBinaryParserIds(page.getCfgsEditable());
+ List<String> idList = new ArrayList<>(Arrays.asList(ids));
+ if (!idList.contains(GNU_ELF_PARSER_ID)) {
+ idList.add(GNU_ELF_PARSER_ID);
+ }
+ if (!idList.contains(ELF_PARSER_ID)) {
+ idList.add(ELF_PARSER_ID);
+ }
+ CoreModelUtil.setBinaryParserIds(page.getCfgsEditable(),
+ idList.toArray(new String[0]));
+ }
+ }
+
+ private void setImageId(String imageId) {
+ if (iCfg instanceof IMultiConfiguration) {
+ IConfiguration[] cfs = (IConfiguration[]) ((IMultiConfiguration) iCfg)
+ .getItems();
+ for (int i = 0; i < cfs.length; i++) {
+ IConfiguration cfg = cfs[i];
+ IOptionalBuildProperties p = cfg.getOptionalBuildProperties();
+ p.setProperty(ContainerCommandLauncher.IMAGE_ID, imageId);
+ }
+ } else {
+ IOptionalBuildProperties p = iCfg.getOptionalBuildProperties();
+ p.setProperty(ContainerCommandLauncher.IMAGE_ID, imageId);
+ }
+ }
+
+ private void setConnection(String uri) {
+ if (iCfg instanceof IMultiConfiguration) {
+ IConfiguration[] cfs = (IConfiguration[]) ((IMultiConfiguration) iCfg)
+ .getItems();
+ for (int i = 0; i < cfs.length; i++) {
+ IConfiguration cfg = cfs[i];
+ IOptionalBuildProperties p = cfg.getOptionalBuildProperties();
+ p.setProperty(ContainerCommandLauncher.CONNECTION_ID, uri);
+ }
+ } else {
+ IOptionalBuildProperties p = iCfg.getOptionalBuildProperties();
+ p.setProperty(ContainerCommandLauncher.CONNECTION_ID, uri);
+ }
+ }
+
+ private void setControlsEnabled(boolean enabled) {
+ imageCombo.setEnabled(enabled);
+ connectionSelector.setEnabled(enabled);
+ setVolumeControlsEnabled(new Button[] { addButton }, enabled);
+ }
+
+ private void initializeEnablementButton() {
+ initialEnabled = false;
+ IOptionalBuildProperties properties = iCfg.getOptionalBuildProperties();
+ String savedEnabled = properties
+ .getProperty(ContainerCommandLauncher.CONTAINER_BUILD_ENABLED);
+ if (savedEnabled != null) {
+ initialEnabled = Boolean
+ .parseBoolean(savedEnabled);
+ }
+ enableButton.setSelection(initialEnabled);
+ setControlsEnabled(initialEnabled);
+ }
+
+ private void initializeConnectionSelector() {
+ int defaultIndex = -1;
+ initialConnection = null;
+ IOptionalBuildProperties properties = iCfg.getOptionalBuildProperties();
+ String id = properties
+ .getProperty(ContainerCommandLauncher.CONNECTION_ID);
+ if (id != null) {
+ initialConnection = id;
+ }
+ connections = DockerConnectionManager.getInstance().getConnections();
+ if (connections.length == 0) {
+ // setErrorMessage(Messages.ContainerTab_Error_No_Connections);
+ return;
+ }
+ String[] connectionNames = new String[connections.length];
+ for (int i = 0; i < connections.length; ++i) {
+ connectionNames[i] = connections[i].getName();
+ if (connections[i].getUri().equals(initialConnection))
+ defaultIndex = i;
+ }
+ if (defaultIndex < 0) {
+ initialEnabled = false;
+ defaultIndex = 0;
+ }
+ connectionSelector.setItems(connectionNames);
+ if (connections.length > 0) {
+ connectionSelector.select(defaultIndex);
+ connection = connections[defaultIndex];
+ connectionName = connection.getName();
+ connectionUri = connection.getUri();
+ initialConnection = connectionUri;
+ model.setConnection(connection);
+ }
+ }
+
+ private void refreshImages() {
+ if (connection != null) {
+ java.util.List<IDockerImage> images = connection.getImages();
+ if (images == null || images.size() == 0) {
+ // setsetErrorMessage(Messages.ContainerTab_Error_No_Images);
+ return;
+ }
+ connection.removeImageListener(containerTab);
+ ArrayList<String> imageNames = new ArrayList<String>();
+ displayedImages = new ArrayList<>();
+ for (IDockerImage image : images) {
+ java.util.List<String> tags = image.repoTags();
+ if (tags != null) {
+ for (String tag : tags) {
+ if (!tag.equals("<none>:<none>")) { //$NON-NLS-1$
+ imageNames.add(tag);
+ displayedImages.add(image);
+ }
+ }
+ }
+ }
+ imageCombo.setItems(imageNames.toArray(new String[0]));
+ if (initialImageId != null) {
+ int index = imageCombo.indexOf(initialImageId);
+ if (index > -1) {
+ imageCombo.select(index);
+ model.setSelectedImage(displayedImages.get(index));
+ setVolumeControlsEnabled(new Button[] { addButton }, true);
+ } else {
+ }
+ }
+ connection.addImageListener(containerTab);
+ }
+
+ }
+
+ private void initializeImageCombo() {
+ initialImageId = null;
+ IOptionalBuildProperties properties = iCfg.getOptionalBuildProperties();
+ String id = properties.getProperty(ContainerCommandLauncher.IMAGE_ID);
+ if (id != null) {
+ initialImageId = id;
+ }
+ refreshImages();
+ }
+
+ private void initializeVolumesTable() {
+ model.clearDataVolumes();
+ int imageSelectionIndex = imageCombo.getSelectionIndex();
+ if (imageSelectionIndex >= 0
+ && imageSelectionIndex < displayedImages.size()) {
+ model.setSelectedImage(displayedImages.get(imageSelectionIndex));
+ }
+
+ IOptionalBuildProperties properties = iCfg.getOptionalBuildProperties();
+ initialVolumes = properties
+ .getProperty(ContainerCommandLauncher.VOLUMES_ID);
+ Map<String, DataVolumeModel> volumeMap = parseVolumes(initialVolumes);
+ initialSelectedVolumes = properties
+ .getProperty(ContainerCommandLauncher.SELECTED_VOLUMES_ID);
+ Map<String, DataVolumeModel> selectedVolumeMap = parseVolumes(
+ initialSelectedVolumes);
+ Set<DataVolumeModel> selectedVolumes = new HashSet<>();
+ for (DataVolumeModel dvm : selectedVolumeMap.values()) {
+ // we need selected volumes to be volumes that are in the volumes
+ // collection, so just replace them in the volumes Map so they will
+ // be
+ // the same objects
+ volumeMap.put(dvm.getContainerPath(), dvm);
+ selectedVolumes.add(dvm);
+ }
+ model.setDataVolumes(volumeMap.values());
+ model.setSelectedDataVolumes(selectedVolumes);
+ }
+
+ private Map<String, DataVolumeModel> parseVolumes(String volumesString) {
+ Map<String, DataVolumeModel> volumeMap = new HashMap<>();
+ if (volumesString != null && !volumesString.equals("")) { //$NON-NLS-1$
+ String[] volumes = volumesString
+ .split("[" + VOLUME_SEPARATOR + "]"); //$NON-NLS-1$ //$NON-NLS-2$
+ for (String volume : volumes) {
+ if (volume != null && !volume.equals("")) { //$NON-NLS-1$
+ DataVolumeModel dataVolume = DataVolumeModel
+ .parseString(volume);
+ volumeMap.put(dataVolume.getContainerPath(), dataVolume);
+ }
+ }
+ }
+ return volumeMap;
+ }
+
+ @Override
+ protected void performApply(ICResourceDescription src,
+ ICResourceDescription dst) {
+ setVolumes();
+ boolean needToRecalculate = false;
+ ICConfigurationDescription defaultCfg = null;
+ if (page.isMultiCfg()) {
+ ICMultiConfigDescription mc1 = (ICMultiConfigDescription) src
+ .getConfiguration();
+ ICMultiConfigDescription mc2 = (ICMultiConfigDescription) dst
+ .getConfiguration();
+ ICConfigurationDescription[] cds1 = (ICConfigurationDescription[]) mc1
+ .getItems();
+ ICConfigurationDescription[] cds2 = (ICConfigurationDescription[]) mc2
+ .getItems();
+ defaultCfg = cds1[0];
+ for (int i = 0; i < cds1.length; i++)
+ needToRecalculate |= applyToCfg(cds1[i], cds2[i]);
+ } else {
+ defaultCfg = src.getConfiguration();
+ needToRecalculate = applyToCfg(src.getConfiguration(),
+ dst.getConfiguration());
+ }
+ if (needToRecalculate) {
+ recalculateSpecs(defaultCfg, true);
+ }
+ }
+
+ private boolean applyToCfg(ICConfigurationDescription c1,
+ ICConfigurationDescription c2) {
+ Configuration cfg01 = (Configuration) getCfg(c1);
+ Configuration cfg02 = (Configuration) getCfg(c2);
+ IOptionalBuildProperties prop1 = cfg01.getOptionalBuildProperties();
+ IOptionalBuildProperties prop2 = cfg02.getOptionalBuildProperties();
+ boolean needToRecalculate = false;
+
+ ICTargetPlatformSetting tps = c1.getTargetPlatformSetting();
+ String[] pids = tps.getBinaryParserIds();
+ ICTargetPlatformSetting tps2 = c2.getTargetPlatformSetting();
+ tps2.setBinaryParserIds(pids);
+
+ String enablementProperty = prop1
+ .getProperty(ContainerCommandLauncher.CONTAINER_BUILD_ENABLED);
+ String enablementProperty2 = prop2
+ .getProperty(ContainerCommandLauncher.CONTAINER_BUILD_ENABLED);
+ if (enablementProperty != null
+ && !enablementProperty.equals(enablementProperty2)) {
+ needToRecalculate = true;
+ }
+ prop2.setProperty(ContainerCommandLauncher.CONTAINER_BUILD_ENABLED,
+ enablementProperty);
+
+ String connectionProperty = prop1
+ .getProperty(ContainerCommandLauncher.CONNECTION_ID);
+ String connectionProperty2 = prop2
+ .getProperty(ContainerCommandLauncher.CONNECTION_ID);
+ if (connectionProperty != null
+ && !connectionProperty.equals(connectionProperty2)) {
+ needToRecalculate = true;
+ }
+ prop2.setProperty(ContainerCommandLauncher.CONNECTION_ID,
+ connectionProperty);
+
+ String imageProperty = prop1
+ .getProperty(ContainerCommandLauncher.IMAGE_ID);
+ String imageProperty2 = prop2
+ .getProperty(ContainerCommandLauncher.IMAGE_ID);
+ if (imageProperty != null && !imageProperty.equals(imageProperty2)) {
+ needToRecalculate = true;
+ }
+ prop2.setProperty(ContainerCommandLauncher.IMAGE_ID, imageProperty);
+
+ String volumesProperty = prop1
+ .getProperty(ContainerCommandLauncher.VOLUMES_ID);
+ prop2.setProperty(ContainerCommandLauncher.VOLUMES_ID, volumesProperty);
+
+ String selectedVolumesProperty = prop1
+ .getProperty(ContainerCommandLauncher.SELECTED_VOLUMES_ID);
+ prop2.setProperty(ContainerCommandLauncher.SELECTED_VOLUMES_ID,
+ selectedVolumesProperty);
+
+ return needToRecalculate;
+ }
+
+
+ protected void recalculateSpecs(ICConfigurationDescription cfgd,
+ boolean performingApply) {
+ IConfiguration cfg = getCfg(cfgd);
+ IOptionalBuildProperties properties = cfg.getOptionalBuildProperties();
+ initialEnabled = Boolean.parseBoolean(properties
+ .getProperty(ContainerCommandLauncher.CONTAINER_BUILD_ENABLED));
+ initialConnection = properties
+ .getProperty(ContainerCommandLauncher.CONNECTION_ID);
+ initialImageId = properties
+ .getProperty(ContainerCommandLauncher.IMAGE_ID);
+ initialVolumes = properties
+ .getProperty(ContainerCommandLauncher.VOLUMES_ID);
+ initialSelectedVolumes = properties
+ .getProperty(ContainerCommandLauncher.SELECTED_VOLUMES_ID);
+ List<ILanguageSettingsProvider> providers = ((ILanguageSettingsProvidersKeeper) cfgd)
+ .getLanguageSettingProviders();
+ for (ILanguageSettingsProvider provider : providers) {
+ if (provider instanceof GCCBuiltinSpecsDetector) {
+ GCCBuiltinSpecsDetector d = (GCCBuiltinSpecsDetector) provider;
+ // force recalculation of gcc include path
+ d.clear();
+ if (performingApply) {
+ d.handleEvent(null);
+ }
+ // final IProject project = getProject();
+ // CCorePlugin.getIndexManager().reindex(CoreModel.getDefault().create(project));
+ }
+ }
+ }
+
+
+ @Override
+ protected void performOK() {
+ boolean needToRecalculate = false;
+ setVolumes();
+ if (iCfg instanceof IMultiConfiguration) {
+ needToRecalculate = multiChange;
+ } else {
+ IOptionalBuildProperties p = iCfg.getOptionalBuildProperties();
+ if (initialEnabled != Boolean.parseBoolean(p.getProperty(
+ ContainerCommandLauncher.CONTAINER_BUILD_ENABLED))) {
+ needToRecalculate = true;
+ } else if (initialEnabled == true) {
+ if (!initialConnection.equals(
+ p.getProperty(ContainerCommandLauncher.CONNECTION_ID))
+ || !initialImageId.equals(p.getProperty(
+ ContainerCommandLauncher.IMAGE_ID))) {
+ needToRecalculate = true;
+ }
+ }
+ }
+ if (needToRecalculate) {
+ recalculateSpecs(
+ ManagedBuildManager.getDescriptionForConfiguration(iCfg),
+ false);
+ }
+ }
+
+ @Override
+ protected void performDefaults() {
+ if (iCfg instanceof IMultiConfiguration) {
+ IConfiguration[] cfs = (IConfiguration[]) ((IMultiConfiguration) iCfg)
+ .getItems();
+ for (int i = 0; i < cfs.length; i++) {
+ IOptionalBuildProperties props = cfs[i]
+ .getOptionalBuildProperties();
+ props.setProperty(
+ ContainerCommandLauncher.CONTAINER_BUILD_ENABLED,
+ Boolean.toString(false));
+ if (connections.length > 0) {
+ props.setProperty(ContainerCommandLauncher.CONNECTION_ID,
+ connections[0].getUri());
+ } else {
+ props.setProperty(ContainerCommandLauncher.CONNECTION_ID,
+ null);
+ }
+ props.setProperty(ContainerCommandLauncher.IMAGE_ID, null);
+ props.setProperty(ContainerCommandLauncher.VOLUMES_ID, null);
+ props.setProperty(ContainerCommandLauncher.SELECTED_VOLUMES_ID,
+ null);
+ }
+ } else {
+ IOptionalBuildProperties props = iCfg.getOptionalBuildProperties();
+ props.setProperty(ContainerCommandLauncher.CONTAINER_BUILD_ENABLED,
+ Boolean.toString(false));
+ if (connections.length > 0) {
+ props.setProperty(ContainerCommandLauncher.CONNECTION_ID,
+ connections[0].getUri());
+ } else {
+ props.setProperty(ContainerCommandLauncher.CONNECTION_ID, null);
+ }
+ props.setProperty(ContainerCommandLauncher.IMAGE_ID, null);
+ }
+ initialEnabled = false;
+ initialConnection = null;
+ initialImageId = null;
+ initialVolumes = null;
+ initialSelectedVolumes = null;
+ if (connections.length > 0) {
+ connectionSelector.select(0);
+ }
+ imageCombo.setText(""); //$NON-NLS-1$
+ model.setDataVolumes(null);
+ model.setSelectedDataVolumes(null);
+ enableButton.setSelection(false);
+ setControlsEnabled(false);
+ }
+
+ @Override
+ public void updateData(ICResourceDescription cfgd) {
+ if (cfgd == null)
+ return;
+ iCfg = getCfg(cfgd.getConfiguration());
+ iCfgd = cfgd.getConfiguration();
+
+ multiChange = false;
+
+ initializeConnectionSelector();
+ initializeImageCombo();
+ initializeEnablementButton();
+ initializeVolumesTable();
+ }
+
+ @Override
+ protected void updateButtons() {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void changeEvent(IDockerConnection changedConnection, int type) {
+ String currUri = null;
+ int currIndex = 0;
+ connections = DockerConnectionManager.getInstance().getConnections();
+ if (connection != null) {
+ currUri = connection.getUri();
+ currIndex = connectionSelector.getSelectionIndex();
+ }
+ String[] connectionNames = new String[connections.length];
+ int index = 0;
+ for (int i = 0; i < connections.length; ++i) {
+ connectionNames[i] = connections[i].getName();
+ if (connections[i].getUri().equals(currUri))
+ index = i;
+ }
+ if (type == IDockerConnectionManagerListener.RENAME_EVENT) {
+ index = currIndex; // no change in connection displayed
+ }
+ connectionSelector.removeModifyListener(connectionModifyListener);
+ connectionSelector.setItems(connectionNames);
+ if (connectionNames.length > 0) {
+ connectionSelector.setText(connectionNames[index]);
+ connection = connections[index];
+ model.setConnection(connection);
+ connectionUri = connection.getUri();
+ } else {
+ connection = null;
+ model.setConnection(null);
+ model.setSelectedImage(null);
+ connectionUri = "";
+ connectionSelector.setText("");
+ }
+ connectionSelector.addModifyListener(connectionModifyListener);
+ }
+
+ @Override
+ public void listChanged(IDockerConnection c,
+ java.util.List<IDockerImage> list) {
+ final IDockerImage[] finalList = list.toArray(new IDockerImage[0]);
+ if (c.getName().equals(connection.getName())) {
+ Display.getDefault().syncExec(new Runnable() {
+ @Override
+ public void run() {
+ connection.removeImageListener(containerTab);
+ ArrayList<String> imageNames = new ArrayList<String>();
+ displayedImages = new ArrayList<>();
+ for (IDockerImage image : finalList) {
+ java.util.List<String> tags = image.repoTags();
+ if (tags != null) {
+ for (String tag : tags) {
+ imageNames.add(tag);
+ displayedImages.add(image);
+ }
+ }
+ }
+ if (!imageCombo.isDisposed())
+ imageCombo.setItems(imageNames.toArray(new String[0]));
+ connection.addImageListener(containerTab);
+ }
+
+ });
+ }
+ }
+
+}
diff --git a/launch/org.eclipse.cdt.docker.launcher/src/org/eclipse/cdt/internal/docker/launcher/ContainerPropertyVolumesModel.java b/launch/org.eclipse.cdt.docker.launcher/src/org/eclipse/cdt/internal/docker/launcher/ContainerPropertyVolumesModel.java
new file mode 100644
index 0000000000..ad4ccbf6cb
--- /dev/null
+++ b/launch/org.eclipse.cdt.docker.launcher/src/org/eclipse/cdt/internal/docker/launcher/ContainerPropertyVolumesModel.java
@@ -0,0 +1,142 @@
+/*******************************************************************************
+ * Copyright (c) 2015, 2016 Red Hat.
+ * 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:
+ * Red Hat - Initial Contribution
+ *******************************************************************************/
+package org.eclipse.cdt.internal.docker.launcher;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.eclipse.core.databinding.observable.list.WritableList;
+import org.eclipse.linuxtools.docker.core.DockerException;
+import org.eclipse.linuxtools.docker.core.IDockerConnection;
+import org.eclipse.linuxtools.docker.core.IDockerImage;
+import org.eclipse.linuxtools.docker.core.IDockerImageInfo;
+
+/**
+ * Databinding model for the {@link ContainerPropertyTab}
+ *
+ */
+public class ContainerPropertyVolumesModel
+ extends BaseDatabindingModel {
+
+ public enum MountType {
+ NONE, HOST_FILE_SYSTEM, CONTAINER;
+ }
+
+
+ public static final String DATA_VOLUMES = "dataVolumes"; //$NON-NLS-1$
+
+ public static final String SELECTED_DATA_VOLUMES = "selectedDataVolumes"; //$NON-NLS-1$
+
+ private IDockerConnection connection;
+
+ private IDockerImageInfo imageInfo = null;
+
+ private Set<DataVolumeModel> selectedDataVolumes = new HashSet<>();
+
+ private WritableList<DataVolumeModel> dataVolumes = new WritableList<>();
+
+ private List<DataVolumeModel> previousVolumes = new ArrayList<>();
+
+ private IDockerImage selectedImage;
+
+ public ContainerPropertyVolumesModel(
+ final IDockerConnection connection) {
+ this.connection = connection;
+ }
+
+ public ContainerPropertyVolumesModel(
+ final IDockerImage selectedImage) throws DockerException {
+ this(selectedImage.getConnection());
+ this.selectedImage = selectedImage;
+ }
+
+ public void setConnection(IDockerConnection connection) {
+ this.connection = connection;
+ setSelectedImage(null);
+ }
+
+ public IDockerConnection getConnection() {
+ return connection;
+ }
+
+ /**
+ * Refreshes the list of Volumes to display in the for the given
+ *
+ * @param selectedImage
+ */
+ public void setSelectedImage(final IDockerImage selectedImage) {
+ if (this.selectedImage == null
+ || !this.selectedImage.equals(selectedImage)) {
+ this.selectedImage = selectedImage;
+ if (selectedImage != null) {
+ this.imageInfo = selectedImage.getConnection()
+ .getImageInfo(selectedImage.id());
+ if (this.imageInfo.config() != null
+ && this.imageInfo.config().volumes() != null) {
+ for (DataVolumeModel dvm : previousVolumes) {
+ removeDataVolume(dvm);
+ selectedDataVolumes.remove(dvm);
+ }
+ final List<DataVolumeModel> volumes = new ArrayList<>();
+ for (String volume : this.imageInfo.config().volumes()) {
+ volumes.add(new DataVolumeModel(volume));
+ }
+ setDataVolumes(volumes);
+ previousVolumes = volumes;
+ }
+ } else {
+ setDataVolumes(Collections.<DataVolumeModel> emptyList());
+ }
+ }
+
+ }
+
+ public IDockerImage getSelectedImage() {
+ return selectedImage;
+ }
+
+ public IDockerImageInfo getSelectedImageInfo() {
+ return imageInfo;
+ }
+
+ public WritableList<DataVolumeModel> getDataVolumes() {
+ return dataVolumes;
+ }
+
+ public void setDataVolumes(final Collection<DataVolumeModel> volumes) {
+ if (volumes != null) {
+ this.dataVolumes.addAll(volumes);
+ }
+ }
+
+ public void clearDataVolumes() {
+ this.dataVolumes.clear();
+ }
+
+ public void removeDataVolume(final DataVolumeModel dataVolume) {
+ this.dataVolumes.remove(dataVolume);
+ }
+
+ public Set<DataVolumeModel> getSelectedDataVolumes() {
+ return selectedDataVolumes;
+ }
+
+ public void setSelectedDataVolumes(
+ final Set<DataVolumeModel> selectedDataVolumes) {
+ firePropertyChange(SELECTED_DATA_VOLUMES, this.selectedDataVolumes,
+ this.selectedDataVolumes = selectedDataVolumes);
+ }
+
+}
diff --git a/launch/org.eclipse.cdt.docker.launcher/src/org/eclipse/cdt/internal/docker/launcher/ContainerTab.java b/launch/org.eclipse.cdt.docker.launcher/src/org/eclipse/cdt/internal/docker/launcher/ContainerTab.java
index 1786646846..0d69db41fd 100644
--- a/launch/org.eclipse.cdt.docker.launcher/src/org/eclipse/cdt/internal/docker/launcher/ContainerTab.java
+++ b/launch/org.eclipse.cdt.docker.launcher/src/org/eclipse/cdt/internal/docker/launcher/ContainerTab.java
@@ -517,7 +517,8 @@ public class ContainerTab extends AbstractLaunchConfigurationTab implements
return SWTImagesFactory.get(SWTImagesFactory.IMG_CONTAINER);
}
- public void changeEvent(int type) {
+ @Override
+ public void changeEvent(IDockerConnection changedConnection, int type) {
String currUri = null;
int currIndex = 0;
connections = DockerConnectionManager.getInstance().getConnections();
@@ -549,10 +550,6 @@ public class ContainerTab extends AbstractLaunchConfigurationTab implements
connectionSelector.addModifyListener(connectionModifyListener);
}
- public void changeEvent(IDockerConnection connection, int event) {
- changeEvent(event);
- }
-
public void listChanged(IDockerConnection c,
java.util.List<IDockerImage> list) {
final IDockerImage[] finalList = list.toArray(new IDockerImage[0]);
diff --git a/launch/org.eclipse.cdt.docker.launcher/src/org/eclipse/cdt/internal/docker/launcher/DataVolumeModel.java b/launch/org.eclipse.cdt.docker.launcher/src/org/eclipse/cdt/internal/docker/launcher/DataVolumeModel.java
new file mode 100644
index 0000000000..d3e5816d18
--- /dev/null
+++ b/launch/org.eclipse.cdt.docker.launcher/src/org/eclipse/cdt/internal/docker/launcher/DataVolumeModel.java
@@ -0,0 +1,347 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Red Hat.
+ * 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:
+ * Red Hat - Initial Contribution
+ *******************************************************************************/
+package org.eclipse.cdt.internal.docker.launcher;
+
+import java.util.UUID;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.eclipse.cdt.internal.docker.launcher.ContainerPropertyVolumesModel.MountType;
+import org.eclipse.core.runtime.Platform;
+
+/**
+ * Data binding model for container data volumes
+ *
+ */
+public class DataVolumeModel extends BaseDatabindingModel
+ implements Comparable<DataVolumeModel> {
+
+ private static final String SEPARATOR = ":"; //$NON-NLS-1$
+
+ public static final String CONTAINER_PATH = "containerPath"; //$NON-NLS-1$
+
+ public static final String MOUNT_TYPE = "mountType"; //$NON-NLS-1$
+
+ public static final String MOUNT = "mount"; //$NON-NLS-1$
+
+ public static final String HOST_PATH_MOUNT = "hostPathMount"; //$NON-NLS-1$
+
+ public static final String READ_ONLY_VOLUME = "readOnly"; //$NON-NLS-1$
+
+ public static final String CONTAINER_MOUNT = "containerMount"; //$NON-NLS-1$
+
+ public static final String SELECTED = "selected"; //$NON-NLS-1$
+
+ private final String id = UUID.randomUUID().toString();
+
+ private String containerPath;
+
+ private MountType mountType;
+
+ private String mount;
+
+ private String hostPathMount;
+
+ private String containerMount;
+
+ private boolean readOnly = false;
+
+ private boolean selected;
+
+
+ /**
+ * Default constructor
+ */
+ public DataVolumeModel() {
+ }
+
+ /**
+ * Constructor
+ *
+ * @param containerPath
+ * the container path
+ */
+ public DataVolumeModel(final String containerPath) {
+ this.containerPath = containerPath;
+ this.mountType = MountType.NONE;
+ }
+
+ public DataVolumeModel(final String containerPath, final String hostPath,
+ final boolean readOnly) {
+ this.containerPath = containerPath;
+ this.mountType = MountType.HOST_FILE_SYSTEM;
+ this.hostPathMount = hostPath;
+ this.mount = this.hostPathMount;
+ this.readOnly = readOnly;
+ }
+
+ public DataVolumeModel(final DataVolumeModel selectedDataVolume) {
+ this.containerPath = selectedDataVolume.getContainerPath();
+ this.mountType = selectedDataVolume.getMountType();
+ if (this.mountType != null) {
+ switch (this.mountType) {
+ case CONTAINER:
+ this.containerMount = selectedDataVolume.getMount();
+ break;
+ case HOST_FILE_SYSTEM:
+ this.hostPathMount = selectedDataVolume.getMount();
+ this.readOnly = selectedDataVolume.isReadOnly();
+ break;
+ case NONE:
+ break;
+ }
+ } else {
+ this.mountType = MountType.NONE;
+ }
+ }
+
+ /**
+ * Create a DataVolumeModel from a toString() output.
+ *
+ * @param fromString
+ * @return DataVolumeModel
+ */
+ public static DataVolumeModel parseString(
+ final String fromString) {
+ final DataVolumeModel model = new DataVolumeModel();
+ final String[] items = fromString.split(SEPARATOR); // $NON-NLS-1$
+ model.containerPath = items[0];
+ model.mountType = MountType.valueOf(items[1]);
+ switch (model.mountType) {
+ case CONTAINER:
+ model.setContainerMount(items[2]);
+ model.setSelected(Boolean.valueOf(items[3]));
+ break;
+ case HOST_FILE_SYSTEM:
+ // For Windows, there are multiple formats. If a user has specified
+ // a windows drive using the : separator, we have to form the
+ // host path by merging the path back together. If the user
+ // has specified an alternate format, we don't do this.
+ if (Platform.OS_WIN32.equals(Platform.getOS())
+ && items.length > 5) {
+ model.setHostPathMount(items[2] + SEPARATOR + items[3]);
+ model.setReadOnly(Boolean.valueOf(items[4]));
+ model.setSelected(Boolean.valueOf(items[5]));
+ } else {
+ model.setHostPathMount(items[2]);
+ model.setReadOnly(Boolean.valueOf(items[3]));
+ model.setSelected(Boolean.valueOf(items[4]));
+ }
+ break;
+ case NONE:
+ model.setSelected(Boolean.valueOf(items[2]));
+ break;
+ }
+ return model;
+ }
+
+ /**
+ * creates a {@link DataVolumeModel} from the 'volumeFrom' container info
+ *
+ * @param volumeFrom
+ * the value to parse.
+ *
+ * Format: <code>&lt;containerName&gt;</code>
+ *
+ * @See <a href="https://docs.docker.com/engine/userguide/dockervolumes/">
+ * https://docs.docker.com/engine/userguide/dockervolumes/</a>
+ */
+ public static DataVolumeModel parseVolumeFrom(String volumeFrom) {
+ final DataVolumeModel model = new DataVolumeModel();
+ model.mountType = MountType.CONTAINER;
+ model.containerMount = volumeFrom;
+ model.selected = true;
+ return model;
+ }
+
+ /**
+ * creates a {@link DataVolumeModel} from the 'volumeFrom' container info
+ *
+ * @param volumeFrom
+ * the value to parse. Format:
+ * <code>&lt;host_path&gt;:&lt;container_path&gt;:&lt;label_suffix_flag&gt;</code>
+ *
+ * @See <a href="https://docs.docker.com/engine/userguide/dockervolumes/">
+ * https://docs.docker.com/engine/userguide/dockervolumes/</a>
+ */
+ public static DataVolumeModel parseHostBinding(String volumeFrom) {
+ final DataVolumeModel model = new DataVolumeModel();
+ final String[] items = volumeFrom.split(SEPARATOR); // $NON-NLS-1$
+ // converts the host path to a valid Win32 path if Platform OS is Win32
+ model.setHostPathMount(convertToWin32Path(Platform.getOS(), items[0]));
+ model.containerPath = items[1];
+ model.mountType = MountType.HOST_FILE_SYSTEM;
+ if (items[2].equals("ro")) {
+ model.setReadOnly(true);
+ } else {
+ model.setReadOnly(false);
+ }
+ model.selected = true;
+ return model;
+ }
+
+ /**
+ * Converts the given path to a portable form, replacing all "\" and ": "
+ * with "/" if the given <code>os</code> is {@link Platform#OS_WIN32}.
+ *
+ * @param os
+ * the current OS
+ * @param path
+ * the path to convert
+ * @return the converted path or the given path
+ * @see {@link Platform#getOS()}
+ */
+ public static String convertToWin32Path(final String os,
+ final String path) {
+ if (os != null && os.equals(Platform.OS_WIN32)) {
+ // replace all "/" with "\" and then drive info (eg "/c/" to "C:/")
+ final Matcher m = Pattern.compile("^/([a-zA-Z])/").matcher(path); //$NON-NLS-1$
+ if (m.find()) {
+ final StringBuffer b = new StringBuffer();
+ m.appendReplacement(b, m.group(1).toUpperCase());
+ b.append(":\\"); //$NON-NLS-1$
+ m.appendTail(b);
+ return b.toString().replace('/', '\\'); // $NON-NLS-1$
+ // //$NON-NLS-2$
+ }
+ }
+ return path;
+ }
+
+ public String getContainerPath() {
+ return this.containerPath;
+ }
+
+ public void setContainerPath(final String containerPath) {
+ firePropertyChange(CONTAINER_PATH, this.containerPath,
+ this.containerPath = containerPath);
+ }
+
+ public String getMount() {
+ return mount;
+ }
+
+ public void setMount(final String mount) {
+ firePropertyChange(MOUNT, this.mount, this.mount = mount);
+ }
+
+ public MountType getMountType() {
+ return mountType;
+ }
+
+ public void setMountType(final MountType mountType) {
+ // ignore 'null' assignments that may come from the UpdateStrategy
+ // in
+ // the EditDataVolumePage when a radion button is unselected.
+ if (mountType == null) {
+ return;
+ }
+ firePropertyChange(MOUNT_TYPE, this.mountType,
+ this.mountType = mountType);
+ if (this.mountType == MountType.NONE) {
+ setMount("");
+ }
+
+ }
+
+ public String getHostPathMount() {
+ return hostPathMount;
+ }
+
+ public void setHostPathMount(final String hostPathMount) {
+ firePropertyChange(HOST_PATH_MOUNT, this.hostPathMount,
+ this.hostPathMount = hostPathMount);
+ if (this.mountType == MountType.HOST_FILE_SYSTEM) {
+ setMount(this.hostPathMount);
+ }
+ }
+
+ public boolean isReadOnly() {
+ return readOnly;
+ }
+
+ public void setReadOnly(final boolean readOnly) {
+ firePropertyChange(READ_ONLY_VOLUME, this.readOnly,
+ this.readOnly = readOnly);
+ }
+
+ public String getContainerMount() {
+ return this.containerMount;
+ }
+
+ public void setContainerMount(final String containerMount) {
+ firePropertyChange(CONTAINER_MOUNT, this.containerMount,
+ this.containerMount = containerMount);
+ if (this.mountType == MountType.CONTAINER) {
+ setMount(this.containerMount);
+ }
+ }
+
+ public boolean getSelected() {
+ return selected;
+ }
+
+ public void setSelected(final boolean selected) {
+ firePropertyChange(SELECTED, this.selected, this.selected = selected);
+ }
+
+ @Override
+ public int compareTo(final DataVolumeModel other) {
+ return this.getContainerPath().compareTo(other.getContainerPath());
+ }
+
+ // FIXME we should have a dedicated method to serialize the bean
+ @Override
+ public String toString() {
+ final StringBuffer buffer = new StringBuffer();
+ buffer.append(
+ this.containerPath + SEPARATOR + getMountType() + SEPARATOR);
+ switch (getMountType()) {
+ case CONTAINER:
+ buffer.append(getContainerMount());
+ break;
+ case HOST_FILE_SYSTEM:
+ buffer.append(getHostPathMount() + SEPARATOR); // $NON-NLS-1$
+ buffer.append(isReadOnly());
+ break;
+ case NONE:
+ break;
+ }
+ buffer.append(SEPARATOR).append(this.selected);
+ return buffer.toString();
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((id == null) ? 0 : id.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ DataVolumeModel other = (DataVolumeModel) obj;
+ if (id == null) {
+ if (other.id != null)
+ return false;
+ } else if (!id.equals(other.id))
+ return false;
+ return true;
+ }
+
+}
diff --git a/launch/org.eclipse.cdt.docker.launcher/src/org/eclipse/cdt/internal/docker/launcher/LaunchShortcut.java b/launch/org.eclipse.cdt.docker.launcher/src/org/eclipse/cdt/internal/docker/launcher/LaunchShortcut.java
index ed716c3361..5ad81d2dcd 100644
--- a/launch/org.eclipse.cdt.docker.launcher/src/org/eclipse/cdt/internal/docker/launcher/LaunchShortcut.java
+++ b/launch/org.eclipse.cdt.docker.launcher/src/org/eclipse/cdt/internal/docker/launcher/LaunchShortcut.java
@@ -19,13 +19,18 @@ import org.eclipse.cdt.core.model.CModelException;
import org.eclipse.cdt.core.model.CoreModel;
import org.eclipse.cdt.core.model.IBinary;
import org.eclipse.cdt.core.model.ICProject;
+import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
import org.eclipse.cdt.debug.core.CDebugUtils;
import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
import org.eclipse.cdt.docker.launcher.DockerLaunchUIPlugin;
import org.eclipse.cdt.dsf.gdb.IGDBLaunchConfigurationConstants;
import org.eclipse.cdt.dsf.gdb.IGdbDebugPreferenceConstants;
import org.eclipse.cdt.dsf.gdb.internal.ui.GdbUIPlugin;
+import org.eclipse.cdt.managedbuilder.buildproperties.IOptionalBuildProperties;
+import org.eclipse.cdt.managedbuilder.core.IConfiguration;
+import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager;
import org.eclipse.cdt.ui.CElementLabelProvider;
+import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
@@ -253,6 +258,31 @@ public class LaunchShortcut implements ILaunchShortcut {
ILaunchConfiguration configuration = null;
ILaunchConfigurationType configType = getLaunchConfigType();
List<ILaunchConfiguration> candidateConfigs = Collections.emptyList();
+ IProject project = bin.getCProject().getProject();
+ ICConfigurationDescription cfgd = CoreModel.getDefault()
+ .getProjectDescription(project).getActiveConfiguration();
+ String connectionUri = null;
+ String imageName = null;
+ if (cfgd != null) {
+ IConfiguration cfg = ManagedBuildManager
+ .getConfigurationForDescription(cfgd);
+ if (cfg != null) {
+ IOptionalBuildProperties props = cfg
+ .getOptionalBuildProperties();
+ String containerBuild = props.getProperty(
+ ContainerCommandLauncher.CONTAINER_BUILD_ENABLED);
+ if (containerBuild != null) {
+ boolean containerBuildEnabled = Boolean
+ .parseBoolean(containerBuild);
+ if (containerBuildEnabled) {
+ connectionUri = props.getProperty(
+ ContainerCommandLauncher.CONNECTION_ID);
+ imageName = props
+ .getProperty(ContainerCommandLauncher.IMAGE_ID);
+ }
+ }
+ }
+ }
try {
ILaunchConfiguration[] configs = DebugPlugin.getDefault()
.getLaunchManager().getLaunchConfigurations(configType);
@@ -265,7 +295,17 @@ public class LaunchShortcut implements ILaunchShortcut {
if (projectName != null
&& projectName.equals(bin.getCProject()
.getProject().getName())) {
- candidateConfigs.add(config);
+ // if we have an active configuration with container
+ // build properties, make sure they match, otherwise
+ // add the launch config as a candidate
+ if (connectionUri.equals(config.getAttribute(
+ ILaunchConstants.ATTR_CONNECTION_URI,
+ connectionUri))) {
+ if (imageName.equals(config.getAttribute(
+ ILaunchConstants.ATTR_IMAGE, imageName))) {
+ candidateConfigs.add(config);
+ }
+ }
}
}
}
@@ -312,11 +352,40 @@ public class LaunchShortcut implements ILaunchShortcut {
String binaryPath = bin.getResource().getProjectRelativePath()
.toString();
+ IProject project = bin.getResource().getProject();
+
+ ICConfigurationDescription cfgd = CoreModel.getDefault()
+ .getProjectDescription(project).getActiveConfiguration();
+ IConfiguration cfg = ManagedBuildManager
+ .getConfigurationForDescription(cfgd);
+
+ IOptionalBuildProperties options = cfg.getOptionalBuildProperties();
+ boolean containerBuild = false;
+ String connectionId = null;
+ String imageName = null;
+
+ if (options != null) {
+ String containerBuildString = options.getProperty(
+ ContainerCommandLauncher.CONTAINER_BUILD_ENABLED);
+ if (containerBuildString != null) {
+ containerBuild = Boolean.parseBoolean(options.getProperty(
+ ContainerCommandLauncher.CONTAINER_BUILD_ENABLED));
+ }
+ if (containerBuild) {
+ connectionId = options.getProperty(
+ ContainerCommandLauncher.CONNECTION_ID);
+ imageName = options
+ .getProperty(ContainerCommandLauncher.IMAGE_ID);
+ }
+ }
+
ILaunchConfigurationType configType = getLaunchConfigType();
ILaunchConfigurationWorkingCopy wc = configType.newInstance(
null,
getLaunchManager().generateLaunchConfigurationName(
- bin.getElementName()));
+ bin.getResource().getName() + (imageName != null
+ ? ("[" + imageName + "]") //$NON-NLS-1$ //$NON-NLS-2$
+ : ""))); //$NON-NLS-1$
// DSF settings...use GdbUIPlugin preference store for defaults
IPreferenceStore preferenceStore = GdbUIPlugin.getDefault()
@@ -357,19 +426,25 @@ public class LaunchShortcut implements ILaunchShortcut {
Preferences prefs = InstanceScope.INSTANCE
.getNode(DockerLaunchUIPlugin.PLUGIN_ID);
- // get the connection from the ConnectionListener which waits for
- // any activity
- // from the DockerExplorerView
- IDockerConnection connection = ConnectionListener.getInstance()
+ // get the connection using following order:
+ // 1. connection used in build of project
+ // 2. current connection
+ // 3. first connection
+ IDockerConnection connection = null;
+ if (connectionId != null) {
+ connection = DockerConnectionManager.getInstance()
+ .getConnectionByUri(connectionId);
+ }
+ if (connection == null) {
+ connection = ConnectionListener.getInstance()
.getCurrentConnection();
+ }
if (connection == null) {
IDockerConnection[] connections = DockerConnectionManager
.getInstance().getConnections();
if (connections != null && connections.length > 0)
- connection = DockerConnectionManager.getInstance()
- .getConnections()[0];
+ connection = connections[0];
}
-
// issue error message if no connections exist
if (connection == null) {
Display.getDefault().syncExec(new Runnable() {
@@ -389,9 +464,14 @@ public class LaunchShortcut implements ILaunchShortcut {
wc.setAttribute(ILaunchConstants.ATTR_CONNECTION_URI,
connection.getUri());
- // get any default image if specified, otherwise use first
+ // use build image if one is specified, otherwise, see if a default
+ // image is set in preferences, otherwise find first image in image
+ // list
// image in image list for connection
- String image = prefs.get(PreferenceConstants.DEFAULT_IMAGE, null);
+ String image = imageName;
+ if (image == null) {
+ image = prefs.get(PreferenceConstants.DEFAULT_IMAGE, null);
+ }
if (image == null) {
List<IDockerImage> images = connection.getImages();
if (images != null && images.size() > 0)
diff --git a/launch/org.eclipse.cdt.docker.launcher/src/org/eclipse/cdt/internal/docker/launcher/Messages.java b/launch/org.eclipse.cdt.docker.launcher/src/org/eclipse/cdt/internal/docker/launcher/Messages.java
index f3d6003d8a..dc90a4e314 100644
--- a/launch/org.eclipse.cdt.docker.launcher/src/org/eclipse/cdt/internal/docker/launcher/Messages.java
+++ b/launch/org.eclipse.cdt.docker.launcher/src/org/eclipse/cdt/internal/docker/launcher/Messages.java
@@ -47,6 +47,13 @@ public class Messages extends NLS {
public static String ContainerTab_Warning_Connection_Not_Found;
public static String ContainerTab_Warning_Image_Not_Found;
+ public static String HeaderPreferencePage_Connection_Label;
+ public static String HeaderPreferencePage_Image_Label;
+ public static String HeaderPreferencePage_Remove_Label;
+ public static String HeaderPreferencePage_Remove_Tooltip;
+ public static String HeaderPreferencePage_Confirm_Removal_Title;
+ public static String HeaderPreferencePage_Confirm_Removal_Msg;
+
public static String Remote_GDB_Debugger_Options;
public static String Gdbserver_Settings_Tab_Name;
public static String Gdbserver_name_textfield_label;
@@ -90,6 +97,14 @@ public class Messages extends NLS {
public static String StandardGDBDebuggerPage14;
+ public static String ContainerPropertyTab_Title;
+ public static String ContainerPropertyTab_Enable_Msg;
+
+ public static String ContainerCommandLauncher_image_msg;
+ public static String CommandLauncher_CommandCancelled;
+
+ public static String ContainerCommandLauncher_invalid_values;
+
static {
// initialize resource bundle
NLS.initializeMessages(BUNDLE_NAME, Messages.class);
diff --git a/launch/org.eclipse.cdt.docker.launcher/src/org/eclipse/cdt/internal/docker/launcher/SWTImagesFactory.java b/launch/org.eclipse.cdt.docker.launcher/src/org/eclipse/cdt/internal/docker/launcher/SWTImagesFactory.java
index b886f2c642..d08edf77d5 100644
--- a/launch/org.eclipse.cdt.docker.launcher/src/org/eclipse/cdt/internal/docker/launcher/SWTImagesFactory.java
+++ b/launch/org.eclipse.cdt.docker.launcher/src/org/eclipse/cdt/internal/docker/launcher/SWTImagesFactory.java
@@ -44,8 +44,21 @@ public class SWTImagesFactory {
private static final int NAME_PREFIX_LENGTH = NAME_PREFIX.length();
public static final String IMG_CONTAINER = NAME_PREFIX
+ "repository-middle.gif"; //$NON-NLS-1$
+ public static final String IMG_FOLDER_CLOSED = NAME_PREFIX
+ + "folder_closed.gif"; //$NON-NLS-1$
+ public static final String IMG_FILE = NAME_PREFIX + "file_obj.gif"; //$NON-NLS-1$
+ public static final String IMG_WARNING = NAME_PREFIX + "warning_obj.gif"; //$NON-NLS-1$
+ public static final String IMG_ERROR = NAME_PREFIX + "error_obj.gif"; //$NON-NLS-1$
+
public static final ImageDescriptor DESC_CONTAINER = createManaged("",
IMG_CONTAINER);
+ public static final ImageDescriptor DESC_FOLDER_CLOSED = createManaged("",
+ IMG_FOLDER_CLOSED);
+ public static final ImageDescriptor DESC_FILE = createManaged("", IMG_FILE);
+ public static final ImageDescriptor DESC_WARNING = createManaged("",
+ IMG_WARNING);
+ public static final ImageDescriptor DESC_ERROR = createManaged("",
+ IMG_ERROR);
private static ImageDescriptor createManaged(String prefix, String name) {
return createManaged(imageRegistry, prefix, name);
diff --git a/launch/org.eclipse.cdt.docker.launcher/src/org/eclipse/cdt/internal/docker/launcher/messages.properties b/launch/org.eclipse.cdt.docker.launcher/src/org/eclipse/cdt/internal/docker/launcher/messages.properties
index 15e1b19a0c..06609d611c 100644
--- a/launch/org.eclipse.cdt.docker.launcher/src/org/eclipse/cdt/internal/docker/launcher/messages.properties
+++ b/launch/org.eclipse.cdt.docker.launcher/src/org/eclipse/cdt/internal/docker/launcher/messages.properties
@@ -40,6 +40,21 @@ ContainerTab_Error_No_Images=No Docker Images exist
ContainerTab_Warning_Connection_Not_Found=Docker Connection: {0} for Launch Configuration not found: defaulting to {1}
ContainerTab_Warning_Image_Not_Found=Docker Image: {0} is not a valid pulled image in current Connection: {1}
+ContainerPropertyTab_Title=Container Settings
+ContainerPropertyTab_Enable_Msg=Build inside Docker Image
+
+HeaderPreferencePage_Connection_Label=Connection
+HeaderPreferencePage_Image_Label=Image
+HeaderPreferencePage_Remove_Label=Remove
+HeaderPreferencePage_Remove_Tooltip=Remove headers cached from Docker image
+HeaderPreferencePage_Confirm_Removal_Title=Confirm Header File Removal
+HeaderPreferencePage_Confirm_Removal_Msg=Confirm removal of specified cached header files
+
+ContainerCommandLauncher_image_msg=[Running in image <{0}>]
+ContainerCommandLauncher_invalid_values=Invalid values for Connection and/or Image name
+
+CommandLauncher_CommandCancelled=Command cancelled
+
Remote_GDB_Debugger_Options=Docker Container GDB Debugger Options
Gdbserver_Settings_Tab_Name=Gdbserver Settings
Gdbserver_name_textfield_label=Gdbserver path:
diff --git a/launch/org.eclipse.cdt.docker.launcher/src/org/eclipse/cdt/internal/docker/launcher/ui/preferences/DockerHeaderPreferencePage.java b/launch/org.eclipse.cdt.docker.launcher/src/org/eclipse/cdt/internal/docker/launcher/ui/preferences/DockerHeaderPreferencePage.java
new file mode 100644
index 0000000000..0e0269ab90
--- /dev/null
+++ b/launch/org.eclipse.cdt.docker.launcher/src/org/eclipse/cdt/internal/docker/launcher/ui/preferences/DockerHeaderPreferencePage.java
@@ -0,0 +1,356 @@
+package org.eclipse.cdt.internal.docker.launcher.ui.preferences;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.cdt.docker.launcher.DockerLaunchUIPlugin;
+import org.eclipse.cdt.internal.docker.launcher.Messages;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.preference.PreferencePage;
+import org.eclipse.jface.viewers.ColumnWeightData;
+import org.eclipse.jface.viewers.ILabelProviderListener;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.ITableLabelProvider;
+import org.eclipse.jface.viewers.TableLayout;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPreferencePage;
+
+public class DockerHeaderPreferencePage extends PreferencePage
+ implements IWorkbenchPreferencePage, Listener {
+
+ // SWT Widgets and content providers
+ private Table hdrTable;
+ private TableViewer hdrTableViewer;
+ private HeaderContentProvider provider;
+ private Button removeButton;
+ private List<IPath> directories;
+
+ private final class HeaderContentProvider
+ implements IStructuredContentProvider, ITableLabelProvider {
+
+ /**
+ * @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(Object)
+ */
+ @Override
+ public Object[] getElements(Object inputElement) {
+ return directories.toArray();
+ }
+
+ /**
+ * @see org.eclipse.jface.viewers.IContentProvider#dispose()
+ */
+ @Override
+ public void dispose() {
+ }
+
+ /**
+ * @see org.eclipse.jface.viewers.IContentProvider#inputChanged(Viewer,
+ * Object, Object)
+ */
+ @Override
+ public void inputChanged(Viewer viewer, Object oldInput,
+ Object newInput) {
+ }
+
+ /**
+ * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnImage(Object,
+ * int)
+ */
+ @Override
+ public Image getColumnImage(Object element, int columnIndex) {
+ return null;
+ }
+
+ private String readNameFile(IPath path) {
+ // try and read real name from special .name file found in
+ // directory.
+ IPath namePath = path.append(".name"); //$NON-NLS-1$
+ // default to use last directory segment if any problems occur.
+ String name = path.lastSegment();
+ if (namePath.toFile().exists()) {
+ try (FileReader reader = new FileReader(namePath.toFile());
+ BufferedReader bufferReader = new BufferedReader(
+ reader);) {
+ name = bufferReader.readLine();
+ } catch (IOException e) {
+ // ignore
+ }
+ }
+ return name;
+ }
+
+ /**
+ * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnText(Object,
+ * int)
+ */
+ @Override
+ public String getColumnText(Object element, int columnIndex) {
+ IPath path = (IPath) element;
+ if (columnIndex == 0) {
+ IPath connectionPath = path.removeLastSegments(1);
+ String connectionName = readNameFile(connectionPath);
+ return connectionName;
+ }
+ String imageName = readNameFile(path);
+ return imageName;
+ }
+
+ /**
+ * @see org.eclipse.jface.viewers.IBaseLabelProvider#addListener(ILabelProviderListener)
+ */
+ @Override
+ public void addListener(ILabelProviderListener listener) {
+ }
+
+ /**
+ * @see org.eclipse.jface.viewers.IBaseLabelProvider#isLabelProperty(Object,
+ * String)
+ */
+ @Override
+ public boolean isLabelProperty(Object element, String property) {
+ return false;
+ }
+
+ /**
+ * @see org.eclipse.jface.viewers.IBaseLabelProvider#removeListener(ILabelProviderListener)
+ */
+ @Override
+ public void removeListener(ILabelProviderListener listener) {
+ }
+
+ }
+
+ public DockerHeaderPreferencePage() {
+ noDefaultAndApplyButton();
+ provider = new HeaderContentProvider();
+ }
+
+ @Override
+ public void init(IWorkbench workbench) {
+ directories = new ArrayList<>();
+ IPath pluginPath = Platform
+ .getStateLocation(
+ Platform.getBundle(DockerLaunchUIPlugin.PLUGIN_ID))
+ .append("HEADERS"); //$NON-NLS-1$
+ File d = pluginPath.toFile();
+
+ if (d.exists() && d.isDirectory()) {
+ File[] connections = d.listFiles();
+ for (File connection : connections) {
+ if (connection.isDirectory()) {
+ File[] images = connection.listFiles();
+ for (File image : images) {
+ if (image.isDirectory()) {
+ directories
+ .add(pluginPath.append(connection.getName())
+ .append(image.getName()));
+ }
+ }
+ }
+ }
+ }
+ }
+
+ @Override
+ protected Control createContents(Composite parent) {
+ Composite page = createComposite(parent, 1, 2, false, null, -1, -1,
+ GridData.FILL);
+ GridData gd = (GridData) page.getLayoutData();
+ gd.grabExcessHorizontalSpace = true;
+ gd.grabExcessVerticalSpace = true;
+
+ // SystemWidgetHelpers.createLabel(page,
+ // SystemResources.RESID_PREF_SIGNON_DESCRIPTION, 2);
+
+ // Header table
+ hdrTable = new Table(page, SWT.FULL_SELECTION | SWT.MULTI | SWT.V_SCROLL
+ | SWT.H_SCROLL | SWT.BORDER);
+ hdrTable.setLinesVisible(true);
+ hdrTable.setHeaderVisible(true);
+ hdrTable.addListener(SWT.Selection, this);
+
+ TableLayout tableLayout = new TableLayout();
+ tableLayout.addColumnData(new ColumnWeightData(60, true));
+ tableLayout.addColumnData(new ColumnWeightData(40, true));
+ hdrTable.setLayout(tableLayout);
+
+ gd = new GridData(GridData.FILL_BOTH);
+ gd.grabExcessHorizontalSpace = true;
+ gd.grabExcessVerticalSpace = true;
+
+ hdrTable.setLayoutData(gd);
+
+ // Connection column
+ TableColumn connectionColumn = new TableColumn(hdrTable, SWT.NONE);
+ connectionColumn
+ .setText(Messages.HeaderPreferencePage_Connection_Label);
+
+ // Image column
+ TableColumn imageColumn = new TableColumn(hdrTable, SWT.NONE);
+ imageColumn.setText(Messages.HeaderPreferencePage_Image_Label);
+
+ hdrTableViewer = new TableViewer(hdrTable);
+ hdrTableViewer.setContentProvider(provider);
+ hdrTableViewer.setLabelProvider(provider);
+ hdrTableViewer.setInput(directories);
+
+ // Create the Button bar for add, change and remove
+ Composite buttonBar = createComposite(page, 1, 1, false, null, -1, -1,
+ GridData.FILL);
+ gd = (GridData) buttonBar.getLayoutData();
+ gd.grabExcessHorizontalSpace = false;
+ gd.grabExcessVerticalSpace = true;
+
+ removeButton = createPushButton(buttonBar, this,
+ Messages.HeaderPreferencePage_Remove_Label,
+ Messages.HeaderPreferencePage_Remove_Tooltip);
+
+ removeButton.setEnabled(false);
+ return parent;
+ }
+
+ private static Composite createComposite(Composite parent, int parentSpan,
+ int numColumns, boolean border, String label, int marginSize,
+ int spacingSize, int verticalAlignment) {
+ // border = true;
+ boolean borderNeeded = border;
+ if (label != null)
+ borderNeeded = true; // force the case
+ int style = SWT.NULL;
+ if (borderNeeded)
+ style |= SWT.SHADOW_ETCHED_IN;
+ Composite composite = null;
+ if (borderNeeded) {
+ composite = new Group(parent, style);
+ if (label != null)
+ ((Group) composite).setText(label);
+ } else {
+ composite = new Composite(parent, style);
+ }
+ // GridLayout
+ GridLayout layout = new GridLayout();
+ layout.numColumns = numColumns;
+ if (marginSize != -1) {
+ layout.marginWidth = 0;
+ layout.marginHeight = 0;
+ }
+ if (spacingSize != -1) {
+ layout.horizontalSpacing = 0;
+ layout.verticalSpacing = 0;
+ }
+ composite.setLayout(layout);
+ // GridData
+ GridData data = new GridData();
+ data.horizontalSpan = parentSpan;
+ data.horizontalAlignment = GridData.FILL;
+ data.grabExcessHorizontalSpace = true;
+
+ data.verticalAlignment = verticalAlignment;
+ data.grabExcessVerticalSpace = false;
+
+ composite.setLayoutData(data);
+ return composite;
+ }
+
+ public static Button createPushButton(Composite group, Listener listener,
+ String label, String tooltip) {
+ Button button = new Button(group, SWT.PUSH);
+ button.setText(label);
+ if (listener != null)
+ button.addListener(SWT.Selection, listener);
+ GridData data = new GridData();
+ data.horizontalAlignment = GridData.FILL;
+ data.grabExcessHorizontalSpace = true;
+ button.setLayoutData(data);
+ if (tooltip != null)
+ button.setToolTipText(tooltip);
+ return button;
+ }
+
+ private class DialogStatus {
+ private boolean status;
+
+ public DialogStatus(boolean status) {
+ this.status = status;
+ }
+
+ public void setStatus(boolean status) {
+ this.status = status;
+ }
+
+ public boolean getStatus() {
+ return status;
+ }
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets.Listener#handleEvent(Event)
+ */
+ @Override
+ public void handleEvent(Event event) {
+ if (event.type == SWT.Selection) {
+ if (event.widget == removeButton) {
+ final DialogStatus confirmed = new DialogStatus(false);
+ Display.getDefault().syncExec(() -> {
+ boolean status = MessageDialog.openConfirm(getShell(),
+ Messages.HeaderPreferencePage_Confirm_Removal_Title,
+ Messages.HeaderPreferencePage_Confirm_Removal_Msg);
+ confirmed.setStatus(status);
+ });
+ if (!confirmed.getStatus()) {
+ return;
+ }
+ int[] indicies = hdrTable.getSelectionIndices();
+ for (int idx = indicies.length - 1; idx >= 0; idx--) {
+ IPath dirPath = directories.get(idx);
+ File f = dirPath.toFile();
+ if (f.exists() && f.isDirectory()) {
+ recursiveDelete(f);
+ }
+ directories.remove(idx);
+ }
+
+ hdrTableViewer.refresh();
+ }
+
+ // Update table buttons based on changes
+ if (hdrTable.getSelectionCount() > 0) {
+ removeButton.setEnabled(true);
+ } else {
+ removeButton.setEnabled(false);
+ }
+ }
+ }
+
+ private void recursiveDelete(File dir) {
+ File[] contents = dir.listFiles();
+ if (contents != null) {
+ for (File f : contents) {
+ recursiveDelete(f);
+ }
+ }
+ dir.delete();
+ }
+}
+
diff --git a/remote/org.eclipse.cdt.remote.core/src/org/eclipse/cdt/remote/core/RemoteCommandLauncher.java b/remote/org.eclipse.cdt.remote.core/src/org/eclipse/cdt/remote/core/RemoteCommandLauncher.java
index 8554685440..da2ee6f03f 100644
--- a/remote/org.eclipse.cdt.remote.core/src/org/eclipse/cdt/remote/core/RemoteCommandLauncher.java
+++ b/remote/org.eclipse.cdt.remote.core/src/org/eclipse/cdt/remote/core/RemoteCommandLauncher.java
@@ -17,7 +17,7 @@ import java.net.URI;
import java.util.Map;
import java.util.Properties;
-import org.eclipse.cdt.core.CommandLauncher;
+import org.eclipse.cdt.core.CommandLauncherManager;
import org.eclipse.cdt.core.ICommandLauncher;
import org.eclipse.cdt.remote.internal.core.Activator;
import org.eclipse.cdt.remote.internal.core.messages.Messages;
@@ -40,6 +40,8 @@ import org.eclipse.remote.core.RemoteProcessAdapter;
public class RemoteCommandLauncher implements ICommandLauncher {
private static final String CYGWIN_PREFIX = "cygdrive"; //$NON-NLS-1$
+
+ private boolean usingLocalLauncher = false;
/**
* Convert a local (workspace) path into the remote equivalent. If the local path is not
@@ -102,7 +104,7 @@ public class RemoteCommandLauncher implements ICommandLauncher {
return s;
}
- private final ICommandLauncher fLocalLauncher = new CommandLauncher();
+ private ICommandLauncher fLocalLauncher = CommandLauncherManager.getInstance().getCommandLauncher();
private boolean fShowCommand;
private String[] fCommandArgs;
private IRemoteConnection fConnection;
@@ -129,13 +131,18 @@ public class RemoteCommandLauncher implements ICommandLauncher {
@Override
public Process execute(IPath commandPath, String[] args, String[] env, IPath workingDirectory, IProgressMonitor monitor)
throws CoreException {
+ ICommandLauncher localLauncher = CommandLauncherManager.getInstance().getCommandLauncher(getProject());
+ localLauncher.setProject(getProject());
+ localLauncher.setErrorMessage(getErrorMessage());
+ usingLocalLauncher = false;
+ fLocalLauncher = localLauncher;
if (getProject() != null) {
IRemoteResource remRes = (IRemoteResource) getProject().getAdapter(IRemoteResource.class);
if (remRes != null) {
URI uri = remRes.getActiveLocationURI();
IRemoteServicesManager remoteServicesManager = Activator.getService(IRemoteServicesManager.class);
IRemoteConnectionType connectionType = remoteServicesManager.getConnectionType(uri);
- if (connectionType != null) {
+ if (connectionType != null && !connectionType.getScheme().equals("file")) { //$NON-NLS-1$
fConnection = connectionType.getConnection(uri);
if (fConnection != null) {
parseEnvironment(env);
@@ -163,16 +170,23 @@ public class RemoteCommandLauncher implements ICommandLauncher {
}
}
}
+ usingLocalLauncher = true;
return fLocalLauncher.execute(commandPath, args, env, workingDirectory, monitor);
}
@Override
public String[] getCommandArgs() {
+ if (usingLocalLauncher) {
+ return fLocalLauncher.getCommandArgs();
+ }
return fCommandArgs;
}
@Override
public String getCommandLine() {
+ if (usingLocalLauncher) {
+ return fLocalLauncher.getCommandLine();
+ }
return getCommandLine(fCommandArgs);
}
@@ -202,6 +216,9 @@ public class RemoteCommandLauncher implements ICommandLauncher {
@Override
public Properties getEnvironment() {
+ if (usingLocalLauncher) {
+ return fLocalLauncher.getEnvironment();
+ }
return fEnvironment;
}
@@ -261,8 +278,15 @@ public class RemoteCommandLauncher implements ICommandLauncher {
fShowCommand = show;
}
+ @SuppressWarnings("deprecation")
@Override
public int waitAndRead(OutputStream out, OutputStream err) {
+
+ if (usingLocalLauncher) {
+ return fLocalLauncher.waitAndRead(out, err);
+ }
+
+ // otherwise remote process
if (fShowCommand) {
printCommandLine(out);
}
@@ -278,6 +302,11 @@ public class RemoteCommandLauncher implements ICommandLauncher {
@Override
public int waitAndRead(OutputStream out, OutputStream err, IProgressMonitor monitor) {
+ if (usingLocalLauncher) {
+ return fLocalLauncher.waitAndRead(out, err, monitor);
+ }
+
+ // otherwise remote process
if (fShowCommand) {
printCommandLine(out);
}

Back to the top