Index: main/trunk/greenstone3/src/java/org/greenstone/admin/guiext/Command.java
===================================================================
--- main/trunk/greenstone3/src/java/org/greenstone/admin/guiext/Command.java	(revision 31664)
+++ main/trunk/greenstone3/src/java/org/greenstone/admin/guiext/Command.java	(revision 31665)
@@ -12,4 +12,6 @@
 import javax.swing.JTextArea;
 import javax.swing.JOptionPane;
+
+import org.greenstone.util.SafeProcess;
 
 public class Command implements Runnable
@@ -57,10 +59,10 @@
 		
 	File workingDirectory = new File(_parent.getParent().getParent().getExtensionDirectory());
-	Process commandLineProc = null;
+	SafeProcess commandLineProc = null;
 	try{
 	    commandLineProc = null;
+	    String[] args = new String[3];
 	    
 	    if(System.getProperty("os.name").contains("Windows")){
-		String[] args = new String[3];
 		args[0] = "cmd.exe";
 		args[1] = "/C";
@@ -75,8 +77,7 @@
 		messageArea.append("\nExecuting \"" + allArgs + "\" on the command line\n");
 
-		commandLineProc = Runtime.getRuntime().exec(args, null, workingDirectory);
+		//commandLineProc = Runtime.getRuntime().exec(args, null, workingDirectory);
 	    }
 	    else{
-		String[] args = new String[3];
 		args[0] = "sh";
 		args[1] = "-c";
@@ -90,7 +91,10 @@
 
 		messageArea.append("\nExecuting \"" + allArgs + "\" on the command line\n");
-		commandLineProc = Runtime.getRuntime().exec(args, null, workingDirectory);
-	    }
-	    
+		//commandLineProc = Runtime.getRuntime().exec(args, null, workingDirectory);
+	    }
+
+	    commandLineProc = new SafeProcess(args, null, workingDirectory); 
+
+	    /*
 	    BufferedReader stdInput = new BufferedReader(new InputStreamReader(commandLineProc.getInputStream()));
 
@@ -104,5 +108,12 @@
 	    
 	    int success = commandLineProc.waitFor();
-	    
+	    */
+
+	    // Replacing the above and its use of the PrinterThread inner class with SafeProcess.java:
+	    SafeProcess.LineByLineHandler outLineHandler = new ProcessLineHandler(messageArea, SafeProcess.STDOUT);
+	    SafeProcess.LineByLineHandler errLineHandler = new ProcessLineHandler(messageArea, SafeProcess.STDERR);		    
+
+	    int success = commandLineProc.runProcess(outLineHandler, errLineHandler);
+
 	    if(success != 0){
 		System.err.println("Command line process \"" + command  + "\" returned unsuccessfully with the value \"" + success + "\"");
@@ -148,4 +159,5 @@
     }
 
+    /*
     public class PrinterThread extends Thread
     {
@@ -173,4 +185,31 @@
 	    }
 	}
+    }*/
+
+    public class ProcessLineHandler extends SafeProcess.LineByLineHandler
+    {
+	// These members need to be final in order to synchronize on them
+	private final JTextArea _messageArea;
+
+	public ProcessLineHandler(JTextArea messageArea, int src)
+	{
+	    super(src); // will set this.source to STDERR or STDOUT
+	    _messageArea = messageArea;
+	}
+
+	public void gotLine(String line) { // first non-null line
+
+	    // messageArea needs to be synchronized, since both the process'
+	    // stderr and stdout will be attempting to append to it
+
+	    synchronized(_messageArea) {
+		_messageArea.append(line + "\n");
+		_messageArea.setSelectionEnd(_messageArea.getDocument().getLength());
+	    }
+	}
+	public void gotException(Exception e) {
+	    e.printStackTrace();
+	}
+
     }
 }
Index: main/trunk/greenstone3/src/java/org/greenstone/gsdl3/service/MapRetrieve.java
===================================================================
--- main/trunk/greenstone3/src/java/org/greenstone/gsdl3/service/MapRetrieve.java	(revision 31664)
+++ main/trunk/greenstone3/src/java/org/greenstone/gsdl3/service/MapRetrieve.java	(revision 31665)
@@ -23,4 +23,5 @@
 import org.greenstone.gsdl3.util.GSXML;
 import org.greenstone.gsdl3.util.XMLConverter;
+import org.greenstone.util.SafeProcess;
 
 import org.w3c.dom.Document;
@@ -459,4 +460,5 @@
 					// get the map size
 					String get_size[] = { "identify", "-size", "10000", temp_image_file };
