The Skoll Client retrieves a set of commands from the Skoll Server to compile and test MySQL; these commands are UNIX shell commands. My Google Summer of Code project is to work on the Java Skoll Client, I spent a great deal of time and effort getting these shell commands to run well in Java. Running shell commands in Java is not always straightforward, here are some techniques I learned to get the job done.
Use Java’s ProcessBuilder class instead of Runtime class for Java 5.0+ projects. There are two reasons. First, ProcessBuilder has redirectErrorStream() method that automatically merges the standard output and standard error together so the output of a command would make more sense and more importantly the process won’t freeze if the developer doesn’t clear the error output stream. Second, the environment() method returns a nice Map the developer can use to manipulate the environment in which the command should run. Unfortunately, I must support Java 1.4 and 5.0 so I had to do everything the hard way.
Modifying the PATH environment variable does not add a location for Java to locate executables, at least not the way I expected it to. I was trying to run the “bzr” command which is not in my default path, I thought setting the PATH environment variable to include the non-default path would allow Java to find “bzr”. That did not work. The environment settings do not take affect until the process has started, but Java cannot start the process because it cannot find the “bzr” command. For now, I set the PATH in the shell script that starts the Skoll Client. But one possible solution is to set the environment variables, then run the command “sh -c ‘bzr’” (not yet tested).
Passing a shell command to Java does not always work. The way Java parses the commands does unexpected things, at least to me at first. I found that parsing the commands myself then passing them to Java guarantees correct execution. This command parsing algorithm divides one command string into an array of command parts; the command parts are divided by whitespace, unless the whitespace appears in quotation. Here is a simple method that prepares the command for Java.
private String[] prepareCommand(String command)
{
ArrayList commandParts = new ArrayList();
StringBuffer currPart = new StringBuffer();
boolean inQuote = false;
for (int x = 0; x < command.length(); x++)
{
char ch = command.charAt(x);
if (ch == ''' || ch == '"')
{
inQuote = !inQuote;
}
else if (Character.isWhitespace(ch) && !inQuote)
{
commandParts.add(currPart.toString());
currPart = new StringBuffer();
}
else
{
currPart.append(ch);
}
// get the last part of the command
if (x == command.length() - 1)
{
commandParts.add(currPart.toString());
}
}
String[] coms = new String[commandParts.size()];
commandParts.toArray(coms);
return coms;
}
Comments
The sequel to the 1987 cult
The sequel to the 1987 cult hit The Lost Boys takes us to the shady surf city of Luna Bay, California, where vampires quickly dispatch anyone who crosses their path. Into this dark world arrive Chris Emerson (Hilgenbrink) and his younger sister, Nicole (Reeser). Having just lost their parents in a car accident, the siblings move in with their eccentric Aunt Jillian and become new prey for the locals way of life…