mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-21 21:52:10 +02:00
Bug 540423 - C/C++ Container Launcher missing Port Binding
- add new ContainerPortDialog class to allow user to specify ports in the launch configuration Container tab - add new ContainerTabModel and ExposedPortModel classes to support new functionality - add new Ports group to ContainerTab and have a table where a user can add, edit, remove, and select ports for publishing to the host - add new attribute ATTR_EXPOSED_PORTS to ILaunchConstants for saving and restoring user selected ports in C launch configuration - add needed internal messages to support new port settings functionality - bump up org.eclipse.cdt.docker.launcher version Change-Id: I93b7503bdc141e3077418800352507ef38e65ab1
This commit is contained in:
parent
f9c8f0da02
commit
331be6c45c
8 changed files with 917 additions and 6 deletions
|
@ -15,7 +15,7 @@ import java.net.NetworkInterface;
|
||||||
import java.net.SocketException;
|
import java.net.SocketException;
|
||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -223,6 +223,39 @@ public class ContainerLaunchConfigurationDelegate extends GdbLaunchDelegate
|
||||||
}
|
}
|
||||||
additionalDirs = dirs;
|
additionalDirs = dirs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<String> ports = new ArrayList<>();
|
||||||
|
List<String> portInfos = configuration.getAttribute(
|
||||||
|
ILaunchConstants.ATTR_EXPOSED_PORTS,
|
||||||
|
Collections.emptyList());
|
||||||
|
for (String portInfo : portInfos) {
|
||||||
|
ExposedPortModel m = ExposedPortModel
|
||||||
|
.createPortModel(portInfo);
|
||||||
|
if (m.getSelected()) {
|
||||||
|
StringBuilder b1 = new StringBuilder();
|
||||||
|
if (m.getHostAddress() != null
|
||||||
|
&& !m.getHostAddress().isEmpty()) {
|
||||||
|
b1.append(m.getHostAddress());
|
||||||
|
b1.append(":"); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
if (m.getHostPort() != null
|
||||||
|
&& !m.getHostPort().isEmpty()) {
|
||||||
|
b1.append(m.getHostPort());
|
||||||
|
}
|
||||||
|
// regardless if we have a host port or not,
|
||||||
|
// we may need to add a separator so we can determine
|
||||||
|
// the case where we don't have a host port vs where we
|
||||||
|
// don't have a host address
|
||||||
|
if (b1.length() > 0) {
|
||||||
|
b1.append(":"); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
String containerPort = m.getContainerPort() + "/" //$NON-NLS-1$
|
||||||
|
+ m.getPortType();
|
||||||
|
b1.append(containerPort);
|
||||||
|
ports.add(b1.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
String image = configuration.getAttribute(
|
String image = configuration.getAttribute(
|
||||||
ILaunchConstants.ATTR_IMAGE, (String) null);
|
ILaunchConstants.ATTR_IMAGE, (String) null);
|
||||||
String connectionUri = configuration.getAttribute(
|
String connectionUri = configuration.getAttribute(
|
||||||
|
@ -240,14 +273,49 @@ public class ContainerLaunchConfigurationDelegate extends GdbLaunchDelegate
|
||||||
connectionUri,
|
connectionUri,
|
||||||
image, command,
|
image, command,
|
||||||
commandDir, workingDir, additionalDirs, origEnv,
|
commandDir, workingDir, additionalDirs, origEnv,
|
||||||
envMap, null, keepContainer, supportStdin,
|
envMap, ports.isEmpty() ? null : ports, keepContainer,
|
||||||
|
supportStdin,
|
||||||
privilegedMode, labels);
|
privilegedMode, labels);
|
||||||
} else if (mode.equals(ILaunchManager.DEBUG_MODE)) {
|
} else if (mode.equals(ILaunchManager.DEBUG_MODE)) {
|
||||||
String gdbserverPortNumber = configuration.getAttribute(
|
String gdbserverPortNumber = configuration.getAttribute(
|
||||||
ILaunchConstants.ATTR_GDBSERVER_PORT,
|
ILaunchConstants.ATTR_GDBSERVER_PORT,
|
||||||
ILaunchConstants.ATTR_GDBSERVER_PORT_DEFAULT);
|
ILaunchConstants.ATTR_GDBSERVER_PORT_DEFAULT);
|
||||||
List<String> ports = Arrays
|
|
||||||
.asList(gdbserverPortNumber + "/tcp"); //$NON-NLS-1$
|
List<String> ports = new ArrayList<>();
|
||||||
|
List<String> portInfos = configuration.getAttribute(
|
||||||
|
ILaunchConstants.ATTR_EXPOSED_PORTS, Collections.emptyList());
|
||||||
|
String gdbserverPort = gdbserverPortNumber + "/tcp"; //$NON-NLS-1$
|
||||||
|
boolean gdbserverPortSpecified = false;
|
||||||
|
for (String portInfo : portInfos) {
|
||||||
|
ExposedPortModel m = ExposedPortModel.createPortModel(portInfo);
|
||||||
|
if (m.getSelected()) {
|
||||||
|
StringBuilder b = new StringBuilder();
|
||||||
|
if (m.getHostAddress() != null && !m.getHostAddress().isEmpty()) {
|
||||||
|
b.append(m.getHostAddress());
|
||||||
|
b.append(":"); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
if (m.getHostPort() != null && !m.getHostPort().isEmpty()) {
|
||||||
|
b.append(m.getHostPort());
|
||||||
|
}
|
||||||
|
// regardless if we have a host port or not,
|
||||||
|
// we may need to add a separator so we can determine
|
||||||
|
// the case where we don't have a host port vs where we
|
||||||
|
// don't have a host address
|
||||||
|
if (b.length() > 0) {
|
||||||
|
b.append(":"); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
String containerPort = m.getContainerPort() + "/" + m.getPortType(); //$NON-NLS-1$
|
||||||
|
b.append(containerPort);
|
||||||
|
if (gdbserverPort.equals(containerPort)) {
|
||||||
|
gdbserverPortSpecified = true;
|
||||||
|
}
|
||||||
|
ports.add(b.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// if user hasn't already specified gdbserver port, we need to add it by default
|
||||||
|
if (!gdbserverPortSpecified) {
|
||||||
|
ports.add(gdbserverPortNumber + "/tcp"); //$NON-NLS-1$
|
||||||
|
}
|
||||||
String gdbserverCommand = configuration.getAttribute(
|
String gdbserverCommand = configuration.getAttribute(
|
||||||
ILaunchConstants.ATTR_GDBSERVER_COMMAND,
|
ILaunchConstants.ATTR_GDBSERVER_COMMAND,
|
||||||
ILaunchConstants.ATTR_GDBSERVER_COMMAND_DEFAULT);
|
ILaunchConstants.ATTR_GDBSERVER_COMMAND_DEFAULT);
|
||||||
|
|
|
@ -0,0 +1,230 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2015, 2018 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 org.eclipse.core.databinding.DataBindingContext;
|
||||||
|
import org.eclipse.core.databinding.beans.BeanProperties;
|
||||||
|
import org.eclipse.core.databinding.observable.value.IValueChangeListener;
|
||||||
|
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.layout.GridDataFactory;
|
||||||
|
import org.eclipse.jface.layout.GridLayoutFactory;
|
||||||
|
import org.eclipse.swt.SWT;
|
||||||
|
import org.eclipse.swt.graphics.Point;
|
||||||
|
import org.eclipse.swt.widgets.Button;
|
||||||
|
import org.eclipse.swt.widgets.Composite;
|
||||||
|
import org.eclipse.swt.widgets.Control;
|
||||||
|
import org.eclipse.swt.widgets.Label;
|
||||||
|
import org.eclipse.swt.widgets.Shell;
|
||||||
|
import org.eclipse.swt.widgets.Text;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author xcoulon
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class ContainerPortDialog extends Dialog {
|
||||||
|
|
||||||
|
private static final String PORT_TYPE = "tcp"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
private final ContainerPortDialogModel model;
|
||||||
|
|
||||||
|
private final DataBindingContext dbc = new DataBindingContext();
|
||||||
|
|
||||||
|
public ContainerPortDialog(final Shell parentShell) {
|
||||||
|
super(parentShell);
|
||||||
|
this.model = new ContainerPortDialogModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ContainerPortDialog(final Shell parentShell,
|
||||||
|
final ExposedPortModel selectedContainerPort) {
|
||||||
|
super(parentShell);
|
||||||
|
this.model = new ContainerPortDialogModel(
|
||||||
|
selectedContainerPort.getContainerPort(),
|
||||||
|
selectedContainerPort.getHostAddress(),
|
||||||
|
selectedContainerPort.getHostPort());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void configureShell(final Shell shell) {
|
||||||
|
super.configureShell(shell);
|
||||||
|
setShellStyle(getShellStyle() | SWT.RESIZE);
|
||||||
|
shell.setText(Messages.ContainerPortDialog_shellTitle);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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(400, super.getInitialSize().y);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Override
|
||||||
|
protected Control createDialogArea(Composite parent) {
|
||||||
|
final int COLUMNS = 2;
|
||||||
|
final Composite container = new Composite(parent, SWT.NONE);
|
||||||
|
GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL)
|
||||||
|
.span(COLUMNS, 1).grab(true, true).applyTo(container);
|
||||||
|
GridLayoutFactory.fillDefaults().numColumns(COLUMNS).margins(10, 10)
|
||||||
|
.applyTo(container);
|
||||||
|
final Label explanationLabel = new Label(container, SWT.NONE);
|
||||||
|
explanationLabel.setText(Messages.ContainerPortDialog_explanationLabel);
|
||||||
|
GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER)
|
||||||
|
.span(COLUMNS, 1).grab(false, false).applyTo(explanationLabel);
|
||||||
|
final Label containerLabel = new Label(container, SWT.NONE);
|
||||||
|
containerLabel.setText(Messages.ContainerPortDialog_containerLabel);
|
||||||
|
GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER)
|
||||||
|
.grab(false, false).applyTo(containerLabel);
|
||||||
|
final Text containerPortText = new Text(container, SWT.BORDER);
|
||||||
|
GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER)
|
||||||
|
.grab(true, false).applyTo(containerPortText);
|
||||||
|
final Label hostAddressLabel = new Label(container, SWT.NONE);
|
||||||
|
hostAddressLabel.setText(Messages.ContainerPortDialog_hostAddressLabel);
|
||||||
|
GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER)
|
||||||
|
.grab(false, false).applyTo(hostAddressLabel);
|
||||||
|
final Text hostAddressText = new Text(container, SWT.BORDER);
|
||||||
|
GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER)
|
||||||
|
.grab(true, false).applyTo(hostAddressText);
|
||||||
|
final Label hostPortLabel = new Label(container, SWT.NONE);
|
||||||
|
hostPortLabel.setText(
|
||||||
|
Messages.ContainerPortDialog_hostPortLabel);
|
||||||
|
GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER)
|
||||||
|
.grab(false, false).applyTo(hostPortLabel);
|
||||||
|
final Text hostPortText = new Text(container, SWT.BORDER);
|
||||||
|
GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER)
|
||||||
|
.grab(true, false).applyTo(hostPortText);
|
||||||
|
// error message
|
||||||
|
final Label errorMessageLabel = new Label(container, SWT.NONE);
|
||||||
|
GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER)
|
||||||
|
.span(COLUMNS, 1).grab(true, false).applyTo(errorMessageLabel);
|
||||||
|
|
||||||
|
// listening to changes
|
||||||
|
final ISWTObservableValue containerPortObservable = WidgetProperties
|
||||||
|
.text(SWT.Modify).observe(containerPortText);
|
||||||
|
dbc.bindValue(containerPortObservable,
|
||||||
|
BeanProperties
|
||||||
|
.value(ContainerPortDialogModel.class,
|
||||||
|
ContainerPortDialogModel.CONTAINER_PORT)
|
||||||
|
.observe(model));
|
||||||
|
final ISWTObservableValue hostAddressObservable = WidgetProperties
|
||||||
|
.text(SWT.Modify).observe(hostAddressText);
|
||||||
|
dbc.bindValue(hostAddressObservable,
|
||||||
|
BeanProperties
|
||||||
|
.value(ContainerPortDialogModel.class,
|
||||||
|
ContainerPortDialogModel.HOST_ADDRESS)
|
||||||
|
.observe(model));
|
||||||
|
final ISWTObservableValue hostPortObservable = WidgetProperties
|
||||||
|
.text(SWT.Modify).observe(hostPortText);
|
||||||
|
dbc.bindValue(hostPortObservable,
|
||||||
|
BeanProperties
|
||||||
|
.value(ContainerPortDialogModel.class,
|
||||||
|
ContainerPortDialogModel.HOST_PORT)
|
||||||
|
.observe(model));
|
||||||
|
|
||||||
|
containerPortObservable.addValueChangeListener(
|
||||||
|
onContainerPortSettingsChanged());
|
||||||
|
hostPortObservable.addValueChangeListener(
|
||||||
|
onContainerPortSettingsChanged());
|
||||||
|
hostAddressObservable.addValueChangeListener(
|
||||||
|
onContainerPortSettingsChanged());
|
||||||
|
return container;
|
||||||
|
}
|
||||||
|
|
||||||
|
private IValueChangeListener<?> onContainerPortSettingsChanged() {
|
||||||
|
return event -> validateInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void validateInput() {
|
||||||
|
final String containerPort = model.getContainerPort();
|
||||||
|
if (containerPort == null || containerPort.isEmpty()) {
|
||||||
|
setOkButtonEnabled(false);
|
||||||
|
} else {
|
||||||
|
setOkButtonEnabled(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setOkButtonEnabled(final boolean enabled) {
|
||||||
|
getButton(IDialogConstants.OK_ID).setEnabled(enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExposedPortModel getPort() {
|
||||||
|
return new ExposedPortModel(model.getContainerPort(), PORT_TYPE,
|
||||||
|
model.getHostAddress(), model.getHostPort());
|
||||||
|
}
|
||||||
|
|
||||||
|
class ContainerPortDialogModel extends BaseDatabindingModel {
|
||||||
|
|
||||||
|
public static final String CONTAINER_PORT = "containerPort"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
public static final String HOST_ADDRESS = "hostAddress"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
public static final String HOST_PORT = "hostPort"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
private String containerPort;
|
||||||
|
|
||||||
|
private String hostAddress;
|
||||||
|
|
||||||
|
private String hostPort;
|
||||||
|
|
||||||
|
public ContainerPortDialogModel() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public ContainerPortDialogModel(final String containerPort,
|
||||||
|
final String hostAddress, final String hostPort) {
|
||||||
|
this.containerPort = containerPort;
|
||||||
|
this.hostAddress = hostAddress;
|
||||||
|
this.hostPort = hostPort;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getContainerPort() {
|
||||||
|
return containerPort;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContainerPort(final String containerPort) {
|
||||||
|
firePropertyChange(CONTAINER_PORT, this.containerPort,
|
||||||
|
this.containerPort = containerPort);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getHostAddress() {
|
||||||
|
return hostAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHostAddress(final String hostName) {
|
||||||
|
firePropertyChange(HOST_ADDRESS, this.hostAddress,
|
||||||
|
this.hostAddress = hostName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getHostPort() {
|
||||||
|
return hostPort;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHostPort(final String hostPort) {
|
||||||
|
firePropertyChange(HOST_PORT, this.hostPort,
|
||||||
|
this.hostPort = hostPort);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -12,13 +12,31 @@ package org.eclipse.cdt.internal.docker.launcher;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
import org.eclipse.cdt.docker.launcher.DockerLaunchUIPlugin;
|
import org.eclipse.cdt.docker.launcher.DockerLaunchUIPlugin;
|
||||||
|
import org.eclipse.core.databinding.DataBindingContext;
|
||||||
|
import org.eclipse.core.databinding.beans.BeanProperties;
|
||||||
import org.eclipse.core.runtime.CoreException;
|
import org.eclipse.core.runtime.CoreException;
|
||||||
import org.eclipse.core.runtime.preferences.InstanceScope;
|
import org.eclipse.core.runtime.preferences.InstanceScope;
|
||||||
import org.eclipse.debug.core.ILaunchConfiguration;
|
import org.eclipse.debug.core.ILaunchConfiguration;
|
||||||
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
|
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
|
||||||
import org.eclipse.debug.ui.AbstractLaunchConfigurationTab;
|
import org.eclipse.debug.ui.AbstractLaunchConfigurationTab;
|
||||||
|
import org.eclipse.jface.databinding.viewers.ObservableListContentProvider;
|
||||||
|
import org.eclipse.jface.databinding.viewers.ViewerSupport;
|
||||||
|
import org.eclipse.jface.databinding.viewers.ViewersObservables;
|
||||||
|
import org.eclipse.jface.dialogs.IDialogConstants;
|
||||||
|
import org.eclipse.jface.layout.GridDataFactory;
|
||||||
|
import org.eclipse.jface.layout.GridLayoutFactory;
|
||||||
|
import org.eclipse.jface.viewers.CheckStateChangedEvent;
|
||||||
|
import org.eclipse.jface.viewers.CheckboxTableViewer;
|
||||||
|
import org.eclipse.jface.viewers.ICheckStateListener;
|
||||||
|
import org.eclipse.jface.viewers.ISelectionChangedListener;
|
||||||
|
import org.eclipse.jface.viewers.IStructuredSelection;
|
||||||
|
import org.eclipse.jface.viewers.TableViewer;
|
||||||
|
import org.eclipse.jface.viewers.TableViewerColumn;
|
||||||
import org.eclipse.linuxtools.docker.core.DockerConnectionManager;
|
import org.eclipse.linuxtools.docker.core.DockerConnectionManager;
|
||||||
import org.eclipse.linuxtools.docker.core.IDockerConnection;
|
import org.eclipse.linuxtools.docker.core.IDockerConnection;
|
||||||
import org.eclipse.linuxtools.docker.core.IDockerConnectionManagerListener;
|
import org.eclipse.linuxtools.docker.core.IDockerConnectionManagerListener;
|
||||||
|
@ -47,6 +65,8 @@ import org.eclipse.swt.widgets.Display;
|
||||||
import org.eclipse.swt.widgets.Group;
|
import org.eclipse.swt.widgets.Group;
|
||||||
import org.eclipse.swt.widgets.Label;
|
import org.eclipse.swt.widgets.Label;
|
||||||
import org.eclipse.swt.widgets.List;
|
import org.eclipse.swt.widgets.List;
|
||||||
|
import org.eclipse.swt.widgets.Table;
|
||||||
|
import org.eclipse.swt.widgets.TableColumn;
|
||||||
import org.osgi.service.prefs.Preferences;
|
import org.osgi.service.prefs.Preferences;
|
||||||
|
|
||||||
public class ContainerTab extends AbstractLaunchConfigurationTab implements
|
public class ContainerTab extends AbstractLaunchConfigurationTab implements
|
||||||
|
@ -65,12 +85,21 @@ public class ContainerTab extends AbstractLaunchConfigurationTab implements
|
||||||
|
|
||||||
private Button newButton;
|
private Button newButton;
|
||||||
private Button removeButton;
|
private Button removeButton;
|
||||||
|
|
||||||
|
private CheckboxTableViewer tableViewer;
|
||||||
|
|
||||||
private Button keepButton;
|
private Button keepButton;
|
||||||
private Button stdinButton;
|
private Button stdinButton;
|
||||||
private Button privilegedButton;
|
private Button privilegedButton;
|
||||||
private Combo imageCombo;
|
private Combo imageCombo;
|
||||||
private Combo connectionSelector;
|
private Combo connectionSelector;
|
||||||
|
|
||||||
|
private ContainerTabModel model;
|
||||||
|
|
||||||
|
private static final int INDENT = 1;
|
||||||
|
|
||||||
|
private final DataBindingContext dbc = new DataBindingContext();
|
||||||
|
|
||||||
private ModifyListener connectionModifyListener = new ModifyListener() {
|
private ModifyListener connectionModifyListener = new ModifyListener() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -92,6 +121,7 @@ public class ContainerTab extends AbstractLaunchConfigurationTab implements
|
||||||
public ContainerTab() {
|
public ContainerTab() {
|
||||||
super();
|
super();
|
||||||
containerTab = this;
|
containerTab = this;
|
||||||
|
model = new ContainerTabModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -146,6 +176,7 @@ public class ContainerTab extends AbstractLaunchConfigurationTab implements
|
||||||
|
|
||||||
createDirectoryList(mainComposite);
|
createDirectoryList(mainComposite);
|
||||||
createButtons(mainComposite);
|
createButtons(mainComposite);
|
||||||
|
createPortSettingsSection(mainComposite);
|
||||||
createOptions(mainComposite);
|
createOptions(mainComposite);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -214,6 +245,205 @@ public class ContainerTab extends AbstractLaunchConfigurationTab implements
|
||||||
removeButton.setEnabled(false);
|
removeButton.setEnabled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private void createPortSettingsSection(final Composite parent) {
|
||||||
|
Font font = parent.getFont();
|
||||||
|
Composite comp = createComposite(parent, 1, 2, GridData.FILL_BOTH);
|
||||||
|
|
||||||
|
Group group = new Group(comp, SWT.NONE);
|
||||||
|
group.setFont(font);
|
||||||
|
group.setText(Messages.ContainerTab_Ports_Group_Name);
|
||||||
|
|
||||||
|
GridData gd2 = new GridData(GridData.FILL_BOTH);
|
||||||
|
group.setLayoutData(gd2);
|
||||||
|
|
||||||
|
group.setLayout(new GridLayout());
|
||||||
|
|
||||||
|
GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER).span(3, 1)
|
||||||
|
.grab(true, false).applyTo(group);
|
||||||
|
|
||||||
|
group.setLayout(new GridLayout());
|
||||||
|
// specify ports
|
||||||
|
final Label portSettingsLabel = new Label(group, SWT.NONE);
|
||||||
|
portSettingsLabel.setText(Messages.ContainerTab_Specify_Ports_Label);
|
||||||
|
GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER)
|
||||||
|
.grab(true, false).span(3, 1)
|
||||||
|
.applyTo(portSettingsLabel);
|
||||||
|
final CheckboxTableViewer exposedPortsTableViewer = createPortSettingsTable(
|
||||||
|
group);
|
||||||
|
tableViewer = exposedPortsTableViewer;
|
||||||
|
GridDataFactory.fillDefaults().align(SWT.FILL, SWT.TOP)
|
||||||
|
.grab(true, false).span(3 - 1, 1).indent(INDENT, 0)
|
||||||
|
.hint(200, 70).applyTo(exposedPortsTableViewer.getTable());
|
||||||
|
// buttons
|
||||||
|
final Composite buttonsContainers = new Composite(parent, SWT.NONE);
|
||||||
|
GridDataFactory.fillDefaults().align(SWT.FILL, SWT.TOP)
|
||||||
|
.grab(false, false).applyTo(buttonsContainers);
|
||||||
|
GridLayoutFactory.fillDefaults().numColumns(1).margins(0, 0)
|
||||||
|
.spacing(SWT.DEFAULT, 0).applyTo(buttonsContainers);
|
||||||
|
|
||||||
|
final Button addButton = new Button(buttonsContainers, SWT.NONE);
|
||||||
|
GridDataFactory.fillDefaults().align(SWT.FILL, SWT.TOP)
|
||||||
|
.grab(true, false).applyTo(addButton);
|
||||||
|
addButton.setText(Messages.ContainerTab_Add_Button);
|
||||||
|
addButton.addSelectionListener(onAddPort(exposedPortsTableViewer));
|
||||||
|
final Button editButton = new Button(buttonsContainers, SWT.NONE);
|
||||||
|
GridDataFactory.fillDefaults().align(SWT.FILL, SWT.TOP)
|
||||||
|
.grab(true, false).applyTo(editButton);
|
||||||
|
editButton.setText(Messages.ContainerTab_Edit_Button);
|
||||||
|
editButton.setEnabled(false);
|
||||||
|
editButton.addSelectionListener(onEditPort(exposedPortsTableViewer));
|
||||||
|
final Button removeButton = new Button(buttonsContainers, SWT.NONE);
|
||||||
|
GridDataFactory.fillDefaults().align(SWT.FILL, SWT.TOP)
|
||||||
|
.grab(true, false).applyTo(removeButton);
|
||||||
|
removeButton.setText(Messages.ContainerTab_Remove_Button);
|
||||||
|
removeButton
|
||||||
|
.addSelectionListener(onRemovePorts(exposedPortsTableViewer));
|
||||||
|
ViewerSupport.bind(exposedPortsTableViewer, model.getExposedPorts(),
|
||||||
|
BeanProperties.values(ExposedPortModel.class,
|
||||||
|
ExposedPortModel.CONTAINER_PORT,
|
||||||
|
ExposedPortModel.PORT_TYPE,
|
||||||
|
ExposedPortModel.HOST_ADDRESS,
|
||||||
|
ExposedPortModel.HOST_PORT));
|
||||||
|
dbc.bindSet(
|
||||||
|
ViewersObservables.observeCheckedElements(
|
||||||
|
exposedPortsTableViewer, ExposedPortModel.class),
|
||||||
|
BeanProperties.set(ContainerTabModel.SELECTED_PORTS)
|
||||||
|
.observe(model));
|
||||||
|
checkAllElements(exposedPortsTableViewer);
|
||||||
|
|
||||||
|
// disable the edit and removeButton if the table is empty
|
||||||
|
exposedPortsTableViewer.addSelectionChangedListener(
|
||||||
|
onSelectionChanged(editButton, removeButton));
|
||||||
|
exposedPortsTableViewer
|
||||||
|
.addCheckStateListener(new ICheckStateListener() {
|
||||||
|
@Override
|
||||||
|
public void checkStateChanged(
|
||||||
|
CheckStateChangedEvent event) {
|
||||||
|
ExposedPortModel e = (ExposedPortModel) event
|
||||||
|
.getElement();
|
||||||
|
e.setSelected(event.getChecked());
|
||||||
|
updateLaunchConfigurationDialog();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkAllElements(
|
||||||
|
final CheckboxTableViewer exposedPortsTableViewer) {
|
||||||
|
exposedPortsTableViewer.setAllChecked(true);
|
||||||
|
model.setSelectedPorts(new HashSet<>(model.getExposedPorts()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private SelectionListener onAddPort(
|
||||||
|
final CheckboxTableViewer exposedPortsTableViewer) {
|
||||||
|
return SelectionListener.widgetSelectedAdapter(e -> {
|
||||||
|
final ContainerPortDialog dialog = new ContainerPortDialog(
|
||||||
|
getShell());
|
||||||
|
dialog.create();
|
||||||
|
if (dialog.open() == IDialogConstants.OK_ID) {
|
||||||
|
final ExposedPortModel port = dialog.getPort();
|
||||||
|
port.setSelected(true);
|
||||||
|
model.addAvailablePort(port);
|
||||||
|
model.getSelectedPorts().add(port);
|
||||||
|
exposedPortsTableViewer.setChecked(port, true);
|
||||||
|
updateLaunchConfigurationDialog();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private SelectionListener onEditPort(
|
||||||
|
final CheckboxTableViewer exposedPortsTableViewer) {
|
||||||
|
return SelectionListener.widgetSelectedAdapter(e -> {
|
||||||
|
final IStructuredSelection selection = exposedPortsTableViewer
|
||||||
|
.getStructuredSelection();
|
||||||
|
final ExposedPortModel selectedContainerPort = (ExposedPortModel) selection
|
||||||
|
.getFirstElement();
|
||||||
|
final ContainerPortDialog dialog = new ContainerPortDialog(
|
||||||
|
getShell(), selectedContainerPort);
|
||||||
|
dialog.create();
|
||||||
|
if (dialog.open() == IDialogConstants.OK_ID) {
|
||||||
|
final ExposedPortModel configuredPort = dialog.getPort();
|
||||||
|
selectedContainerPort
|
||||||
|
.setContainerPort(configuredPort.getContainerPort());
|
||||||
|
selectedContainerPort
|
||||||
|
.setHostAddress(configuredPort.getHostAddress());
|
||||||
|
selectedContainerPort.setHostPort(configuredPort.getHostPort());
|
||||||
|
exposedPortsTableViewer.refresh();
|
||||||
|
updateLaunchConfigurationDialog();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private SelectionListener onRemovePorts(
|
||||||
|
final TableViewer portsTableViewer) {
|
||||||
|
return SelectionListener.widgetSelectedAdapter(e -> {
|
||||||
|
final IStructuredSelection selection = portsTableViewer
|
||||||
|
.getStructuredSelection();
|
||||||
|
for (@SuppressWarnings("unchecked")
|
||||||
|
Iterator<ExposedPortModel> iterator = selection.iterator(); iterator
|
||||||
|
.hasNext();) {
|
||||||
|
final ExposedPortModel port = iterator.next();
|
||||||
|
model.removeAvailablePort(port);
|
||||||
|
model.getSelectedPorts().remove(port);
|
||||||
|
updateLaunchConfigurationDialog();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private ISelectionChangedListener onSelectionChanged(
|
||||||
|
final Button... targetButtons) {
|
||||||
|
return e -> {
|
||||||
|
if (e.getSelection().isEmpty()) {
|
||||||
|
setControlsEnabled(targetButtons, false);
|
||||||
|
} else {
|
||||||
|
setControlsEnabled(targetButtons, true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void setControlsEnabled(final Control[] controls,
|
||||||
|
final boolean enabled) {
|
||||||
|
for (Control control : controls) {
|
||||||
|
control.setEnabled(enabled);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private CheckboxTableViewer createPortSettingsTable(
|
||||||
|
final Composite container) {
|
||||||
|
final Table table = new Table(container, SWT.BORDER | SWT.FULL_SELECTION
|
||||||
|
| SWT.V_SCROLL | SWT.H_SCROLL | SWT.CHECK);
|
||||||
|
final CheckboxTableViewer tableViewer = new CheckboxTableViewer(table);
|
||||||
|
table.setHeaderVisible(true);
|
||||||
|
table.setLinesVisible(true);
|
||||||
|
createTableViewerColum(tableViewer,
|
||||||
|
Messages.ContainerTab_Port_Column,
|
||||||
|
100);
|
||||||
|
createTableViewerColum(tableViewer,
|
||||||
|
Messages.ContainerTab_Type_Column,
|
||||||
|
50);
|
||||||
|
createTableViewerColum(tableViewer,
|
||||||
|
Messages.ContainerTab_HostAddress_Column,
|
||||||
|
100);
|
||||||
|
createTableViewerColum(tableViewer,
|
||||||
|
Messages.ContainerTab_HostPort_Column,
|
||||||
|
100);
|
||||||
|
tableViewer.setContentProvider(new ObservableListContentProvider());
|
||||||
|
return tableViewer;
|
||||||
|
}
|
||||||
|
|
||||||
|
private TableViewerColumn createTableViewerColum(
|
||||||
|
final TableViewer tableViewer, final String title,
|
||||||
|
final int width) {
|
||||||
|
final TableViewerColumn viewerColumn = new TableViewerColumn(
|
||||||
|
tableViewer, SWT.NONE);
|
||||||
|
final TableColumn column = viewerColumn.getColumn();
|
||||||
|
if (title != null) {
|
||||||
|
column.setText(title);
|
||||||
|
}
|
||||||
|
column.setWidth(width);
|
||||||
|
return viewerColumn;
|
||||||
|
}
|
||||||
|
|
||||||
private void createOptions(Composite parent) {
|
private void createOptions(Composite parent) {
|
||||||
Font font = parent.getFont();
|
Font font = parent.getFont();
|
||||||
Composite comp = createComposite(parent, 1, 3, GridData.FILL_BOTH);
|
Composite comp = createComposite(parent, 1, 3, GridData.FILL_BOTH);
|
||||||
|
@ -406,6 +636,8 @@ public class ContainerTab extends AbstractLaunchConfigurationTab implements
|
||||||
public void setDefaults(ILaunchConfigurationWorkingCopy configuration) {
|
public void setDefaults(ILaunchConfigurationWorkingCopy configuration) {
|
||||||
configuration.setAttribute(ILaunchConstants.ATTR_ADDITIONAL_DIRS,
|
configuration.setAttribute(ILaunchConstants.ATTR_ADDITIONAL_DIRS,
|
||||||
(String) null);
|
(String) null);
|
||||||
|
configuration.setAttribute(ILaunchConstants.ATTR_EXPOSED_PORTS,
|
||||||
|
(String) null);
|
||||||
configuration.setAttribute(ILaunchConstants.ATTR_CONNECTION_URI, ""); //$NON-NLS-1$
|
configuration.setAttribute(ILaunchConstants.ATTR_CONNECTION_URI, ""); //$NON-NLS-1$
|
||||||
Preferences prefs = InstanceScope.INSTANCE
|
Preferences prefs = InstanceScope.INSTANCE
|
||||||
.getNode(DockerLaunchUIPlugin.PLUGIN_ID);
|
.getNode(DockerLaunchUIPlugin.PLUGIN_ID);
|
||||||
|
@ -427,6 +659,19 @@ public class ContainerTab extends AbstractLaunchConfigurationTab implements
|
||||||
|
|
||||||
if (additionalDirs != null)
|
if (additionalDirs != null)
|
||||||
directoriesList.setItems(additionalDirs.toArray(new String[0]));
|
directoriesList.setItems(additionalDirs.toArray(new String[0]));
|
||||||
|
|
||||||
|
java.util.List<String> exposedPortInfos = configuration
|
||||||
|
.getAttribute(ILaunchConstants.ATTR_EXPOSED_PORTS,
|
||||||
|
Collections.<String> emptyList());
|
||||||
|
model.removeExposedPorts();
|
||||||
|
for (String port : exposedPortInfos) {
|
||||||
|
ExposedPortModel m = ExposedPortModel.createPortModel(port);
|
||||||
|
model.addAvailablePort(m);
|
||||||
|
if (m.getSelected()) {
|
||||||
|
model.getSelectedPorts().add(m);
|
||||||
|
tableViewer.setChecked(m, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
connectionUri = configuration.getAttribute(
|
connectionUri = configuration.getAttribute(
|
||||||
ILaunchConstants.ATTR_CONNECTION_URI, (String) "");
|
ILaunchConstants.ATTR_CONNECTION_URI, (String) "");
|
||||||
int defaultIndex = 0;
|
int defaultIndex = 0;
|
||||||
|
@ -480,6 +725,8 @@ public class ContainerTab extends AbstractLaunchConfigurationTab implements
|
||||||
stdinButton.getSelection());
|
stdinButton.getSelection());
|
||||||
configuration.setAttribute(ILaunchConstants.ATTR_PRIVILEGED_MODE,
|
configuration.setAttribute(ILaunchConstants.ATTR_PRIVILEGED_MODE,
|
||||||
privilegedButton.getSelection());
|
privilegedButton.getSelection());
|
||||||
|
configuration.setAttribute(ILaunchConstants.ATTR_EXPOSED_PORTS,
|
||||||
|
ExposedPortModel.toArrayString(model.getExposedPorts()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -0,0 +1,87 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2018 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.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.eclipse.core.databinding.observable.list.WritableList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 1.2.1
|
||||||
|
* @author jjohnstn
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class ContainerTabModel extends BaseDatabindingModel {
|
||||||
|
|
||||||
|
public static final String PUBLISH_ALL_PORTS = "publishAllPorts"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
public static final String EXPOSED_PORTS = "exposedPorts"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
public static final String SELECTED_PORTS = "selectedPorts"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
private boolean publishAllPorts = true;
|
||||||
|
|
||||||
|
private final WritableList<ExposedPortModel> exposedPorts = new WritableList<>();
|
||||||
|
|
||||||
|
private Set<ExposedPortModel> selectedPorts;
|
||||||
|
|
||||||
|
public boolean isPublishAllPorts() {
|
||||||
|
return publishAllPorts;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPublishAllPorts(boolean publishAllPorts) {
|
||||||
|
firePropertyChange(PUBLISH_ALL_PORTS, this.publishAllPorts,
|
||||||
|
this.publishAllPorts = publishAllPorts);
|
||||||
|
}
|
||||||
|
|
||||||
|
public WritableList<ExposedPortModel> getExposedPorts() {
|
||||||
|
return exposedPorts;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addAvailablePort(final ExposedPortModel port) {
|
||||||
|
this.exposedPorts.add(port);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeAvailablePort(final ExposedPortModel port) {
|
||||||
|
this.exposedPorts.remove(port);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setExposedPorts(final List<ExposedPortModel> exposedPorts) {
|
||||||
|
this.exposedPorts.clear();
|
||||||
|
this.exposedPorts.addAll(exposedPorts);
|
||||||
|
// FIXME: also add all given exposedPorts to selectedExposedPorts ?
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addExposedPort(final ExposedPortModel exposedPort) {
|
||||||
|
if (!this.exposedPorts.contains(exposedPort)) {
|
||||||
|
this.exposedPorts.add(exposedPort);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeExposedPort(final ExposedPortModel exposedPort) {
|
||||||
|
this.exposedPorts.remove(exposedPort);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeExposedPorts() {
|
||||||
|
this.exposedPorts.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<ExposedPortModel> getSelectedPorts() {
|
||||||
|
return this.selectedPorts;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSelectedPorts(final Set<ExposedPortModel> ports) {
|
||||||
|
firePropertyChange(SELECTED_PORTS, this.selectedPorts,
|
||||||
|
this.selectedPorts = ports);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,246 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2018 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.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import org.eclipse.core.runtime.Assert;
|
||||||
|
|
||||||
|
public class ExposedPortModel extends BaseDatabindingModel
|
||||||
|
implements Comparable<ExposedPortModel> {
|
||||||
|
|
||||||
|
private static final String SEPARATOR = ":"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
private static final String CONTAINER_TYPE_SEPARATOR = "/"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
public static final String SELECTED = "selected"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
public static final String CONTAINER_PORT = "containerPort"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
public static final String PORT_TYPE = "portType"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
public static final String HOST_ADDRESS = "hostAddress"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
public static final String HOST_PORT = "hostPort"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
private final String id = UUID.randomUUID().toString();
|
||||||
|
|
||||||
|
private boolean selected;
|
||||||
|
|
||||||
|
private String containerPort;
|
||||||
|
|
||||||
|
private String portType;
|
||||||
|
|
||||||
|
private String hostAddress;
|
||||||
|
|
||||||
|
private String hostPort;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses and converts the {@link List} of the given {@link String} values
|
||||||
|
* into a {@link List} of {@link ExposedPortModel}
|
||||||
|
*
|
||||||
|
* @param exposedPortInfos
|
||||||
|
* the input values
|
||||||
|
* @return the corresponding {@link ExposedPortModel}s
|
||||||
|
*/
|
||||||
|
public static List<ExposedPortModel> fromStrings(
|
||||||
|
final Collection<String> exposedPortInfos) {
|
||||||
|
final List<ExposedPortModel> exposedPorts = new ArrayList<>();
|
||||||
|
for (String exposedPortInfo : exposedPortInfos) {
|
||||||
|
final ExposedPortModel exposedPort = ExposedPortModel
|
||||||
|
.fromString(exposedPortInfo);
|
||||||
|
if (exposedPort != null) {
|
||||||
|
exposedPorts.add(exposedPort);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return exposedPorts;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a collection of ExposedPortModel to a {@link List} of
|
||||||
|
* {@link String} values
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param exposedPorts
|
||||||
|
* collection of ExposedPortModel instances
|
||||||
|
* @return the corresponding {@link List} of {@link String}s
|
||||||
|
*/
|
||||||
|
public static List<String> toArrayString(
|
||||||
|
final Collection<ExposedPortModel> exposedPorts) {
|
||||||
|
final List<String> exposedPortList = new ArrayList<>();
|
||||||
|
for (ExposedPortModel exposedPort : exposedPorts) {
|
||||||
|
final String exposedPortString = exposedPort.toString();
|
||||||
|
if (exposedPort != null) {
|
||||||
|
exposedPortList.add(exposedPortString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return exposedPortList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse the given value and returns an instance of
|
||||||
|
* {@link ExposedPortModel}.
|
||||||
|
*
|
||||||
|
* @param exposedPortInfo
|
||||||
|
* the value to parse
|
||||||
|
* @return the corresponding {@link ExposedPortModel}
|
||||||
|
*/
|
||||||
|
public static ExposedPortModel fromString(final String exposedPortInfo) {
|
||||||
|
final String privatePort = exposedPortInfo.substring(0,
|
||||||
|
exposedPortInfo.indexOf(CONTAINER_TYPE_SEPARATOR));
|
||||||
|
// exposed ports without host IP/port info
|
||||||
|
final int firstColumnSeparator = exposedPortInfo.indexOf(SEPARATOR);
|
||||||
|
if (firstColumnSeparator == -1
|
||||||
|
&& exposedPortInfo.indexOf(CONTAINER_TYPE_SEPARATOR) != -1) {
|
||||||
|
final String type = exposedPortInfo.substring(
|
||||||
|
exposedPortInfo.indexOf(CONTAINER_TYPE_SEPARATOR)); // $NON-NLS-1$
|
||||||
|
final ExposedPortModel exposedPort = new ExposedPortModel(
|
||||||
|
privatePort, type, "", privatePort); // $NON-NLS-1$
|
||||||
|
return exposedPort; // $NON-NLS-1$
|
||||||
|
} else {
|
||||||
|
final int secondColumnSeparator = exposedPortInfo.indexOf(SEPARATOR,
|
||||||
|
firstColumnSeparator + 1);
|
||||||
|
final String type = exposedPortInfo.substring(
|
||||||
|
exposedPortInfo.indexOf(CONTAINER_TYPE_SEPARATOR), // $NON-NLS-1$
|
||||||
|
firstColumnSeparator); // $NON-NLS-1$
|
||||||
|
final String hostIP = exposedPortInfo
|
||||||
|
.substring(firstColumnSeparator + 1, secondColumnSeparator);
|
||||||
|
final String hostPort = exposedPortInfo
|
||||||
|
.substring(secondColumnSeparator + 1);
|
||||||
|
final ExposedPortModel exposedPort = new ExposedPortModel(
|
||||||
|
privatePort, type, hostIP, hostPort); // $NON-NLS-1$
|
||||||
|
return exposedPort; // $NON-NLS-1$
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Full constructor
|
||||||
|
*
|
||||||
|
* @param privatePort
|
||||||
|
* @param portType
|
||||||
|
* @param hostAddress
|
||||||
|
* @param hostPort
|
||||||
|
*/
|
||||||
|
public ExposedPortModel(final String privatePort, final String type,
|
||||||
|
final String hostAddress, final String hostPort) {
|
||||||
|
Assert.isNotNull(privatePort,
|
||||||
|
"Port Mapping privatePort cannot be null"); //$NON-NLS-1$
|
||||||
|
Assert.isNotNull(type, "Port Mapping portType cannot be null"); //$NON-NLS-1$
|
||||||
|
this.containerPort = privatePort;
|
||||||
|
this.hostPort = hostPort;
|
||||||
|
this.portType = type;
|
||||||
|
this.hostAddress = hostAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an ExposedPortModel from its toString output
|
||||||
|
*
|
||||||
|
* @param stringValue
|
||||||
|
* @return ExposedPortModel
|
||||||
|
*/
|
||||||
|
static public ExposedPortModel createPortModel(String stringValue) {
|
||||||
|
final String[] elements = stringValue.split(SEPARATOR);
|
||||||
|
final String[] containerPortElements = elements[0]
|
||||||
|
.split(CONTAINER_TYPE_SEPARATOR);
|
||||||
|
ExposedPortModel model = new ExposedPortModel(containerPortElements[0],
|
||||||
|
containerPortElements[1], elements[1], elements[2]);
|
||||||
|
// check the last argument if exists otherwise assume 'true'
|
||||||
|
model.selected = (elements.length == 4) ? Boolean.valueOf(elements[3])
|
||||||
|
: true;
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getContainerPort() {
|
||||||
|
return containerPort;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContainerPort(final String containerPort) {
|
||||||
|
firePropertyChange(CONTAINER_PORT, this.containerPort,
|
||||||
|
this.containerPort = containerPort);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPortType() {
|
||||||
|
return portType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPortType(final String type) {
|
||||||
|
firePropertyChange(PORT_TYPE, this.portType, this.portType = type);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getSelected() {
|
||||||
|
return selected;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSelected(final boolean selected) {
|
||||||
|
firePropertyChange(SELECTED, this.selected, this.selected = selected);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getHostPort() {
|
||||||
|
return hostPort;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHostPort(final String hostPort) {
|
||||||
|
firePropertyChange(HOST_PORT, this.hostPort, this.hostPort = hostPort);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getHostAddress() {
|
||||||
|
return hostAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHostAddress(final String hostAddress) {
|
||||||
|
firePropertyChange(HOST_ADDRESS, this.hostAddress,
|
||||||
|
this.hostAddress = hostAddress);
|
||||||
|
}
|
||||||
|
|
||||||
|
@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;
|
||||||
|
ExposedPortModel other = (ExposedPortModel) obj;
|
||||||
|
if (id == null) {
|
||||||
|
if (other.id != null)
|
||||||
|
return false;
|
||||||
|
} else if (!id.equals(other.id))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compareTo(final ExposedPortModel other) {
|
||||||
|
return this.containerPort.compareTo(other.containerPort);
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME we should have a dedicated method to serialize the bean
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
StringBuffer buffer = new StringBuffer();
|
||||||
|
buffer.append(containerPort + CONTAINER_TYPE_SEPARATOR + portType
|
||||||
|
+ SEPARATOR + (hostAddress != null ? hostAddress : "")
|
||||||
|
+ SEPARATOR + hostPort + SEPARATOR + selected);
|
||||||
|
return buffer.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -21,6 +21,9 @@ public interface ILaunchConstants {
|
||||||
public final static String ATTR_ADDITIONAL_DIRS = DockerLaunchUIPlugin
|
public final static String ATTR_ADDITIONAL_DIRS = DockerLaunchUIPlugin
|
||||||
.getUniqueIdentifier() + ".additional_dirs"; //$NON-NLS-1$
|
.getUniqueIdentifier() + ".additional_dirs"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
public final static String ATTR_EXPOSED_PORTS = DockerLaunchUIPlugin
|
||||||
|
.getUniqueIdentifier() + ".exposed_ports"; //$NON-NLS-1$
|
||||||
|
|
||||||
public final static String ATTR_IMAGE = DockerLaunchUIPlugin.getUniqueIdentifier()
|
public final static String ATTR_IMAGE = DockerLaunchUIPlugin.getUniqueIdentifier()
|
||||||
+ ".image"; //$NON-NLS-1$
|
+ ".image"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
|
|
@ -15,8 +15,6 @@ import org.eclipse.osgi.util.NLS;
|
||||||
public class Messages extends NLS {
|
public class Messages extends NLS {
|
||||||
private static final String BUNDLE_NAME = "org.eclipse.cdt.internal.docker.launcher.messages"; //$NON-NLS-1$
|
private static final String BUNDLE_NAME = "org.eclipse.cdt.internal.docker.launcher.messages"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static String LaunchShortcut_Binaries;
|
public static String LaunchShortcut_Binaries;
|
||||||
public static String LaunchShortcut_Binary_not_found;
|
public static String LaunchShortcut_Binary_not_found;
|
||||||
public static String LaunchShortcut_Choose_a_launch_configuration;
|
public static String LaunchShortcut_Choose_a_launch_configuration;
|
||||||
|
@ -34,14 +32,25 @@ public class Messages extends NLS {
|
||||||
public static String ContainerTab_Name;
|
public static String ContainerTab_Name;
|
||||||
public static String ContainerTab_Group_Name;
|
public static String ContainerTab_Group_Name;
|
||||||
public static String ContainerTab_Option_Group_Name;
|
public static String ContainerTab_Option_Group_Name;
|
||||||
|
public static String ContainerTab_Ports_Group_Name;
|
||||||
|
public static String ContainerTab_Specify_Ports_Label;
|
||||||
|
|
||||||
|
public static String ContainerTab_Add_Button;
|
||||||
|
public static String ContainerTab_Edit_Button;
|
||||||
public static String ContainerTab_New_Button;
|
public static String ContainerTab_New_Button;
|
||||||
public static String ContainerTab_Remove_Button;
|
public static String ContainerTab_Remove_Button;
|
||||||
public static String ContainerTab_Keep_Label;
|
public static String ContainerTab_Keep_Label;
|
||||||
|
public static String ContainerTab_Publish_All_Ports_Label;
|
||||||
public static String ContainerTab_Stdin_Support_Label;
|
public static String ContainerTab_Stdin_Support_Label;
|
||||||
public static String ContainerTab_Privileged_Mode_Label;
|
public static String ContainerTab_Privileged_Mode_Label;
|
||||||
public static String ContainerTab_Error_Reading_Configuration;
|
public static String ContainerTab_Error_Reading_Configuration;
|
||||||
public static String ContainerTab_Connection_Selector_Label;
|
public static String ContainerTab_Connection_Selector_Label;
|
||||||
public static String ContainerTab_Image_Selector_Label;
|
public static String ContainerTab_Image_Selector_Label;
|
||||||
|
public static String ContainerTab_Port_Column;
|
||||||
|
public static String ContainerTab_Type_Column;
|
||||||
|
public static String ContainerTab_HostAddress_Column;
|
||||||
|
public static String ContainerTab_HostPort_Column;
|
||||||
|
|
||||||
public static String ContainerTab_Error_No_Connections;
|
public static String ContainerTab_Error_No_Connections;
|
||||||
public static String ContainerTab_Error_No_Images;
|
public static String ContainerTab_Error_No_Images;
|
||||||
public static String ContainerTab_Warning_Connection_Not_Found;
|
public static String ContainerTab_Warning_Connection_Not_Found;
|
||||||
|
@ -113,6 +122,12 @@ public class Messages extends NLS {
|
||||||
|
|
||||||
public static String Gdbserver_Settings_Remotetimeout_tooltip;
|
public static String Gdbserver_Settings_Remotetimeout_tooltip;
|
||||||
|
|
||||||
|
public static String ContainerPortDialog_hostAddressLabel;
|
||||||
|
public static String ContainerPortDialog_hostPortLabel;
|
||||||
|
public static String ContainerPortDialog_shellTitle;
|
||||||
|
public static String ContainerPortDialog_containerLabel;
|
||||||
|
public static String ContainerPortDialog_explanationLabel;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
// initialize resource bundle
|
// initialize resource bundle
|
||||||
NLS.initializeMessages(BUNDLE_NAME, Messages.class);
|
NLS.initializeMessages(BUNDLE_NAME, Messages.class);
|
||||||
|
|
|
@ -26,20 +26,35 @@ Keep_Container_After_Launch=Keep Container after launch
|
||||||
|
|
||||||
ContainerTab_Name=Container
|
ContainerTab_Name=Container
|
||||||
ContainerTab_New_Button=New...
|
ContainerTab_New_Button=New...
|
||||||
|
ContainerTab_Add_Button=Add...
|
||||||
|
ContainerTab_Edit_Button=Edit...
|
||||||
ContainerTab_Remove_Button=Remove
|
ContainerTab_Remove_Button=Remove
|
||||||
ContainerTab_Keep_Label=Keep Container after launch
|
ContainerTab_Keep_Label=Keep Container after launch
|
||||||
ContainerTab_Stdin_Support_Label=Support stdin input
|
ContainerTab_Stdin_Support_Label=Support stdin input
|
||||||
ContainerTab_Privileged_Mode_Label=Run in privileged mode
|
ContainerTab_Privileged_Mode_Label=Run in privileged mode
|
||||||
ContainerTab_Group_Name=Required host directories
|
ContainerTab_Group_Name=Required host directories
|
||||||
|
ContainerTab_Ports_Group_Name=Ports
|
||||||
|
ContainerTab_Specify_Ports_Label=Manually specify ports and only publish selected entries to the host:
|
||||||
|
ContainerTab_Publish_All_Ports_Label=Publish all default exposed ports for image to random ports on the host
|
||||||
ContainerTab_Option_Group_Name=Additional Options
|
ContainerTab_Option_Group_Name=Additional Options
|
||||||
ContainerTab_Connection_Selector_Label=Connection:
|
ContainerTab_Connection_Selector_Label=Connection:
|
||||||
ContainerTab_Image_Selector_Label=Image:
|
ContainerTab_Image_Selector_Label=Image:
|
||||||
|
ContainerTab_Port_Column=Container Port
|
||||||
|
ContainerTab_Type_Column=Type
|
||||||
|
ContainerTab_HostAddress_Column=Host Address
|
||||||
|
ContainerTab_HostPort_Column=Host Port
|
||||||
ContainerTab_Error_Reading_Configuration=Error occurred reading the launch configuration: {0}
|
ContainerTab_Error_Reading_Configuration=Error occurred reading the launch configuration: {0}
|
||||||
ContainerTab_Error_No_Connections=No Docker Connections exist
|
ContainerTab_Error_No_Connections=No Docker Connections exist
|
||||||
ContainerTab_Error_No_Images=No Docker Images exist
|
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_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}
|
ContainerTab_Warning_Image_Not_Found=Docker Image: {0} is not a valid pulled image in current Connection: {1}
|
||||||
|
|
||||||
|
ContainerPortDialog_shellTitle=Exposing a Container Port
|
||||||
|
ContainerPortDialog_explanationLabel=Specify the container port to expose:
|
||||||
|
ContainerPortDialog_containerLabel=Container port:
|
||||||
|
ContainerPortDialog_hostAddressLabel=Host address:
|
||||||
|
ContainerPortDialog_hostPortLabel=Host port:
|
||||||
|
|
||||||
ContainerPropertyTab_Title=Container Settings
|
ContainerPropertyTab_Title=Container Settings
|
||||||
ContainerPropertyTab_Enable_Msg=Build inside Docker Image
|
ContainerPropertyTab_Enable_Msg=Build inside Docker Image
|
||||||
ContainerPropertyTab_Run_Autotools_In_Container_Msg=Run all Autotools in Container
|
ContainerPropertyTab_Run_Autotools_In_Container_Msg=Run all Autotools in Container
|
||||||
|
|
Loading…
Add table
Reference in a new issue