| /******************************************************************************* |
| * Copyright (c) 2015, 2020 Red Hat and others. |
| * |
| * This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * Red Hat - Initial Contribution |
| *******************************************************************************/ |
| package org.eclipse.cdt.internal.docker.launcher; |
| |
| import java.net.InetAddress; |
| import java.net.NetworkInterface; |
| import java.net.SocketException; |
| import java.net.UnknownHostException; |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.regex.Matcher; |
| import java.util.regex.Pattern; |
| |
| import org.eclipse.cdt.core.CCorePlugin; |
| import org.eclipse.cdt.core.build.ICBuildConfiguration; |
| import org.eclipse.cdt.core.build.ICBuildConfigurationManager; |
| import org.eclipse.cdt.core.build.IToolChain; |
| import org.eclipse.cdt.core.build.IToolChainManager; |
| import org.eclipse.cdt.core.model.CoreModel; |
| import org.eclipse.cdt.core.model.IBinary; |
| import org.eclipse.cdt.debug.core.CDebugCorePlugin; |
| import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants; |
| import org.eclipse.cdt.docker.launcher.ContainerTargetTypeProvider; |
| import org.eclipse.cdt.docker.launcher.DockerLaunchUIPlugin; |
| import org.eclipse.cdt.docker.launcher.IContainerLaunchTarget; |
| import org.eclipse.cdt.dsf.gdb.IGDBLaunchConfigurationConstants; |
| import org.eclipse.cdt.dsf.gdb.launching.GdbLaunchDelegate; |
| import org.eclipse.core.resources.IFile; |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.core.resources.IProjectDescription; |
| import org.eclipse.core.resources.IResource; |
| import org.eclipse.core.resources.ResourcesPlugin; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IPath; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.Path; |
| import org.eclipse.core.runtime.Status; |
| import org.eclipse.core.runtime.jobs.Job; |
| import org.eclipse.core.variables.VariablesPlugin; |
| import org.eclipse.debug.core.ILaunch; |
| import org.eclipse.debug.core.ILaunchConfiguration; |
| import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; |
| import org.eclipse.debug.core.ILaunchManager; |
| import org.eclipse.launchbar.core.target.ILaunchTarget; |
| import org.eclipse.launchbar.core.target.ILaunchTargetManager; |
| import org.eclipse.launchbar.core.target.ILaunchTargetWorkingCopy; |
| import org.eclipse.linuxtools.docker.core.Activator; |
| import org.eclipse.linuxtools.docker.core.IDockerContainerInfo; |
| import org.eclipse.linuxtools.docker.core.IDockerNetworkSettings; |
| import org.eclipse.linuxtools.docker.core.IDockerPortBinding; |
| import org.eclipse.linuxtools.docker.ui.launch.ContainerLauncher; |
| import org.eclipse.linuxtools.docker.ui.launch.IContainerLaunchListener; |
| |
| public class ContainerLaunchConfigurationDelegate extends GdbLaunchDelegate { |
| |
| private ContainerLauncher launcher; |
| |
| private final static String NONE = ""; //$NON-NLS-1$ |
| |
| private class StartGdbServerJob extends Job implements IContainerLaunchListener { |
| |
| private boolean started; |
| private boolean done; |
| private IDockerContainerInfo info; |
| |
| public StartGdbServerJob(String name) { |
| super(name); |
| } |
| |
| @Override |
| protected IStatus run(IProgressMonitor monitor) { |
| monitor.beginTask(getName(), IProgressMonitor.UNKNOWN); |
| |
| while (!done) { |
| if (monitor.isCanceled()) { |
| return Status.CANCEL_STATUS; |
| } |
| if (started && getIpAddress() != null) |
| done = true; |
| try { |
| Thread.sleep(500); |
| } catch (InterruptedException e) { |
| monitor.done(); |
| return Status.CANCEL_STATUS; |
| } |
| } |
| monitor.done(); |
| return Status.OK_STATUS; |
| } |
| |
| @Override |
| public void newOutput(String output) { |
| if (output.contains(Messages.Gdbserver_up) || output.contains("gdbserver:")) { //$NON-NLS-1$ |
| started = true; |
| } |
| |
| } |
| |
| public String getIpAddress() { |
| if (info != null) { |
| IDockerNetworkSettings networkSettings = info.networkSettings(); |
| return networkSettings.ipAddress(); |
| } |
| return null; |
| } |
| |
| public Map<String, List<IDockerPortBinding>> getPorts() { |
| if (info != null) { |
| IDockerNetworkSettings networkSettings = info.networkSettings(); |
| return networkSettings.ports(); |
| } |
| return null; |
| } |
| |
| public IDockerContainerInfo getContainerInfo() { |
| return info; |
| } |
| |
| @Override |
| public void done() { |
| done = true; |
| } |
| |
| @Override |
| public void containerInfo(IDockerContainerInfo info) { |
| this.info = info; |
| } |
| } |
| |
| public ContainerLaunchConfigurationDelegate() { |
| super(); |
| launcher = new ContainerLauncher(); |
| } |
| |
| @Override |
| public void launch(ILaunchConfiguration configuration, String mode, ILaunch launch, IProgressMonitor monitor) |
| throws CoreException { |
| |
| IPath commandPath = getCommandPath(configuration); |
| if (commandPath != null) { |
| // create some labels to allow user to filter out such Containers if |
| // kept |
| HashMap<String, String> labels = new HashMap<>(); |
| labels.put("org.eclipse.cdt.container-launch", ""); //$NON-NLS-1$ //$NON-NLS-2$ |
| String projectName = configuration.getAttribute(ICDTLaunchConfigurationConstants.ATTR_PROJECT_NAME, ""); //$NON-NLS-1$ |
| labels.put("org.eclipse.cdt.project-name", projectName); //$NON-NLS-1$ |
| if (mode.equals(ILaunchManager.RUN_MODE)) { |
| String commandDir = commandPath.removeLastSegments(1).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(commandString); |
| |
| String arguments = getProgramArguments(configuration); |
| if (arguments.trim().length() > 0) { |
| b.append(" "); //$NON-NLS-1$ |
| b.append(arguments); |
| } |
| |
| String command = b.toString(); |
| |
| String workingDir = configuration.getAttribute(ICDTLaunchConfigurationConstants.ATTR_WORKING_DIRECTORY, |
| (String) null); |
| // if we don't have a working directory, the default is to use |
| // the project |
| if (workingDir == null && projectName != null) { |
| IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName); |
| workingDir = project.getLocation().toOSString(); |
| } |
| |
| 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); |
| Map<String, String> origEnv = null; |
| boolean appendEnv = configuration.getAttribute(ILaunchManager.ATTR_APPEND_ENVIRONMENT_VARIABLES, false); |
| if (appendEnv) { |
| origEnv = System.getenv(); |
| } |
| 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(':', '/'); //$NON-NLS-1$ |
| } |
| dirs.add(dir); |
| } |
| 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(ILaunchConstants.ATTR_IMAGE, (String) null); |
| String connectionUri = configuration.getAttribute(ILaunchConstants.ATTR_CONNECTION_URI, NONE); |
| boolean keepContainer = configuration.getAttribute(ILaunchConstants.ATTR_KEEP_AFTER_LAUNCH, false); |
| |
| boolean supportStdin = configuration.getAttribute(ILaunchConstants.ATTR_STDIN_SUPPORT, false); |
| |
| boolean privilegedMode = configuration.getAttribute(ILaunchConstants.ATTR_PRIVILEGED_MODE, false); |
| |
| launcher.launch(DockerLaunchUIPlugin.PLUGIN_ID, null, connectionUri, image, command, commandDir, |
| workingDir, additionalDirs, origEnv, envMap, ports.isEmpty() ? null : ports, keepContainer, |
| supportStdin, privilegedMode, labels); |
| } else if (mode.equals(ILaunchManager.DEBUG_MODE)) { |
| String gdbserverPortNumber = configuration.getAttribute(ILaunchConstants.ATTR_GDBSERVER_PORT, |
| ILaunchConstants.ATTR_GDBSERVER_PORT_DEFAULT); |
| |
| 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(ILaunchConstants.ATTR_GDBSERVER_COMMAND, |
| ILaunchConstants.ATTR_GDBSERVER_COMMAND_DEFAULT); |
| |
| String commandString = commandPath.toPortableString(); |
| String commandDir = commandPath.removeLastSegments(1).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(); |
| |
| b.append(gdbserverCommand).append(' ').append(commandArguments); |
| |
| String arguments = getProgramArguments(configuration); |
| if (arguments.trim().length() > 0) { |
| b.append(" "); //$NON-NLS-1$ |
| b.append(arguments); |
| } |
| |
| String command = b.toString(); |
| String workingDir = configuration.getAttribute(ICDTLaunchConfigurationConstants.ATTR_WORKING_DIRECTORY, |
| (String) null); |
| // if we don't have a working directory, the default is to use |
| // the project |
| if (workingDir == null && projectName != null) { |
| IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName); |
| workingDir = project.getLocation().toOSString(); |
| } |
| 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); |
| Map<String, String> origEnv = null; |
| boolean appendEnv = configuration.getAttribute(ILaunchManager.ATTR_APPEND_ENVIRONMENT_VARIABLES, false); |
| if (appendEnv) { |
| origEnv = System.getenv(); |
| } |
| 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(':', '/'); //$NON-NLS-1$ |
| } |
| dirs.add(dir); |
| } |
| additionalDirs = dirs; |
| } |
| |
| String image = configuration.getAttribute(ILaunchConstants.ATTR_IMAGE, (String) null); |
| String connectionUri = configuration.getAttribute(ILaunchConstants.ATTR_CONNECTION_URI, NONE); |
| boolean isLocalConnection = true; |
| try { |
| Pattern ipaddrPattern = Pattern.compile("[a-z]*://([0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+)[:]*[0-9]*"); //$NON-NLS-1$ |
| Matcher m = ipaddrPattern.matcher(connectionUri); |
| if (m.matches()) { |
| String ipaddr = m.group(1); |
| InetAddress addr = InetAddress.getByName(ipaddr); |
| if (addr.isAnyLocalAddress() || addr.isLoopbackAddress()) { |
| isLocalConnection = true; |
| } else { |
| // Check if the address is defined on any interface |
| try { |
| isLocalConnection = NetworkInterface.getByInetAddress(addr) != null; |
| } catch (SocketException e) { |
| isLocalConnection = false; |
| } |
| } |
| } |
| } catch (UnknownHostException e) { |
| // should not happen |
| Activator.log(e); |
| } |
| |
| boolean keepContainer = configuration.getAttribute(ILaunchConstants.ATTR_KEEP_AFTER_LAUNCH, false); |
| |
| boolean supportStdin = configuration.getAttribute(ILaunchConstants.ATTR_STDIN_SUPPORT, false); |
| |
| boolean privilegedMode = configuration.getAttribute(ILaunchConstants.ATTR_PRIVILEGED_MODE, false); |
| |
| StartGdbServerJob job = new StartGdbServerJob(Messages.Gdbserver_start); |
| job.schedule(); |
| launcher.launch(DockerLaunchUIPlugin.PLUGIN_ID, job, connectionUri, image, command, commandDir, |
| workingDir, additionalDirs, origEnv, envMap, ports, keepContainer, supportStdin, privilegedMode, |
| labels, "seccomp:unconfined"); //$NON-NLS-1$ |
| |
| // wait until gdbserver is started successfully and we have its |
| // ip address or |
| // gdbserver has failed |
| try { |
| job.join(); |
| } catch (InterruptedException e) { |
| // ignore |
| } |
| |
| // if gdbserver started successfully and we have its ip address, |
| // launch the debugger |
| if (job.getResult() == Status.OK_STATUS && job.getIpAddress() != null) { |
| // Let debugger know how gdbserver was started on the remote |
| // container |
| ILaunchConfigurationWorkingCopy wc = configuration.getWorkingCopy(); |
| wc.setAttribute(IGDBLaunchConfigurationConstants.ATTR_REMOTE_TCP, true); |
| wc.setAttribute(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_START_MODE, |
| IGDBLaunchConfigurationConstants.DEBUGGER_MODE_REMOTE); |
| Map<String, List<IDockerPortBinding>> hostPorts = new HashMap<>(); |
| if (job.getPorts() != null && isLocalConnection) { |
| hostPorts = job.getPorts(); |
| } |
| List<IDockerPortBinding> bindingList = hostPorts.get(gdbserverPortNumber + "/tcp"); //$NON-NLS-1$ |
| if (bindingList != null && !bindingList.isEmpty()) { |
| IDockerPortBinding firstBinding = bindingList.get(0); |
| wc.setAttribute(IGDBLaunchConfigurationConstants.ATTR_HOST, "localhost"); //$NON-NLS-1$ |
| wc.setAttribute(IGDBLaunchConfigurationConstants.ATTR_PORT, firstBinding.hostPort()); |
| } else { |
| wc.setAttribute(IGDBLaunchConfigurationConstants.ATTR_HOST, job.getIpAddress()); |
| wc.setAttribute(IGDBLaunchConfigurationConstants.ATTR_PORT, gdbserverPortNumber); |
| } |
| wc.doSave(); |
| try { |
| super.launch(configuration, mode, launch, monitor); |
| } catch (CoreException ex) { |
| // launch failed, need to cleanup any container we |
| // created for the gdbserver |
| launcher.cleanup(connectionUri, job.getContainerInfo()); |
| throw ex; |
| } finally { |
| monitor.done(); |
| } |
| } |
| } |
| } |
| } |
| |
| /** |
| * Get the program arguments and perform substitution. |
| * |
| * @param config |
| * launch configuration |
| * @return argument String |
| * @throws CoreException |
| */ |
| private String getProgramArguments(ILaunchConfiguration config) throws CoreException { |
| String args = config.getAttribute(ICDTLaunchConfigurationConstants.ATTR_PROGRAM_ARGUMENTS, NONE); |
| if (args != null && args.length() > 0) { |
| args = VariablesPlugin.getDefault().getStringVariableManager().performStringSubstitution(args); |
| } |
| return args; |
| } |
| |
| /** |
| * Form command path using the project and program name. |
| * |
| * @param configuration |
| * @return command path |
| * @throws CoreException |
| */ |
| private IPath getCommandPath(ILaunchConfiguration configuration) throws CoreException { |
| String projectName = configuration.getAttribute(ICDTLaunchConfigurationConstants.ATTR_PROJECT_NAME, NONE); |
| if (projectName.length() > 0) { |
| IProject project = CCorePlugin.getWorkspace().getRoot().getProject(projectName); |
| if (project == null) |
| return null; |
| |
| String name = configuration.getAttribute(ICDTLaunchConfigurationConstants.ATTR_PROGRAM_NAME, NONE); |
| |
| if (name.length() == 0) |
| return null; |
| |
| IPath exePath = new Path(name); |
| if (!exePath.isAbsolute()) { |
| IPath location = project.getLocation(); |
| if (location == null) { |
| return null; |
| } |
| |
| exePath = location.append(name); |
| if (!exePath.toFile().exists()) { |
| // Try the old way, which is required to support linked |
| // resources. |
| IFile projFile = null; |
| try { |
| projFile = project.getFile(name); |
| } catch (IllegalArgumentException e) { |
| // thrown if relative path that resolves to a root file |
| // ("..\somefile") |
| } |
| if (projFile == null || !projFile.exists()) { |
| return null; |
| } else { |
| exePath = projFile.getLocation(); |
| } |
| } |
| } |
| if (!exePath.toFile().exists()) { |
| return null; |
| } |
| |
| if (!exePath.toFile().isFile()) { |
| return null; |
| } |
| return exePath; |
| } else { |
| return null; |
| } |
| } |
| |
| private String spaceEscapify(String inputString) { |
| if (inputString == null) |
| return null; |
| |
| return inputString.replaceAll(" ", "\\\\ "); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| |
| public static IProject getProject(ILaunchConfiguration configuration) throws CoreException { |
| // TODO - make sure this is really the correct project |
| return configuration.getMappedResources()[0].getProject(); |
| } |
| |
| /** |
| * @since 1.2 |
| */ |
| protected ICBuildConfigurationManager configManager = CDebugCorePlugin |
| .getService(ICBuildConfigurationManager.class); |
| /** |
| * @since 1.2 |
| */ |
| protected IToolChainManager toolChainManager = CDebugCorePlugin.getService(IToolChainManager.class); |
| |
| /* |
| * @since 1.2 |
| */ |
| protected ICBuildConfiguration getBuildConfiguration(ILaunchConfiguration configuration, String mode, |
| ILaunchTarget target, IProgressMonitor monitor) throws CoreException { |
| IProject project = getProject(configuration); |
| String toolchainId = configuration.getAttribute(ICBuildConfiguration.TOOLCHAIN_ID, (String) null); |
| if (toolchainId != null) { |
| String providerId = configuration.getAttribute(ICBuildConfiguration.TOOLCHAIN_TYPE, ""); //$NON-NLS-1$ |
| IToolChain toolchain = toolChainManager.getToolChain(providerId, toolchainId); |
| if (toolchain != null) { |
| return configManager.getBuildConfiguration(project, toolchain, mode, monitor); |
| } |
| } |
| |
| // Pick the first one that matches |
| Map<String, String> properties = new HashMap<>(); |
| properties.putAll(target.getAttributes()); |
| for (IToolChain toolChain : toolChainManager.getToolChainsMatching(properties)) { |
| ICBuildConfiguration buildConfig = configManager.getBuildConfiguration(project, toolChain, mode, monitor); |
| if (buildConfig != null) { |
| return buildConfig; |
| } |
| } |
| |
| return null; |
| } |
| |
| @Override |
| public boolean buildForLaunch(ILaunchConfiguration configuration, String mode, IProgressMonitor monitor) |
| throws CoreException { |
| IProject project = getProject(configuration); |
| String name = configuration.getName(); |
| Pattern p = Pattern.compile(".*?\\[([^\\]]+)\\](.*)"); //$NON-NLS-1$ |
| Matcher m = p.matcher(name); |
| if (m.matches()) { |
| ILaunchTargetManager targetManager = CCorePlugin.getService(ILaunchTargetManager.class); |
| ILaunchTarget target = null; |
| ILaunchTarget[] targets = targetManager.getLaunchTargetsOfType(ContainerTargetTypeProvider.TYPE_ID); |
| for (ILaunchTarget t : targets) { |
| if (t.getAttribute(IContainerLaunchTarget.ATTR_IMAGE_ID, "").replaceAll(":", "_").equals(m.group(1))) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ |
| target = t; |
| break; |
| } |
| } |
| if (target != null) { |
| ICBuildConfiguration cconfig = getBuildConfiguration(configuration, mode, target, monitor); |
| if (cconfig != null) { |
| CoreModel model = CoreModel.getDefault(); |
| synchronized (model) { |
| IProjectDescription desc = project.getDescription(); |
| desc.setActiveBuildConfig(cconfig.getBuildConfiguration().getName()); |
| project.setDescription(desc, monitor); |
| } |
| } |
| } |
| } |
| |
| return super.buildForLaunch(configuration, mode, monitor); |
| } |
| |
| @Override |
| public boolean finalLaunchCheck(ILaunchConfiguration configuration, String mode, IProgressMonitor monitor) |
| throws CoreException { |
| IProject project = getProject(configuration); |
| ILaunchTargetManager targetManager = CCorePlugin.getService(ILaunchTargetManager.class); |
| ILaunchTarget target = null; |
| // force ContainerTargetTypeProvider to flush all check jobs by calling getStatus() |
| ILaunchTarget fakeTarget = new ILaunchTarget() { |
| |
| @Override |
| public <T> T getAdapter(Class<T> adapter) { |
| return null; |
| } |
| |
| @Override |
| public String getId() { |
| return "org.eclipse.cdt.docker.launch.fakeTarget"; //$NON-NLS-1$ |
| } |
| |
| @Override |
| public String getTypeId() { |
| return ContainerTargetTypeProvider.TYPE_ID; |
| } |
| |
| @Override |
| public String getAttribute(String key, String defValue) { |
| return defValue; |
| } |
| |
| @Override |
| public Map<String, String> getAttributes() { |
| return Collections.emptyMap(); |
| } |
| |
| @Override |
| public ILaunchTargetWorkingCopy getWorkingCopy() { |
| throw new UnsupportedOperationException(); |
| } |
| |
| }; |
| targetManager.getStatus(fakeTarget); |
| |
| // now that check jobs are flushed, get launch targets |
| ILaunchTarget[] targets = targetManager.getLaunchTargetsOfType(ContainerTargetTypeProvider.TYPE_ID); |
| String image = configuration.getAttribute(IContainerLaunchTarget.ATTR_IMAGE_ID, (String) null); |
| String connection = configuration.getAttribute(IContainerLaunchTarget.ATTR_CONNECTION_URI, (String) null); |
| for (ILaunchTarget t : targets) { |
| if (t.getAttribute(IContainerLaunchTarget.ATTR_IMAGE_ID, "").equals(image)) { //$NON-NLS-1$ |
| target = t; |
| break; |
| } |
| } |
| String program = configuration.getAttribute(ICDTLaunchConfigurationConstants.ATTR_PROGRAM_NAME, (String) null); |
| if (program == null) { |
| ICBuildConfiguration cconfig = getBuildConfiguration(configuration, mode, target, monitor); |
| if (cconfig != null) { |
| IBinary[] binaries = cconfig.getBuildOutput(); |
| for (IBinary b : binaries) { |
| if (b.isExecutable() && b.getElementName().contains(project.getName())) { |
| ILaunchConfigurationWorkingCopy wc = configuration.getWorkingCopy(); |
| wc.setAttribute(ICDTLaunchConfigurationConstants.ATTR_PROGRAM_NAME, |
| b.getResource().getProjectRelativePath().toString()); |
| wc.setMappedResources(new IResource[] { b.getResource(), b.getResource().getProject() }); |
| wc.setAttribute(ICDTLaunchConfigurationConstants.ATTR_WORKING_DIRECTORY, (String) null); // default is the project |
| // directory |
| wc.setAttribute(ILaunchConstants.ATTR_CONNECTION_URI, connection); |
| wc.setAttribute(ILaunchConstants.ATTR_IMAGE, image); |
| |
| wc.doSave(); |
| break; |
| } |
| } |
| } |
| } |
| return super.finalLaunchCheck(configuration, mode, monitor); |
| } |
| |
| @Override |
| public boolean preLaunchCheck(ILaunchConfiguration config, String mode, IProgressMonitor monitor) |
| throws CoreException { |
| String projectName = config.getAttribute(ICDTLaunchConfigurationConstants.ATTR_PROJECT_NAME, (String) null); |
| IProject project = null; |
| if (projectName == null) { |
| IResource[] resources = config.getMappedResources(); |
| if (resources != null && resources.length > 0) { |
| project = resources[0].getProject(); |
| } |
| if (project != null) { |
| ILaunchConfigurationWorkingCopy wc = config.getWorkingCopy(); |
| wc.setAttribute(ICDTLaunchConfigurationConstants.ATTR_PROJECT_NAME, project.getName()); |
| wc.doSave(); |
| } |
| } else { |
| projectName = projectName.trim(); |
| if (!projectName.isEmpty()) { |
| project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName); |
| } |
| } |
| |
| return super.preLaunchCheck(config, mode, monitor); |
| } |
| |
| @Override |
| protected String getPluginID() { |
| return DockerLaunchUIPlugin.PLUGIN_ID; |
| } |
| } |