Saturday, April 09, 2011

Runtime Command Execution in Java

for everything there is always an obvious and simple way of doing and there is an intutive way of doing the same stuff, as they say its either the “Berkeley way” or the “MIT” way among the techies. For those who are not femaliear with that, here is a bit of background, when you design a software most often you would take one of these approaches, you can make it easy and intutive for the user and hence byte the complexity within the software/code and hence your user interface would look simple, elegant and easy to use, while your code might be a nighmare to maintain – a.k.a “Berkeley way” [OR] you can keep the user interface basic, hard to use and sometimes complex/non-intutive for the user, while keeping the code simple a.k.a “MIT way” . Both are valid apporaches depending on where you apply it.

One such instance is “Executing native command/applications from a Java Application” . It seems a simple task, but i have seen many applications like “Hudson” making a living out of it so read on if you are interested.

Executing a native command from java is a simple task as it can get in java, it can be accomplished in few lines of code, example below.

Runtime rt = Runtime.getRuntime();Process proc = rt.exec("ping localhost");

But think of its impact on the user, if you have ever used hudson to build your code or run your unit test you would realize the importance for the user to know whats going on as the build is being executed, this would be true if he were to be running the command natively, but hudson provides a way to dynamically append the command output as the command is being executed natively rather than dump the results at the end of the execution as it would be in the previous case, which makes it one of the most useful features. details below. for more details check this out

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
public class RuntimeExec {
public StreamWrapper getStreamWrapper(InputStream is, String type){
return new StreamWrapper(is, type);
}
private class StreamWrapper extends Thread {
InputStream is = null;
String type = null;
String message = null;
public String getMessage() {
return message;
}
StreamWrapper(InputStream is, String type) {
this.is = is;
this.type = type;
}
public void run() {
try {
BufferedReader br = new BufferedReader(new InputStreamReader(is));
StringBuffer buffer = new StringBuffer();
String line = null;
while ( (line = br.readLine()) != null) {
buffer.append(line);//.append("\n");
}
message = buffer.toString();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
}
// this is where the action is
public static void main(String[] args) {
Runtime rt = Runtime.getRuntime();
RuntimeExec rte = new RuntimeExec();
StreamWrapper error, output;
try {
Process proc = rt.exec("ping localhost");
error = rte.getStreamWrapper(proc.getErrorStream(), "ERROR");
output = rte.getStreamWrapper(proc.getInputStream(), "OUTPUT");
int exitVal = 0;
error.start();
output.start();
error.join(3000);
output.join(3000);
exitVal = proc.waitFor();
System.out.println("Output: "+output.message+"\nError: "+error.message);
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

No comments: