/* (C) 2012 Pragmatic Software
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/
*/
package com.googlecode.networklog;
import android.util.Log;
import java.lang.Runtime;
import java.lang.Process;
import java.io.DataOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.BufferedReader;
import java.io.IOException;
import java.lang.Thread;
import java.util.Arrays;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
public class ShellCommand {
Runtime rt;
String[] command;
String tag = "";
Process process;
DataOutputStream stdin;
StreamReader stdout;
private String error;
public int exitval;
public ShellCommand(String[] command, String tag) {
this(command);
this.tag = tag;
}
public ShellCommand(String[] command) {
this.command = command;
rt = Runtime.getRuntime();
}
public String[] start(boolean waitForExit) {
MyLog.d("ShellCommand: starting [" + tag + "] " + Arrays.toString(command));
exitval = -1;
error = null;
try {
process = new ProcessBuilder()
.command(command)
.redirectErrorStream(true)
.start();
stdout = new StreamReader(process.getInputStream());
stdout.start();
} catch(Exception e) {
Log.e("NetworkLog", "Failure starting shell command [" + tag + "]", e);
error = e.getCause().getMessage();
return null;
}
if(waitForExit) {
waitForExit();
String[] output = stdout.buffer.toArray(new String[stdout.buffer.size()]);
return output;
}
stdin = new DataOutputStream(process.getOutputStream());
return null;
}
public boolean hasError() {
return error != null;
}
public String getError(boolean clearError) {
if(clearError) {
String ret = error;
error = null;
return ret;
} else {
return error;
}
}
public int waitForExit() {
try {
if(process != null) {
exitval = process.waitFor();
MyLog.d("ShellCommand exited: [" + tag + "] exit " + exitval);
} else {
MyLog.d("ShellCommand waitForExit: [" + tag + "] has no process");
}
finish();
} catch (InterruptedException e) {
e.printStackTrace();
}
return exitval;
}
public boolean checkForExit() {
return checkForExit(false);
}
public boolean checkForExit(boolean ignoreStdout) {
if(process == null) {
System.out.println("checkForExit process null");
return true;
}
try {
exitval = process.exitValue();
if(ignoreStdout == true) {
MyLog.d("ShellCommand exited: [" + tag + "] exit " + exitval);
return true;
} else if(stdout.buffer.size() == 0) {
MyLog.d("ShellCommand exited: [" + tag + "] exit " + exitval);
return true;
} else {
return false;
}
} catch(IllegalThreadStateException e) {
return false;
}
}
public void close() {
finish();
}
public void finish() {
MyLog.d("ShellCommand: finishing [" + tag + "] " + Arrays.toString(command));
try {
if(stdout != null) {
stdout.join();
stdout.close();
}
if(stdin != null) {
stdin.close();
}
} catch(Exception e) {
Log.e("NetworkLog", "Exception finishing [" + tag + "]", e);
}
if(process != null) {
process.destroy();
}
}
public boolean sendCommand(String command) {
if(MyLog.enabled) {
if(!command.equals("echo;echo ..EOF..$?\n")) {
MyLog.d("ShellCommand [" + tag + "] Executing command [" + command.trim() + "]");
}
}
if(stdin == null) {
Log.e("NetworkLog", "ShellCommand [" + tag + "] Error attempting to execute command [" + command.trim() + "] -- process has no stdin");
error = "Process has no stdin";
return false;
}
if(checkForExit(true)) {
Log.e("NetworkLog", "ShellCommand [" + tag + "] Error attempting to execute command [" + command.trim() + "] -- process has exited");
error = "Process has exited";
return false;
}
try {
stdin.writeBytes(command);
if(command.length() > 0 && command.charAt(command.length() - 1) != '\n') {
stdin.writeBytes("\n");
}
stdin.flush();
} catch (IOException e) {
e.printStackTrace();
error = e.getCause().getMessage();
return false;
}
return true;
}
class StreamReader extends Thread {
InputStream is;
String tag;
LinkedBlockingQueue<String> buffer = new LinkedBlockingQueue<String>();
StreamReader(InputStream is) {
this(is, null);
}
StreamReader(InputStream is, String tag) {
this.is = is;
this.tag = tag;
}
public void run() {
String outTag = null;
if(tag != null && tag.length() > 0) {
outTag = tag + "> ";
}
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
String line;
while((line = reader.readLine()) != null) {
if(tag == null || tag.length() == 0) {
buffer.put(line);
} else {
buffer.put(outTag + line);
}
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("StreamReader done");
}
public boolean lineAvailable() {
return buffer.size() != 0;
}
public String readLine() {
String result;
try {
if(checkForExit() && buffer.size() == 0) {
return null;
}
while(checkForExit() == false) {
result = buffer.poll(200, TimeUnit.MILLISECONDS);
if(result != null) {
return result;
}
}
if(buffer.size() != 0) {
result = buffer.take();
return result;
}
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
public void close() {
try {
is.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}