1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-06-06 17:26:01 +02:00

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
This commit is contained in:
Jeff Johnston 2017-02-09 18:43:05 -05:00
parent 4c1a6e0ccd
commit c96d126b86
67 changed files with 4543 additions and 66 deletions

View file

@ -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[] =

View file

@ -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();

View file

@ -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()))

View file

@ -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();

View file

@ -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();
}

View file

@ -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.

View file

@ -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$

View file

@ -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$

View file

@ -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();
}

View file

@ -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$

View file

@ -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() {

View file

@ -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);
}
}
}

View file

@ -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;
}

View file

@ -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());
@ -626,6 +635,10 @@ public class Configuration extends BuildObject implements IConfiguration, IBuild
this.buildProperties = new BuildObjectProperties(cloneConfig.buildProperties, this, this);
}
if (cloneConfig.optionalBuildProperties != null) {
this.optionalBuildProperties = new OptionalBuildProperties(cloneConfig.optionalBuildProperties);
}
this.description = cloneConfig.getDescription();
// set managedBuildRevision
@ -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){
@ -2408,6 +2441,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());
}

View file

@ -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
@ -192,6 +194,10 @@ public class ManagedProject extends BuildObject implements IManagedProject, IBui
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){
if(buildProperties == 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();

View file

@ -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) {

View file

@ -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();
}
}

View file

@ -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
@ -707,6 +709,28 @@ public class ProjectType extends BuildObject implements IProjectType, IBuildProp
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;
}
OptionalBuildProperties findOptionalBuildProperties(){
if(optionalBuildProperties == null){
if(superClass != null){
return ((ProjectType)superClass).findOptionalBuildProperties();
}
return null;
}
return optionalBuildProperties;
}
@Override
public void propertiesChanged() {
List<Configuration> list = getConfigurationList();

View file

@ -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);
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);
}

View file

@ -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);
}
}

View file

@ -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; }

View file

@ -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() {

View file

@ -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));

View file

@ -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

View file

@ -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);
}
}
/**
@ -168,6 +172,10 @@ public class LanguageSettingsSerializableProvider extends LanguageSettingsBasePr
}
}
if (cfgDescription != null) {
entries = CommandLauncherManager.getInstance().getLanguageSettingEntries(cfgDescription.getProjectDescription().getProject(), entries);
}
return entries;
}

View file

@ -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;

View file

@ -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">

View file

@ -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>

View file

@ -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$

View file

@ -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;
}
}

View file

@ -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);
}

View file

@ -217,14 +217,18 @@ public class ProcessClosure {
fProcess.destroy();
fProcess = null;
}
if (fOutputReader != null) {
if (!fOutputReader.finished()) {
fOutputReader.waitFor();
}
fOutputReader.close();
}
if (fErrorReader != null) {
if (!fErrorReader.finished()) {
fErrorReader.waitFor();
}
fOutputReader.close();
fErrorReader.close();
}
fOutputReader = null;
fErrorReader = null;
}

View file

@ -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);

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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,

Binary file not shown.

After

Width:  |  Height:  |  Size: 339 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 349 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 219 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 337 B

View file

@ -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

View file

@ -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>

View file

@ -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$
}
}

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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);
}
}
}

View file

@ -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(

View file

@ -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);
}
}

View file

@ -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]);

View file

@ -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;
}
}

View file

@ -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,10 +295,20 @@ public class LaunchShortcut implements ILaunchShortcut {
if (projectName != null
&& projectName.equals(bin.getCProject()
.getProject().getName())) {
// 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);
}
}
}
}
}
} catch (CoreException e) {
DockerLaunchUIPlugin.log(e);
}
@ -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)

View file

@ -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);

View file

@ -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);

View file

@ -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:

View file

@ -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();
}
}

View file

@ -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;
@ -41,6 +41,8 @@ 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
* absolute, then do nothing.
@ -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);
}