Forum Controls
Spotlight Features

The Rich Engineering Heritage Behind Dependency Injection

Andrew McVeigh takes us on a tour of the rich heritage behind dependency injection, what it represents, and tells us why its here to stay.

NetBeans 6: Matisse Updates

NetBeans 6 delivers great updates to the Matisse GUI builder. Spend a few minutes with Roman Strobl and get an expert briefing on what's new and what has changed.

Introduction to Groovy Part 3

In this, the third and final installation of Andres' Introduction to Groovy series, you learn about how Groovy handles variable numbers of arguments, named parameters, currying, and more about Groovy operators. Including, some new operators.

Easier Custom Components with Swing Fuse

Swing Fuse (actually just Fuse), is a framework designed to make it easier to create your own custom desktop components. In this article, Daniel Spiewak shows you how to get started and provides sample source code you can download.

Benchmark Analysis: Guice vs Spring

Willam Louth shows how he uses JXInsight Probes to investigate probable performance issues with code bases that he is not familiar with. He also highlights possible pitfalls in creating a benchmark, as well as in the analysis of results.
Replies: 9 - Pages: 1  
Threads: [ Previous | Next ]
  Click to reply to this thread Reply

How to run a command-line OR execute a system command

At 8:23 AM on Oct 31, 2005, Venkataramana M DeveloperZone Top 100 wrote:

Very often Java applications, in a loose integration scenario, may like to run external applications by invoking a system command-line. How do we do it ? Some may be knowing, but I wrote a small class which encapsulates some of the issues like creating new Process, getting the standard-output and standard-error, pipe them possibly to a logging device etc., Hope this will be of some use to those in need. All are free to use (no bindings whatsoever).

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
 
/**
 * Usage of following class can go as ...
 * <P><PRE><CODE>
 * 		SysCommandExecutor cmdExecutor = new SysCommandExecutor();
 * 		cmdExecutor.setOutputLogDevice(new LogDevice());
 * 		cmdExecutor.setErrorLogDevice(new LogDevice());
 * 		int exitStatus = cmdExecutor.runCommand(commandLine);
 * </CODE></PRE></P>
 * 
 * OR
 * 
 * <P><PRE><CODE>
 * 		SysCommandExecutor cmdExecutor = new SysCommandExecutor(); 		
 * 		int exitStatus = cmdExecutor.runCommand(commandLine);
 * 
 * 		String cmdError = cmdExecutor.getCommandError();
 * 		String cmdOutput = cmdExecutor.getCommandOutput(); 
 * </CODE></PRE></P> 
 */
public class SysCommandExecutor
{	
	private ILogDevice fOuputLogDevice = null;
	private ILogDevice fErrorLogDevice = null;
	private String fWorkingDirectory = null;
	private List fEnvironmentVarList = null;
	
	private StringBuffer fCmdOutput = null;
	private StringBuffer fCmdError = null;
	private AsyncStreamReader fCmdOutputThread = null;
	private AsyncStreamReader fCmdErrorThread = null;	
	
	public void setOutputLogDevice(ILogDevice logDevice)
	{
		fOuputLogDevice = logDevice;
	}
	
	public void setErrorLogDevice(ILogDevice logDevice)
	{
		fErrorLogDevice = logDevice;
	}
	
	public void setWorkingDirectory(String workingDirectory) {
		fWorkingDirectory = workingDirectory;
	}
	
	public void setEnvironmentVar(String name, String value)
	{
		if( fEnvironmentVarList == null )
			fEnvironmentVarList = new ArrayList();
		
		fEnvironmentVarList.add(new EnvironmentVar(name, value));
	}
	
	public String getCommandOutput() {		
		return fCmdOutput.toString();
	}
	
	public String getCommandError() {
		return fCmdError.toString();
	}
	
	public int runCommand(String commandLine) throws Exception
	{
		/* run command */
		Process process = runCommandHelper(commandLine);
		
		/* start output and error read threads */
		startOutputAndErrorReadThreads(process.getInputStream(), process.getErrorStream());
	    
		/* wait for command execution to terminate */
		int exitStatus = -1;
		try {
			exitStatus = process.waitFor();
					
		} catch (Throwable ex) {
			throw new Exception(ex.getMessage());
			
		} finally {
			/* notify output and error read threads to stop reading */
			notifyOutputAndErrorReadThreadsToStopReading();
		}
		
		return exitStatus;
	}	
	
