From 5bb00b500976002872921f28f32debebfe977d15 Mon Sep 17 00:00:00 2001 From: Martin Oberhuber < martin.oberhuber@windriver.com> Date: Fri, 11 Apr 2008 13:36:45 +0000 Subject: [PATCH] [170910][api] Add API for Stream-based shells and terminals in RSE --- .../META-INF/MANIFEST.MF | 1 + .../terminals/AbstractTerminalShell.java | 77 ++++++++ .../terminals/BaseShellDecorator.java | 85 +++++++++ .../services/terminals/IBaseShell.java | 167 ++++++++++++++++++ .../services/terminals/ITerminalService.java | 92 ++++++++++ .../services/terminals/ITerminalShell.java | 101 +++++++++++ .../services/terminals/ProcessBaseShell.java | 148 ++++++++++++++++ .../terminals/TerminalShellDecorator.java | 59 +++++++ 8 files changed, 730 insertions(+) create mode 100644 rse/plugins/org.eclipse.rse.services/src/org/eclipse/rse/internal/services/terminals/AbstractTerminalShell.java create mode 100644 rse/plugins/org.eclipse.rse.services/src/org/eclipse/rse/internal/services/terminals/BaseShellDecorator.java create mode 100644 rse/plugins/org.eclipse.rse.services/src/org/eclipse/rse/internal/services/terminals/IBaseShell.java create mode 100644 rse/plugins/org.eclipse.rse.services/src/org/eclipse/rse/internal/services/terminals/ITerminalService.java create mode 100644 rse/plugins/org.eclipse.rse.services/src/org/eclipse/rse/internal/services/terminals/ITerminalShell.java create mode 100644 rse/plugins/org.eclipse.rse.services/src/org/eclipse/rse/internal/services/terminals/ProcessBaseShell.java create mode 100644 rse/plugins/org.eclipse.rse.services/src/org/eclipse/rse/internal/services/terminals/TerminalShellDecorator.java diff --git a/rse/plugins/org.eclipse.rse.services/META-INF/MANIFEST.MF b/rse/plugins/org.eclipse.rse.services/META-INF/MANIFEST.MF index fa7c7d9ac07..4892387c897 100644 --- a/rse/plugins/org.eclipse.rse.services/META-INF/MANIFEST.MF +++ b/rse/plugins/org.eclipse.rse.services/META-INF/MANIFEST.MF @@ -13,6 +13,7 @@ Export-Package: org.eclipse.rse.internal.services;x-internal:=true, org.eclipse.rse.internal.services.clientserver.archiveutils;x-internal:=true, org.eclipse.rse.internal.services.clientserver.java;x-internal:=true, org.eclipse.rse.internal.services.shells;x-internal:=true, + org.eclipse.rse.internal.services.terminals;x-internal:=true, org.eclipse.rse.services, org.eclipse.rse.services.clientserver, org.eclipse.rse.services.clientserver.archiveutils, diff --git a/rse/plugins/org.eclipse.rse.services/src/org/eclipse/rse/internal/services/terminals/AbstractTerminalShell.java b/rse/plugins/org.eclipse.rse.services/src/org/eclipse/rse/internal/services/terminals/AbstractTerminalShell.java new file mode 100644 index 00000000000..44527624bdc --- /dev/null +++ b/rse/plugins/org.eclipse.rse.services/src/org/eclipse/rse/internal/services/terminals/AbstractTerminalShell.java @@ -0,0 +1,77 @@ +/******************************************************************************* + * Copyright (c) 2008 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Martin Oberhuber (Wind River) - initial API and implementation + *******************************************************************************/ + +package org.eclipse.rse.internal.services.terminals; + +import java.io.InputStream; + +import org.eclipse.core.runtime.PlatformObject; + +/** + * Abstract base class for clients to create an ITerminalShell instance. + * + * This abstract base class provides valid default implementations for all + * {@link ITerminalShell} methods where possible. Clients should extend this + * base class rather than implementing ITerminalShell directly, in order to + * remain compatible when the ITerminalShell interface is evolved in the future. + * + *

+ * EXPERIMENTAL. This class or interface has been added as + * part of a work in progress. There is no guarantee that this API will work or + * that it will remain the same. Please do not use this API without consulting + * with the Target Management + * team. + *

+ * + * @since org.eclipse.rse.services 3.0 + */ +public abstract class AbstractTerminalShell extends PlatformObject implements ITerminalShell { + + public String getDefaultEncoding() { + return null; + } + + public String getPtyType() { + return null; + } + + public boolean isLocalEcho() { + return false; + } + + public void setTerminalSize(int newWidth, int newHeight) { + // do nothing + } + + public InputStream getErrorStream() { + return null; + } + + public int exitValue() { + // exit values are not supported by default, but we need to observe the + // API by throwing IllegalThreadStateException + if (isActive()) + throw new IllegalThreadStateException(); + return 0; + } + + public boolean waitFor(long timeout) throws InterruptedException { + boolean active = isActive(); + if (active) { + synchronized (this) { + wait(timeout); + } + active = isActive(); + } + return active; + } + +} diff --git a/rse/plugins/org.eclipse.rse.services/src/org/eclipse/rse/internal/services/terminals/BaseShellDecorator.java b/rse/plugins/org.eclipse.rse.services/src/org/eclipse/rse/internal/services/terminals/BaseShellDecorator.java new file mode 100644 index 00000000000..3d898d20212 --- /dev/null +++ b/rse/plugins/org.eclipse.rse.services/src/org/eclipse/rse/internal/services/terminals/BaseShellDecorator.java @@ -0,0 +1,85 @@ +/******************************************************************************* + * Copyright (c) 2008 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Martin Oberhuber (Wind River) - initial API and implementation + *******************************************************************************/ + +package org.eclipse.rse.internal.services.terminals; + +import java.io.InputStream; +import java.io.OutputStream; + +import org.eclipse.core.runtime.PlatformObject; + +/** + * Abstract base class for clients to decorate an IBaseShell instance they have + * with additional functionality. + * + * Typically, such additional functionality can be provided either by additional + * knowledge about the underlying system or process, or by analyzing the input + * and output streams for some well-known data that gives such additional + * knowledge. + * + *

+ * EXPERIMENTAL. This class or interface has been added as + * part of a work in progress. There is no guarantee that this API will work or + * that it will remain the same. Please do not use this API without consulting + * with the Target Management + * team. + *

+ * + * @since org.eclipse.rse.services 3.0 + */ +public abstract class BaseShellDecorator extends PlatformObject implements IBaseShell { + + protected final IBaseShell fDelegate; + + public BaseShellDecorator(IBaseShell delegate) { + fDelegate = delegate; + } + + public void exit() { + fDelegate.exit(); + } + + public int exitValue() { + return fDelegate.exitValue(); + } + + public InputStream getErrorStream() { + return fDelegate.getErrorStream(); + } + + public InputStream getInputStream() { + return fDelegate.getInputStream(); + } + + public OutputStream getOutputStream() { + return fDelegate.getOutputStream(); + } + + public boolean isActive() { + return fDelegate.isActive(); + } + + public boolean waitFor(long timeout) throws InterruptedException { + return fDelegate.waitFor(timeout); + } + + public Object getAdapter(Class adapterType) { + // TODO do we want to delegate here or have our own adapter??? + // I think we're most flexible first letting adapt to ourselves, + // and only if not successful then ask the delegate to adapt. + Object adapter = super.getAdapter(adapterType); + if (adapter == null) { + adapter = fDelegate.getAdapter(adapterType); + } + return adapter; + } + +} diff --git a/rse/plugins/org.eclipse.rse.services/src/org/eclipse/rse/internal/services/terminals/IBaseShell.java b/rse/plugins/org.eclipse.rse.services/src/org/eclipse/rse/internal/services/terminals/IBaseShell.java new file mode 100644 index 00000000000..de65abb1bee --- /dev/null +++ b/rse/plugins/org.eclipse.rse.services/src/org/eclipse/rse/internal/services/terminals/IBaseShell.java @@ -0,0 +1,167 @@ +/******************************************************************************* + * Copyright (c) 2008 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Martin Oberhuber (Wind River) - initial API and implementation + *******************************************************************************/ + +package org.eclipse.rse.internal.services.terminals; + +import java.io.InputStream; +import java.io.OutputStream; + +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.core.runtime.PlatformObject; + +/** + * A basic shell, representing the connection to some process that may be + * running local or remote. Clients may implement this interface. + * + * Clients implementing this interface are encouraged to extend + * {@link PlatformObject} for providing the {@link #getAdapter(Class)} + * functionality. + * + * A simple implementation of IBaseShell is the {@link ProcessBaseShell}, which + * wraps a Java {@link java.lang.Process} object in the IBaseShell interface to + * provide more convenient access to it through the {{@link #isActive()} and {{@link #waitFor(long)} + * methods, as well as making it adaptable. + * + * The resulting IBaseShell can be decorated by clients with additional + * functionality easily by instantiating their subclassed variant of + * {@link BaseShellDecorator}. + * + *

+ * EXPERIMENTAL. This class or interface has been added as + * part of a work in progress. There is no guarantee that this API will work or + * that it will remain the same. Please do not use this API without consulting + * with the Target Management + * team. + *

+ * + * @see java.lang.Process + * @see ProcessBaseShell + * @see BaseShellDecorator + * @since org.eclipse.rse.services 3.0 + */ +public interface IBaseShell extends IAdaptable { + + /** + * Get a local-to-remote OutputStream connected to the standard input of the + * underlying Process. + * + * Clients must not close the obtained OutputStream themselves, since the + * behavior that this may have on the underlying shell or process is + * undefined. Use {#exit()} instead to terminate the shell if that is + * desired, it will close all relevant Streams. + * + * @return an OutputStream for talking to the underlying process. + */ + public OutputStream getOutputStream(); + + /** + * Get a remote-to-local InputStream connected to the standard output of the + * underlying Process. + * + * Clients must not close the obtained InputStream themselves, since the + * behavior that this may have on the underlying shell or process is + * undefined. Use {#exit()} instead to terminate the shell if that is + * desired, it will close all relevant Streams. + * + * @return an InputStream for reading from the underlying process. + */ + public InputStream getInputStream(); + + /** + * Get a remote-to-local InputStream connected to the standard error output + * of the underlying Process. + * + * Implementations may return null if they do not support + * separate Streams for output and error. + * + * Clients must not close the obtained InputStream themselves, since the + * behavior that this may have on the underlying shell or process is + * undefined. Use {#exit()} instead to terminate the shell if that is + * desired, it will close all relevant Streams. + * + * @return an InputStream for reading error output from the underlying + * process, or null if separate output and error + * streams are not supported. Error output will be merged with the + * Stream obtained from {@link #getInputStream()} in that case. + */ + public InputStream getErrorStream(); + + /** + * Test whether this connection is active. + * + * @return true if the connection is active, i.e. the Process + * underlying this connection is running, and the Streams connected + * to it are not closed. + * @see #exitValue() + */ + public boolean isActive(); + + /** + * Exit this shell. + * + * Implementations are encouraged to try terminating the underlying process + * in a clean way, if they can. Depending on the implementation, this may be + * possible or not. What's guaranteed to happen is that the Streams + * connected with the process are closed so the shell will not be active any + * more. + * + * Execution of this method may run asynchronously in the sense that the + * method performs everything to initiate terminating the shell but then + * returns immediately. Clients may use {@link #waitFor(long)} after calling + * this method to know when the shell is really terminated. At any rate, the + * exit() method returns quickly and guarantees that the shell will be + * terminated as soon as possible, after any required (and possible) cleanup + * is finished. + * + * @see java.lang.Process#destroy() + */ + public void exit(); + + /** + * Return the exit value of the Process connected by this shell. + * + * Depending on the underlying implementation, this call may not be + * supported. Implementations which do not support this must throw an + * IllegalThreadStateException when the shell is still active, or return 0 + * the shell has terminated. + * + * @return the exit value of the Process connected by this shell, provided + * that it has already terminated. By convention, the exit value 0 + * indicates successful completion or the fact that transmission of + * exit values is not supported by an implementation. + * @exception IllegalThreadStateException when the shell is still active. + * @see java.lang.Process#exitValue() + */ + public int exitValue(); + + /** + * Block the calling Thread until this shell is no longer active, or the + * specified timeout has elapsed. If the underlying shell has already + * terminated, this method returns immediately. + * + * When this method returns false, the shell is no longer + * active, so an {@link #exitValue()} may be obtained. + * + * @param timeout the maximum time (in milliseconds) to wait. + * Implementations may return sooner even if the underlying + * Process has not yet terminated, so clients always need to keep + * track of time themselves and need to check the return value. A + * timeout value of zero causes this method to not limit the wait + * time. Negative wait time has undefined behavior. + * @return true if the Shell is still active after waiting + * (e.g. because the timeout has elapsed); false if + * the shell is no longer active. + * @throws InterruptedException if the waiting Thread has been interrupted, + * e.g. because the main application is shutting down. + * @see #isActive() + */ + public boolean waitFor(long timeout) throws InterruptedException; +} diff --git a/rse/plugins/org.eclipse.rse.services/src/org/eclipse/rse/internal/services/terminals/ITerminalService.java b/rse/plugins/org.eclipse.rse.services/src/org/eclipse/rse/internal/services/terminals/ITerminalService.java new file mode 100644 index 00000000000..a59f441cf78 --- /dev/null +++ b/rse/plugins/org.eclipse.rse.services/src/org/eclipse/rse/internal/services/terminals/ITerminalService.java @@ -0,0 +1,92 @@ +/******************************************************************************* + * Copyright (c) 2008 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Martin Oberhuber (Wind River) - initial API and implementation + *******************************************************************************/ + +package org.eclipse.rse.internal.services.terminals; + +import org.eclipse.core.runtime.IProgressMonitor; + +import org.eclipse.rse.services.AbstractService; +import org.eclipse.rse.services.IService; +import org.eclipse.rse.services.clientserver.messages.SystemMessageException; + +/** + * Interface for getting Terminal Connections from a remote side, also known as + * terminal session with Streams. + * + * One ITerminalService instance is typically associated with one particular + * connection to a (potentially remote) system, such that the ITerminalService + * instance can also hold state data about that session, such as connected + * state, login and authentication information, configuration data or + * environment variables. + * + * Each + * {@link #launchTerminal(String, String, String[], String, String, IProgressMonitor)} + * invocation, however, acts as a factory method such that it creates a new + * (remote) process and associated {@link ITerminalShell} connection. + * + * @noimplement This interface is not intended to be implemented by clients. + * Clients must subclass the {@link AbstractService} class rather + * than implementing this interface directly. + * + *

+ * EXPERIMENTAL. This class or interface has been added as + * part of a work in progress. There is no guarantee that this API will work or + * that it will remain the same. Please do not use this API without consulting + * with the Target Management + * team. + *

+ * + * @since org.eclipse.rse.services 3.0 + * + */ +public interface ITerminalService extends IService { + + /** + * Launch a new terminal connection, also known as shell session with + * Streams. + * + * @param ptyType requested terminal type for the new Terminal. Since not + * all Terminal implementations support specifying the Terminal + * Type, there is no guarantee that a particular setting has any + * effect. Use null to fall back to a default + * terminal type. + * @param encoding Stream encoding to use for sending initial working + * directory and initial commandToRun, and to return on + * {@link ITerminalShell#getDefaultEncoding()} request. Use + * null to fall back to a default encoding. The + * Terminal Service will make efforts to determine a proper + * default encoding on the remote side but this is not guaranteed + * to be correct. + * @param environment Array of environment variable Strings of the form + * "var=text". Since not all terminal implementations support the + * passing of environment variables, there is no guarantee that + * the created shell will actually have the specified environment + * set. Passing null is allowed in order to + * specify that no specific environment needs to be passed. + * @param initialWorkingDirectory initial working directory or empty String + * ("") if not relevant. The remote shell will launch in a + * directory of its own choice in that case (typically a user's + * home directory). + * @param commandToRun initial command to send to the remote side. + * @param monitor Progress Monitor for monitoring and cancellation during + * connection creation. + * @return the terminal connection object. Note that the connection may not + * actually be usable in case the remote side allows opening a + * channel but immediately closes it again. In this case, + * {@link ITerminalShell#getInputStream()} will throw an + * exception or be closed from the very beginning. + * @throws SystemMessageException in case an error occurred or the user + * chose to cancel the operation via the progress monitor. + */ + public ITerminalShell launchTerminal(String ptyType, String encoding, String[] environment, String initialWorkingDirectory, String commandToRun, + IProgressMonitor monitor) throws SystemMessageException; + +} diff --git a/rse/plugins/org.eclipse.rse.services/src/org/eclipse/rse/internal/services/terminals/ITerminalShell.java b/rse/plugins/org.eclipse.rse.services/src/org/eclipse/rse/internal/services/terminals/ITerminalShell.java new file mode 100644 index 00000000000..25eb8ae8ecf --- /dev/null +++ b/rse/plugins/org.eclipse.rse.services/src/org/eclipse/rse/internal/services/terminals/ITerminalShell.java @@ -0,0 +1,101 @@ +/******************************************************************************* + * Copyright (c) 2008 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Martin Oberhuber (Wind River) - initial API and implementation + *******************************************************************************/ + +package org.eclipse.rse.internal.services.terminals; + +import org.eclipse.rse.services.shells.IHostShell; + +/** + * Interface representing a terminal connection through Streams. + * + * Rather than the underlying {@link IBaseShell}, an ITerminalShell connection + * adds methods that describe the presentation of the data transmitted over its + * Streams, as well as methods like {@link #setTerminalSize(int, int)} to change + * the behavior of the presentation of this data. An instance of ITerminalShell + * is typically obtained from an {@link ITerminalService}. + * + * In RSE, a single remote shell instance can only either support the streamed + * ITerminalShell interface or the listener-based {@link IHostShell} interface, + * but not both. Note, though, that with the capabilities that an ITerminalShell + * has, it is always possible to adapt it to an IHostShell; this is typically + * not possible the other way round. We therefore recommend extenders of RSE + * that used to subclass IHostShell to move to the new IBaseShell / + * ITerminalShell APIs eventually, if they can. + * + * @noimplement This interface is not intended to be implemented by clients. + * Clients must subclass the provided {@link AbstractTerminalShell} + * or {@link TerminalShellDecorator} classes rather than + * implementing this interface directly. + * + *

+ * EXPERIMENTAL. This class or interface has been added as + * part of a work in progress. There is no guarantee that this API will work or + * that it will remain the same. Please do not use this API without consulting + * with the Target Management + * team. + *

+ * + * @see IBaseShell + * @see ITerminalService + * @see AbstractTerminalShell + * @see TerminalShellDecorator + * @since org.eclipse.rse.services 3.0 + */ +public interface ITerminalShell extends IBaseShell { + + /** + * Get the Terminal Type that's expected on this connection. + * + * The terminal type may be specified by the client when constructing a + * concrete instance of an ITerminalShell, or a remote side may actually + * expect a particular terminal type to be present. + * + * @return the terminal type expected by the remote side to properly render + * the Streams associated with this Terminal, or null + * if the ITerminalShell does not know what kind of Terminal Type is + * expected. + */ + public String getPtyType(); + + /** + * Return the default encoding that the terminal service had specified when + * creating this terminal connection, or that's known from the remote side + * to be expected. This is not necessarily known or accurate, and may be + * null. + * + * TODO I'm not actually sure if this method is a good idea. Perhaps we + * should use the IAdaptable mechanism for dealing with encodings, since our + * shells basically deal with binary data only. + * + * @return the specified default encoding, or null if + * unknown. + */ + public String getDefaultEncoding(); + + /** + * Notify the remote site that the size of the terminal has changed. There + * is no guarantee that the remote side is actually capable of changing the + * Terminal size. + * + * @param newWidth + * @param newHeight + */ + void setTerminalSize(int newWidth, int newHeight); + + /** + * Test if local echo is needed on this terminal connection. Clients are + * expected to return false if in doubt. + * + * @return true if a local echo is needed. + */ + boolean isLocalEcho(); + +} diff --git a/rse/plugins/org.eclipse.rse.services/src/org/eclipse/rse/internal/services/terminals/ProcessBaseShell.java b/rse/plugins/org.eclipse.rse.services/src/org/eclipse/rse/internal/services/terminals/ProcessBaseShell.java new file mode 100644 index 00000000000..d569d7837ef --- /dev/null +++ b/rse/plugins/org.eclipse.rse.services/src/org/eclipse/rse/internal/services/terminals/ProcessBaseShell.java @@ -0,0 +1,148 @@ +/******************************************************************************* + * Copyright (c) 2008 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Martin Oberhuber (Wind River) - initial API and implementation + *******************************************************************************/ + +package org.eclipse.rse.internal.services.terminals; + +import java.io.InputStream; +import java.io.OutputStream; + +import org.eclipse.core.runtime.PlatformObject; + +/** + * A wrapper for Java {@link Process} objects to give more convenient access to + * them through the {@link IBaseShell} interface. + * + *

+ * EXPERIMENTAL. This class or interface has been added as + * part of a work in progress. There is no guarantee that this API will work or + * that it will remain the same. Please do not use this API without consulting + * with the Target Management + * team. + *

+ * + * @since org.eclipse.rse.services 3.0 + */ +public class ProcessBaseShell extends PlatformObject implements IBaseShell { + + /** + * The underlying Process instance. + */ + protected final Process fProcess; + + /** + * Constructor. + * + * @param p the Process to wrap with this IBaseShell interface. + */ + public ProcessBaseShell(Process p) { + fProcess = p; + } + + /** + * Forcefully terminate the underlying Process through + * {@link Process#destroy()}. Subclasses may want to override this behavior + * by trying to terminate the underlying Process in a cleaner way. + * + * @see IBaseShell#exit() + */ + public void exit() { + fProcess.destroy(); + } + + public int exitValue() { + return fProcess.exitValue(); + } + + public InputStream getErrorStream() { + return fProcess.getErrorStream(); + } + + public InputStream getInputStream() { + return fProcess.getInputStream(); + } + + public OutputStream getOutputStream() { + return fProcess.getOutputStream(); + } + + /** + * Check if the underlying Process is still active. Does not check whether + * the Streams for the Process have been closed by the client, since this + * does not influence the process active state anyways. + * + * @see IBaseShell#isActive() + */ + public boolean isActive() { + try { + fProcess.exitValue(); + } catch (IllegalThreadStateException e) { + return true; + } + return false; + } + + /** + * A Watchdog Thread, to interrupt other Threads after a given time unless a + * specified condition is met. + * + * Sleeps for a given time, and upon wakeup checks if a condition is met. If + * not, the specified Thread is interrupted. + */ + private abstract static class Watchdog extends Thread { + private final Thread fThreadToWatch; + private long fTimeout; + + public Watchdog(Thread threadToWatch, long timeout) { + fThreadToWatch = threadToWatch; + fTimeout = timeout; + } + + protected abstract boolean conditionDone(); + + public void run() { + try { + sleep(fTimeout); + } catch (InterruptedException e) { + /* ignore */ + } finally { + if (!conditionDone()) { + fThreadToWatch.interrupt(); + } + } + } + } + + public boolean waitFor(long timeout) throws InterruptedException { + boolean active = isActive(); + if (active) { + Thread watchdog = null; + if (timeout > 0) { + watchdog = new Watchdog(Thread.currentThread(), timeout) { + protected boolean conditionDone() { + return !isActive(); + } + }; + watchdog.start(); + } + try { + fProcess.waitFor(); + } catch (InterruptedException e) { + /* ignore */ + } + if (watchdog != null) { + watchdog.interrupt(); + } + active = isActive(); + } + return active; + } + +} diff --git a/rse/plugins/org.eclipse.rse.services/src/org/eclipse/rse/internal/services/terminals/TerminalShellDecorator.java b/rse/plugins/org.eclipse.rse.services/src/org/eclipse/rse/internal/services/terminals/TerminalShellDecorator.java new file mode 100644 index 00000000000..492ce473fdf --- /dev/null +++ b/rse/plugins/org.eclipse.rse.services/src/org/eclipse/rse/internal/services/terminals/TerminalShellDecorator.java @@ -0,0 +1,59 @@ +/******************************************************************************* + * Copyright (c) 2008 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Martin Oberhuber (Wind River) - initial API and implementation + *******************************************************************************/ + +package org.eclipse.rse.internal.services.terminals; + +/** + * Abstract base class for clients to decorate an ITerminalShell instance they + * have with additional functionality. + * + * Typically, such additional functionality can be provided either by additional + * knowledge about the underlying system or process, or by analyzing the input + * and output streams for some well-known data that gives such additional + * knowledge. + * + *

+ * EXPERIMENTAL. This class or interface has been added as + * part of a work in progress. There is no guarantee that this API will work or + * that it will remain the same. Please do not use this API without consulting + * with the Target Management + * team. + *

+ * + * @since org.eclipse.rse.services 3.0 + */ +public abstract class TerminalShellDecorator extends BaseShellDecorator implements ITerminalShell { + + public TerminalShellDecorator(ITerminalShell delegate) { + super(delegate); + } + + protected ITerminalShell getDelegate() { + return (ITerminalShell) fDelegate; + } + + public String getPtyType() { + return getDelegate().getPtyType(); + } + + public String getDefaultEncoding() { + return getDelegate().getDefaultEncoding(); + } + + public boolean isLocalEcho() { + return getDelegate().isLocalEcho(); + } + + public void setTerminalSize(int newWidth, int newHeight) { + getDelegate().setTerminalSize(newWidth, newHeight); + } + +}