Index: /greenstone3/trunk/src/java/org/greenstone/server/BaseServer.java
===================================================================
--- /greenstone3/trunk/src/java/org/greenstone/server/BaseServer.java	(revision 18968)
+++ /greenstone3/trunk/src/java/org/greenstone/server/BaseServer.java	(revision 18969)
@@ -62,6 +62,5 @@
 	reloadConfigProperties();
 
-	dictionary = new Dictionary("server", lang, this.getClass().getClassLoader());
-
+	dictionary = new Dictionary("server", lang, this.getClass().getClassLoader());	
     }
 
@@ -69,5 +68,4 @@
     {
 	String auto_start = config_properties.getProperty(BaseServer.Property.AUTOSTART, "true");
-
 	if (auto_start.equals("true") || auto_start.equals("1")) {
 	    String start_browser = config_properties.getProperty(BaseServer.Property.START_BROWSER, "true");
@@ -78,5 +76,7 @@
 	    else{
 		start();
-	    }  
+	    }
+	    
+	    server_control_.setState(java.awt.Frame.ICONIFIED); // minimise the server interface window
 	} else {
 	    reload(); // browser URL or other important properties may not yet be initialised
@@ -86,5 +86,5 @@
     }
 
-    // package access method
+    // package access methods
     BaseServerControl getServerControl() { 
 	return server_control_; 
@@ -103,5 +103,6 @@
     public abstract void reload(); // reload properties, since they may have changed
     protected void preStop() {}
-
+    protected void postStart() {}
+    
     public void reconfigRequired()
     {
@@ -126,5 +127,5 @@
 	       recordError(CONFIGURE_CMD);
 	   }
-	   reload();
+	   reload(); // work out the browserURL again
 	   configure_required_ = false;
 	}
@@ -137,10 +138,10 @@
 	if (state != RunTarget.SUCCESS){
 	    recordError(START_CMD);
-            server_state_ = SERVER_START_FAILED;  
-            
+            server_state_ = SERVER_START_FAILED;            
 	}	            
 	else{
 	    recordSuccess(START_CMD); 
             server_state_ = SERVER_STARTED; 
+	    postStart();
        	} 
 
Index: /greenstone3/trunk/src/java/org/greenstone/server/BaseServerControl.java
===================================================================
--- /greenstone3/trunk/src/java/org/greenstone/server/BaseServerControl.java	(revision 18968)
+++ /greenstone3/trunk/src/java/org/greenstone/server/BaseServerControl.java	(revision 18969)
@@ -165,4 +165,5 @@
 	    }
         default:{
+	    enter_button.setText(BaseServer.dictionary.get("ServerControl.EnterLibrary"));
 	    enter_button.setEnabled(false);
 	    fMenu.setEnabled(false);
@@ -175,5 +176,5 @@
 	info_label.setText(stringToHTML("<br>"+message));           
     }