	private Process runCommandHelper(String commandLine) throws IOException
	{
		Process process = null;		
		if( fWorkingDirectory == null )
			process = Runtime.getRuntime().exec(commandLine, getEnvTokens());
		else
			process = Runtime.getRuntime().exec(commandLine, getEnvTokens(), new File(fWorkingDirectory));
		
		return process;
	}
	
	private void startOutputAndErrorReadThreads(InputStream processOut, InputStream processErr)
	{
		fCmdOutput = new StringBuffer();
		fCmdOutputThread = new AsyncStreamReader(processOut, fCmdOutput, fOuputLogDevice, "OUTPUT");		
		fCmdOutputThread.start();
		
		fCmdError = new StringBuffer();
		fCmdErrorThread = new AsyncStreamReader(processErr, fCmdError, fErrorLogDevice, "ERROR");
		fCmdErrorThread.start();
	}
	
	private void notifyOutputAndErrorReadThreadsToStopReading()
	{
		fCmdOutputThread.stopReading();
		fCmdErrorThread.stopReading();
	}
	
	private String[] getEnvTokens()
	{
		if( fEnvironmentVarList == null )
			return null;
		
		String[] envTokenArray = new String[fEnvironmentVarList.size()];
		Iterator envVarIter = fEnvironmentVarList.iterator();
		int nEnvVarIndex = 0; 
		while (envVarIter.hasNext() == true)
		{
			EnvironmentVar envVar = (EnvironmentVar)(envVarIter.next());
			String envVarToken = envVar.fName + "=" + envVar.fValue;
			envTokenArray[nEnvVarIndex++] = envVarToken;
		}
		
		return envTokenArray;
	}	
}
 
class AsyncStreamReader extends Thread
{
	private StringBuffer fBuffer = null;
	private InputStream fInputStream = null;
	private String fThreadId = null;
	private boolean fStop = false;
	private ILogDevice fLogDevice = null;
	
	private String fNewLine = null;
	
	public AsyncStreamReader(InputStream inputStream, StringBuffer buffer, ILogDevice logDevice, String threadId)
	{
		fInputStream = inputStream;
		fBuffer = buffer;
		fThreadId = threadId;
		fLogDevice = logDevice;
		
		fNewLine = System.getProperty("line.separator");
	}	
	
	public String getBuffer() {		
		return fBuffer.toString();
	}
	
	public void run()
	{
		try {
			readCommandOutput();
		} catch (Exception ex) {
			//ex.printStackTrace(); //DEBUG
		}
	}
	
	private void readCommandOutput() throws IOException
	{		
		BufferedReader bufOut = new BufferedReader(new InputStreamReader(fInputStream));		
		String line = null;
		while ( (fStop == false) && ((line = bufOut.readLine()) != null) )
		{
			fBuffer.append(line + fNewLine);
			printToDisplayDevice(line);
		}		
		bufOut.close();
		//printToConsole("END OF: " + fThreadId); //DEBUG
	}
	
	public void stopReading() {
		fStop = true;
	}
	
	private void printToDisplayDevice(String line)
	{
		if( fLogDevice != null )
			fLogDevice.log(line);
		else
		{
			//printToConsole(line);//DEBUG
		}
	}
	
	private synchronized void printToConsole(String line) {
		System.out.println(line);
	}
}
 
class EnvironmentVar
{
	public String fName = null;
	public String fValue = null;
	
	public EnvironmentVar(String name, String value)
	{
		fName = name;
		fValue = value;
	}
}
 
public interface ILogDevice
{
	public void log(String str);
}


Thanks
~Venkat
1 . At 12:28 PM on Oct 31, 2005, vijay wrote:
  Click to reply to this thread Reply

Re: How to run a command-line OR execute a system command

And the following code will also do the job of just executing a command line or shell commands:

import java.io.*;

class cli{
public static void main(String Argv[]) {
try {
String ls_str;

Process ls_proc = Runtime.getRuntime().exec("ls -l");

// get its output (your input) stream

DataInputStream ls_in = new DataInputStream(
ls_proc.getInputStream());

try {
while ((ls_str = ls_in.readLine()) != null) {
System.out.println(ls_str);
}
} catch (IOException e) {
System.exit(0);
}
} catch (IOException e1) {
System.err.println(e1);
System.exit(1);
}

System.exit(0);
}
}
Vijay Automation Developer Canada
2 . At 5:40 PM on Nov 1, 2005, Guillaume Desnoix DeveloperZone Top 100 wrote:
  Click to reply to this thread Reply

Re: How to run a command-line OR execute a system command

What about the input? Easy to add.

