/******************************************************************************* * Copyright (c) 2014, 2015 Wind River Systems, Inc. * 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: * Markus Schorn - initial API and implementation *******************************************************************************/ package org.eclipse.tcf.te.tcf.remote.core; import static java.text.MessageFormat.format; import java.io.IOException; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import org.eclipse.core.filesystem.IFileStore; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.OperationCanceledException; import org.eclipse.core.runtime.SubMonitor; import org.eclipse.remote.core.AbstractRemoteProcessBuilder; import org.eclipse.remote.core.IRemoteProcess; import org.eclipse.tcf.te.runtime.interfaces.properties.IPropertiesContainer; import org.eclipse.tcf.te.runtime.properties.PropertiesContainer; import org.eclipse.tcf.te.tcf.core.interfaces.IChannelManager; import org.eclipse.tcf.te.tcf.processes.core.interfaces.launcher.IProcessLauncher; import org.eclipse.tcf.te.tcf.processes.core.launcher.ProcessLauncher; import org.eclipse.tcf.te.tcf.remote.core.operation.TCFOperationStartProcess; public class TCFProcessBuilder extends AbstractRemoteProcessBuilder { private final TCFConnection fConnection; private Map<String, String> fEnv; public TCFProcessBuilder(TCFConnection connection, List<String> command) { super(connection.getRemoteConnection(), command); fConnection = connection; } public TCFProcessBuilder(TCFConnection connection, String... command) { this(connection, Arrays.asList(command)); } @Override public IFileStore directory() { IFileStore dir = super.directory(); if (dir == null) { dir = fConnection.getResource(fConnection.getWorkingDirectory()); directory(dir); } return dir; } @Override public Map<String, String> environment() { if (fEnv == null) { fEnv = new HashMap<String, String>(fConnection.getEnv()); } return fEnv; } @Override public int getSupportedFlags() { return 0; } @Override public IRemoteProcess start(int flags) throws IOException { if (!fConnection.isOpen()) { throw new IOException(format(Messages.TCFProcessBuilder_errorConnectionClosed, fConnection.getName())); } IFileStore dirStore = super.directory(); String dir; if (dirStore instanceof TCFFileStore) { dir = ((TCFFileStore) dirStore).getPath(); } else { dir = ""; //$NON-NLS-1$ } List<String> cmd = command(); if (cmd.size() < 1) throw new IOException(Messages.TCFProcessBuilder_errorNoCommand); String process= cmd.get(0); String[] args= cmd.subList(1, cmd.size()).toArray(new String[cmd.size()-1]); IPropertiesContainer launcherProps = new PropertiesContainer(); launcherProps.setProperty(IProcessLauncher.PROP_PROCESS_CWD, dir); launcherProps.setProperty(IProcessLauncher.PROP_PROCESS_PATH, process); launcherProps.setProperty(IProcessLauncher.PROP_PROCESS_ARGS, args); launcherProps.setProperty(IChannelManager.FLAG_FORCE_NEW, Boolean.FALSE); launcherProps.setProperty(ProcessLauncher.PROCESS_LAUNCH_FAILED_MESSAGE, format("Failed to launch process {0}" , process)); //$NON-NLS-1$ TCFProcessStreams streamsProxy = new TCFProcessStreams(); ProcessLauncher launcher = new ProcessLauncher(streamsProxy) { @SuppressWarnings("synthetic-access") @Override protected void mergeEnvironment(Map<String,String> processEnv, Map<String,String> processEnvDiff) { if (fEnv != null) { processEnv.clear(); processEnv.putAll(fEnv); } } }; TCFProcess remoteProcess = new TCFProcess(this, launcher); boolean ok = false; try { new TCFOperationStartProcess(fConnection.getPeerNode().getPeer(), launcher, launcherProps).execute(SubMonitor.convert(null)); remoteProcess.connectStreams(streamsProxy, redirectErrorStream()); ok = true; return remoteProcess; } catch (OperationCanceledException e) { return null; } catch (CoreException e) { throw new IOException(Messages.TCFProcessBuilder_errorLaunchingProcess, e); } finally { if (!ok) remoteProcess.destroy(); } } }