blob: d2a5dc93d264ff69542e085b00a8f7807bb59db4 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2007 IBM Corporation 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:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.debug.internal.core;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Vector;
import org.eclipse.debug.core.DebugPlugin;
/**
* Writes to the input stream of a system process,
* queueing output if the stream is blocked.
*
* The input stream monitor writes to system in via
* an output stream.
*/
public class InputStreamMonitor {
/**
* The stream which is being written to (connected to system in).
*/
private OutputStream fStream;
/**
* The queue of output.
*/
private Vector fQueue;
/**
* The thread which writes to the stream.
*/
private Thread fThread;
/**
* A lock for ensuring that writes to the queue are contiguous
*/
private Object fLock;
/**
* Whether the underlying output stream has been closed
*/
private boolean fClosed = false;
/**
* Creates an input stream monitor which writes
* to system in via the given output stream.
*
* @param stream output stream
*/
public InputStreamMonitor(OutputStream stream) {
fStream= stream;
fQueue= new Vector();
fLock= new Object();
}
/**
* Appends the given text to the stream, or
* queues the text to be written at a later time
* if the stream is blocked.
*
* @param text text to append
*/
public void write(String text) {
synchronized(fLock) {
fQueue.add(text);
fLock.notifyAll();
}
}
/**
* Starts a thread which writes the stream.
*/
public void startMonitoring() {
if (fThread == null) {
fThread= new Thread(new Runnable() {
public void run() {
write();
}
}, DebugCoreMessages.InputStreamMonitor_label);
fThread.setDaemon(true);
fThread.start();
}
}
/**
* Close all communications between this
* monitor and the underlying stream.
*/
public void close() {
if (fThread != null) {
Thread thread= fThread;
fThread= null;
thread.interrupt();
}
}
/**
* Continuously writes to the stream.
*/
protected void write() {
while (fThread != null) {
writeNext();
}
if (!fClosed) {
try {
fStream.close();
} catch (IOException e) {
DebugPlugin.log(e);
}
}
}
/**
* Write the text in the queue to the stream.
*/
protected void writeNext() {
while (!fQueue.isEmpty() && !fClosed) {
String text = (String)fQueue.firstElement();
fQueue.removeElementAt(0);
try {
fStream.write(text.getBytes());
fStream.flush();
} catch (IOException e) {
DebugPlugin.log(e);
}
}
try {
synchronized(fLock) {
fLock.wait();
}
} catch (InterruptedException e) {
}
}
/**
* Closes the output stream attached to the standard input stream of this
* monitor's process.
*
* @exception IOException if an exception occurs closing the input stream
*/
public void closeInputStream() throws IOException {
if (!fClosed) {
fClosed = true;
fStream.close();
} else {
throw new IOException();
}
}
}