+					/*
 					Process proc;
 					proc = Runtime.getRuntime().exec(get_size);
@@ -464,4 +466,10 @@
 					img_size = br.readLine();
 					proc.waitFor();
+					*/
+					SafeProcess proc = new SafeProcess(get_size);
+					proc.runProcess();
+					img_size = proc.getStdOutput();
+					proc = null;
+
 					img_size = img_size.substring(img_size.indexOf("JPEG") + 5, img_size.indexOf(" ", img_size.indexOf("JPEG") + 5));
 					width = Integer.parseInt(img_size.substring(0, img_size.indexOf("x")));
@@ -541,5 +549,5 @@
 					BufferedWriter bw = new BufferedWriter(new FileWriter(this.temp_files_dir + "add_x_" + uid));
 					;
-					Process proc;
+					SafeProcess proc;
 
 					// if a new search
@@ -547,14 +555,23 @@
 					{
 						// copy requested map to temp.jpg
-						proc = Runtime.getRuntime().exec("cp " + this.files_home_dir + "maps" + File.separator + img_num + ".jpg " + temp_image_file);
-						proc.waitFor();
+						/*proc = Runtime.getRuntime().exec("cp " + this.files_home_dir + "maps" + File.separator + img_num + ".jpg " + temp_image_file);
+						  proc.waitFor();*/
+					    proc = new SafeProcess("cp " + this.files_home_dir + "maps" + File.separator + img_num + ".jpg " + temp_image_file);
+					    proc.runProcess();
+					    proc = null;					    
 					}
 
 					//get the image size
 					String get_size[] = { "identify", "-size", "10000", temp_image_file };
-					proc = Runtime.getRuntime().exec(get_size);
+					/*proc = Runtime.getRuntime().exec(get_size);				
 					BufferedReader br = new BufferedReader(new InputStreamReader(proc.getInputStream()));
 					img_size = br.readLine();
 					proc.waitFor();
+					*/
+					proc = new SafeProcess(get_size);
+					proc.runProcess();
+					img_size = proc.getStdOutput();
+					proc = null;
+
 					img_size = img_size.substring(img_size.indexOf("JPEG") + 5, img_size.indexOf(" ", img_size.indexOf("JPEG") + 5));
 					if (img_size.indexOf("+") != -1)
@@ -754,6 +771,9 @@
 							buf.close();
 							// execute the command for the legend image
-							proc = Runtime.getRuntime().exec("sh " + this.temp_files_dir + "add_l_" + uid);
-							proc.waitFor();
+							/*proc = Runtime.getRuntime().exec("sh " + this.temp_files_dir + "add_l_" + uid);
+							  proc.waitFor();*/
+							proc = new SafeProcess("sh " + this.temp_files_dir + "add_l_" + uid);
+							proc.runProcess();
+							proc = null;
 						}
 						inType.close();
@@ -763,6 +783,10 @@
 
 					// execute the convert commands etc.
-					proc = Runtime.getRuntime().exec("sh " + this.temp_files_dir + "add_x_" + uid);
+					/*proc = Runtime.getRuntime().exec("sh " + this.temp_files_dir + "add_x_" + uid);
 					proc.waitFor();
+					*/
+					proc = new SafeProcess("sh " + this.temp_files_dir + "add_x_" + uid);
+					proc.runProcess();
+					proc = null;
 
 				}
Index: main/trunk/greenstone3/src/java/org/greenstone/gsdl3/util/GDBMWrapper.java
===================================================================
--- main/trunk/greenstone3/src/java/org/greenstone/gsdl3/util/GDBMWrapper.java	(revision 31664)
+++ main/trunk/greenstone3/src/java/org/greenstone/gsdl3/util/GDBMWrapper.java	(revision 31665)
@@ -29,4 +29,6 @@
 import java.util.ArrayList;
 
+import org.greenstone.util.SafeProcess;
+
 /**
  * java wrapper class for gdbm - uses Java-GDBM written by Martin Pool replaces
@@ -113,5 +115,17 @@
 								String cmdTest = "perl -v 2>&1";
 								//String cmdTest = "echo %PATH%";
-								int returnValue = Processing.runProcess(cmdTest);
+								
+								//int returnValue = Processing.runProcess(cmdTest);
+
+								// replace Processing.java with SafeProcess.java
+								// so retain the same behaviour (logging)
+								SafeProcess process = new SafeProcess(cmdTest);
+								logger.error("executing command "+cmdTest);
+								int returnValue = process.runProcess();
+								// do something with the messages
+								logger.error("err>"+process.getStdError());
+								logger.error("out>"+process.getStdOutput());
+								process = null;
+								
 								if (returnValue != 0)
 								{
@@ -122,5 +136,16 @@
 
 								String cmd = "perl -S txtgz-to-gdbm.pl \"" + txtgzFilename + "\" \"" + filename + "\"";
-								returnValue = Processing.runProcess(cmd);
+								//returnValue = Processing.runProcess(cmd);
+
+								// replace Processing.java with SafeProcess.java
+								// so retain the same behaviour (logging)
+								process = new SafeProcess(cmd);
+								logger.error("executing command "+cmd);
+								returnValue = process.runProcess();
+								// do something with the messages
+								logger.error("err>"+process.getStdError());
+								logger.error("out>"+process.getStdOutput());
+								process = null;
+
 								// For some reason, launching this command with gsdl_system() still returns 1
 								// even when it returns 0 when run from the command-line. We can check whether
Index: main/trunk/greenstone3/src/java/org/greenstone/server/BaseServer.java
===================================================================
--- main/trunk/greenstone3/src/java/org/greenstone/server/BaseServer.java	(revision 31664)
+++ main/trunk/greenstone3/src/java/org/greenstone/server/BaseServer.java	(revision 31665)
@@ -86,5 +86,5 @@
 	    if (configure_required_){
 		server_control_.displayMessage(dictionary.get("ServerControl.Configuring"));
-		int state = runTarget(CONFIGURE_CMD);
+		int state = run(CONFIGURE_CMD);
 		
 		if (state != RunTarget.SUCCESS){
@@ -114,4 +114,14 @@
 
     protected abstract int runTarget(String cmd);
+
+    protected int run(String cmd) {
+	int result = runTarget(cmd);
+	server_control_.repaint();
+	// from Java 7, can just call revalidate() instead of invalidate() and validate():
+	server_control_.invalidate();
+	server_control_.validate();
+	return result;
+    }
+
     public abstract String getBrowserURL();
     public abstract void reload(); // reload properties, since they may have changed
@@ -136,5 +146,5 @@
         if (configure_required_){
 	    server_control_.displayMessage(dictionary.get("ServerControl.Configuring"));
-	    state = runTarget(CONFIGURE_CMD);
+	    state = run(CONFIGURE_CMD);
 	    
 	   if (state != RunTarget.SUCCESS){
@@ -153,5 +163,5 @@
 	    logger_.error("Exception trying to sleep: " + e);
 	}
-        state = runTarget(START_CMD);
+        state = run(START_CMD);
 	
 	if (state != RunTarget.SUCCESS){
@@ -239,5 +249,5 @@
 	    server_control_.displayMessage(dictionary.get("ServerControl.Stopping"));
 	}
-	int state = runTarget(STOP_CMD);
+	int state = run(STOP_CMD);
 	
         if (state != RunTarget.SUCCESS){
Index: main/trunk/greenstone3/src/java/org/greenstone/util/BrowserLauncher.java
===================================================================
--- main/trunk/greenstone3/src/java/org/greenstone/util/BrowserLauncher.java	(revision 31664)
+++ main/trunk/greenstone3/src/java/org/greenstone/util/BrowserLauncher.java	(revision 31665)
@@ -7,4 +7,5 @@
 import org.greenstone.server.BaseProperty;
 import org.greenstone.util.Misc;
+import org.greenstone.util.SafeProcess;
 import org.apache.log4j.*;
 
@@ -50,5 +51,5 @@
 	     // we try to look for a browser
  	    for (int i=0; i<default_browsers.length; i++) {
- 		if (isAvailable(default_browsers[i])) {
+ 		if (SafeProcess.isAvailable(default_browsers[i])) {
  		    this.command = default_browsers[i] + " %1";
  		    break;
@@ -60,4 +61,6 @@
     }
 
+    // Replaced by SafeProcess.isAvailable(program)
+    /*
     protected boolean isAvailable(String program) {
 	try {
@@ -76,5 +79,5 @@
 	    return false;
 	}
-    }
+    }*/
 
     public  int getBrowserState(){
@@ -100,23 +103,31 @@
 		logger.info(new_command);
 		Runtime rt = Runtime.getRuntime();
-		Process process = rt.exec(new_command);
+		//Process process = rt.exec(new_command);
                	state = LAUNCHSUCCESS;
-		exitCode = process.waitFor();
+		//exitCode = process.waitFor();
+		SafeProcess process = new SafeProcess(new_command);
+		exitCode = process.runProcess();
+		process = null;
 		logger.info("ExitCode:" + exitCode);              
 		if (exitCode != 0) { // if Netscape or mozilla was not open
 		    logger.info("couldn't do remote, trying original command");
                     logger.info(this.command);
-		    process = rt.exec(this.command); // try the original command
+		    //process = rt.exec(this.command); // try the original command
                     state = LAUNCHSUCCESS;
 		    //for some reason the following part is not executed sometimes.
-                    exitCode = process.waitFor();
+                    //exitCode = process.waitFor();
+		    process = new SafeProcess(this.command);
+		    exitCode = process.runProcess();
+		    process = null;
 		}
 	    } else {
 		logger.info(this.command);
                 Runtime rt = Runtime.getRuntime();
-		Process process = rt.exec(this.command);
+		//Process process = rt.exec(this.command);
                 state = LAUNCHSUCCESS;
               	//for some reason the following part is not executed sometimes.
-              	exitCode = process.waitFor();
+              	//exitCode = process.waitFor();
+		SafeProcess process = new SafeProcess(this.command);
+		exitCode = process.runProcess();
 	    }
 
Index: main/trunk/greenstone3/src/java/org/greenstone/util/RunTarget.java
===================================================================
--- main/trunk/greenstone3/src/java/org/greenstone/util/RunTarget.java	(revision 31664)
+++ main/trunk/greenstone3/src/java/org/greenstone/util/RunTarget.java	(revision 31665)
@@ -3,4 +3,5 @@
 import java.io.IOException;
 import java.io.BufferedReader;
+import java.io.Closeable;
 import java.io.InputStream;
 import java.io.InputStreamReader;
@@ -28,9 +29,9 @@
 	 try {
 	     state = -1;
-	     Runtime run = Runtime.getRuntime();
-
 	     String targetCmd = getTargetCmd();
 	     logger.info("Target: " + targetCmd);
 
+	     /*
+	     Runtime run = Runtime.getRuntime();
              Process process = run.exec(targetCmd);
 	     BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()));
@@ -55,5 +56,30 @@
 	     
 	     br.close();
+	     */
+	     
+	     
+	     SafeProcess process = new SafeProcess(targetCmd);
+	     process.setSplitStdOutputNewLines(true);
+	     process.runProcess();	     
+	     String output = process.getStdOutput();
+	     String[] lines = output.split("[\\r\\n]+"); // http://stackoverflow.com/questions/454908/split-java-string-by-new-line
+	     for(int i = 0; i < lines.length; i++) {
+		 //System.err.println("*** Got line:|" + lines[i] + "|***");
+		 String line = lines[i].trim();
+		 if (line.equals(targetSuccess)){
+		     state = 0;
+		 }
+		 
+		 if (line.equals(targetFailed)){
+		     state = 1; 
+		 }
 
+		 if(line.startsWith(targetFinished)){
+		     break;		 
+		 }
+	     }
+	     //System.err.println("\n\n");
+
+	     
 	     if(state < 0) {
 		 logger.info("Unexpected end of input when running target: " + targetCmd);
Index: main/trunk/greenstone3/src/java/org/greenstone/util/SafeProcess.java
===================================================================
--- main/trunk/greenstone3/src/java/org/greenstone/util/SafeProcess.java	(revision 31664)
+++ main/trunk/greenstone3/src/java/org/greenstone/util/SafeProcess.java	(revision 31665)
@@ -33,5 +33,5 @@
 
 public class SafeProcess {
-    public static int DEBUG = 0;
+    public static int DEBUG = 1;
 
     public static final int STDERR = 0;
@@ -741,6 +741,10 @@
 	SafeProcess prcs = new SafeProcess("which " + program);		
 	prcs.runProcess();
-	String output = prcs.getStdOutput();
+	String output = prcs.getStdOutput().trim();	
+	///System.err.println("*** 'which " + program + "' returned: |" + output + "|");
 	if(output.equals("")) {
+	    return false;
+	} else if(output.indexOf("no "+program) !=-1) { // from GS3's org.greenstone.util.BrowserLauncher.java's isAvailable(program)
+	    log("@@@ SafeProcess.isAvailable(): " + program + "is not available");
 	    return false;
 	}
@@ -1010,5 +1014,5 @@
 	logger.info(msg);
 
-	//System.err.println(msg);
+	System.err.println(msg);
 
 	//DebugStream.println(msg);
@@ -1019,6 +1023,6 @@
 	logger.error(msg, e);
 
-	//System.err.println(msg);
-	//e.printStackTrace();
+	System.err.println(msg);
+	e.printStackTrace();
 
 	//DebugStream.println(msg);
@@ -1030,5 +1034,5 @@
 	logger.error(e);
 
-	//e.printStackTrace();
+	e.printStackTrace();
 
 	//DebugStream.printStackTrace(e);