Your code is fine but the main problem I face when running an external process was the synchronization of the output and error streams (not mixing lines but still displaying them in order). I still haven't find a perfect solution.
JDistro (shared runtime and swing desktop) -- J NLP (application catalog) -- Alma (source code tool) -- Slaf (swing look and feel) -- Pixels Loupanthère
3 . At 3:47 AM on Nov 2, 2005, Venkataramana M DeveloperZone Top 100 wrote:
  Click to reply to this thread Reply

Re: How to run a command-line OR execute a system command

Desnoix, Thanks for pointing out the the inconsistency in showing the output and error in the same order as written by the external-process. I feel that might happen because of discrepancy in code itself like the one I had posted ...

Since output and error read-threads are reading the stream line by line, if actually the process doesn't write line by line sometimes, then the order will not be retained. So a character read should take away that inconsistency.

So the new code with the fix could be like this ...
class AsyncStreamReader extends Thread
{
	private StringBuffer fBuffer = null;
	private InputStream fInputStream = null;
	private String fThreadId = null;
	private boolean fStop = false;
	private ILogDevice fLogDevice = null;
	
	private String fNewLine = null;
	
	public AsyncStreamReader(InputStream inputStream, StringBuffer buffer, ILogDevice logDevice, String threadId)
	{
		fInputStream = inputStream;
		fBuffer = buffer;
		fThreadId = threadId;
		fLogDevice = logDevice;
		
		fNewLine = System.getProperty("line.separator");
	}	
	
	public String getBuffer() {		
		return fBuffer.toString();
	}
	
	public void run()
	{
		try {
			readCommandOutput();
		} catch (Exception ex) {
			//ex.printStackTrace(); //DEBUG
		}
	}
	
	private void readCommandOutput() throws IOException
	{		
		BufferedReader bufOut = new BufferedReader(new InputStreamReader(fInputStream));		
		
		char c = '\0';
		while ( (fStop == false) && ((c = (char)bufOut.read()) != -1) )
		{
			fBuffer.append(c);
			printToDisplayDevice(c);
		}		
		bufOut.close();
		//printToConsole("END OF: " + fThreadId); //DEBUG
	}
	
	public void stopReading() {
		fStop = true;
	}
	
	private void printToDisplayDevice(char c)
	{
		if( fLogDevice != null )
			fLogDevice.log(c);
		else
		{
			//printToConsole(c);//DEBUG
		}
	}
	
	private synchronized void printToConsole(char c) {
		System.out.print(c);
	}
}
 
public interface ILogDevice
{
	public void log(char c);
}


As far as feeding the process with an input, that should be an easy change.

Thanks a lot.
~Venkat
~Venkat + plus magazine ... living mathematics
4 . At 5:29 PM on Jan 3, 2007, RIchard Cook wrote:
  Click to reply to this thread Reply

Re: How to run a command-line OR execute a system command

There is a bug in your character reading code:

while ( (fStop == false) && ((c = (char)bufOut.read()) != -1) )


You cast the int to a char before testing if it is -1. This causes an infinite loop in my testing. You need to do the test before casting.
int charInt;
while ( (fStop == false) && ((charInt = bufOut.read()) != -1) )
{
c = (char)charInt;
....
5 . At 6:18 AM on Mar 19, 2007, Israr Ahmed wrote:
  Click to reply to this thread Reply

Re: How to run a command-line OR execute a system command

Vijay's code is running properly.
There certainly have been performance issues with Java. We've been working really hard on them. The primary way we've attacked the problem is with advanced virtual machines. The performance has been getting very nice. --James Gosling, 1999.
6 . At 2:31 AM on Aug 20, 2007, shailendra wrote:
  Click to reply to this thread Reply

Re: How to run a command-line OR execute a system command

Yup its working.

jYog
7 . At 9:36 AM on Aug 20, 2007, Javatower wrote:
  Click to reply to this thread Reply

Re: How to run a command-line OR execute a system command

It seems there are two ways to ruan the external applications. Which is better?
Thanks a lot.
java tutorials -- java programming
8 . At 5:09 AM on Jan 31, 2008, --- wrote:
  Click to reply to this thread Reply

Re: How to run a command-line OR execute a system command

Yup its working.
JSP tutorials
JSP tutorials
9 . At 3:17 AM on Feb 13, 2008, perlon wrote:
  Click to reply to this thread Reply

Re: How to run a command-line OR execute a system command

Good script...

phnetermine no prescription , hydrocodone ambien beeswax hgh


thread.rss_message