/*
* Lokomo OneCMDB - An Open Source Software for Configuration
* Management of Datacenter Resources
*
* Copyright (C) 2006 Lokomo Systems AB
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*
* Lokomo Systems AB can be contacted via e-mail: info@lokomo.com or via
* paper mail: Lokomo Systems AB, Sv�rdv�gen 27, SE-182 33
* Danderyd, Sweden.
*
*/
package org.onecmdb.ui.gwt.desktop.server.command.exec;
import java.io.IOException;
import java.io.LineNumberReader;
import java.io.PrintWriter;
import java.io.Reader;
import java.io.Writer;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class StreamHandler {
Log log = LogFactory.getLog(this.getClass());
public class PipeThread extends Thread {
Log pipeLog = LogFactory.getLog(this.getClass());
private LineNumberReader reader;
private PrintWriter writer;
public PipeThread(String name) {
setName(name);
}
public void setReader(Reader reader) {
this.reader = new LineNumberReader(reader);
}
public void setWriter(Writer writer) {
this.writer = new PrintWriter(writer);
}
public void run() {
// Wait to start...
pipeLog.info(getName() + " start.");
control.log(getName() + " start.");
synchronized(this) {
if (!control.isTerminate()) {
if (this.reader == null || this.writer == null) {
pipeLog.info(getName() + "Will wait...");
control.log(getName() + "Will wait...");
if (!control.isTerminate()) {
try {
this.wait();
} catch (InterruptedException e) {
}
}
}
}
}
pipeLog.info(getName() + " started.");
control.log(getName() + " started.");
boolean eof = false;
if (this.reader == null) {
pipeLog.info(getName() + " no reader set");
control.log(this.getName() + " no reader set.");
eof = true;
}
try {
while(!eof) {
if (control.isTerminate()) {
eof = true;
continue;
}
String data;
data = this.reader.readLine();
if (data == null) {
eof = true;
continue;
}
writer.println(data);
control.log(getName() + " - " + data);
}
} catch (IOException e) {
pipeLog.error(getName() + " failed:", e);
}
if (autoClose) {
pipeLog.info(getName() + " auto-close streams.");
control.log(getName() + " auto-close streams");
try {
if (writer != null) {
writer.close();
}
} catch (Throwable t) {
//
}
try {
if (reader != null) {
reader.close();
}
} catch (Throwable t) {
//
}
}
pipeLog.info(getName() + " terminated.");
control.log(getName() + " terminated");
}
}
private PipeThread stdout;
private PipeThread stderr;
private PipeThread stdin;
private boolean autoClose;
private MDRExecThread control;
public StreamHandler(MDRExecThread execThread, String name) {
this.control = execThread;
stdout = new PipeThread(name + " - [STDOUT]");
stderr = new PipeThread(name + " - [STDERR]");
stdin = new PipeThread(name + " - [STDIN]");
stdout.setDaemon(true);
stderr.setDaemon(true);
stdin.setDaemon(true);
// Start threads.
stdout.start();
stderr.start();
stdin.start();
}
public void setStdout(Writer writer) {
stdout.setWriter(writer);
}
public void setStderr(Writer writer) {
stderr.setWriter(writer);
}
public void setStdin(Reader reader) {
stdin.setReader(reader);
}
/**
* Set's the stdin writer, will kick of the writer thread.
* @param reader
*/
protected void setStdin(Writer writer) {
stdin.setWriter(writer);
synchronized(stdin) {
stdin.notify();
}
}
/**
* Set's the stdout reader, will kick of the reader thread.
* @param reader
*/
protected void setStdout(Reader reader) {
stdout.setReader(reader);
synchronized(stdout) {
stdout.notify();
}
}
/**
* Set's the stderr reader, will kick of the reader thread.
* @param reader
*/
protected void setStderr(Reader reader) {
stderr.setReader(reader);
synchronized(stderr) {
stderr.notify();
}
}
public void setAutoClose(boolean value) {
this.autoClose = value;
}
public void terminate() {
if (stderr != null) {
synchronized(stderr) {
stderr.notify();
}
}
if (stdout != null) {
synchronized(stdout) {
stdout.notify();
}
}
if (stdin != null) {
synchronized(stdin) {
stdin.notify();
}
}
}
}