blob: 4fe6af3fba8805a0007fabf82479e4b7e8aad111 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2006 PalmSource, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Ewa Matejska (PalmSource) - initial version
* Martin Oberhuber (Wind River) - adapt to IHostOutput API (bug 161773, 158312)
* Martin Oberhuber (Wind River) - moved from org.eclipse.rse.remotecdt (bug 161777)
* Martin Oberhuber (Wind River) - renamed from HostShellAdapter (bug 161777)
* Martin Oberhuber (Wind River) - improved Javadoc
*******************************************************************************/
package org.eclipse.dltk.core.internal.rse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import org.eclipse.rse.services.shells.HostShellOutputStream;
import org.eclipse.rse.services.shells.IHostOutput;
import org.eclipse.rse.services.shells.IHostShell;
import org.eclipse.rse.services.shells.IHostShellChangeEvent;
import org.eclipse.rse.services.shells.IHostShellOutputListener;
/**
* This class represents a host shell process. It does not represent one process
* running in the shell. This means that the output of multiple shell commands
* will be returned until the shell exits.
*
* @author Ewa Matejska
*/
public class MyHostShellProcessAdapter extends Process implements
IHostShellOutputListener {
private IHostShell hostShell;
private PipedInputStream inputStream = null;
private PipedInputStream errorStream = null;
private HostShellOutputStream outputStream = null;
private PipedOutputStream hostShellInput = null;
private PipedOutputStream hostShellError = null;
private String pattern1;
/**
* Constructor.
*
* @param hostShell
* An instance of the IHostShell class.
* @param postfix
* @throws java.io.IOException
*/
public MyHostShellProcessAdapter(IHostShell hostShell, String pattern1)
throws java.io.IOException {
this.hostShell = hostShell;
hostShellInput = new PipedOutputStream();
hostShellError = new PipedOutputStream();
inputStream = new PipedInputStream(hostShellInput);
errorStream = new PipedInputStream(hostShellError);
outputStream = new HostShellOutputStream(hostShell);
this.hostShell.getStandardOutputReader().addOutputListener(this);
this.hostShell.getStandardErrorReader().addOutputListener(this);
this.pattern1 = pattern1;
}
/**
* Exits the shell.
*
* @see java.lang.Process#destroy()
*/
public synchronized void destroy() {
hostShell.exit();
notifyAll();
try {
hostShellInput.close();
hostShellError.close();
inputStream.close();
errorStream.close();
outputStream.close();
} catch (IOException e) {
// FIXME IOException when closing one of the streams will leave
// others open
// Ignore
}
}
/**
* There is no relevant exit value to return when the shell exits. This
* always returns 0.
*/
public synchronized int exitValue() {
if (hostShell.isActive())
throw new IllegalThreadStateException();
// No way to tell what the exit value was.
// TODO it would be possible to get the exit value
// when the remote process is started like this:
// sh -c' remotecmd ; echo" -->RSETAG<-- $?\"'
// Then the output steram could be examined for -->RSETAG<-- to get the
// exit value.
return 0;
}
/**
* Returns the error stream of the shell.
*
* @see java.lang.Process#getErrorStream()
*/
public InputStream getErrorStream() {
return errorStream;
}
/**
* Returns the input stream for the shell.
*
* @see java.lang.Process#getInputStream()
*/
public InputStream getInputStream() {
return inputStream;
}
/**
* Returns the output stream for the shell.
*
* @see java.lang.Process#getOutputStream()
*/
public OutputStream getOutputStream() {
return outputStream;
}
/**
* Waits for the shell to exit.
*
* @see java.lang.Process#waitFor()
*/
public synchronized int waitFor() throws InterruptedException {
while (hostShell.isActive()) {
try {
wait(1000);
} catch (InterruptedException e) {
// ignore because we're polling to see if shell is still active.
}
}
try {
// Wait a second to try to get some more output from the target
// shell before closing.
wait(1000);
// Allow for the data from the stream to be read if it's available
if (inputStream.available() != 0 || errorStream.available() != 0)
throw new InterruptedException();
hostShellInput.close();
hostShellError.close();
inputStream.close();
errorStream.close();
outputStream.close();
} catch (IOException e) {
// Ignore
}
return 0;
}
/**
* Process an RSE Shell event, by writing the lines of text contained in the
* event into the adapter's streams.
*
* @see org.eclipse.rse.services.shells.IHostShellOutputListener#
* shellOutputChanged
* (org.eclipse.rse.services.shells.IHostShellChangeEvent)
*/
private boolean skip = true;
private int prefixCounter = 0;
public void shellOutputChanged(IHostShellChangeEvent event) {
IHostOutput[] input = event.getLines();
OutputStream outputStream = event.isError() ? hostShellError
: hostShellInput;
try {
for (int i = 0; i < input.length; i++) {
String line = input[i].getString();
// System.out.println("RSEExecEnvironment:" + line);
String trimLine = line.trim();
if (trimLine.endsWith(this.pattern1)) {
if (!trimLine.equals(this.pattern1)) {
// We need to output part of line
int pos = line.indexOf(this.pattern1);
outputStream.write(line.substring(0, pos).getBytes());
outputStream.write('\n');
outputStream.flush();
}
prefixCounter++;
if (prefixCounter == 2) {
// System.out.println("CALL DESTROY");
hostShellError.close();
hostShellInput.close();
return;
}
skip = !skip;
continue;
}
if (!skip) {
outputStream.write(line.getBytes());
outputStream.write('\n');
outputStream.flush();
}
}
} catch (IOException e) {
// Ignore
}
}
}