-    
+
     private class MyAdapter extends WindowAdapter{   
 	public void windowClosing(WindowEvent env){
Index: /greenstone3/trunk/src/java/org/greenstone/server/BaseServerSettings.java
===================================================================
--- /greenstone3/trunk/src/java/org/greenstone/server/BaseServerSettings.java	(revision 18968)
+++ /greenstone3/trunk/src/java/org/greenstone/server/BaseServerSettings.java	(revision 18969)
@@ -60,6 +60,6 @@
 	}
 
-	String auto_start_str = server.config_properties.getProperty(BaseServer.Property.AUTOSTART);
-	if ((auto_start_str.trim()).equals("true")) {
+	String auto_start_str = server.config_properties.getProperty(BaseServer.Property.AUTOSTART).trim();
+	if (auto_start_str.equals("true") || auto_start_str.equals("1")) {
 	    this.autoStart = true;
 	} else {
@@ -272,7 +272,4 @@
 		newFileLines = scriptReadWrite.queryReplace(oldFileLines, BaseServer.Property.WEB_PORT, portNum+"");
 		
-		String newAutoEnter = (new Boolean(autoEnter.isSelected())).toString();
-		newFileLines = scriptReadWrite.queryReplace(newFileLines, BaseServer.Property.AUTOSTART, newAutoEnter);
-		
 		// call the subclass' save() method to save custom elements
 		save(scriptReadWrite, newFileLines);
@@ -287,6 +284,11 @@
 					     newFileLines);
 		server.reloadConfigProperties();
+		server.reload(); // work out the URL again in case it has changed
 		if (require_restart){
 		    JOptionPane.showMessageDialog(null,server.dictionary.get("ServerSetting.SettingChanged"),"Info", JOptionPane.INFORMATION_MESSAGE);
+		    if(autoStart) {
+			server.autoStart();
+			server.getServerControl().updateControl();
+		    }
 		}
 	    } 
Index: /greenstone3/trunk/src/java/org/greenstone/server/BrowserLauncher.java
===================================================================
--- /greenstone3/trunk/src/java/org/greenstone/server/BrowserLauncher.java	(revision 18968)
+++ /greenstone3/trunk/src/java/org/greenstone/server/BrowserLauncher.java	(revision 18969)
@@ -94,5 +94,5 @@
 	    String lower_name = prog_name.toLowerCase();
 	    if (lower_name.indexOf("mozilla") != -1 || lower_name.indexOf("firefox") != -1) { 
-		logger.info("found mozilla or firefox, trying remote it");
+		logger.info("found mozilla or firefox, trying to remotely launch it");
                 // mozilla and netscape, try using a remote command to get things in the same window
 		String new_command = prog_name +" -raise -remote openURL("+url+",new-tab)";
Index: /greenstone3/trunk/src/java/org/greenstone/server/PortFinder.java
===================================================================
--- /greenstone3/trunk/src/java/org/greenstone/server/PortFinder.java	(revision 18969)
+++ /greenstone3/trunk/src/java/org/greenstone/server/PortFinder.java	(revision 18969)
@@ -0,0 +1,132 @@
+package org.greenstone.server;
+
+/** Verbatim copy of what's in GLI's org.greenstone.gatherer.util */
+
+import java.io.IOException;
+import java.net.ServerSocket;
+import java.net.BindException;
+
+// When needing to use sockets, this class can be used to find an available port
+public class PortFinder {
+
+    // Port numbers range from 0 to 65,535. RESERVED PORTS are below 1025
+    // see http://www.gnu.org/software/hello/manual/libc/Ports.html
+    public static final int MAX_PORT = 65535;
+    public static final int PORTS_RESERVED = 1024;
+
+    // Considering a limited range of ports that will be reused (circular buffer)
+    public final int PORT_BASE;
+    public final int PORT_BLOCK_SIZE;
+
+    // Keep track of what port numbers we have checked for availability
+    private int nextFreePort;
+
+    // The socket port number that we will use
+    private int port = -1;
+
+    public PortFinder() {
+	this( PORTS_RESERVED+1, (MAX_PORT - PORTS_RESERVED) );
+    }
+        
+    public PortFinder(int base, int blocksize) {
+	PORT_BASE = base;
+	PORT_BLOCK_SIZE = blocksize;
+
+	nextFreePort = PORT_BASE;
+    }
+
+    /** Circular buffer. Modifies the value of nextFreePort (the buffer index). */
+    private void incrementNextFreePort() {
+	int offset = nextFreePort - PORT_BASE;
+	offset = (offset + 1) % PORT_BLOCK_SIZE;
+	nextFreePort = PORT_BASE + offset;
+    } 
+
+    /** Finds the first available port in the range specified during Constructor call.
+     *  @return the number of an available port.	
+     */
+    public int findPortInRange() throws Exception {	
+	try {
+	    boolean foundFreePort = false;
+	    for(int i = 0; i < PORT_BLOCK_SIZE; i++) {
+		
+		if(isPortAvailable(nextFreePort)) {
+		    foundFreePort = true;
+		    break;
+		    
+		} else {
+		    incrementNextFreePort();
+		}
+	    }
+	    
+	    if(foundFreePort) {
+		// Free port number currently found becomes the port number of the socket
+		// that will be used
+		this.port = nextFreePort;
+		incrementNextFreePort();
+		
+	    } else {
+		throw new Exception("Cannot find an available port in the range " 
+				    + PORT_BASE + "-" + (PORT_BASE+PORT_BLOCK_SIZE)
+				    + "\nwhich is necessary for forcibly terminating wget.");
+	    }
+	    
+	}catch(IOException e) {
+	    System.err.println("Error when trying to find an available port. In PortFinder.findPort() " + e);
+	}
+	return port;
+    }
+
+    /** @return true if the portnumber is in the valid range. */
+    public static boolean isValidPortNumber(int portNum) {
+	return (portNum >= 0 && portNum <= MAX_PORT);
+    }
+
+    /** @return true if the portnumber is in the useable range. */
+    public static boolean isAssignablePortNumber(int portNum) {
+	return (portNum > PORTS_RESERVED && portNum <= MAX_PORT);
+    }
+
+    /** Finds an available port.
+     * @return the number of an available port.
+     */
+    public static int findAnyFreePort() throws Exception {	
+	ServerSocket tmpSocket = null;
+	int portNumber = -1;
+	try {
+	    // Creates a server socket, bound to the specified port.
+	    // A port of 0 creates a socket on any free port. 
+	    tmpSocket = new ServerSocket(0);
+	    portNumber = tmpSocket.getLocalPort();
+	    tmpSocket.close();
+	} catch(Exception e) {
+	    System.err.println("Unable to find a free port or close it. Got Exception: " + e);
+	    tmpSocket = null;
+	}
+	return portNumber;
+    }
+
+    /** @return true if the portnum is available for use */
+    public static boolean isPortAvailable(int portnum) {
+	ServerSocket tmpSocket = null;
+	try {
+	    tmpSocket = new ServerSocket(portnum);
+	    tmpSocket.close();
+	    //System.err.println("Port " + portnum + " not yet in use.");
+	    return true;
+	    
+	} catch(BindException ex){
+	    // "Signals that an error occurred while attempting to bind a 
+	    // socket to a local address and port. Typically, the port is 
+	    // in use, or the requested local address could not be assigned."
+	    System.err.println("Port " + portnum + " already in use or can't be assigned.");
+	    tmpSocket = null;
+	    return false;	    
+	} catch(Exception ex) { 
+	    // Some other problem creating or closing the server socket
+	    System.err.println("Problem creating or closing server socket at port " + portnum);
+	    tmpSocket = null;
+	    return false;
+	}
+    }
+}
Index: /greenstone3/trunk/src/java/org/greenstone/server/Server2.java
===================================================================
--- /greenstone3/trunk/src/java/org/greenstone/server/Server2.java	(revision 18968)
+++ /greenstone3/trunk/src/java/org/greenstone/server/Server2.java	(revision 18969)
@@ -2,7 +2,14 @@
 package org.greenstone.server;
 
+import java.io.BufferedReader;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
+import java.io.InputStreamReader;
+import java.io.IOException;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.URL;
+//import java.net.URLConnection;
 import java.util.Properties;
 import java.util.ArrayList;
@@ -17,16 +24,64 @@
     protected String libraryURL;
 
-    public Server2(String gsdl2_home, String lang, String configfile)
+    private class QuitListener extends Thread 
+    {
+	int quitPort = -1;
+	ServerSocket serverSocket = null;
+
+	public QuitListener(int quitport) throws Exception {
+	    ///Server2.this.recordSuccess("In QuitListener constructor");
+	    this.quitPort = quitport;
+	    serverSocket = new ServerSocket(quitPort);
+	}
+
+	public void run() {
+	    // Server2.this.recordSuccess("In QuitListener.run()");
+
+	    Socket connection = null;
+
+	    try {
+		// wait for a connection
+		connection = serverSocket.accept();
+
+		///Server2.this.recordSuccess("In QuitListener - accepted connection");
+
+		// read input
+		try {
+		    BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
+		    String line = null;
+		    if((line = reader.readLine()) != null) {
+			// Server2.this.recordSuccess("In QuitListener - Got a line");
+			if(line.equals("QUIT")) {
+			    // Server2.this.recordSuccess("In QuitListener - line is QUIT");
+			    reader.close();
+			    reader = null;
+			    serverSocket.close();
+			    serverSocket = null;
+			}
+		    }
+		} catch(Exception e) {
+		    Server2.this.recordError("Exception in QuitListener thread.");
+		} finally {
+		    Server2.this.stop();
+		    System.exit(0);
+		}
+	    } catch(IOException ioe) {
+		Server2.this.recordError("Server2.QuitListener: Unable to make the connection with the client socket." + ioe);
+	    }
+	}
+    }
+
+
+    public Server2(String gsdl2_home, String lang, String configfile, int quitPort)
     {
 	super(gsdl2_home, lang, configfile, "etc"+File.separator+"logs-gsi");	
 	               // configfile can be either glisite.cfg or llssite.cfg
 
-
 	Property = new Server2Property();
-
+	
 	String frame_title = dictionary.get("ServerControl.Frame_Title");
 	server_control_ = new Server2Control(this,frame_title);
 
-	/** Make command tagets for managing Web server */
+	/* Make command tagets for managing Web server */
 	START_CMD     = "web-start";
 	RESTART_CMD   = "web-restart";
@@ -34,4 +89,20 @@
 	STOP_CMD      = "web-stop";
 
+	// now we can monitor for the quit command if applicable
+	// First check if given port is within the range of allowed ports
+	if(!PortFinder.isAssignablePortNumber(quitPort)) {
+	    recordError("QuitPort provided is not within acceptable range: ("
+			       + PortFinder.PORTS_RESERVED + " - " + PortFinder.MAX_PORT + "]" );
+	    quitPort = -1;
+	}
+	
+	if(quitPort != -1) {
+	    try {
+		new QuitListener(quitPort).start();
+	    } catch(Exception e) {
+		Server2.this.recordError("Exception constructing the QuitListener thread.");
+	    }
+	}
+	
 	autoStart();
     }
@@ -98,5 +169,5 @@
 	// default values, to be replaced with what's in gsdlsite.cfg
 	String host = "localhost";
-	String port = "8080";
+	String port = "80";
 	String gwcgi;
 	String httpprefix = "greenstone";
@@ -123,21 +194,46 @@
 		recordError("Could not open gsdlsite_cfg for reading, using default library prefix.");
 	    }
-	    reloadConfigProperties();
+	    //reloadConfigProperties();
 	    port = config_properties.getProperty("portnumber", port);
-
 	} catch(Exception e) {
 	    recordError("Exception trying to load properties from gsdlsite_cfg. Using default library prefix.", e);
 	    suffix = httpprefix + suffix;
 	}
