2007/11/14

Original Code: WinCuiClient MonitorReader


package my.man

import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;

/**
* make read no wait and
*
* monitorReader = new MonitorReader(getReader());
* monitorReader.asyncRead(this);
* synchronized (this) {
* wait ();
* }
* monitorReader.getLines();
*
* @author f.yang
*/
public class MonitorReader extends Reader {
/** actual reader */
private BufferedReader reader;
/** history */ // TODO deal with large history that out of memory
private StringBuffer history = new StringBuffer(1000);
/** current lines buffer */
private StringBuffer lines = new StringBuffer(100);
/** asynchronized reading waiter */
private Object waiter = null;
/** continue reading signal */
private Object readSignal = new Object();
/** closed boolean */
private boolean closed = false;
/** this for inner class */
private MonitorReader monitorReader = this;

/**
* reader monitor thread
*/
protected Thread readerMonitorThread = new Thread(new Runnable () {
public void run () {
while(!closed) {
// wait read sinal
try {
synchronized (readSignal) {
readSignal.wait();
}
if (closed) {
break;
}
} catch (InterruptedException ex) {
}
synchronized (monitorReader) {
readAll();
// notify one waiter
synchronized (waiter) {
waiter.notifyAll();
}
waiter = null;
}
}
}
});

/**
* constructor
* @param reader
*/
public MonitorReader(BufferedReader reader) {
this.reader = reader;
this.readerMonitorThread.start();
}

/**
* get read lines
* @return
*/
public StringBuffer getLines () {
synchronized (lines) {
return new StringBuffer(lines);
}
}

/**
* @param waiter
*/
public void asyncRead (Object waiter) {
synchronized (this) {
// TODO add waiter to waiters list for furture notification


if (this.waiter != null) {
throw new RuntimeException ("Re-enter asyncReadLines");
}
this.waiter = waiter;

history.append(lines);
lines.delete(0, lines.length());

// wake up worker thread read line
synchronized (readSignal) {
readSignal.notify();
}
}
}

/**
* provides a method to determine wether the monitor is under reading
* @return is read waiting
*/
public boolean isReading () {
synchronized (this) {
return this.waiter != null;
}
}

//-------------------------------------------------
// compatible public methods

/**
* for compatible with BufferedReader
* @return readLine
*/
public String readLine () throws IOException {
synchronized (history) {
synchronized (lines) {
history.append(lines);
lines.delete(0, lines.length());
String str = reader.readLine();
lines.append(str);
return str;
}
}
}


/**
* for read abstract class compatible
* @override
*/
public synchronized int read(char[] cbuf, int off, int len) throws IOException {
archiveToHistory();
int readLen = reader.read(cbuf, off, len);
lines.append(cbuf, off, readLen);
return readLen;
}

/**
* for read abstract class compatible
* @Override
*/
public synchronized void close() throws IOException {
if (!closed) {
closed = true;
synchronized (readSignal) {
readSignal.notify();
}
}
}

//-------------------------------------------------
// private

/**
* read all ready information into lines buffer
* @return
*/
private synchronized void readAll () {
try {
archiveToHistory();
// read all lines that generated in the buffer once
char[] buf = new char[100];
while (reader.ready()) {
int readLen = reader.read(buf, 0, buf.length);
lines.append(buf, 0, readLen);
}
} catch (IOException e) {
throw new RuntimeException (e);
}
}
/**
* move lines to history with protecting history and lines
*/
private synchronized void archiveToHistory () {
history.append(lines);
lines.delete(0, lines.length());
}
}



package my.man;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.Map;

/**
* windows command line auto-answer utility
* Asynchronized read/write console
* but have some problem on process synchronizing and lock
* should be debug furture.
* Demo:
public static void main(String[] args) {
// TODO code application logic here
//new MainJFrame().setVisible(true);
Map param = new HashMap ();
WinCuiClient cuiClient = new WinCuiClient(param);
cuiClient.execute("dir");
cuiClient.exit();
}
* @author f.yang
*/
public class WinCuiClient extends CuiClientImpl {
/** proc */
protected Process proc;

public static final String COMMAND_LINE_KEY = "commandLine";

public WinCuiClient(Map param) {
init(param);
}

/**
* init shell process
* @param param
* @throws java.io.IOException
*/
public void initProc(Map param) throws IOException {
if (param.containsKey(COMMAND_LINE_KEY)) {
proc = Runtime.getRuntime().exec(
(String) param.get(COMMAND_LINE_KEY));
} else {
proc = Runtime.getRuntime().exec("cmd.exe /k");
}
}

/**
* execute command with shell process
* @param command
*/
public void execute(String command) {
try {
// TODO add check and rule
System.out.print("[man]" + "executing :" + command);
stdinWriter.println(command);
stdinWriter.flush();
stdoutReader.asyncRead(this);
stderrReader.asyncRead(this);
Thread.sleep(5000L);
synchronized (this) {
wait();
}
System.out.println("[out]" + stdoutReader.getLines().toString());
System.out.println("[err]" + stderrReader.getLines().toString());
System.out.println("[man]" + "executing finished");
} catch (InterruptedException ex) {
new RuntimeException(ex);
//Logger.getLogger(WinCuiClient.class.getName()).log(Level.SEVERE, null, ex);
}
}

public void exit() {
try {
execute("exit");
stdinWriter.close();
stdoutReader.close();
stderrReader.close();
proc.destroy();
} catch (IOException e) {
new RuntimeException(e);
}
}

/**
* execute multiple commands with shell process
* @param commands
*/
public void executeBatch(String[] commands) {
// TODO add check and rule
for (int i = 0; i < commands.length; i++) {
execute(commands[i]);
}
}

/**
* @Override
* @param param
* @return
*/
public void init(Map param) {
super.init(param);
try {
initProc(param);
stdinWriter = new PrintWriter(proc.getOutputStream());
stdoutReader = new MonitorReader(new BufferedReader(
new InputStreamReader(proc.getInputStream())));
stderrReader = new MonitorReader(new BufferedReader(
new InputStreamReader(proc.getErrorStream())));
} catch (IOException ex) {
throw new RuntimeException(ex);
}
}
}



import java.io.BufferedReader;
import java.io.PrintWriter;
import java.io.Reader;
import java.util.Map;

/**
* implementation
* @author funnyok
*/
public abstract class CuiClientImpl implements CuiClient {
protected PrintWriter stdinWriter;
protected MonitorReader stdoutReader;
protected MonitorReader stderrReader;
protected Map param;

public void init (Map param) {
this.param = param;
}

/**
* @Override
* @return stdoutReader
*/
public MonitorReader getStdoutReader() {
return stdoutReader;
}

/**
* @Override
* @return stderrReader
*/
public MonitorReader getStderrReader() {
return stderrReader;
}

/**
* @Override
* @return stdinWriter
*/
public PrintWriter getStdinWriter() {
return stdinWriter;
}

}

No comments: