diff --git a/bundles/org.eclipse.remote.proxy.core/plugin.xml b/bundles/org.eclipse.remote.proxy.core/plugin.xml index 4f56f948bd4..2de33ec7138 100644 --- a/bundles/org.eclipse.remote.proxy.core/plugin.xml +++ b/bundles/org.eclipse.remote.proxy.core/plugin.xml @@ -40,7 +40,7 @@ + + T getService(IRemoteConnection connection, Class service) { - if (IRemoteCommandShellService.class.equals(service)) { - return (T) new ProxyCommandShellService(connection); - } - return null; - } - } -} diff --git a/bundles/org.eclipse.remote.proxy.core/src/org/eclipse/remote/internal/proxy/core/ProxyConnection.java b/bundles/org.eclipse.remote.proxy.core/src/org/eclipse/remote/internal/proxy/core/ProxyConnection.java index fa2d269c113..20a0cfcd324 100644 --- a/bundles/org.eclipse.remote.proxy.core/src/org/eclipse/remote/internal/proxy/core/ProxyConnection.java +++ b/bundles/org.eclipse.remote.proxy.core/src/org/eclipse/remote/internal/proxy/core/ProxyConnection.java @@ -37,8 +37,8 @@ import org.eclipse.remote.internal.proxy.core.commands.GetCwdCommand; import org.eclipse.remote.internal.proxy.core.commands.GetEnvCommand; import org.eclipse.remote.internal.proxy.core.commands.GetPropertiesCommand; import org.eclipse.remote.internal.proxy.core.messages.Messages; -import org.eclipse.remote.proxy.protocol.core.StreamChannelManager; import org.eclipse.remote.proxy.protocol.core.StreamChannel; +import org.eclipse.remote.proxy.protocol.core.StreamChannelManager; import org.eclipse.remote.proxy.protocol.core.exceptions.ProxyException; import com.jcraft.jsch.ChannelShell; @@ -48,7 +48,8 @@ import com.jcraft.jsch.ChannelShell; */ public class ProxyConnection implements IRemoteConnectionControlService, IRemoteConnectionChangeListener, IRemoteProcessService, - IRemoteCommandShellService, IRemoteConnectionHostService { + IRemoteCommandShellService, IRemoteConnectionHostService, + IRemoteConnectionPropertyService { // Connection Type ID public static final String JSCH_ID = "org.eclipse.remote.Proxy"; //$NON-NLS-1$ @@ -72,7 +73,6 @@ public class ProxyConnection implements IRemoteConnectionControlService, private StreamChannelManager channelMux; private StreamChannel commandChannel; private boolean isOpen; - private boolean proxyRunning; private final IRemoteConnection fRemoteConnection; @@ -133,7 +133,8 @@ public class ProxyConnection implements IRemoteConnectionControlService, || IRemoteConnectionPropertyService.class.equals(service) || IRemoteConnectionHostService.class.equals(service) || IRemoteProcessService.class.equals(service) - || IRemoteCommandShellService.class.equals(service)) { + || IRemoteCommandShellService.class.equals(service) + || IRemoteConnectionPropertyService.class.equals(service)) { return (T) connection.getService(ProxyConnection.class); } else { return null; @@ -348,7 +349,7 @@ public class ProxyConnection implements IRemoteConnectionControlService, @Override public IRemoteProcess getCommandShell(int flags) throws IOException { - throw new IOException("Not implemented yet"); + return new ProxyProcessBuilder(this).start(flags); } @Override @@ -454,4 +455,9 @@ public class ProxyConnection implements IRemoteConnectionControlService, wc.setAttribute(USERNAME_ATTR, username); } } + + @Override + public String getProperty(String key) { + return fProperties.get(key); + } } diff --git a/bundles/org.eclipse.remote.proxy.core/src/org/eclipse/remote/internal/proxy/core/ProxyConnectionBootstrap.java b/bundles/org.eclipse.remote.proxy.core/src/org/eclipse/remote/internal/proxy/core/ProxyConnectionBootstrap.java index 9262b93d5fc..03b2aa2017e 100644 --- a/bundles/org.eclipse.remote.proxy.core/src/org/eclipse/remote/internal/proxy/core/ProxyConnectionBootstrap.java +++ b/bundles/org.eclipse.remote.proxy.core/src/org/eclipse/remote/internal/proxy/core/ProxyConnectionBootstrap.java @@ -211,7 +211,7 @@ public class ProxyConnectionBootstrap { int n; while ((n = in.read(buf)) >= 0) { if (n < 510) { - writer.write(encoder.encodeToString(Arrays.copyOf(buf, n)) + "\n"); + writer.write(encoder.encodeToString(Arrays.copyOf(buf, n)) + "\n"); //$NON-NLS-1$ } else { writer.write(encoder.encodeToString(buf)); } @@ -311,7 +311,7 @@ public class ProxyConnectionBootstrap { throw new RemoteConnectionException(Messages.ProxyConnectionBootstrap_8); } exec = (ChannelExec) session.openChannel("exec"); //$NON-NLS-1$ - exec.setCommand("/bin/sh -l"); //$NON-NLS-1$ + exec.setCommand("/bin/bash -l"); //$NON-NLS-1$ exec.connect(); return exec; } catch (JSchException e) { diff --git a/bundles/org.eclipse.remote.proxy.core/src/org/eclipse/remote/internal/proxy/core/ProxyProcess.java b/bundles/org.eclipse.remote.proxy.core/src/org/eclipse/remote/internal/proxy/core/ProxyProcess.java index 5ac03036b44..95cd5a9de16 100644 --- a/bundles/org.eclipse.remote.proxy.core/src/org/eclipse/remote/internal/proxy/core/ProxyProcess.java +++ b/bundles/org.eclipse.remote.proxy.core/src/org/eclipse/remote/internal/proxy/core/ProxyProcess.java @@ -12,18 +12,18 @@ import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.util.List; -import org.eclipse.remote.core.IRemoteConnection; import org.eclipse.remote.core.IRemoteProcess; -import org.eclipse.remote.core.IRemoteProcessBuilder; import org.eclipse.remote.core.IRemoteProcessControlService; import org.eclipse.remote.core.IRemoteProcessSignalService; import org.eclipse.remote.core.IRemoteProcessTerminalService; -import org.eclipse.remote.internal.core.RemoteProcess; +import org.eclipse.remote.proxy.protocol.core.Protocol; import org.eclipse.remote.proxy.protocol.core.StreamChannel; -public class ProxyProcess extends RemoteProcess implements IRemoteProcessControlService, IRemoteProcessTerminalService { +public class ProxyProcess implements IRemoteProcessControlService, IRemoteProcessTerminalService { private IRemoteProcess remoteProcess; + private final StreamChannel stdIOChan; private final StreamChannel stdErrChan; private final StreamChannel controlChan; @@ -44,8 +44,8 @@ public class ProxyProcess extends RemoteProcess implements IRemoteProcessControl @SuppressWarnings("unchecked") @Override public T getService(IRemoteProcess remoteProcess, Class service) { - if (ProxyProcess.class.equals(service) && remoteProcess instanceof ProxyProcess) { - return (T) remoteProcess; + if (ProxyProcess.class.equals(service)) { + return (T) new ProxyProcess(remoteProcess); } if (IRemoteProcessControlService.class.equals(service) || IRemoteProcessSignalService.class.equals(service) || IRemoteProcessTerminalService.class.equals(service)) { @@ -55,17 +55,19 @@ public class ProxyProcess extends RemoteProcess implements IRemoteProcessControl } } - public ProxyProcess(IRemoteConnection connection, IRemoteProcessBuilder builder, StreamChannel stdIO, StreamChannel stdErr, StreamChannel control) { - super(connection, builder); - stdIOChan = stdIO; - stdErrChan = stdErr; - controlChan = control; - cmdStream = new DataOutputStream(control.getOutputStream()); - resultStream = new DataInputStream(control.getInputStream()); + protected ProxyProcess(IRemoteProcess process) { + remoteProcess = process; + ProxyProcessBuilder builder = (ProxyProcessBuilder)process.getProcessBuilder(); + List streams = builder.getStreams(); + controlChan = streams.get(0); + stdIOChan = streams.get(1); + stdErrChan = streams.size() > 2 ? streams.get(2) : null; + cmdStream = new DataOutputStream(controlChan.getOutputStream()); + resultStream = new DataInputStream(controlChan.getInputStream()); isCompleted = false; exitValue = 0; - cmdThread = new Thread("process " + builder.command().get(0) + " result reader") { //$NON-NLS-1$ //$NON-NLS-2$ + cmdThread = new Thread("process result reader") { //$NON-NLS-1$ @Override public void run() { try { @@ -77,36 +79,15 @@ public class ProxyProcess extends RemoteProcess implements IRemoteProcessControl try { stdIOChan.close(); } catch (IOException e1) { - // TODO Auto-generated catch block - e1.printStackTrace(); + // Ignore } try { - stdErrChan.close(); + if (stdErrChan != null) { + stdErrChan.close(); + } } catch (IOException e1) { - // TODO Auto-generated catch block - e1.printStackTrace(); + // Ignore } -// if (stdout == null) { -// try { -// stdIOChan.getInputStream().close(); -// } catch (IOException e) { -// // Ignore -// } -// } -// if (stdin == null) { -// try { -// stdIOChan.getOutputStream().close(); -// } catch (IOException e) { -// // Ignore -// } -// } -// if (stderr == null) { -// try { -// stdErrChan.close(); -// } catch (IOException e) { -// // Ignore -// } -// } try { controlChan.close(); } catch (IOException e) { @@ -125,7 +106,7 @@ public class ProxyProcess extends RemoteProcess implements IRemoteProcessControl @Override public void destroy() { try { - cmdStream.writeByte(0); + cmdStream.writeByte(Protocol.CONTROL_KILL); cmdStream.flush(); } catch (IOException e) { isCompleted = true; @@ -152,6 +133,19 @@ public class ProxyProcess extends RemoteProcess implements IRemoteProcessControl */ @Override public InputStream getErrorStream() { + if (stdErrChan == null) { + return new InputStream() { + @Override + public int read() throws IOException { + return -1; + } + + @Override + public int available() { + return 0; + } + }; + } return stdErrChan.getInputStream(); } @@ -203,6 +197,15 @@ public class ProxyProcess extends RemoteProcess implements IRemoteProcessControl @Override public void setTerminalSize(int cols, int rows, int pwidth, int pheight) { - // Nothing? + try { + cmdStream.writeByte(Protocol.CONTROL_SETTERMINALSIZE); + cmdStream.writeInt(cols); + cmdStream.writeInt(rows); + cmdStream.writeInt(pwidth); + cmdStream.writeInt(pheight); + cmdStream.flush(); + } catch (IOException e) { + // Dealt with somewhere else hopefully + } } } diff --git a/bundles/org.eclipse.remote.proxy.core/src/org/eclipse/remote/internal/proxy/core/ProxyProcessBuilder.java b/bundles/org.eclipse.remote.proxy.core/src/org/eclipse/remote/internal/proxy/core/ProxyProcessBuilder.java index 4d509ec1205..024119405a7 100644 --- a/bundles/org.eclipse.remote.proxy.core/src/org/eclipse/remote/internal/proxy/core/ProxyProcessBuilder.java +++ b/bundles/org.eclipse.remote.proxy.core/src/org/eclipse/remote/internal/proxy/core/ProxyProcessBuilder.java @@ -8,6 +8,7 @@ package org.eclipse.remote.internal.proxy.core; import java.io.IOException; +import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; @@ -22,6 +23,7 @@ import org.eclipse.remote.core.IRemoteFileService; import org.eclipse.remote.core.IRemoteProcess; import org.eclipse.remote.core.IRemoteProcessBuilder; import org.eclipse.remote.internal.proxy.core.commands.ExecCommand; +import org.eclipse.remote.internal.proxy.core.commands.ShellCommand; import org.eclipse.remote.internal.proxy.core.messages.Messages; import org.eclipse.remote.proxy.protocol.core.StreamChannel; import org.eclipse.remote.proxy.protocol.core.exceptions.ProxyException; @@ -29,6 +31,7 @@ import org.eclipse.remote.proxy.protocol.core.exceptions.ProxyException; public class ProxyProcessBuilder extends AbstractRemoteProcessBuilder { private final ProxyConnection proxyConnection; private Map remoteEnv; + private List streams = new ArrayList<>(); public ProxyProcessBuilder(ProxyConnection connection, List command) { super(connection.getRemoteConnection(), command); @@ -42,6 +45,17 @@ public class ProxyProcessBuilder extends AbstractRemoteProcessBuilder { public ProxyProcessBuilder(ProxyConnection connection, String... command) { this(connection, Arrays.asList(command)); } + + /** + * Constructor for creating command shell + * @param connection + */ + public ProxyProcessBuilder(ProxyConnection connection) { + super(connection.getRemoteConnection(), (List)null); + proxyConnection = connection; + redirectErrorStream(true); + } + /* * (non-Javadoc) @@ -76,41 +90,66 @@ public class ProxyProcessBuilder extends AbstractRemoteProcessBuilder { */ @Override public IRemoteProcess start(int flags) throws IOException { - final List cmdArgs = command(); - if (cmdArgs.size() < 1) { - throw new IndexOutOfBoundsException(); - } - /* - * If environment has not been touched, then don't send anything - */ - final Map env = new HashMap(); - if (remoteEnv != null) { - env.putAll(remoteEnv); - } - final boolean append = (flags & IRemoteProcessBuilder.APPEND_ENVIRONMENT) != 0 || remoteEnv == null; - final ProxyConnection conn = getRemoteConnection().getService(ProxyConnection.class); if (conn == null) { throw new IOException(Messages.ProxyProcessBuilder_0); } - final StreamChannel chanStdIO = conn.openChannel(); - final StreamChannel chanStdErr = conn.openChannel(); - final StreamChannel chanControl = conn.openChannel(); + Job job; - Job job = new Job("process executor") { //$NON-NLS-1$ - @Override - protected IStatus run(IProgressMonitor monitor) { - ExecCommand cmd = new ExecCommand(conn, cmdArgs, env, directory().toURI().getPath(), redirectErrorStream(), append, - chanStdIO.getId(), chanStdErr.getId(), chanControl.getId()); - try { - cmd.getResult(monitor); - } catch (ProxyException e) { - return new Status(IStatus.ERROR, Activator.getUniqueIdentifier(), e.getMessage()); - } - return monitor.isCanceled() ? Status.CANCEL_STATUS : Status.OK_STATUS; + final List cmdArgs = command(); + if (cmdArgs != null) { + if (cmdArgs.size() < 1) { + throw new IOException(Messages.ProxyProcessBuilder_1); } - }; + /* + * If environment has not been touched, then don't send anything + */ + final Map env = new HashMap(); + if (remoteEnv != null) { + env.putAll(remoteEnv); + } + + final boolean append = (flags & IRemoteProcessBuilder.APPEND_ENVIRONMENT) != 0 || remoteEnv == null; + + streams.add(conn.openChannel()); + streams.add(conn.openChannel()); + streams.add(conn.openChannel()); + + job = new Job("process executor") { //$NON-NLS-1$ + @Override + protected IStatus run(IProgressMonitor monitor) { + ExecCommand cmd = new ExecCommand(conn, cmdArgs, env, directory().toURI().getPath(), redirectErrorStream(), append, + streams.get(0).getId(), streams.get(1).getId(), streams.get(2).getId()); + try { + cmd.getResult(monitor); + } catch (ProxyException e) { + return new Status(IStatus.ERROR, Activator.getUniqueIdentifier(), e.getMessage()); + } + return monitor.isCanceled() ? Status.CANCEL_STATUS : Status.OK_STATUS; + } + }; + } else { + /* + * Start command shell + */ + streams.add(conn.openChannel()); + streams.add(conn.openChannel()); + + job = new Job("process executor") { //$NON-NLS-1$ + @Override + protected IStatus run(IProgressMonitor monitor) { + ShellCommand cmd = new ShellCommand(conn, streams.get(0).getId(), streams.get(1).getId()); + try { + cmd.getResult(monitor); + } catch (ProxyException e) { + return new Status(IStatus.ERROR, Activator.getUniqueIdentifier(), e.getMessage()); + } + return monitor.isCanceled() ? Status.CANCEL_STATUS : Status.OK_STATUS; + } + }; + } + job.schedule(); try { job.join(); @@ -121,7 +160,10 @@ public class ProxyProcessBuilder extends AbstractRemoteProcessBuilder { throw new IOException(job.getResult().getMessage()); } - ProxyProcess proc = new ProxyProcess(getRemoteConnection(), this, chanStdIO, chanStdErr, chanControl); - return proc; + return newRemoteProcess(); + } + + public List getStreams() { + return streams; } } diff --git a/bundles/org.eclipse.remote.proxy.core/src/org/eclipse/remote/internal/proxy/core/commands/AbstractCommand.java b/bundles/org.eclipse.remote.proxy.core/src/org/eclipse/remote/internal/proxy/core/commands/AbstractCommand.java index 52e14cc8fed..dec2d98c77c 100644 --- a/bundles/org.eclipse.remote.proxy.core/src/org/eclipse/remote/internal/proxy/core/commands/AbstractCommand.java +++ b/bundles/org.eclipse.remote.proxy.core/src/org/eclipse/remote/internal/proxy/core/commands/AbstractCommand.java @@ -19,6 +19,7 @@ import java.util.concurrent.TimeoutException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.SubMonitor; import org.eclipse.remote.internal.proxy.core.ProxyConnection; +import org.eclipse.remote.internal.proxy.core.messages.Messages; import org.eclipse.remote.proxy.protocol.core.StreamChannel; import org.eclipse.remote.proxy.protocol.core.exceptions.ProxyException; @@ -28,15 +29,11 @@ public abstract class AbstractCommand implements Callable { private static ExecutorService executors = Executors.newSingleThreadExecutor(); private final ProxyConnection connection; - private Future asyncCmdInThread() throws ProxyException { return executors.submit(this); } - private void finalizeCmdInThread() { - } - public StreamChannel openChannel() throws IOException { return connection.openChannel(); } @@ -52,12 +49,8 @@ public abstract class AbstractCommand implements Callable { public T getResult(IProgressMonitor monitor) throws ProxyException { Future future = null; progressMonitor = SubMonitor.convert(monitor, 10); - try { - future = asyncCmdInThread(); - return waitCmdInThread(future); - } finally { - finalizeCmdInThread(); - } + future = asyncCmdInThread(); + return waitCmdInThread(future); } private T waitCmdInThread(Future future) throws ProxyException { @@ -78,7 +71,7 @@ public abstract class AbstractCommand implements Callable { Thread.currentThread().interrupt(); // set current thread flag } future.cancel(true); - throw new ProxyException("Operation cancelled by user"); + throw new ProxyException(Messages.AbstractCommand_0); } @Override diff --git a/bundles/org.eclipse.remote.proxy.core/src/org/eclipse/remote/internal/proxy/core/commands/ChildInfosCommand.java b/bundles/org.eclipse.remote.proxy.core/src/org/eclipse/remote/internal/proxy/core/commands/ChildInfosCommand.java index 325f5c6732a..3e6af47c3f0 100644 --- a/bundles/org.eclipse.remote.proxy.core/src/org/eclipse/remote/internal/proxy/core/commands/ChildInfosCommand.java +++ b/bundles/org.eclipse.remote.proxy.core/src/org/eclipse/remote/internal/proxy/core/commands/ChildInfosCommand.java @@ -44,7 +44,6 @@ public class ChildInfosCommand extends AbstractCommand { byte res = in.readByte(); if (res != Protocol.PROTO_OK) { String errMsg = in.readUTF(); - System.err.println("childinfos command failed:" + errMsg); throw new ProxyException(errMsg); } diff --git a/bundles/org.eclipse.remote.proxy.core/src/org/eclipse/remote/internal/proxy/core/commands/DeleteCommand.java b/bundles/org.eclipse.remote.proxy.core/src/org/eclipse/remote/internal/proxy/core/commands/DeleteCommand.java index 96e44aa1c04..bd7463c8f16 100644 --- a/bundles/org.eclipse.remote.proxy.core/src/org/eclipse/remote/internal/proxy/core/commands/DeleteCommand.java +++ b/bundles/org.eclipse.remote.proxy.core/src/org/eclipse/remote/internal/proxy/core/commands/DeleteCommand.java @@ -41,7 +41,6 @@ public class DeleteCommand extends AbstractCommand { byte res = in.readByte(); if (res != Protocol.PROTO_OK) { String errMsg = in.readUTF(); - System.err.println("delete command failed:" + errMsg); throw new ProxyException(errMsg); } return null; diff --git a/bundles/org.eclipse.remote.proxy.core/src/org/eclipse/remote/internal/proxy/core/commands/ExecCommand.java b/bundles/org.eclipse.remote.proxy.core/src/org/eclipse/remote/internal/proxy/core/commands/ExecCommand.java index 3bf1136fe88..c03decd2e73 100644 --- a/bundles/org.eclipse.remote.proxy.core/src/org/eclipse/remote/internal/proxy/core/commands/ExecCommand.java +++ b/bundles/org.eclipse.remote.proxy.core/src/org/eclipse/remote/internal/proxy/core/commands/ExecCommand.java @@ -26,12 +26,12 @@ public class ExecCommand extends AbstractCommand { private final String directory; private final boolean appendEnv; private final boolean redirect; - private final int chanA; - private final int chanB; - private final int chanC; + private final int cmdChan; + private final int ioChan; + private final int errChan; public ExecCommand(ProxyConnection conn, List command, Map env, String directory, boolean redirect, boolean appendEnv, - int chanA, int chanB, int chanC) { + int cmdChan, int ioChan, int errChan) { super(conn); this.out = new DataOutputStream(conn.getCommandChannel().getOutputStream()); this.in = new DataInputStream(conn.getCommandChannel().getInputStream()); @@ -40,18 +40,18 @@ public class ExecCommand extends AbstractCommand { this.directory = directory; this.redirect = redirect; this.appendEnv = appendEnv; - this.chanA = chanA; - this.chanB = chanB; - this.chanC = chanC; + this.cmdChan = cmdChan; + this.ioChan = ioChan; + this.errChan = errChan; } public Void call() throws ProxyException { try { out.writeByte(Protocol.PROTO_COMMAND); out.writeShort(Protocol.CMD_EXEC); - out.writeByte(chanA); - out.writeByte(chanB); - out.writeByte(chanC); + out.writeByte(cmdChan); + out.writeByte(ioChan); + out.writeByte(errChan); out.writeInt(command.size()); for (String arg : command) { out.writeUTF(arg); @@ -69,7 +69,6 @@ public class ExecCommand extends AbstractCommand { byte res = in.readByte(); if (res != Protocol.PROTO_OK) { String errMsg = in.readUTF(); - System.err.println("exec command failed:" + errMsg); throw new ProxyException(errMsg); } } catch (IOException e) { diff --git a/bundles/org.eclipse.remote.proxy.core/src/org/eclipse/remote/internal/proxy/core/commands/FetchInfoCommand.java b/bundles/org.eclipse.remote.proxy.core/src/org/eclipse/remote/internal/proxy/core/commands/FetchInfoCommand.java index b04ce3f8e82..06163711351 100644 --- a/bundles/org.eclipse.remote.proxy.core/src/org/eclipse/remote/internal/proxy/core/commands/FetchInfoCommand.java +++ b/bundles/org.eclipse.remote.proxy.core/src/org/eclipse/remote/internal/proxy/core/commands/FetchInfoCommand.java @@ -44,7 +44,6 @@ public class FetchInfoCommand extends AbstractCommand { byte res = in.readByte(); if (res != Protocol.PROTO_OK) { String errMsg = in.readUTF(); - System.err.println("fetchinfo command failed:" + errMsg); throw new ProxyException(errMsg); } diff --git a/bundles/org.eclipse.remote.proxy.core/src/org/eclipse/remote/internal/proxy/core/commands/GetCwdCommand.java b/bundles/org.eclipse.remote.proxy.core/src/org/eclipse/remote/internal/proxy/core/commands/GetCwdCommand.java index 2d1eb027c96..99a373cae13 100644 --- a/bundles/org.eclipse.remote.proxy.core/src/org/eclipse/remote/internal/proxy/core/commands/GetCwdCommand.java +++ b/bundles/org.eclipse.remote.proxy.core/src/org/eclipse/remote/internal/proxy/core/commands/GetCwdCommand.java @@ -40,7 +40,6 @@ public class GetCwdCommand extends AbstractCommand { byte res = in.readByte(); if (res != Protocol.PROTO_OK) { String errMsg = in.readUTF(); - System.err.println("getcwd command failed:" + errMsg); throw new ProxyException(errMsg); } diff --git a/bundles/org.eclipse.remote.proxy.core/src/org/eclipse/remote/internal/proxy/core/commands/GetEnvCommand.java b/bundles/org.eclipse.remote.proxy.core/src/org/eclipse/remote/internal/proxy/core/commands/GetEnvCommand.java index df9e8d3e7ed..773f39f3f42 100644 --- a/bundles/org.eclipse.remote.proxy.core/src/org/eclipse/remote/internal/proxy/core/commands/GetEnvCommand.java +++ b/bundles/org.eclipse.remote.proxy.core/src/org/eclipse/remote/internal/proxy/core/commands/GetEnvCommand.java @@ -42,7 +42,6 @@ public class GetEnvCommand extends AbstractCommand> { byte res = in.readByte(); if (res != Protocol.PROTO_OK) { String errMsg = in.readUTF(); - System.err.println("getenv command failed:" + errMsg); throw new ProxyException(errMsg); } diff --git a/bundles/org.eclipse.remote.proxy.core/src/org/eclipse/remote/internal/proxy/core/commands/GetInputStreamCommand.java b/bundles/org.eclipse.remote.proxy.core/src/org/eclipse/remote/internal/proxy/core/commands/GetInputStreamCommand.java index 472868c2c4c..b93b695b729 100644 --- a/bundles/org.eclipse.remote.proxy.core/src/org/eclipse/remote/internal/proxy/core/commands/GetInputStreamCommand.java +++ b/bundles/org.eclipse.remote.proxy.core/src/org/eclipse/remote/internal/proxy/core/commands/GetInputStreamCommand.java @@ -14,8 +14,8 @@ import java.io.IOException; import java.io.InputStream; import org.eclipse.remote.internal.proxy.core.ProxyConnection; -import org.eclipse.remote.proxy.protocol.core.StreamChannel; import org.eclipse.remote.proxy.protocol.core.Protocol; +import org.eclipse.remote.proxy.protocol.core.StreamChannel; import org.eclipse.remote.proxy.protocol.core.exceptions.ProxyException; public class GetInputStreamCommand extends AbstractCommand { @@ -47,7 +47,6 @@ public class GetInputStreamCommand extends AbstractCommand { byte res = in.readByte(); if (res != Protocol.PROTO_OK) { String errMsg = in.readUTF(); - System.err.println("getinputstream command failed:" + errMsg); throw new ProxyException(errMsg); } diff --git a/bundles/org.eclipse.remote.proxy.core/src/org/eclipse/remote/internal/proxy/core/commands/GetOutputStreamCommand.java b/bundles/org.eclipse.remote.proxy.core/src/org/eclipse/remote/internal/proxy/core/commands/GetOutputStreamCommand.java index 35be0bf6d16..c1fc27719bd 100644 --- a/bundles/org.eclipse.remote.proxy.core/src/org/eclipse/remote/internal/proxy/core/commands/GetOutputStreamCommand.java +++ b/bundles/org.eclipse.remote.proxy.core/src/org/eclipse/remote/internal/proxy/core/commands/GetOutputStreamCommand.java @@ -14,8 +14,8 @@ import java.io.IOException; import java.io.OutputStream; import org.eclipse.remote.internal.proxy.core.ProxyConnection; -import org.eclipse.remote.proxy.protocol.core.StreamChannel; import org.eclipse.remote.proxy.protocol.core.Protocol; +import org.eclipse.remote.proxy.protocol.core.StreamChannel; import org.eclipse.remote.proxy.protocol.core.exceptions.ProxyException; public class GetOutputStreamCommand extends AbstractCommand { @@ -47,7 +47,6 @@ public class GetOutputStreamCommand extends AbstractCommand { byte res = in.readByte(); if (res != Protocol.PROTO_OK) { String errMsg = in.readUTF(); - System.err.println("getoutputstream command failed:" + errMsg); throw new ProxyException(errMsg); } diff --git a/bundles/org.eclipse.remote.proxy.core/src/org/eclipse/remote/internal/proxy/core/commands/GetPropertiesCommand.java b/bundles/org.eclipse.remote.proxy.core/src/org/eclipse/remote/internal/proxy/core/commands/GetPropertiesCommand.java index a01b27aad2f..ad77868ad45 100644 --- a/bundles/org.eclipse.remote.proxy.core/src/org/eclipse/remote/internal/proxy/core/commands/GetPropertiesCommand.java +++ b/bundles/org.eclipse.remote.proxy.core/src/org/eclipse/remote/internal/proxy/core/commands/GetPropertiesCommand.java @@ -42,7 +42,6 @@ public class GetPropertiesCommand extends AbstractCommand> { byte res = in.readByte(); if (res != Protocol.PROTO_OK) { String errMsg = in.readUTF(); - System.err.println("getproperties command failed:" + errMsg); throw new ProxyException(errMsg); } diff --git a/bundles/org.eclipse.remote.proxy.core/src/org/eclipse/remote/internal/proxy/core/commands/MkdirCommand.java b/bundles/org.eclipse.remote.proxy.core/src/org/eclipse/remote/internal/proxy/core/commands/MkdirCommand.java index a6cf33b74c8..eebb748f543 100644 --- a/bundles/org.eclipse.remote.proxy.core/src/org/eclipse/remote/internal/proxy/core/commands/MkdirCommand.java +++ b/bundles/org.eclipse.remote.proxy.core/src/org/eclipse/remote/internal/proxy/core/commands/MkdirCommand.java @@ -41,7 +41,6 @@ public class MkdirCommand extends AbstractCommand { byte res = in.readByte(); if (res != Protocol.PROTO_OK) { String errMsg = in.readUTF(); - System.err.println("mkdir command failed:" + errMsg); throw new ProxyException(errMsg); } return null; diff --git a/bundles/org.eclipse.remote.proxy.core/src/org/eclipse/remote/internal/proxy/core/commands/PutInfoCommand.java b/bundles/org.eclipse.remote.proxy.core/src/org/eclipse/remote/internal/proxy/core/commands/PutInfoCommand.java index 6e5a4fc6b3a..d4a61492c08 100644 --- a/bundles/org.eclipse.remote.proxy.core/src/org/eclipse/remote/internal/proxy/core/commands/PutInfoCommand.java +++ b/bundles/org.eclipse.remote.proxy.core/src/org/eclipse/remote/internal/proxy/core/commands/PutInfoCommand.java @@ -47,7 +47,6 @@ public class PutInfoCommand extends AbstractCommand { byte res = in.readByte(); if (res != Protocol.PROTO_OK) { String errMsg = in.readUTF(); - System.err.println("fetchinfo command failed:" + errMsg); throw new ProxyException(errMsg); } return null; diff --git a/bundles/org.eclipse.remote.proxy.core/src/org/eclipse/remote/internal/proxy/core/commands/ShellCommand.java b/bundles/org.eclipse.remote.proxy.core/src/org/eclipse/remote/internal/proxy/core/commands/ShellCommand.java new file mode 100644 index 00000000000..66a10884142 --- /dev/null +++ b/bundles/org.eclipse.remote.proxy.core/src/org/eclipse/remote/internal/proxy/core/commands/ShellCommand.java @@ -0,0 +1,51 @@ +/******************************************************************************* + * Copyright (c) 2016 Oak Ridge National Laboratory 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 + *******************************************************************************/ +package org.eclipse.remote.internal.proxy.core.commands; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import org.eclipse.remote.internal.proxy.core.ProxyConnection; +import org.eclipse.remote.proxy.protocol.core.Protocol; +import org.eclipse.remote.proxy.protocol.core.exceptions.ProxyException; + +public class ShellCommand extends AbstractCommand { + + private final DataOutputStream out; + private final DataInputStream in; + private final int cmdChan; + private final int ioChan; + + public ShellCommand(ProxyConnection conn, int cmdChan, int ioChan) { + super(conn); + this.out = new DataOutputStream(conn.getCommandChannel().getOutputStream()); + this.in = new DataInputStream(conn.getCommandChannel().getInputStream()); + this.cmdChan = cmdChan; + this.ioChan = ioChan; + } + + public Void call() throws ProxyException { + try { + out.writeByte(Protocol.PROTO_COMMAND); + out.writeShort(Protocol.CMD_SHELL); + out.writeByte(cmdChan); + out.writeByte(ioChan); + out.flush(); + + byte res = in.readByte(); + if (res != Protocol.PROTO_OK) { + String errMsg = in.readUTF(); + throw new ProxyException(errMsg); + } + } catch (IOException e) { + throw new ProxyException(e.getMessage()); + } + return null; + } +} diff --git a/bundles/org.eclipse.remote.proxy.core/src/org/eclipse/remote/internal/proxy/core/messages/Messages.java b/bundles/org.eclipse.remote.proxy.core/src/org/eclipse/remote/internal/proxy/core/messages/Messages.java index be67bf97d0d..6d7c896a54f 100755 --- a/bundles/org.eclipse.remote.proxy.core/src/org/eclipse/remote/internal/proxy/core/messages/Messages.java +++ b/bundles/org.eclipse.remote.proxy.core/src/org/eclipse/remote/internal/proxy/core/messages/Messages.java @@ -16,6 +16,8 @@ import org.eclipse.osgi.util.NLS; public class Messages extends NLS { private static final String BUNDLE_ID = "org.eclipse.remote.internal.proxy.core.messages.messages"; //$NON-NLS-1$ + public static String AbstractCommand_0; + public static String AbstractRemoteCommand_format1; public static String AbstractRemoteCommand_format2; public static String AbstractRemoteCommand_Get_symlink_target; @@ -56,6 +58,8 @@ public class Messages extends NLS { public static String JschFileStore_A_file_of_name_already_exists; public static String JschFileStore_The_parent_of_directory_does_not_exist; + public static String ProxyCommandShell_0; + public static String ProxyConnection_0; public static String ProxyConnection_2; @@ -98,6 +102,8 @@ public class Messages extends NLS { public static String ProxyProcessBuilder_0; + public static String ProxyProcessBuilder_1; + static { // load message values from bundle file NLS.initializeMessages(BUNDLE_ID, Messages.class); diff --git a/bundles/org.eclipse.remote.proxy.core/src/org/eclipse/remote/internal/proxy/core/messages/messages.properties b/bundles/org.eclipse.remote.proxy.core/src/org/eclipse/remote/internal/proxy/core/messages/messages.properties index a8a051178fc..d96b42bbd0c 100755 --- a/bundles/org.eclipse.remote.proxy.core/src/org/eclipse/remote/internal/proxy/core/messages/messages.properties +++ b/bundles/org.eclipse.remote.proxy.core/src/org/eclipse/remote/internal/proxy/core/messages/messages.properties @@ -8,6 +8,7 @@ # Contributors: # IBM Corporation - initial implementation ############################################################################### +AbstractCommand_0=Operation cancelled by user AbstractRemoteCommand_format1={0,number,integer} {1} completed AbstractRemoteCommand_format2={0,number,integer} {1} of {2,number,integer} {3} complete ({4,number,percent}) AbstractRemoteCommand_Get_symlink_target=Get symlink target @@ -43,6 +44,7 @@ JschFileStore_No_remote_services_found_for_URI=No remote services found for URI: JschFileStore_The_directory_could_not_be_created=The directory {0} could not be created JschFileStore_A_file_of_name_already_exists=A file of name {0} already exists JschFileStore_The_parent_of_directory_does_not_exist=The parent of directory {0} does not exist +ProxyCommandShell_0=Unable to locate connection for command shell ProxyConnection_0=Opening connection... ProxyConnection_2=User canceled opening connection ProxyConnectionBootstrap_0=Initializing @@ -64,3 +66,4 @@ ProxyFileStore_5=A file of name {0} already exists ProxyFileStore_6=File {0} does not exist ProxyFileStore_7={0} is a directory ProxyProcessBuilder_0=Unable to located connection for this process +ProxyProcessBuilder_1=No command to run\! diff --git a/bundles/org.eclipse.remote.proxy.protocol.core/META-INF/MANIFEST.MF b/bundles/org.eclipse.remote.proxy.protocol.core/META-INF/MANIFEST.MF index db3c660a187..fdfcbeb9b3b 100644 --- a/bundles/org.eclipse.remote.proxy.protocol.core/META-INF/MANIFEST.MF +++ b/bundles/org.eclipse.remote.proxy.protocol.core/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %pluginName Bundle-SymbolicName: org.eclipse.remote.proxy.protocol.core;singleton:=true -Bundle-Version: 1.0.0.qualifier +Bundle-Version: 2.0.0.qualifier Bundle-Activator: org.eclipse.remote.internal.proxy.protocol.core.Activator Bundle-Vendor: %pluginProvider Bundle-ActivationPolicy: lazy diff --git a/bundles/org.eclipse.remote.proxy.protocol.core/pom.xml b/bundles/org.eclipse.remote.proxy.protocol.core/pom.xml index ef7267b5509..ac47f7a1cda 100644 --- a/bundles/org.eclipse.remote.proxy.protocol.core/pom.xml +++ b/bundles/org.eclipse.remote.proxy.protocol.core/pom.xml @@ -12,5 +12,5 @@ org.eclipse.remote.proxy.protocol.core eclipse-plugin -1.0.0-SNAPSHOT +2.0.0-SNAPSHOT diff --git a/bundles/org.eclipse.remote.proxy.protocol.core/src/org/eclipse/remote/proxy/protocol/core/Protocol.java b/bundles/org.eclipse.remote.proxy.protocol.core/src/org/eclipse/remote/proxy/protocol/core/Protocol.java index e10835bcf06..0e7257e9d26 100644 --- a/bundles/org.eclipse.remote.proxy.protocol.core/src/org/eclipse/remote/proxy/protocol/core/Protocol.java +++ b/bundles/org.eclipse.remote.proxy.protocol.core/src/org/eclipse/remote/proxy/protocol/core/Protocol.java @@ -17,16 +17,25 @@ public class Protocol { public final static short CmdBase = 100; - public final static short CMD_EXEC = CmdBase + 1; - public final static short CMD_SHELL = CmdBase + 2; - public final static short CMD_GETCWD = CmdBase + 3; - public final static short CMD_GETENV = CmdBase + 4; - public final static short CMD_CHILDINFOS = CmdBase + 5; - public final static short CMD_DELETE = CmdBase + 6; - public final static short CMD_FETCHINFO = CmdBase + 7; - public final static short CMD_GETINPUTSTREAM = CmdBase + 8; + public final static short CMD_EXEC = CmdBase + 1; + public final static short CMD_SHELL = CmdBase + 2; + public final static short CMD_GETCWD = CmdBase + 3; + public final static short CMD_GETENV = CmdBase + 4; + public final static short CMD_CHILDINFOS = CmdBase + 5; + public final static short CMD_DELETE = CmdBase + 6; + public final static short CMD_FETCHINFO = CmdBase + 7; + public final static short CMD_GETINPUTSTREAM = CmdBase + 8; public final static short CMD_GETOUTPUTSTREAM = CmdBase + 9; - public final static short CMD_MKDIR = CmdBase + 10; + public final static short CMD_MKDIR = CmdBase + 10; public final static short CMD_PUTINFO = CmdBase + 11; - public final static short CMD_GETPROPERTIES = CmdBase + 12; + public final static short CMD_GETPROPERTIES = CmdBase + 12; + + /** + * @since 2.0 + */ + public final static byte CONTROL_KILL = 0; + /** + * @since 2.0 + */ + public final static byte CONTROL_SETTERMINALSIZE = 1; } diff --git a/bundles/org.eclipse.remote.proxy.server.core/.settings/org.eclipse.jdt.core.prefs b/bundles/org.eclipse.remote.proxy.server.core/.settings/org.eclipse.jdt.core.prefs index 0c68a61dca8..a698e59674f 100644 --- a/bundles/org.eclipse.remote.proxy.server.core/.settings/org.eclipse.jdt.core.prefs +++ b/bundles/org.eclipse.remote.proxy.server.core/.settings/org.eclipse.jdt.core.prefs @@ -1,7 +1,12 @@ eclipse.preferences.version=1 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate org.eclipse.jdt.core.compiler.problem.assertIdentifier=error org.eclipse.jdt.core.compiler.problem.enumIdentifier=error org.eclipse.jdt.core.compiler.source=1.8 diff --git a/bundles/org.eclipse.remote.proxy.server.core/.settings/org.eclipse.jdt.ui.prefs b/bundles/org.eclipse.remote.proxy.server.core/.settings/org.eclipse.jdt.ui.prefs new file mode 100644 index 00000000000..44ccb79db9a --- /dev/null +++ b/bundles/org.eclipse.remote.proxy.server.core/.settings/org.eclipse.jdt.ui.prefs @@ -0,0 +1,59 @@ +eclipse.preferences.version=1 +editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true +sp_cleanup.add_default_serial_version_id=true +sp_cleanup.add_generated_serial_version_id=false +sp_cleanup.add_missing_annotations=true +sp_cleanup.add_missing_deprecated_annotations=true +sp_cleanup.add_missing_methods=false +sp_cleanup.add_missing_nls_tags=false +sp_cleanup.add_missing_override_annotations=true +sp_cleanup.add_missing_override_annotations_interface_methods=true +sp_cleanup.add_serial_version_id=false +sp_cleanup.always_use_blocks=true +sp_cleanup.always_use_parentheses_in_expressions=false +sp_cleanup.always_use_this_for_non_static_field_access=false +sp_cleanup.always_use_this_for_non_static_method_access=false +sp_cleanup.convert_functional_interfaces=false +sp_cleanup.convert_to_enhanced_for_loop=false +sp_cleanup.correct_indentation=false +sp_cleanup.format_source_code=false +sp_cleanup.format_source_code_changes_only=false +sp_cleanup.insert_inferred_type_arguments=false +sp_cleanup.make_local_variable_final=true +sp_cleanup.make_parameters_final=false +sp_cleanup.make_private_fields_final=true +sp_cleanup.make_type_abstract_if_missing_method=false +sp_cleanup.make_variable_declarations_final=false +sp_cleanup.never_use_blocks=false +sp_cleanup.never_use_parentheses_in_expressions=true +sp_cleanup.on_save_use_additional_actions=false +sp_cleanup.organize_imports=true +sp_cleanup.qualify_static_field_accesses_with_declaring_class=false +sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true +sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true +sp_cleanup.qualify_static_member_accesses_with_declaring_class=false +sp_cleanup.qualify_static_method_accesses_with_declaring_class=false +sp_cleanup.remove_private_constructors=true +sp_cleanup.remove_redundant_type_arguments=false +sp_cleanup.remove_trailing_whitespaces=false +sp_cleanup.remove_trailing_whitespaces_all=true +sp_cleanup.remove_trailing_whitespaces_ignore_empty=false +sp_cleanup.remove_unnecessary_casts=true +sp_cleanup.remove_unnecessary_nls_tags=false +sp_cleanup.remove_unused_imports=false +sp_cleanup.remove_unused_local_variables=false +sp_cleanup.remove_unused_private_fields=true +sp_cleanup.remove_unused_private_members=false +sp_cleanup.remove_unused_private_methods=true +sp_cleanup.remove_unused_private_types=true +sp_cleanup.sort_members=false +sp_cleanup.sort_members_all=false +sp_cleanup.use_anonymous_class_creation=false +sp_cleanup.use_blocks=false +sp_cleanup.use_blocks_only_for_return_and_throw=false +sp_cleanup.use_lambda=true +sp_cleanup.use_parentheses_in_expressions=false +sp_cleanup.use_this_for_non_static_field_access=false +sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true +sp_cleanup.use_this_for_non_static_method_access=false +sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true diff --git a/bundles/org.eclipse.remote.proxy.server.core/META-INF/MANIFEST.MF b/bundles/org.eclipse.remote.proxy.server.core/META-INF/MANIFEST.MF index 589f2fde12e..e20134257e4 100644 --- a/bundles/org.eclipse.remote.proxy.server.core/META-INF/MANIFEST.MF +++ b/bundles/org.eclipse.remote.proxy.server.core/META-INF/MANIFEST.MF @@ -15,3 +15,4 @@ Import-Package: org.eclipse.core.filesystem, org.osgi.framework.launch Bundle-Vendor: %pluginProvider Bundle-Localization: plugin +Require-Bundle: org.eclipse.cdt.core.native diff --git a/bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/core/Application.java b/bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/core/Application.java index da92a67da0a..0ad311029cd 100644 --- a/bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/core/Application.java +++ b/bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/core/Application.java @@ -25,7 +25,7 @@ public class Application implements IApplication { public Object start(IApplicationContext context) throws Exception { String[] args = (String[])context.getArguments().get(IApplicationContext.APPLICATION_ARGS); for (String arg : args) { - if (arg.equals("-magic")) { + if (arg.equals("-magic")) { //$NON-NLS-1$ ByteBuffer b = ByteBuffer.allocate(4); b.putInt(Protocol.MAGIC); System.out.write(b.array()); @@ -40,5 +40,6 @@ public class Application implements IApplication { * @see org.eclipse.equinox.app.IApplication#stop() */ public void stop() { + // Nothing } } diff --git a/bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/core/CommandServer.java b/bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/core/CommandServer.java index c58c2d88aa0..e600a47c471 100644 --- a/bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/core/CommandServer.java +++ b/bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/core/CommandServer.java @@ -16,18 +16,19 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import org.eclipse.remote.internal.proxy.server.commands.AbstractServerCommand; -import org.eclipse.remote.internal.proxy.server.commands.ServerChildInfosCommand; -import org.eclipse.remote.internal.proxy.server.commands.ServerDeleteCommand; -import org.eclipse.remote.internal.proxy.server.commands.ServerExecCommand; -import org.eclipse.remote.internal.proxy.server.commands.ServerFetchInfoCommand; -import org.eclipse.remote.internal.proxy.server.commands.ServerGetCwdCommand; -import org.eclipse.remote.internal.proxy.server.commands.ServerGetEnvCommand; -import org.eclipse.remote.internal.proxy.server.commands.ServerGetInputStreamCommand; -import org.eclipse.remote.internal.proxy.server.commands.ServerGetOutputStreamCommand; -import org.eclipse.remote.internal.proxy.server.commands.ServerGetPropertiesCommand; -import org.eclipse.remote.internal.proxy.server.commands.ServerMkdirCommand; -import org.eclipse.remote.internal.proxy.server.commands.ServerPutInfoCommand; +import org.eclipse.remote.internal.proxy.server.core.commands.AbstractServerCommand; +import org.eclipse.remote.internal.proxy.server.core.commands.ServerChildInfosCommand; +import org.eclipse.remote.internal.proxy.server.core.commands.ServerDeleteCommand; +import org.eclipse.remote.internal.proxy.server.core.commands.ServerExecCommand; +import org.eclipse.remote.internal.proxy.server.core.commands.ServerFetchInfoCommand; +import org.eclipse.remote.internal.proxy.server.core.commands.ServerGetCwdCommand; +import org.eclipse.remote.internal.proxy.server.core.commands.ServerGetEnvCommand; +import org.eclipse.remote.internal.proxy.server.core.commands.ServerGetInputStreamCommand; +import org.eclipse.remote.internal.proxy.server.core.commands.ServerGetOutputStreamCommand; +import org.eclipse.remote.internal.proxy.server.core.commands.ServerGetPropertiesCommand; +import org.eclipse.remote.internal.proxy.server.core.commands.ServerMkdirCommand; +import org.eclipse.remote.internal.proxy.server.core.commands.ServerPutInfoCommand; +import org.eclipse.remote.internal.proxy.server.core.commands.ServerShellCommand; import org.eclipse.remote.proxy.protocol.core.Protocol; import org.eclipse.remote.proxy.protocol.core.SerializableFileInfo; import org.eclipse.remote.proxy.protocol.core.StreamChannel; @@ -48,7 +49,7 @@ public class CommandServer implements Runnable { } public void run() { - new Thread("cmd reader") { + new Thread("cmd reader") { //$NON-NLS-1$ @Override public void run() { try { @@ -117,6 +118,10 @@ public class CommandServer implements Runnable { serverCmd = cmdExec(in); break; + case Protocol.CMD_SHELL: + serverCmd = cmdShell(in); + break; + case Protocol.CMD_FETCHINFO: serverCmd = cmdFetchInfo(in); break; @@ -151,16 +156,16 @@ public class CommandServer implements Runnable { default: System.err.println("Invalid command ID: " + cmd); - throw new ProxyException("Invalid command ID: " + cmd); + throw new ProxyException("Invalid command ID: " + cmd); //$NON-NLS-1$ } serverCmd.exec(); } private AbstractServerCommand cmdExec(DataInputStream in) throws ProxyException, IOException { - int chanAId = in.readByte(); - int chanBId = in.readByte(); - int chanCId = in.readByte(); + int cmdChanId = in.readByte(); + int ioChanId = in.readByte(); + int errChanId = in.readByte(); int length = in.readInt(); List command = new ArrayList(length); for (int i = 0; i < length; i++) { @@ -176,25 +181,30 @@ public class CommandServer implements Runnable { String dir = in.readUTF(); boolean redirect = in.readBoolean(); boolean appendEnv = in.readBoolean(); - System.err.print("dispatch: "); - for (String s:command) { - System.err.print(" " + s); + StreamChannel cmdChan = server.getChannel(cmdChanId); + StreamChannel ioChan = server.getChannel(ioChanId); + StreamChannel errChan= server.getChannel(errChanId); + if (cmdChan == null || ioChan == null || errChan == null) { + throw new ProxyException("Unable to locate channels for command"); //$NON-NLS-1$ } - System.err.println(" [" + chanAId + "," + chanBId+ ","+ chanCId + "]"); - StreamChannel chanA = server.getChannel(chanAId); - StreamChannel chanB = server.getChannel(chanBId); - StreamChannel chanC= server.getChannel(chanCId); - if (chanA == null || chanB == null || chanC == null) { - throw new ProxyException("Unable to locate channels for command"); - } - return new ServerExecCommand(command, env, dir, redirect, appendEnv, chanA, chanB, chanC); + return new ServerExecCommand(command, env, dir, redirect, appendEnv, cmdChan, ioChan, errChan); } + private AbstractServerCommand cmdShell(DataInputStream in) throws ProxyException, IOException { + int cmdChanId = in.readByte(); + int ioChanId = in.readByte(); + StreamChannel cmdChan = server.getChannel(cmdChanId); + StreamChannel ioChan = server.getChannel(ioChanId); + if (cmdChan == null || ioChan == null) { + throw new ProxyException("Unable to locate channels for command"); //$NON-NLS-1$ + } + return new ServerShellCommand(cmdChan, ioChan); + } private AbstractServerCommand cmdGetCwd(DataInputStream in) throws ProxyException, IOException { int chanId = in.readByte(); StreamChannel chan = server.getChannel(chanId); if (chan == null) { - throw new ProxyException("Unable to locate channel for command"); + throw new ProxyException("Unable to locate channel for command"); //$NON-NLS-1$ } return new ServerGetCwdCommand(chan); } @@ -203,7 +213,7 @@ public class CommandServer implements Runnable { int chanId = in.readByte(); StreamChannel chan = server.getChannel(chanId); if (chan == null) { - throw new ProxyException("Unable to locate channel for command"); + throw new ProxyException("Unable to locate channel for command"); //$NON-NLS-1$ } return new ServerGetEnvCommand(chan); } @@ -212,7 +222,7 @@ public class CommandServer implements Runnable { int chanId = in.readByte(); StreamChannel chan = server.getChannel(chanId); if (chan == null) { - throw new ProxyException("Unable to locate channel for command"); + throw new ProxyException("Unable to locate channel for command"); //$NON-NLS-1$ } return new ServerGetPropertiesCommand(chan); } @@ -221,7 +231,7 @@ public class CommandServer implements Runnable { int chanId = in.readByte(); StreamChannel chan = server.getChannel(chanId); if (chan == null) { - throw new ProxyException("Unable to locate channel for command"); + throw new ProxyException("Unable to locate channel for command"); //$NON-NLS-1$ } String path = in.readUTF(); return new ServerChildInfosCommand(chan, path); @@ -231,7 +241,7 @@ public class CommandServer implements Runnable { int chanId = in.readByte(); StreamChannel chan = server.getChannel(chanId); if (chan == null) { - throw new ProxyException("Unable to locate channel for command"); + throw new ProxyException("Unable to locate channel for command"); //$NON-NLS-1$ } String path = in.readUTF(); return new ServerFetchInfoCommand(chan, path); @@ -241,7 +251,7 @@ public class CommandServer implements Runnable { int chanId = in.readByte(); StreamChannel chan = server.getChannel(chanId); if (chan == null) { - throw new ProxyException("Unable to locate channel for command"); + throw new ProxyException("Unable to locate channel for command"); //$NON-NLS-1$ } int options = in.readInt(); String path = in.readUTF(); @@ -252,7 +262,7 @@ public class CommandServer implements Runnable { int chanId = in.readByte(); StreamChannel chan = server.getChannel(chanId); if (chan == null) { - throw new ProxyException("Unable to locate channel for command"); + throw new ProxyException("Unable to locate channel for command"); //$NON-NLS-1$ } int options = in.readInt(); String path = in.readUTF(); diff --git a/bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/commands/AbstractServerCommand.java b/bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/core/commands/AbstractServerCommand.java similarity index 91% rename from bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/commands/AbstractServerCommand.java rename to bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/core/commands/AbstractServerCommand.java index f4d2dfaf670..c25198a9140 100644 --- a/bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/commands/AbstractServerCommand.java +++ b/bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/core/commands/AbstractServerCommand.java @@ -5,7 +5,7 @@ * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html *******************************************************************************/ -package org.eclipse.remote.internal.proxy.server.commands; +package org.eclipse.remote.internal.proxy.server.core.commands; import org.eclipse.remote.proxy.protocol.core.exceptions.ProxyException; diff --git a/bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/commands/ServerExecCommand.java b/bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/core/commands/AbstractServerExecCommand.java similarity index 54% rename from bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/commands/ServerExecCommand.java rename to bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/core/commands/AbstractServerExecCommand.java index 5d100da442d..9fc61b1d259 100644 --- a/bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/commands/ServerExecCommand.java +++ b/bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/core/commands/AbstractServerExecCommand.java @@ -5,14 +5,13 @@ * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html *******************************************************************************/ -package org.eclipse.remote.internal.proxy.server.commands; +package org.eclipse.remote.internal.proxy.server.core.commands; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.BufferedWriter; import java.io.DataInputStream; import java.io.DataOutputStream; -import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -23,83 +22,37 @@ import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; +import org.eclipse.remote.proxy.protocol.core.Protocol; import org.eclipse.remote.proxy.protocol.core.StreamChannel; import org.eclipse.remote.proxy.protocol.core.exceptions.ProxyException; -/** - * TODO: Fix hang if command fails... - * - */ -public class ServerExecCommand extends AbstractServerCommand { - - private final List command; - private final Map env; - private final boolean redirect; - private final boolean appendEnv; - private final String directory; - private final InputStream stdin; - private final OutputStream stdout; - private final OutputStream stderr; - private final DataOutputStream result; - private final DataInputStream cmd; - - private Process proc; +public abstract class AbstractServerExecCommand extends AbstractServerCommand { private class CommandRunner implements Runnable { @Override public void run() { - ProcessBuilder builder = new ProcessBuilder(command); - try { - if (!appendEnv) { - builder.environment().clear(); - builder.environment().putAll(env); - } else { - for (Map.Entry entry : env.entrySet()) { - String val = builder.environment().get(entry.getKey()); - if (val == null || !val.equals(entry.getValue())) { - builder.environment().put(entry.getKey(), entry.getValue()); - } - } - } - } catch (UnsupportedOperationException | IllegalArgumentException e) { - // Leave environment untouched - } - File dir = new File(directory); - if (dir.exists() && dir.isAbsolute()) { - builder.directory(dir); - } - builder.redirectErrorStream(redirect); try { int exit = 0; try { - proc = builder.start(); - Forwarder stdoutFwd = startForwarder("stdout", proc.getInputStream(), stdout); //$NON-NLS-1$ + proc = doRun(); + Forwarder stdoutFwd = startForwarder("stdout", proc.getInputStream(), stdoutChan); //$NON-NLS-1$ Forwarder stderrFwd = null; if (!redirect) { - stderrFwd = startForwarder("stderr", proc.getErrorStream(), stderr); //$NON-NLS-1$ + stderrFwd = startForwarder("stderr", proc.getErrorStream(), stderrChan); //$NON-NLS-1$ } - startForwarder("stdin", stdin, proc.getOutputStream()); //$NON-NLS-1$ + startForwarder("stdin", stdinChan, proc.getOutputStream()); //$NON-NLS-1$ new Thread(new ProcMonitor(), "process monitor").start(); //$NON-NLS-1$ - System.err.println("wait for process"); exit = proc.waitFor(); - System.err.println("wait for process close in"); -// stdoutFwd.terminate(); -// if (!redirect) { -// stderrFwd.terminate(); -// } - System.err.println("wait for readers"); /* * After the process has finished, wait for the stdout and stderr forwarders to finish to * ensure that all output is flushed. */ -// stdoutFwd.waitFor(); -// System.err.println("wait for process finished out"); -// if (stderrFwd != null) { -// stderrFwd.waitFor(); -// } - System.err.println("wait for readers done"); + stdoutFwd.waitFor(); + if (stderrFwd != null) { + stderrFwd.waitFor(); + } } catch (IOException e) { - BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(stderr)); + BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(stderrChan)); try { writer.write(e.getMessage()); writer.flush(); @@ -109,8 +62,8 @@ public class ServerExecCommand extends AbstractServerCommand { exit = -1; } try { - result.writeInt(exit); - result.flush(); + resultStream.writeInt(exit); + resultStream.flush(); } catch (IOException e) { // We're finished anyway } @@ -124,9 +77,17 @@ public class ServerExecCommand extends AbstractServerCommand { @Override public void run() { try { - cmd.readByte(); - if (proc.isAlive()) { - proc.destroyForcibly(); + switch (cmdStream.readByte()) { + case Protocol.CONTROL_KILL: + doKill(proc); + break; + case Protocol.CONTROL_SETTERMINALSIZE: + int cols = cmdStream.readInt(); + int rows = cmdStream.readInt(); + cmdStream.readInt(); // pixel dimensions not supported + cmdStream.readInt(); // pixel dimensions not supported + doSetTerminalSize(proc, cols, rows); + break; } } catch (IOException e) { // Finish @@ -139,8 +100,7 @@ public class ServerExecCommand extends AbstractServerCommand { private final OutputStream out; private final String name; - private volatile boolean running = true; - private boolean terminated = false; + private boolean running = true; private final Lock lock = new ReentrantLock(); private final Condition cond = lock.newCondition(); @@ -156,58 +116,44 @@ public class ServerExecCommand extends AbstractServerCommand { byte[] buf = new byte[8192]; int n; try { - while (true) { -// if (in.available() == 0) { -// System.err.println("avail=0"); -// /* Avoid spinning if no data */ -// lock.lock(); -// try { -// cond.await(100, TimeUnit.MILLISECONDS); -// } catch (InterruptedException e) { -// } finally { -// lock.unlock(); -// } -// continue; -// } + while (running) { n = in.read(buf); if (n > 0) { out.write(buf, 0, n); out.flush(); } - if (n==0) System.err.println("forwarder n=0"); if (n < 0) break; } } catch (IOException e) { // Finish - System.err.println("forwarder "+e.getMessage()); } - System.err.println("forwarder closing name="+name); - try { - out.close(); - } catch (IOException e) { - // Best effort - } lock.lock(); - terminated = true; try { + running = false; + try { + out.close(); + } catch (IOException e) { + // Best effort + } cond.signalAll(); } finally { lock.unlock(); } } - public void terminate() { - running = false; + public String getName() { + return name; } public synchronized void waitFor() { lock.lock(); try { - if (!terminated) { + while (running) { try { cond.await(); } catch (InterruptedException e) { + // Check terminated flag } } } finally { @@ -215,28 +161,71 @@ public class ServerExecCommand extends AbstractServerCommand { } } } + + private final List command; + private final Map env; + private final boolean redirect; + private final boolean appendEnv; + private final String directory; + + private final InputStream stdinChan; + private final OutputStream stdoutChan; + private final OutputStream stderrChan; + + private final DataInputStream cmdStream; + private final DataOutputStream resultStream; - public ServerExecCommand(List command, Map env, String directory, boolean redirect, boolean appendEnv, StreamChannel chanA, StreamChannel chanB, StreamChannel chanC) { + private Process proc; + + public AbstractServerExecCommand(List command, Map env, String directory, boolean redirect, boolean appendEnv, StreamChannel cmdChan, StreamChannel ioChan, StreamChannel errChan) { this.command = command; this.env = env; this.directory = directory; this.redirect = redirect; this.appendEnv = appendEnv; - this.stdin = chanA.getInputStream(); - this.stdout = chanA.getOutputStream(); - this.stderr = chanB.getOutputStream(); - this.result = new DataOutputStream(chanC.getOutputStream()); - this.cmd = new DataInputStream(chanC.getInputStream()); + this.stdinChan = ioChan.getInputStream(); + this.stdoutChan = ioChan.getOutputStream(); + + this.stderrChan = errChan != null ? errChan.getOutputStream() : this.stdoutChan; + + this.resultStream = new DataOutputStream(cmdChan.getOutputStream()); + this.cmdStream = new DataInputStream(cmdChan.getInputStream()); } + protected abstract Process doRun() throws IOException; + + protected abstract void doKill(Process proc); + + protected abstract void doSetTerminalSize(Process proc, int col, int rows); + + protected List getCommand() { + return command; + } + + protected Map getEnv() { + return env; + } + + protected boolean isRedirect() { + return redirect; + } + + protected boolean isAppendEnv() { + return appendEnv; + } + + protected String getDirectory() { + return directory; + } + public void exec() throws ProxyException { - new Thread(new CommandRunner(), command.get(0)).start(); + new Thread(new CommandRunner()).start(); } private Forwarder startForwarder(String name, InputStream in, OutputStream out) { Forwarder forwarder = new Forwarder(name, in, out); - Thread thread = new Thread(forwarder, command.get(0) + " " + name); //$NON-NLS-1$ + Thread thread = new Thread(forwarder, forwarder.getName()); thread.start(); return forwarder; } diff --git a/bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/commands/ServerChildInfosCommand.java b/bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/core/commands/ServerChildInfosCommand.java similarity index 94% rename from bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/commands/ServerChildInfosCommand.java rename to bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/core/commands/ServerChildInfosCommand.java index 5d1d28ac022..7f471e1da34 100644 --- a/bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/commands/ServerChildInfosCommand.java +++ b/bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/core/commands/ServerChildInfosCommand.java @@ -5,7 +5,7 @@ * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html *******************************************************************************/ -package org.eclipse.remote.internal.proxy.server.commands; +package org.eclipse.remote.internal.proxy.server.core.commands; import java.io.DataOutputStream; import java.io.IOException; @@ -15,8 +15,8 @@ import java.net.URI; import org.eclipse.core.filesystem.EFS; import org.eclipse.core.filesystem.IFileInfo; import org.eclipse.core.runtime.CoreException; -import org.eclipse.remote.proxy.protocol.core.StreamChannel; import org.eclipse.remote.proxy.protocol.core.SerializableFileInfo; +import org.eclipse.remote.proxy.protocol.core.StreamChannel; import org.eclipse.remote.proxy.protocol.core.exceptions.ProxyException; public class ServerChildInfosCommand extends AbstractServerCommand { @@ -45,7 +45,7 @@ public class ServerChildInfosCommand extends AbstractServerCommand { public ServerChildInfosCommand(StreamChannel chan, String path) { this.out = chan.getOutputStream(); - this.uri = URI.create("file:" + path); + this.uri = URI.create("file:" + path); //$NON-NLS-1$ } public void exec() throws ProxyException { diff --git a/bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/commands/ServerDeleteCommand.java b/bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/core/commands/ServerDeleteCommand.java similarity index 90% rename from bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/commands/ServerDeleteCommand.java rename to bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/core/commands/ServerDeleteCommand.java index ba2435ec160..a259e779187 100644 --- a/bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/commands/ServerDeleteCommand.java +++ b/bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/core/commands/ServerDeleteCommand.java @@ -5,7 +5,7 @@ * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html *******************************************************************************/ -package org.eclipse.remote.internal.proxy.server.commands; +package org.eclipse.remote.internal.proxy.server.core.commands; import java.net.URI; @@ -20,7 +20,7 @@ public class ServerDeleteCommand extends AbstractServerCommand { public ServerDeleteCommand(int options, String path) { this.options = options; - this.uri = URI.create("file:" + path); + this.uri = URI.create("file:" + path); //$NON-NLS-1$ } public void exec() throws ProxyException { diff --git a/bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/core/commands/ServerExecCommand.java b/bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/core/commands/ServerExecCommand.java new file mode 100644 index 00000000000..f56a64188a6 --- /dev/null +++ b/bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/core/commands/ServerExecCommand.java @@ -0,0 +1,65 @@ +/******************************************************************************* + * Copyright (c) 2016 Oak Ridge National Laboratory 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 + *******************************************************************************/ +package org.eclipse.remote.internal.proxy.server.core.commands; + +import java.io.File; +import java.io.IOException; +import java.util.List; +import java.util.Map; + +import org.eclipse.remote.proxy.protocol.core.StreamChannel; + +/** + * TODO: Fix hang if command fails... + * + */ +public class ServerExecCommand extends AbstractServerExecCommand { + public Process doRun() throws IOException { + System.err.print("exec: "); + for (String arg:getCommand()) { + System.err.print(arg + " "); + } + System.err.println(); + ProcessBuilder builder = new ProcessBuilder(getCommand()); + try { + if (!isAppendEnv()) { + builder.environment().clear(); + builder.environment().putAll(getEnv()); + } else { + for (Map.Entry entry : getEnv().entrySet()) { + String val = builder.environment().get(entry.getKey()); + if (val == null || !val.equals(entry.getValue())) { + builder.environment().put(entry.getKey(), entry.getValue()); + } + } + } + } catch (UnsupportedOperationException | IllegalArgumentException e) { + // Leave environment untouched + } + File dir = new File(getDirectory()); + if (dir.exists() && dir.isAbsolute()) { + builder.directory(dir); + } + builder.redirectErrorStream(isRedirect()); + return builder.start(); + } + + protected void doKill(Process proc) { + if (proc.isAlive()) { + proc.destroyForcibly(); + } + } + + protected void doSetTerminalSize(Process proc, int cols, int rows) { + // Not supported + } + + public ServerExecCommand(List command, Map env, String directory, boolean redirect, boolean appendEnv, StreamChannel cmdChan, StreamChannel ioChan, StreamChannel errChan) { + super(command, env, directory, redirect, appendEnv, cmdChan, ioChan, errChan); + } +} diff --git a/bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/commands/ServerFetchInfoCommand.java b/bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/core/commands/ServerFetchInfoCommand.java similarity index 93% rename from bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/commands/ServerFetchInfoCommand.java rename to bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/core/commands/ServerFetchInfoCommand.java index 0f2d15eae38..d03b01626a1 100644 --- a/bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/commands/ServerFetchInfoCommand.java +++ b/bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/core/commands/ServerFetchInfoCommand.java @@ -5,7 +5,7 @@ * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html *******************************************************************************/ -package org.eclipse.remote.internal.proxy.server.commands; +package org.eclipse.remote.internal.proxy.server.core.commands; import java.io.DataOutputStream; import java.io.IOException; @@ -15,8 +15,8 @@ import java.net.URI; import org.eclipse.core.filesystem.EFS; import org.eclipse.core.filesystem.IFileInfo; import org.eclipse.core.runtime.CoreException; -import org.eclipse.remote.proxy.protocol.core.StreamChannel; import org.eclipse.remote.proxy.protocol.core.SerializableFileInfo; +import org.eclipse.remote.proxy.protocol.core.StreamChannel; import org.eclipse.remote.proxy.protocol.core.exceptions.ProxyException; public class ServerFetchInfoCommand extends AbstractServerCommand { @@ -42,7 +42,7 @@ public class ServerFetchInfoCommand extends AbstractServerCommand { public ServerFetchInfoCommand(StreamChannel chan, String path) { this.out = chan.getOutputStream(); - this.uri = URI.create("file:" + path); + this.uri = URI.create("file:" + path); //$NON-NLS-1$ } public void exec() throws ProxyException { diff --git a/bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/commands/ServerGetCwdCommand.java b/bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/core/commands/ServerGetCwdCommand.java similarity index 95% rename from bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/commands/ServerGetCwdCommand.java rename to bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/core/commands/ServerGetCwdCommand.java index 6ce413677ef..9bc2a5f4d2d 100644 --- a/bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/commands/ServerGetCwdCommand.java +++ b/bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/core/commands/ServerGetCwdCommand.java @@ -5,7 +5,7 @@ * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html *******************************************************************************/ -package org.eclipse.remote.internal.proxy.server.commands; +package org.eclipse.remote.internal.proxy.server.core.commands; import java.io.DataOutputStream; import java.io.IOException; @@ -35,7 +35,7 @@ public class ServerGetCwdCommand extends AbstractServerCommand { } public void exec() throws ProxyException { - cwd = System.getProperty("user.dir"); + cwd = System.getProperty("user.dir"); //$NON-NLS-1$ new Thread(new CommandRunner()).start(); } } diff --git a/bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/commands/ServerGetEnvCommand.java b/bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/core/commands/ServerGetEnvCommand.java similarity index 95% rename from bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/commands/ServerGetEnvCommand.java rename to bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/core/commands/ServerGetEnvCommand.java index d94b9a49995..624911024e7 100644 --- a/bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/commands/ServerGetEnvCommand.java +++ b/bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/core/commands/ServerGetEnvCommand.java @@ -5,7 +5,7 @@ * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html *******************************************************************************/ -package org.eclipse.remote.internal.proxy.server.commands; +package org.eclipse.remote.internal.proxy.server.core.commands; import java.io.DataOutputStream; import java.io.IOException; diff --git a/bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/commands/ServerGetInputStreamCommand.java b/bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/core/commands/ServerGetInputStreamCommand.java similarity index 97% rename from bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/commands/ServerGetInputStreamCommand.java rename to bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/core/commands/ServerGetInputStreamCommand.java index d01ca9d7ad9..6fb283553c0 100644 --- a/bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/commands/ServerGetInputStreamCommand.java +++ b/bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/core/commands/ServerGetInputStreamCommand.java @@ -5,7 +5,7 @@ * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html *******************************************************************************/ -package org.eclipse.remote.internal.proxy.server.commands; +package org.eclipse.remote.internal.proxy.server.core.commands; import java.io.BufferedInputStream; import java.io.IOException; diff --git a/bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/commands/ServerGetOutputStreamCommand.java b/bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/core/commands/ServerGetOutputStreamCommand.java similarity index 97% rename from bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/commands/ServerGetOutputStreamCommand.java rename to bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/core/commands/ServerGetOutputStreamCommand.java index 7e12bb19806..ab2517e58ee 100644 --- a/bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/commands/ServerGetOutputStreamCommand.java +++ b/bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/core/commands/ServerGetOutputStreamCommand.java @@ -5,7 +5,7 @@ * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html *******************************************************************************/ -package org.eclipse.remote.internal.proxy.server.commands; +package org.eclipse.remote.internal.proxy.server.core.commands; import java.io.BufferedOutputStream; import java.io.IOException; diff --git a/bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/commands/ServerGetPropertiesCommand.java b/bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/core/commands/ServerGetPropertiesCommand.java similarity index 95% rename from bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/commands/ServerGetPropertiesCommand.java rename to bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/core/commands/ServerGetPropertiesCommand.java index 3c7168dbc6b..dab727e0123 100644 --- a/bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/commands/ServerGetPropertiesCommand.java +++ b/bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/core/commands/ServerGetPropertiesCommand.java @@ -5,7 +5,7 @@ * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html *******************************************************************************/ -package org.eclipse.remote.internal.proxy.server.commands; +package org.eclipse.remote.internal.proxy.server.core.commands; import java.io.DataOutputStream; import java.io.IOException; @@ -32,7 +32,7 @@ public class ServerGetPropertiesCommand extends AbstractServerCommand { props.put(IRemoteConnection.OS_NAME_PROPERTY, System.getProperty(IRemoteConnection.OS_NAME_PROPERTY)); props.put(IRemoteConnection.OS_VERSION_PROPERTY, System.getProperty(IRemoteConnection.OS_VERSION_PROPERTY)); props.put(IRemoteConnection.OS_ARCH_PROPERTY, System.getProperty(IRemoteConnection.OS_ARCH_PROPERTY)); - props.put(IRemoteConnection.LOCALE_CHARMAP_PROPERTY, System.getProperty("file.encoding")); + props.put(IRemoteConnection.LOCALE_CHARMAP_PROPERTY, System.getProperty("file.encoding")); //$NON-NLS-1$ result.writeInt(props.size()); for (Map.Entry entry : props.entrySet()) { diff --git a/bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/commands/ServerMkdirCommand.java b/bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/core/commands/ServerMkdirCommand.java similarity index 90% rename from bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/commands/ServerMkdirCommand.java rename to bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/core/commands/ServerMkdirCommand.java index ac186062a3b..cb3ddb43e6a 100644 --- a/bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/commands/ServerMkdirCommand.java +++ b/bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/core/commands/ServerMkdirCommand.java @@ -5,7 +5,7 @@ * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html *******************************************************************************/ -package org.eclipse.remote.internal.proxy.server.commands; +package org.eclipse.remote.internal.proxy.server.core.commands; import java.net.URI; @@ -20,7 +20,7 @@ public class ServerMkdirCommand extends AbstractServerCommand { public ServerMkdirCommand(int options, String path) { this.options = options; - this.uri = URI.create("file:" + path); + this.uri = URI.create("file:" + path); //$NON-NLS-1$ } public void exec() throws ProxyException { diff --git a/bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/commands/ServerPutInfoCommand.java b/bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/core/commands/ServerPutInfoCommand.java similarity index 91% rename from bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/commands/ServerPutInfoCommand.java rename to bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/core/commands/ServerPutInfoCommand.java index 9ee1c5d3e14..61d2abfde37 100644 --- a/bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/commands/ServerPutInfoCommand.java +++ b/bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/core/commands/ServerPutInfoCommand.java @@ -5,7 +5,7 @@ * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html *******************************************************************************/ -package org.eclipse.remote.internal.proxy.server.commands; +package org.eclipse.remote.internal.proxy.server.core.commands; import java.net.URI; @@ -23,7 +23,7 @@ public class ServerPutInfoCommand extends AbstractServerCommand { public ServerPutInfoCommand(IFileInfo info, int options, String path) { this.info = info; this.options = options; - this.uri = URI.create("file:" + path); + this.uri = URI.create("file:" + path); //$NON-NLS-1$ } public void exec() throws ProxyException { diff --git a/bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/core/commands/ServerShellCommand.java b/bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/core/commands/ServerShellCommand.java new file mode 100644 index 00000000000..74545c63f7f --- /dev/null +++ b/bundles/org.eclipse.remote.proxy.server.core/src/org/eclipse/remote/internal/proxy/server/core/commands/ServerShellCommand.java @@ -0,0 +1,178 @@ +/******************************************************************************* + * Copyright (c) 2016 Oak Ridge National Laboratory 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 + *******************************************************************************/ +package org.eclipse.remote.internal.proxy.server.core.commands; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; + +import org.eclipse.cdt.utils.pty.PTY; +import org.eclipse.cdt.utils.pty.PTY.Mode; +import org.eclipse.cdt.utils.spawner.ProcessFactory; +import org.eclipse.remote.proxy.protocol.core.StreamChannel; + +/** + * TODO: Fix hang if command fails... + * + */ +public class ServerShellCommand extends AbstractServerExecCommand { + private class ShellProcess extends Process { + private final Process proc; + private final PTY pty; + + public ShellProcess(Process proc, PTY pty) { + this.proc = proc; + this.pty = pty; + } + + @Override + public OutputStream getOutputStream() { + if (pty != null) { + return pty.getOutputStream(); + } + return proc.getOutputStream(); + } + + @Override + public InputStream getInputStream() { + if (pty != null) { + return pty.getInputStream(); + } + return proc.getInputStream(); + } + + @Override + public InputStream getErrorStream() { + if (pty != null) { + return pty.getInputStream(); + } + return proc.getErrorStream(); + } + + @Override + public int waitFor() throws InterruptedException { + return proc.waitFor(); + } + + @Override + public int exitValue() { + return proc.exitValue(); + } + + @Override + public void destroy() { + proc.destroy(); + } + + public void setTerminalSize(int cols, int rows) { + if (pty != null) { + pty.setTerminalSize(cols, rows); + } + } + } + + public ServerShellCommand(StreamChannel cmdChan, StreamChannel ioChan) { + super(null, null, null, true, false, cmdChan, ioChan, null); + } + + public Process doRun() throws IOException { + String shell = findLoginShell(); + + if (PTY.isSupported(Mode.TERMINAL)) { + PTY pty = new PTY(Mode.TERMINAL); + Process p = ProcessFactory.getFactory().exec(new String[] {shell, "-l"}, null, null, pty); //$NON-NLS-1$ + return new ShellProcess(p, pty); + } + + return ProcessFactory.getFactory().exec(new String[] {shell, "-l"}, null, null); //$NON-NLS-1$ + } + + protected void doKill(Process proc) { + if (proc.isAlive()) { + proc.destroyForcibly(); + } + } + + protected void doSetTerminalSize(Process proc, int cols, int rows) { + if (proc.isAlive() && proc instanceof ShellProcess) { + ShellProcess shell = (ShellProcess)proc; + shell.setTerminalSize(cols, rows); + } + } + + /** + * Find the login shell. + * + * On Linux, use `getent passwd $USER` + * On Mac OSX, use `dscl . -read /Users/$USER UserShell` + * + * @return + */ + private String findLoginShell() throws IOException { + String res; + + String osName = System.getProperty("os.name"); //$NON-NLS-1$ + String userName = System.getProperty("user.name"); //$NON-NLS-1$ + if (osName == null || userName == null) { + throw new IOException("Unable to obtain information needed to find login shell"); //$NON-NLS-1$ + } + switch (osName) { + case "Mac OS X": //$NON-NLS-1$ + res = executeCommand("dscl . -read /Users/" + userName + " UserShell"); //$NON-NLS-1$ //$NON-NLS-2$ + if (res != null) { + String[] vals = res.split(" "); //$NON-NLS-1$ + if (vals.length == 2) { + return vals[1]; + } + } + break; + case "Linux": //$NON-NLS-1$ + res = executeCommand("getent passwd " + userName); //$NON-NLS-1$ + if (res != null) { + String[] vals = res.split(":"); //$NON-NLS-1$ + if (vals.length == 7) { + return vals[6]; + } + } + break; + default: + break; + } + throw new IOException("Unable to find login shell for os=" + osName + " user=" + userName); //$NON-NLS-1$ //$NON-NLS-2$ + } + + private String executeCommand(String command) throws IOException { + String line; + StringBuffer output = new StringBuffer(); + + Process p; + try { + p = Runtime.getRuntime().exec(command); + } catch (Exception e) { + throw new IOException(e.getMessage()); + } + try { + p.waitFor(); + } catch (InterruptedException e) { + throw new IOException(e.getMessage()); + } + BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream())); + line = reader.readLine(); + while (line != null) { + output.append(line); + line = reader.readLine(); + if (line != null) { + output.append("\n"); //$NON-NLS-1$ + } + } + + return output.toString(); + } +} diff --git a/releng/org.eclipse.remote.proxy.server.product/proxy.server.product b/releng/org.eclipse.remote.proxy.server.product/proxy.server.product index 345cc64651e..87104e6ef3d 100644 --- a/releng/org.eclipse.remote.proxy.server.product/proxy.server.product +++ b/releng/org.eclipse.remote.proxy.server.product/proxy.server.product @@ -16,7 +16,6 @@ - @@ -28,6 +27,8 @@ + + @@ -53,10 +54,6 @@ - - - - diff --git a/releng/org.eclipse.remote.target/oxygen.target b/releng/org.eclipse.remote.target/oxygen.target index b0b715fceb0..f3a2707f1bf 100644 --- a/releng/org.eclipse.remote.target/oxygen.target +++ b/releng/org.eclipse.remote.target/oxygen.target @@ -1,20 +1,20 @@ - - + - + - + - + +