-
+	
 	libraryURL = "http://" + host + ":" + port + suffix;
-	
-	// the URL has been changed
-	// write the URL to the file since this should work like GS2's Local Lib Server for Windows
-	ScriptReadWrite scriptReadWrite = new ScriptReadWrite();
-	ArrayList fileLines = scriptReadWrite.readInFile(BaseServer.config_properties_file);
-	scriptReadWrite.replaceOrAddLine(fileLines, "url", libraryURL, true);
-	scriptReadWrite.writeOutFile(config_properties_file, fileLines);
-    }
+    }
+
+    public void reloadConfigProperties() {
+	super.reloadConfigProperties();
+
+	// make sure the port is okay, otherwise find another port
+	// first choice is port 80, second choice starts at 8282
+	String port = config_properties.getProperty("portnumber", "80");
+	int portDefault = 8282;
+	try {
+	    int portNum = Integer.parseInt(port);
+	    
+	    if(!PortFinder.isPortAvailable(portNum)) {
+		
+		PortFinder portFinder = new PortFinder(portDefault, 101);
+		portNum = portFinder.findPortInRange();
+		port = (portNum == -1) ? Integer.toString(portDefault) : Integer.toString(portNum);
+		config_properties.setProperty("portnumber", port); // store the correct port
+
+		// write this updated port to the config file, since the configure target uses the file to run
+		ScriptReadWrite scriptReadWrite = new ScriptReadWrite();
+		ArrayList fileLines = scriptReadWrite.readInFile(BaseServer.config_properties_file);
+		scriptReadWrite.replaceOrAddLine(fileLines, "portnumber", port, false); // write the correct port
+		scriptReadWrite.writeOutFile(config_properties_file, fileLines);
+
+		configure_required_ = true;
+	    }    
+	} catch (Exception e) {
+	    recordError("Exception in Server2.reload(): " + e.getMessage());
+	    port = Integer.toString(portDefault);
+	}
+	
+    }
+
     
     // About to stop the webserver
@@ -153,8 +249,62 @@
     }
 
+    // Called when the URL has been changed (called after a reload() and starting the server).
+    // By the time we get here, reload() would already have been called and have set
+    // both the port and worked out libraryURL
+    // This method needs to write the URL to the configfile since things should work
+    // like GS2's Local Lib Server for Windows
+    protected void postStart() {
+
+	URL libURL = null;
+	try {
+	    libURL = new URL(libraryURL);
+	} catch (Exception e) {
+	    recordError("Unable to convert library URL string into a valid URL, Server2.java." + e);
+	}
+	
+	// 1. Test that the server is running at the libraryURL before writing it out to glisite.cfg/configfile 
+	// A quick test involves opening a connection to get the home page for this collection
+	if(libURL != null) {
+
+	    boolean ready = false; 
+	    for(int i = 0; i < 60 && !ready; i++) {
+		try {
+		    libURL.openConnection();
+		    //URLConnection connection = new URL(libraryURL).openConnection();
+		    //connection.getContent();
+		    ready = true;
+		    recordSuccess("Try connecting to server on url: '" + libraryURL + "'");
+		} catch (IOException bad_url_connection) {
+		    // keep looping
+		    recordSuccess("NOT YET CONNECTED. Waiting to try again...");
+		    try {
+			Thread.sleep(1000);
+		    } catch (InterruptedException ie) {
+			ready = true;
+			recordError("Unexpected: got an InterruptedException in sleeping thread, Server2.java." + ie);
+		    }
+		} catch (Exception e) {
+		    ready = true;
+		    recordError("Got an Exception while waiting for the connection to become live, Server2.java." + e);
+		}
+	    }
+	}
+
+	// 2. Now write the URL to the config file
+	String port = config_properties.getProperty("portnumber");
+
+	ScriptReadWrite scriptReadWrite = new ScriptReadWrite();
+	ArrayList fileLines = scriptReadWrite.readInFile(BaseServer.config_properties_file);
+	scriptReadWrite.replaceOrAddLine(fileLines, "url", libraryURL, true);
+	scriptReadWrite.replaceOrAddLine(fileLines, "portnumber", port, false); // write the correct port
+	scriptReadWrite.writeOutFile(config_properties_file, fileLines);
+    }
+
+
     public static void main (String[] args)
     {
-    	if ((args.length < 1) || (args.length > 3)) {
-	    System.err.println("Usage: java org.greenstone.server.Server2 <gsdl2-home-dir> [lang] [--config=configfile]");
+    	if ((args.length < 1) || (args.length > 4)) {
+	    System.err.println(
+	       "Usage: java org.greenstone.server.Server2 <gsdl2-home-dir> [lang] [--config=configfile] [--quitport=portNum]");
 	    System.exit(1);
 	}
@@ -170,5 +320,5 @@
 	
 	// if no config file is given, then the following defaults to llssite.cfg
-	String configfile = (args.length==3 && args[2].startsWith("--config=")) ? args[2] : gsdl2_home+File.separator+"llssite.cfg";
+	String configfile = (args.length>=3 && args[2].startsWith("--config=")) ? args[2] : gsdl2_home+File.separator+"llssite.cfg";
 	int equalSign = configfile.indexOf('=');
 	if(equalSign != -1) {
@@ -176,5 +326,19 @@
 	}
 
-	new Server2(gsdl2_home,lang,configfile);
+	String quitport = (args.length == 4 && args[3].startsWith("--quitport=")) ? args[3] : "";
+	equalSign = quitport.indexOf('=');
+	int port = -1;
+	if(equalSign != -1) {
+	    try {
+		quitport = quitport.substring(equalSign+1);
+		port = Integer.parseInt(quitport);
+	    } catch(Exception e) { // parse fails
+		System.err.println("Port must be numeric. Continuing without it.");
+	    }
+	}
+
+	//System.err.println("Running server with config file: " + configfile);
+	
+	new Server2(gsdl2_home, lang, configfile, port);
     }
 }
Index: /greenstone3/trunk/src/java/org/greenstone/server/Server2Settings.java
===================================================================
--- /greenstone3/trunk/src/java/org/greenstone/server/Server2Settings.java	(revision 18968)
+++ /greenstone3/trunk/src/java/org/greenstone/server/Server2Settings.java	(revision 18969)
@@ -38,11 +38,19 @@
     public String onSave() 
     {
-	return "";
+	String result = "";
+	if (!server.getBrowserURL().equals(prefix_combobox.getSelectedItem())) {
+	    result += "changed";
+	    result += "restart";
+	}
+	return result;
     }
 
     public void save(ScriptReadWrite scriptReadWrite, ArrayList newFileLines) 
     {
-	String newAutoEnter = autoEnter.isSelected() ? "1" : "0";
-	newFileLines = scriptReadWrite.queryReplace(newFileLines, BaseServer.Property.AUTOSTART, newAutoEnter);
+	boolean auto_enter = autoEnter.isSelected();
+	if(autoStart != auto_enter) {
+	    String newAutoEnter = auto_enter ? "1" : "0";
+	    newFileLines = scriptReadWrite.queryReplace(newFileLines, BaseServer.Property.AUTOSTART, newAutoEnter);
+	}
     }
 
