Index: /trunk/gli/src/org/greenstone/gatherer/Configuration.java
===================================================================
--- /trunk/gli/src/org/greenstone/gatherer/Configuration.java	(revision 7738)
+++ /trunk/gli/src/org/greenstone/gatherer/Configuration.java	(revision 7739)
@@ -67,7 +67,7 @@
     static final private String ARGUMENT_NAME = "name";
     /** The name of the general Gatherer configuration file. */
-    static final private String CONFIG_XML = "config.xml";
+    static public String CONFIG_XML = "config.xml";
     /** The name of the general Gatherer configuration file for running with GS3. */
-    static final private String GS3_CONFIG_XML = "config3.xml";
+    static public String GS3_CONFIG_XML = "config3.xml";
 
     static final private String CURRENT_CONFIGURATION_VERSION = "2.51u";
@@ -87,5 +87,5 @@
     static final private String OTHER_INFO = "Info";
     /** The name of the general Gatherer configuration template. */
-    static final private String TEMPLATE_CONFIG_XML = "xml/config.xml";
+    static public String TEMPLATE_CONFIG_XML = "xml/config.xml";
     /** The first of three patterns used during tokenization, this pattern handles a comma separated list. */
     static final private String TOKENIZER_PATTERN1 = " ,\n\t";
@@ -191,12 +191,15 @@
 	    Gatherer.println("exec_address != null -> " + exec_address);
 	}
+
 	///ystem.err.println("Perl path.");
 	this.perl_path = perl_path;
 	// Ensure the perl path includes exe under windoze
-	if(Utility.isWindows() && !perl_path.toLowerCase().endsWith(".exe")) {
-	    if(!perl_path.endsWith(File.separator)) {
-		perl_path = perl_path + File.separator;
-	    }
-	    perl_path = perl_path + "perl.exe";
+	if (!Gatherer.isGsdlRemote) {
+	    if(Utility.isWindows() && !perl_path.toLowerCase().endsWith(".exe")) {
+		if(!perl_path.endsWith(File.separator)) {
+		    perl_path = perl_path + File.separator;
+		}
+		perl_path = perl_path + "perl.exe";
+	    }
 	}
 
@@ -215,5 +218,5 @@
 	    config_xml = new File(config_xml_name);
 	    if(config_xml.exists()) {
-		general_config = Utility.parse(config_xml_name, false);
+		general_config = Utility.parse(config_xml_name, true);
 	    }
 	}
Index: /trunk/gli/src/org/greenstone/gatherer/Gatherer.java
===================================================================
--- /trunk/gli/src/org/greenstone/gatherer/Gatherer.java	(revision 7738)
+++ /trunk/gli/src/org/greenstone/gatherer/Gatherer.java	(revision 7739)
@@ -26,11 +26,4 @@
  */
 package org.greenstone.gatherer;
-
-/**************************************************************************************
- * Written:      ??/??/02
- * Revised:      ??/??/02 - Commented
- *               ??/??/03 - Added support for local library server
- *               20/07/03 - Rewrote argument parsing so that spaces no longer cause GLI to die. Also added time out when starting local library.
- **************************************************************************************/
 
 //import com.l2fprod.gui.*;
@@ -67,5 +60,10 @@
 import sun.misc.*;
 
-/** Containing the main() method for the Gatherer, this class is the starting point for the rest of the application. It first parses the command line arguments, preparing to update the configuration as required. Next it loads several important support classes such as the Configuration and Dictionary. Finally it creates the other important managers and sends them on their way.
+/** Containing the top-level "core" for the Gatherer, this class is the
+ * common core for the GLI application and applet. It first parses the
+ * command line arguments, preparing to update the configuration as
+ * required. Next it loads several important support classes such as the
+ * Configuration and Dictionary. Finally it creates the other important
+ * managers and sends them on their way.
  * @author John Thompson, Greenstone Digital Library, University of Waikato
  * @version 2.3
@@ -122,4 +120,7 @@
     static public boolean GS3 = false;
 
+    static public boolean isGsdlRemote = false;
+    static public String cgiBase = "";
+
     // feedback stuff
     /** is the feedback feature enabled? */
@@ -139,36 +140,31 @@
     }
 
-    public Gatherer() {
+    public Gatherer() 
+    {
 	this.self = this;
-    }
-
-    /** Run method. Make the three main modules, c_man, f_man and g_man, and any other necessary classes such as Dictionary.
-     * @param size The desired size of the Gatherer window as a <strong>Dimension</strong>.
-     * @param gsdl_path The path to the gsdl directory, gathered from the startup arguments, and presented as a <strong>String</strong>.
-     * @param gsdl3_path The path to the gsdl3 directory, gathered from the startup arguments, and presented as a <strong>String</strong>.
-     * @param exec_path The path to the library executable, gathered from the startup arguments, and presented as a <strong>String</strong>.
-     * @param debug_enabled <i>true</i> to print verbose debug messages to "debug.txt", <i>false</i> otherwise.
-     * @param perl_path The path to the PERL compiler as a <strong>String</strong>. Necessary for windows platform versions.
-     * @param no_load <i>true</i> to prevent the previously opened collection from reopening.
-     * @param splash A reference to the splash screen.
-     * @param open_collection
-     * @param mirroring_enabled
-     * @param wget_version_str
-     * @param wget_path
-     * @see java.io.FileOutputStream
-     * @see java.io.PrintStream
-     * @see java.lang.Exception
-     * @see java.lang.StringBuffer
-     * @see java.util.Calendar
-     * @see org.greenstone.gatherer.Configuration
-     * @see org.greenstone.gatherer.Dictionary
-     * @see org.greenstone.gatherer.Gatherer.CTRLCHandler
-     * @see org.greenstone.gatherer.GAuthenticator
-     * @see org.greenstone.gatherer.collection.CollectionManager
-     * @see org.greenstone.gatherer.file.FileManager
-     * @see org.greenstone.gatherer.gui.GUIManager
-     * @see org.greenstone.gatherer.gui.Splash
-     */
-    public void run(Dimension size, String gsdl_path, String gsdl3_path, String exec_path, boolean debug_enabled, String perl_path, boolean no_load, Splash splash, String open_collection, String site_name, String servlet_path, boolean mirroring_enabled, String wget_version_str, String wget_path) {
+
+	init_images();
+    }
+
+    protected void init_images()
+    {
+	Class base = this.getClass();
+	Utility.BLANK_ICON = new ImageIcon(base.getResource("/images/blank.gif"));
+	Utility.ERROR_ICON = new ImageIcon(base.getResource("/images/error.gif"));
+	Utility.HELP_ICON  = new ImageIcon(base.getResource("/images/help.gif"));
+	Utility.ON_ICON    = new ImageIcon(base.getResource("/images/check.gif"));
+	Utility.OFF_ICON   = new ImageIcon(base.getResource("/images/cross.gif"));
+
+	Utility.base = base;
+    }
+
+
+    public GUIManager init(Dimension size, String gsdl_path, String gsdl3_path, 
+			   String exec_path, boolean debug_enabled, String perl_path, 
+			   boolean no_load, String open_collection, 
+			   String site_name, String servlet_path, 
+			   boolean mirroring_enabled, String wget_version_str, 
+			   String wget_path) 
+    {
 
 	// This will hopefully catch ctrl-c and terminate, and exit gracefully. However it is platform specific, and may not be supported by some JVMs.
@@ -239,24 +235,31 @@
 	    }
 
-	    // Perl path is a little different as it is perfectly ok to start the Gatherer without providing a perl path
-	    boolean found_perl = false;
-	    if (config.perl_path != null) {
-		// See if the file pointed to actually exists
-		File perl_file = new File(config.perl_path);
-		found_perl = perl_file.exists();
-		perl_file = null;
-	    }
-	    if (config.perl_path == null || !found_perl) {
-		// Run test to see if we can run perl as is.
-		PerlTest perl_test = new PerlTest();
-		if (perl_test.found()) {
-		    // If so replace the perl path with the system default (or null for unix).
-		    config.perl_path = perl_test.toString();
-		    found_perl = true;
-		}
-	    }
-	    if (!found_perl) {
-		// Time for an error message.
-		missingPERL();
+	    if (Gatherer.isGsdlRemote) {
+		Gatherer.println("Not checking for perl path/exe");
+	    }
+	    else {
+		// Perl path is a little different as it is perfectly ok to
+		// start the Gatherer without providing a perl path
+		boolean found_perl = false;
+		if (config.perl_path != null) {
+		    // See if the file pointed to actually exists
+		    File perl_file = new File(config.perl_path);
+		    found_perl = perl_file.exists();
+		    perl_file = null;
+		}
+		if (config.perl_path == null || !found_perl) {
+		    // Run test to see if we can run perl as is.
+		    PerlTest perl_test = new PerlTest();
+		    if (perl_test.found()) {
+			// If so replace the perl path with the system
+			// default (or null for unix).
+			config.perl_path = perl_test.toString();
+			found_perl = true;
+		    }
+		}
+		if (!found_perl) {
+		    // Time for an error message.
+		    missingPERL();
+		}
 	    }
 
@@ -300,25 +303,5 @@
 		config.setWGetVersion(wget_version_str);
 	    }
-	    // Size and place the frame on the screen
-	    Rectangle bounds = config.getBounds("general.bounds", true);
-	    if (bounds == null) {
-		// Choose a sensible default value
-		bounds = new Rectangle(0, 0, 640, 480);
-	    }
-
-	    // Ensure width and height are reasonable
-	    size = bounds.getSize();
-	    if (size.width < 640) {
-		size.width = 640;
-	    }
- 	    else if (size.width > config.screen_size.width) {
- 		size.width = config.screen_size.width;
-	    }
-	    if (size.height < 480) {
-		size.height = 480;
-	    }
- 	    else if (size.height > config.screen_size.height) {
- 		size.height = config.screen_size.height;
- 	    }
+
 	    // Set default font
 	    setUIFont(config.getFont("general.font", true), config.getFont("general.tooltip_font", true));
@@ -352,29 +335,66 @@
 	    }
 
-	    // Create GUI Manager (last) or else suffer the death of a thousand NPE's
-	    splash.toFront();
-	    g_man = new GUIManager(size);
-	    g_man.display();
-
-	    // Place the window in the desired location on the screen, if this is do-able (not under most linux window managers apparently. In fact you're lucky if they listen to any of your screen size requests).
-	    g_man.setLocation(bounds.x, bounds.y);
-	    g_man.setVisible(true);
-
-	    // After the window has been made visible, check that it is in the correct place
-	    // sometimes java places a window not in the correct place, 
-	    // but with an offset. If so, we work out what the offset is
-	    // and change the desired location to take that into account 
-	    Point location = g_man.getLocation();
-	    int x_offset = bounds.x - location.x;
-	    int y_offset = bounds.y - location.y;
-	    // If not, offset the window to move it into the correct location
-	    if (x_offset > 0 || y_offset > 0) {
-		///ystem.err.println("changing the location to "+(bounds.x + x_offset)+" "+ (bounds.y + y_offset));
-		g_man.setLocation(bounds.x + x_offset, bounds.y + y_offset);
-	    }
-
-	    // The 'after-display' triggers several events which don't occur until after the visual components are actually available on screen. Examples of these would be the various html renderings, as they can't happen offscreen.
-	    g_man.afterDisplay();
-
+	}
+	catch (Exception error) {
+	    error.printStackTrace();
+	}
+
+	// Create GUI Manager (last) or else suffer the death of a thousand NPE's
+	g_man = new GUIManager(size);
+
+	return g_man;
+    }
+
+
+
+    public void run(Dimension size, Splash splash, GUIManager g_man) 
+    {
+	// Size and place the frame on the screen
+	Rectangle bounds = config.getBounds("general.bounds", true);
+	if (bounds == null) {
+	    // Choose a sensible default value
+	    bounds = new Rectangle(0, 0, 640, 480);
+	}
+	
+	// Ensure width and height are reasonable
+	size = bounds.getSize();
+	if (size.width < 640) {
+	    size.width = 640;
+	}
+	else if (size.width > config.screen_size.width) {
+	    size.width = config.screen_size.width;
+	}
+	if (size.height < 480) {
+	    size.height = 480;
+	}
+	else if (size.height > config.screen_size.height) {
+	    size.height = config.screen_size.height;
+	}
+	
+	if (splash != null) { splash.toFront(); }
+
+	g_man.display();
+
+	// Place the window in the desired location on the screen, if this is do-able (not under most linux window managers apparently. In fact you're lucky if they listen to any of your screen size requests).
+	g_man.setLocation(bounds.x, bounds.y);
+	g_man.setVisible(true);
+
+	// After the window has been made visible, check that it is in the correct place
+	// sometimes java places a window not in the correct place, 
+	// but with an offset. If so, we work out what the offset is
+	// and change the desired location to take that into account 
+	Point location = g_man.getLocation();
+	int x_offset = bounds.x - location.x;
+	int y_offset = bounds.y - location.y;
+	// If not, offset the window to move it into the correct location
+	if (x_offset > 0 || y_offset > 0) {
+	    ///ystem.err.println("changing the location to "+(bounds.x + x_offset)+" "+ (bounds.y + y_offset));
+	    g_man.setLocation(bounds.x + x_offset, bounds.y + y_offset);
+	}
+
+	// The 'after-display' triggers several events which don't occur until after the visual components are actually available on screen. Examples of these would be the various html renderings, as they can't happen offscreen.
+	g_man.afterDisplay();
+
+	if (splash != null) {
 	    // Hide the splash screen
 	    splash.hide();
@@ -382,8 +402,6 @@
 	    splash = null;
 	}
-	catch (Exception error) {
-	    error.printStackTrace();
-	}
-    }
+    }
+
 
     /** Exits the Gatherer after ensuring that things needing saving are saved.
@@ -444,5 +462,7 @@
 
 	if(apps.size() == 0) {
-	    System.exit(0);
+	    if (!Gatherer.isGsdlRemote) {
+		System.exit(0);
+	    }
 	}
 	else {
@@ -543,219 +563,4 @@
 	    ///ystem.err.println("No browser command available."); 
 	}
-    }
-    
-    /** The entry point into the Gatherer. Parses arguments.
-     * @param args A collection of arguments that may include: initial screen size, dictionary, path to the GSDL etc.
-     * @see java.io.File
-     * @see java.io.FileInputStream
-     * @see java.lang.Exception
-     * @see java.util.Properties
-     * @see org.greenstone.gatherer.Dictionary
-     * @see org.greenstone.gatherer.Gatherer
-     * @see org.greenstone.gatherer.gui.Splash
-     * @see org.greenstone.gatherer.util.StaticStrings
-     */
-    static public void main(String[] args) {
-	// A serious hack, but its good enough to stop crappy 'Could not lock user prefs' error messages.
-	// Thanks to Walter Schatz from the java forums.
-	System.setProperty("java.util.prefs.syncInterval","2000000"); // One message every 600 hours!
-
-	// Override the exception handler with a new one which we can easily quiet the exceptions from.
-	// System.setProperty("sun.awt.exception.handler", "GLIExceptionHandler");
-
-	// Ensure platform specific LAF
-	try {
-	    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
-	}
-	catch(Exception exception) {
-	    exception.printStackTrace();
-	}
-	
-	Gatherer gatherer = new Gatherer();
-	boolean debug = false;
-	boolean feedback_enabled = false;
-	boolean mirroring_enabled = false;
-	boolean no_load = false;
-	Dictionary dictionary = new Dictionary(null, null); // Default dictionary. Only used for starting error messages.
-	Dimension size = new Dimension(800, 540);
-	String exec_path = null;
-	String extra = null;
-	String filename = null;
-	String gsdl_path = null;
-	String gsdl3_path = null;
-	String perl_path = null;
-	String site_name = null; // for GS3
-	String servlet_path = null;
-	String wget_path = null;
-	String wget_version_str = StaticStrings.NO_WGET_STR;
-	// Parse arguments
-	int argument_index = 0;
-	String next_token = null;
-	while(argument_index < args.length || next_token != null) {
-	    // 1. We start by attempting to parse an argument name. An argument must start with a '-', and should not contain spaces. If anything else is encountered it is ignored.
-	    String argument_name = null;
-	    if(next_token == null) {
-		next_token = args[argument_index];
-		argument_index++;
-	    }
-	    if(next_token.startsWith(StaticStrings.MINUS_CHARACTER)) {
-		// Trim second '-' just to be kind to Unixy-type people
-		if(next_token.startsWith(StaticStrings.MINUS_CHARACTER + StaticStrings.MINUS_CHARACTER)) {
-		    argument_name = next_token.substring(1);
-		}
-		else {
-		    argument_name = next_token;
-		}
-	    }
-	    next_token = null;
-	    // 2. If we now have an argument name we continue by attempting to parse a value. A value is taken to be the sequence of space seperated Strings between the last argument name and up to but not including the next argument name. Of course an argument needn't have any value (ie -debug, -help), in which case value will be null.
-	    if(argument_name != null) {
-		String argument_value = null;
-		StringBuffer argument_value_buffer = new StringBuffer("");
-		while(argument_index < args.length && next_token == null) {
-		    next_token = args[argument_index];
-		    argument_index++;
-		    // If we just parsed an arbitary String then append it to value, followed by a single space
-		    if(!next_token.startsWith(StaticStrings.MINUS_CHARACTER)) {
-			argument_value_buffer.append(next_token);
-			argument_value_buffer.append(StaticStrings.SPACE_CHARACTER);
-			next_token = null;
-		    }
-		    // If the argument token retrieved is an argument name, then leave it in next_token, which will cause the argument parsing process to move onto the next step.
-		}
-		// If a value now exists in argument buffer, retrieve it. Remove the last character as it will be an erroneous space.
-		if(argument_value_buffer.length() > 0) {
-		    argument_value = argument_value_buffer.substring(0, argument_value_buffer.length() - 1);
-		}
-		
-		// 3. We now have the argument name, and any associated value. We are ready to store the data in the appropriate variables.
-		Gatherer.println("Parsed Argument: name=" + argument_name + (argument_value != null ? (", value=" + argument_value) : ", no value"));
-		// 3a. First those arguments that have no associated value
-		if(argument_value == null) {
-		    if(argument_name.equals(StaticStrings.HELP_ARGUMENT)) {
-			printUsage(dictionary);
-			System.exit(0);
-		    }
-		    // Run GLI in debug mode. Produces debug log plus extra messages.
-		    else if(argument_name.equals(StaticStrings.DEBUG_ARGUMENT)) {
-			debug = true;
-		    }
-		    // Run GLI with feedback enabled. 
-		    else if(argument_name.equals(StaticStrings.FEEDBACK_ARGUMENT)) {
-			feedback_enabled = true;
-		    }
-		    // Forces no loading on previous collection.
-		    else if(argument_name.equals(StaticStrings.NO_LOAD_ARGUMENT)) {
-			no_load = true;
-			filename = null;
-		    }
-		    // Run the GLI with mirroring enabled
-		    else if(argument_name.equals(StaticStrings.MIRROR_ARGUMENT)) {
-			mirroring_enabled = true;
-		    }
-		    /* I've got a sneak suspicion Aqua look and feel is not free domain
-		       // Specify the use of Greenstone LAF.
-		       else if(argument_name.equals(StaticStrings.SKIN_ARGUMENT)) {
-		       // SkinLF
-		       try {
-		       SkinLookAndFeel.setSkin(SkinLookAndFeel.loadThemePackDefinition(SkinUtils.toURL(new File(SKIN_DEFINITION_FILE))));
-		       SkinLookAndFeel.enable();
-		       }
-		       catch (Exception error) {
-		       ///ystem.err.println("Error: " + error);
-		       error.printStackTrace();
-		       }
-		       }
-		    */
-		}
-		// 3b. Now for those that do
-		else {
-		    // Parse the path to the GSDL. Required argument.
-		    if(argument_name.equals(StaticStrings.GSDL_ARGUMENT)) {
-			if(argument_value.endsWith(File.separator)) {
-			    gsdl_path = argument_value;
-			}
-			else {
-			    gsdl_path = argument_value + File.separator;
-			}
-		    }
-		    // GSDL3 path
-		    if(argument_name.equals(StaticStrings.GSDL3_ARGUMENT)) {
-			if(argument_value.endsWith(File.separator)) {
-			    gsdl3_path = argument_value;
-			}
-			else {
-			    gsdl3_path = argument_value + File.separator;
-			}
-		    }
-		    else if (argument_name.equals(StaticStrings.SITE_ARGUMENT)) {
-			site_name = argument_value;
-		    }
-		    else if (argument_name.equals(StaticStrings.SERVLET_ARGUMENT)) {
-			servlet_path = argument_value;
-		    }
-		    // Specify a collection to load initially. Could be used for file associations.
-		    else if(argument_name.equals(StaticStrings.LOAD_ARGUMENT)) {
-			filename = argument_value;
-			no_load = false;
-		    }
-		    // Parse the url to a running web server, or a file path to the local library server.
-		    else if(argument_name.equals(StaticStrings.LIBRARY_ARGUMENT)) {
-			exec_path = argument_value;
-			// If there is no colon in first five characters of the exec_path (which would either be an existing protocol, or a windows file path to say a local library), we can append the protocol http://.
-			if(argument_value.lastIndexOf(StaticStrings.COLON_CHARACTER, 5) == -1) {
-			    exec_path = StaticStrings.HTTP_PROTOCOL_STR + argument_value;
-			}
-			else {
-			    exec_path = argument_value;
-			}
-			// If the user has given us an address, but it ends with a '/' we assume we're using the greenstone library.cgi
-			if(exec_path.startsWith(StaticStrings.HTTP_PROTOCOL_STR) && exec_path.endsWith(StaticStrings.URL_SEPARATOR_CHARACTER)) {
-			    exec_path = exec_path + StaticStrings.LIBRARY_STR;
-			}
-		    }
-		    // Parse the path to PERL. If not provided its assumes perl should be availble on the PATH.
-		    else if(argument_name.equals(StaticStrings.PERL_ARGUMENT)) {
-			perl_path = argument_value;
-			// Test whether this points to the Perl bin directory or the Perl executable itself.
-			File perl_file = new File(perl_path);
-			if(perl_file.isDirectory()) {
-			    // If this is windows we create a child file perl.exe, otherwise we create perl
-			    if(Utility.isWindows()) {
-				perl_file = new File(perl_file, Utility.PERL_EXECUTABLE_WINDOWS);
-			    }
-			    else {
-				perl_file = new File(perl_file, Utility.PERL_EXECUTABLE_UNIX);
-			    }
-			    // And store this new path.
-			    perl_path = perl_file.getAbsolutePath();
-			    perl_file = null;
-			}
-			// Otherwise its fine as it is
-		    }
-		    // Test for the presence of a WGet version. This is only useful if the user has enabled mirroring. Note that mirroring can be enabled by running the GLI with -mirror, editing the config.xml for GLI, or through a new option on the connections page of the preferences.
-		    else if(argument_name.equals(StaticStrings.WGET_ARGUMENT)) {
-			wget_version_str = StaticStrings.WGET_STR;
-			wget_path = argument_value;
-		    }
-		}
-	    }
-	    // Argument name was null, nothing to be done.
-	}
-	next_token = null;
-	// Arguments all parsed.
-
-	if (feedback_enabled) {
-	    // if feedback is enabled, set up the recorder dialog
-	    Locale currLocale = Locale.getDefault(); // use the default locale for now - this will be changed by the Gatherer run method
-	    ActionRecorderDialog dlg = new ActionRecorderDialog (currLocale);
-	    gatherer.feedback_enabled = true;
-	    gatherer.feedback_dialog = dlg;
-	}
-	
-	// Splash screen.
-	Splash splash = new Splash();
-	// dictionary.destroy();
-	gatherer.run(size, gsdl_path, gsdl3_path, exec_path, debug, perl_path, no_load, splash, filename, site_name, servlet_path, mirroring_enabled, wget_version_str, wget_path);
     }
 
@@ -901,5 +706,5 @@
 	}
 	catch (Exception error) {
-	    Gatherer.println("config.xml is not a well formed XML document.");
+	    Gatherer.println(Configuration.CONFIG_XML+" is not a well formed XML document.");
 	    Gatherer.printStackTrace(error);
 	}
@@ -1164,5 +969,5 @@
 		    Gatherer.println("found mozilla or netscape, trying remote it");
 		    // mozilla and netscape, try using a remote command to get things in the same window
-		    String [] new_commands = new String[] {prog_name, "-raise", "-remote", "openURL("+url+")"};
+		    String [] new_commands = new String[] {prog_name, "-raise", "-remote", "openURL("+url+",new-tab)"};
 		    if(debug != null) {
 			printArray(new_commands);
@@ -1271,11 +1076,3 @@
 	}
     }
-
-//      static public class GLIExceptionHandler {
-//  	public void handle(Throwable thrown) {
-//  	    if(always_show_exceptions || debug != null) {
-//  		thrown.printStackTrace();
-//  	    }
-//  	}
-//      }
 }
Index: /trunk/gli/src/org/greenstone/gatherer/cdm/CollectionDesignManager.java
===================================================================
--- /trunk/gli/src/org/greenstone/gatherer/cdm/CollectionDesignManager.java	(revision 7738)
+++ /trunk/gli/src/org/greenstone/gatherer/cdm/CollectionDesignManager.java	(revision 7739)
@@ -44,4 +44,5 @@
 import org.greenstone.gatherer.cdm.TranslationView;
 import org.greenstone.gatherer.util.GSDLSiteConfig;
+import org.greenstone.gatherer.util.Utility;
 
 /** This manager provides access to submanagers, which in turn provide tools for the designing of Greenstone collections via the information stored in etc/collect.cfg. This class acts as a hub for the managers that handle specific parts of the configuration such as classifiers, format strings and language settings.
@@ -211,7 +212,10 @@
       ///ystem.err.println("Would have released collection if necessary.");
       boolean collection_released = false;
-      if(format_manager.formatsChanged() && Gatherer.c_man.built() && Gatherer.config.exec_file != null) {
+      String col_name = Gatherer.c_man.getCollection().getName();
+      boolean formats_changed = format_manager.formatsChanged();
+
+      if(formats_changed && Gatherer.c_man.built() && Gatherer.config.exec_file != null) {
 	  // Release the collection
-	  Gatherer.self.configServer(GSDLSiteConfig.RELEASE_COMMAND + Gatherer.c_man.getCollection().getName());
+	  Gatherer.self.configServer(GSDLSiteConfig.RELEASE_COMMAND + col_name);
 	  // This is very important -- it ensures that the above command has finished
 	  Gatherer.self.configServer("");
@@ -222,15 +226,26 @@
       collect_config.save();
 
+      if (Gatherer.isGsdlRemote) {
+	  if(formats_changed && Gatherer.c_man.built()) {
+	      // upload etc/collect.cfg to server to reflect changes
+	      Utility.zipup(col_name,Utility.CONFIG_FILE);
+	      Utility.upload_url_zip(col_name,"etc");
+	  }
+      }
+
       // Readd collection
       ///ystem.err.println("Would have added collection if it had been released.");
       if(collection_released) {
-	  // Then re-add it to force format commands to be processed
-	  Gatherer.self.configServer(GSDLSiteConfig.ADD_COMMAND + Gatherer.c_man.getCollection().getName());
+	  // Now re-add collection to server to force format commands to be processed
+	  Gatherer.self.configServer(GSDLSiteConfig.ADD_COMMAND + col_name);
 	  // This is very important -- it ensures that the above command has finished
 	  Gatherer.self.configServer("");
-	 // Unset formats changed
-	 format_manager.setFormatsChanged(false);
-      }
-    }
+      }
+
+      if (formats_changed) {
+	  // Unset formats changed
+	  format_manager.setFormatsChanged(false);
+      }
+   }
 
 //     /** Ensures that the collection is now public. Useful for collections that are based on another, or that are about to be exported */
Index: /trunk/gli/src/org/greenstone/gatherer/collection/BuildOptions.java
===================================================================
--- /trunk/gli/src/org/greenstone/gatherer/collection/BuildOptions.java	(revision 7738)
+++ /trunk/gli/src/org/greenstone/gatherer/collection/BuildOptions.java	(revision 7739)
@@ -3,4 +3,5 @@
 import java.io.*;
 import java.lang.ref.*;
+import java.net.*;
 import java.util.*;
 import org.apache.xerces.parsers.DOMParser;
@@ -377,31 +378,50 @@
     private Element loadArguments(String filename, String lang) {
 	Element arguments_element = null;
+	InputStream input_stream = null;
+
 	// Run the required program.
 	try {
 	    String args[];
-	    if(Utility.isWindows()) {
-		args = new String[6];
-		args[0] = Gatherer.config.perl_path;
-		args[1] = "-S";
-		args[2] = Gatherer.config.getScriptPath() + filename;
-		args[3] = "-xml";
-		args[4] = "-language";
-		args[5] = lang;
+	    if (Gatherer.isGsdlRemote) {
+		    String launch  = Gatherer.cgiBase + "launch";
+		    launch += "?cmd=" + filename;
+		    launch += "&xml=&language="+lang;
+
+		    System.err.println("*** launch = " + launch);
+
+		    URL launch_url = new URL(launch);
+		    URLConnection launch_connection = launch_url.openConnection();
+		    input_stream = launch_connection.getInputStream();
 	    }
 	    else {
-		args = new String[4];
-		args[0] = Gatherer.config.getScriptPath() + filename;
-		args[1] = "-xml";
-		args[2] = "-language";
-		args[3] = lang;
-	    }
-	    // Create the process.
-	    Runtime runtime = Runtime.getRuntime();
-	    Process process = runtime.exec(args);
-	    //InputStream input_stream = process.getErrorStream();
-	    InputSource source = new InputSource(new InputStreamReader(process.getErrorStream(), "UTF-8"));
-	    DOMParser parser = new DOMParser();
-	    parser.parse(source);
-	    Document document = parser.getDocument();
+		if(Utility.isWindows()) {
+		    args = new String[6];
+		    args[0] = Gatherer.config.perl_path;
+		    args[1] = "-S";
+		    args[2] = Gatherer.config.getScriptPath() + filename;
+		    args[3] = "-xml";
+		    args[4] = "-language";
+		    args[5] = lang;
+		}
+		else {
+		    args = new String[4];
+		    args[0] = Gatherer.config.getScriptPath() + filename;
+		    args[1] = "-xml";
+		    args[2] = "-language";
+		    args[3] = lang;
+		}
+
+		// Create the process.
+		Runtime runtime = Runtime.getRuntime();
+		Process process = runtime.exec(args);
+
+		input_stream = process.getErrorStream();
+	    }
+
+	    Document document = Utility.parse(input_stream,false);
+
+	    //DOMParser parser = new DOMParser();
+	    //parser.parse(source);
+	    //Document document = parser.getDocument();
 	    arguments_element = document.getDocumentElement();
 	}
Index: /trunk/gli/src/org/greenstone/gatherer/collection/CollectionManager.java
===================================================================
--- /trunk/gli/src/org/greenstone/gatherer/collection/CollectionManager.java	(revision 7738)
+++ /trunk/gli/src/org/greenstone/gatherer/collection/CollectionManager.java	(revision 7739)
@@ -158,6 +158,6 @@
 
 	String args[];
-	if(Utility.isWindows()) {
-	    args = new String[9];
+	if((Utility.isWindows()) && (!Gatherer.isGsdlRemote)) {
+	    args = new String[8];
 	    args[0] = Gatherer.config.perl_path;
 	    args[1] = "-S";
@@ -168,8 +168,7 @@
 	    args[6] = "-collectdir";
 	    args[7] = collect_dir;
-	    args[8] = collection.getName();
 	}
 	else {
-	    args = new String[7];
+	    args = new String[6];
 	    args[0] = Gatherer.config.getScriptPath() + "buildcol.pl";
 	    args[1] = "-gli";
@@ -178,7 +177,7 @@
 	    args[4] = "-collectdir";
 	    args[5] = collect_dir;
-	    args[6] = collection.getName();
 	}
 	args = ArrayTools.add(args, collection.build_options.getBuildValues());
+	args = ArrayTools.add(args, collection.getName());
 	GShell shell = new GShell(args, GShell.BUILD, BUILDING, this, build_monitor, GShell.GSHELL_BUILD);
 	shell.addGShellListener(Gatherer.g_man.create_pane);
@@ -259,5 +258,5 @@
 	String collect_dir = getCollectDirectory();
 	
-	if(Utility.isWindows()) {
+	if((Utility.isWindows()) && (!Gatherer.isGsdlRemote)) {
 	    command = new String[6];
 	    command[0] = Gatherer.config.perl_path;
@@ -338,5 +337,5 @@
 	    makeCollection(description, email, name, title);
 	    progress.setProgress(1);
-	    // *******************8
+	    // *******************
 	    String a_dir;
 	    if (Gatherer.GS3) {
@@ -837,6 +836,6 @@
 	    String args[];
 	    String lang = Gatherer.config.getLanguage();
-	    if(Utility.isWindows()) {
-		args = new String[9];
+	    if((Utility.isWindows()) && (!Gatherer.isGsdlRemote)) {
+		args = new String[8];
 		args[0] = Gatherer.config.perl_path;
 		args[1] = "-S";
@@ -847,8 +846,7 @@
 		args[6] = "-collectdir";
 		args[7] = collect_dir;
-		args[8] = collection.getName();
 	    }
 	    else {
-		args = new String[7];
+		args = new String[6];
 		args[0] = Gatherer.config.getScriptPath() + "import.pl";
 		args[1] = "-gli";
@@ -857,8 +855,9 @@
 		args[4] = "-collectdir";
 		args[5] = collect_dir;
-		args[6] = collection.getName();
 	    }
 	    collect_dir = null;
 	    args = ArrayTools.add(args, collection.build_options.getImportValues());
+	    args = ArrayTools.add(args, collection.getName());
+
 	    GShell shell = new GShell(args, GShell.IMPORT, BUILDING, this, import_monitor, GShell.GSHELL_IMPORT);
 	    shell.addGShellListener(Gatherer.g_man.create_pane);
@@ -1043,7 +1042,7 @@
 	// Run the mkcol command.
 	String command[];
-	if(Utility.isWindows()) {
+	if((Utility.isWindows()) && (!Gatherer.isGsdlRemote)) {
 	    if(description == null || title == null) {
-		command = new String[6];
+		command = new String[8];
 		command[0] = Gatherer.config.perl_path;
 		command[1] = "-S";
@@ -1051,21 +1050,10 @@
 		command[3] = "-collectdir";
 		command[4] = collect_dir;
-		command[5] = name;
+		command[5] = "-win31compat";
+		command[6] = (Gatherer.isGsdlRemote) ? "false" : "true";
+		command[7] = name;
 	    }
 	    // Users are no longer required to supply an email
 	    else if(email == null) {
-		command = new String[10];
-		command[0] = Gatherer.config.perl_path;
-		command[1] = "-S";
-		command[2] = Gatherer.config.getScriptPath() + "mkcol.pl";
-		command[3] = "-collectdir";
-		command[4] = collect_dir;
-		command[5] = "-title";
-		command[6] = title;
-		command[7] = "-about";
-		command[8] = description;
-		command[9] = name;
-	    }
-	    else {
 		command = new String[12];
 		command[0] = Gatherer.config.perl_path;
@@ -1074,4 +1062,60 @@
 		command[3] = "-collectdir";
 		command[4] = collect_dir;
+		command[5] = "-win31compat";
+		command[6] = (Gatherer.isGsdlRemote) ? "false" : "true";
+		command[7] = "-title";
+		command[8] = title;
+		command[9] = "-about";
+		command[10] = description;
+		command[11] = name;
+	    }
+	    else {
+		command = new String[14];
+		command[0] = Gatherer.config.perl_path;
+		command[1] = "-S";
+		command[2] = Gatherer.config.getScriptPath() + "mkcol.pl";
+		command[3] = "-collectdir";
+		command[4] = collect_dir;
+		command[5] = "-win31compat";
+		command[6] = (Gatherer.isGsdlRemote) ? "false" : "true";
+		command[7] = "-title";
+		command[8] = title;
+		command[9] = "-creator";
+		command[10] = email;
+		command[11] = "-about";
+		command[12] = description;
+		command[13] = name;
+	    }
+	}
+	else {
+	    if(description == null || title == null) {
+		command = new String[6];
+		command[0] = "mkcol.pl";
+		command[1] = "-collectdir";
+		command[2] = collect_dir;
+		command[3] = "-win31compat";
+		command[4] = (Gatherer.isGsdlRemote) ? "false" : "true";
+		command[5] = name;
+	    }
+	    else if(email == null) {
+		command = new String[10];
+		command[0] = "mkcol.pl";
+		command[1] = "-collectdir";
+		command[2] = collect_dir;
+		command[3] = "-win31compat";
+		command[4] = (Gatherer.isGsdlRemote) ? "false" : "true";
+		command[5] = "-title";
+		command[6] = title;
+		command[7] = "-about";
+		command[8] = description;
+		command[9] = name;
+	    }
+	    else {
+		command = new String[12];
+		command[0] = "mkcol.pl";
+		command[1] = "-collectdir";
+		command[2] = collect_dir;
+		command[3] = "-win31compat";
+		command[4] = (Gatherer.isGsdlRemote) ? "false" : "true";
 		command[5] = "-title";
 		command[6] = title;
@@ -1081,37 +1125,4 @@
 		command[10] = description;
 		command[11] = name;
-	    }
-	}
-	else {
-	    if(description == null || title == null) {
-		command = new String[4];
-		command[0] = "mkcol.pl";
-		command[1] = "-collectdir";
-		command[2] = collect_dir;
-		command[3] = name;
-	    }
-	    else if(email == null) {
-		command = new String[8];
-		command[0] = "mkcol.pl";
-		command[1] = "-collectdir";
-		command[2] = collect_dir;
-		command[3] = "-title";
-		command[4] = title;
-		command[5] = "-about";
-		command[6] = description;
-		command[7] = name;
-	    }
-	    else {
-		command = new String[10];
-		command[0] = "mkcol.pl";
-		command[1] = "-collectdir";
-		command[2] = collect_dir;
-		command[3] = "-title";
-		command[4] = title;
-		command[5] = "-creator";
-		command[6] = email;
-		command[7] = "-about";
-		command[8] = description;
-		command[9] = name;
 	    }
 	}
Index: /trunk/gli/src/org/greenstone/gatherer/gui/GUIManager.java
===================================================================
--- /trunk/gli/src/org/greenstone/gatherer/gui/GUIManager.java	(revision 7738)
+++ /trunk/gli/src/org/greenstone/gatherer/gui/GUIManager.java	(revision 7739)
@@ -201,4 +201,5 @@
 	else if(esrc == menu_bar.file_exit) {
 	    //menu_bar.exit();
+	    System.err.println("*** menu bar file exit called");
 	    exit();
 	}
@@ -515,5 +516,5 @@
 	catch (Exception e) {
 	    Gatherer.printStackTrace(e);
-	    // The GUI failing to build is a app killer
+	    // The GUI failing to build is an app killer
 	    e.printStackTrace();
 	    System.exit(1);
@@ -524,16 +525,29 @@
     public void exit() {
 	// Tell everyone who cares that they are losing focus
+	System.err.println("**** GUIManager exit called!");
+
 	if(!Gatherer.c_man.ready() || design_pane.canSave()) {
-	    boolean cont = true;
-	    if(Gatherer.c_man.ready() && !Gatherer.c_man.saved()) {
-		cont = showSaveCollectionBox(false, true);
+
+	    if (Gatherer.isGsdlRemote) {		    
+		// consider saving???
+		System.err.println("**** Hiding GUI panel");
+		hide();
 	    }
 	    else {
-		// Deal to help
-		if(help != null) {
-		    help.destroy();
-		    help = null;
+
+		boolean cont = true;
+		if(Gatherer.c_man.ready() && !Gatherer.c_man.saved()) {
+		    System.err.println("***** c_man not saved");
+		    cont = showSaveCollectionBox(false, true);
 		}
-		Gatherer.self.exit();
+		else {
+		    // Deal to help
+		    if(help != null) {
+			help.destroy();
+			help = null;
+		    }
+		    System.err.println("**** Calling Gatherer.self.exit");
+		    Gatherer.self.exit();
+		}
 	    }
 	}
@@ -970,4 +984,5 @@
     protected void processWindowEvent(WindowEvent event) {
 	if(event.getID() == WindowEvent.WINDOW_CLOSING) {
+	    System.err.println("***** Processing Window Event ... closing");
 	    exit();
 	}
Index: /trunk/gli/src/org/greenstone/gatherer/shell/GShell.java
===================================================================
--- /trunk/gli/src/org/greenstone/gatherer/shell/GShell.java	(revision 7738)
+++ /trunk/gli/src/org/greenstone/gatherer/shell/GShell.java	(revision 7739)
@@ -38,5 +38,7 @@
 
 import java.io.*;
+import java.net.*;
 import java.util.ArrayList;
+import java.util.Enumeration;
 import javax.swing.*;
 import javax.swing.event.*;
@@ -48,4 +50,6 @@
 import org.greenstone.gatherer.shell.GShellListener;
 import org.greenstone.gatherer.shell.GShellProgressMonitor;
+import org.greenstone.gatherer.util.StaticStrings; 
+import org.greenstone.gatherer.util.Utility;
 
 /** The <strong>GShell</strong> is reponsible for running a separately threaded process in the command shell. This is necessary for executing the Perl Scripts and also for other system related funcitonality.
@@ -103,4 +107,5 @@
     static public boolean processRunning(Process process) {
 	boolean process_running = false;
+
 	try {
 	    process.exitValue(); // This will throw an exception if the process hasn't ended yet.
@@ -149,6 +154,253 @@
        } */
 
+
+
+    protected boolean got_stream_char(InputStreamReader isr, StringBuffer line_buffer,
+				      BufferedOutputStream bos) throws IOException 
+    {
+	// Hopefully this doesn't block if the process is trying to write to STDOUT/STDERR.
+
+	boolean input_status = false;
+
+	if(isr.ready()) {
+	    input_status = true;
+	    int c = isr.read();
+	    if(c == '\n' || c == '\r') {
+		if(line_buffer.length() > 0) {
+		    String line = line_buffer.toString();
+		    Gatherer.println("* " + line + " *");
+		    fireMessage(type, typeAsString(type) + "> " + line, status, bos);
+		    line = null;
+		    line_buffer = new StringBuffer();
+		}
+	    }
+	    else {
+		line_buffer.append((char)c);
+	    }
+	}
+
+	return input_status;
+    }
+
+
+    protected StringBuffer get_stream_char(InputStreamReader isr, StringBuffer line_buffer,
+				   BufferedOutputStream bos) throws IOException 
+    {
+	int c = isr.read();
+	///atherer.println("isr: '" + (char) c + "'");
+	if(c == '\n' || c == '\r') {
+	    if(line_buffer.length() > 0) {
+		String line = line_buffer.toString();
+		// Gatherer.println("* " + line + " *");
+		fireMessage(type, typeAsString(type) + "> " + line, status, bos);
+		line_buffer = new StringBuffer();
+	    }
+	}
+	else {
+	    line_buffer.append((char)c);
+	}
+
+	return line_buffer;
+    }
+
+    protected void runRemote(String[] args, BufferedOutputStream bos) 
+    {
+	try {
+
+	    String perl_cmd = args[0];
+	    int perl_cmd_root = perl_cmd.lastIndexOf(File.separator);
+		
+	    if (perl_cmd_root > 0) {
+		String perl_cmd_cut = perl_cmd.substring(perl_cmd_root+1);
+		perl_cmd = perl_cmd_cut;
+	    }
+
+	    String launch  = Gatherer.cgiBase + "launch";
+	    launch = launch + "?cmd=" + perl_cmd;
+
+	    for(int i = 1; i<args.length; i++) {
+		    
+		String arg = args[i];
+
+		if (arg.equals("-collectdir") || arg.equals("-importdir")
+		    || arg.equals("-builddir")) {
+		    // skip it
+		    i++;
+		    continue;
+		}
+	    
+		launch += "&";
+	    
+		if(arg.startsWith(StaticStrings.MINUS_CHARACTER)) {
+		    String name = arg.substring(1);
+		    launch = launch + name + "=";
+		    if (i+1<args.length-1) {
+			if (!args[i+1].startsWith(StaticStrings.MINUS_CHARACTER)) {
+			    i++;
+			    String val = args[i];
+			    launch = launch + val;
+			}
+		    }
+		}
+		else {
+		    launch = launch + "c=" + arg;
+		}
+	    }
+
+	    System.err.println("**** launch url = " + launch);
+
+	    URL launch_url = new URL(launch);
+	    URLConnection launch_connection = launch_url.openConnection();
+	    InputStream stdis = launch_connection.getInputStream();
+	    InputStreamReader stdisr = new InputStreamReader(stdis, "UTF-8"  );
+	
+	    BufferedReader stdbr = new BufferedReader(stdisr);
+	
+	    if (type == GShell.NEW) {
+		while(true) {
+		    String line = stdbr.readLine();
+		    if (line == null) { break; }
+		}		
+	    }
+	    else {
+		while(!hasSignalledStop()) {
+		    String line = stdbr.readLine();
+		    if (line == null) { break; }
+		    fireMessage(type, typeAsString(type) + "> " + line, status, bos);
+		}		
+	    }
+	    stdbr.close();
+	
+	    status = OK;
+	    fireMessage(type, typeAsString(type) + "> " + Dictionary.get("GShell.Success"), status, null);
+	}
+	// Exception
+	catch (Exception exception) {
+	    Gatherer.println("Exception in GShell.runRemove() - unexpected");
+	    Gatherer.printStackTrace(exception);
+	    status = ERROR;
+	}
+    }
+
+
+    protected void runLocal(String[] args, BufferedOutputStream bos) 
+    {
+	try {
+	    String command = "";
+	    for(int i = 0; i < args.length; i++) {
+		command = command + args[i] + " ";
+	    }
+	    
+	    Gatherer.println("Command: "+command);
+	    ///ystem.err.println("Command: " + command);
+	    fireMessage(type, Dictionary.get("GShell.Command") + ": " + command, status, null);
+	    
+	    Runtime rt = Runtime.getRuntime();
+	    Process prcs = rt.exec(args);
+	    
+	    InputStreamReader eisr = new InputStreamReader( prcs.getErrorStream(), "UTF-8" );
+	    InputStreamReader stdisr = new InputStreamReader( prcs.getInputStream(), "UTF-8"  );
+	    //BufferedReader ebr = new BufferedReader( eisr );
+	    //BufferedReader stdinbr = new BufferedReader( stdinisr );
+	    // Captures the std err of a program and pipes it into std in of java
+	
+	    StringBuffer eline_buffer = new StringBuffer();
+	    StringBuffer stdline_buffer = new StringBuffer();
+	
+	    while(type != GShell.NEW && processRunning(prcs) && !hasSignalledStop()) {
+		// Hopefully this doesn't block if the process is trying to write to STDOUT.
+		if((eisr!=null) && eisr.ready()) { 
+		    eline_buffer = get_stream_char(eisr,eline_buffer,bos);
+		}
+		// Hopefully this won't block if the process is trying to write to STDERR
+		else if(stdisr.ready()) {
+		    stdline_buffer = get_stream_char(stdisr,stdline_buffer,bos);
+		}
+		else {
+		    try {
+			sleep(100);
+		    }
+		    catch(Exception exception) {
+		    }
+		}
+	    }
+	
+	    if(!hasSignalledStop()) {
+		// Of course, just because the process is finished doesn't
+		// mean the incoming streams are empty. Unfortunately I've
+		// got no chance of preserving order, so I'll process the
+		// error stream first, then the out stream
+		while(eisr.ready()) {
+		    eline_buffer = get_stream_char(eisr,eline_buffer,bos);
+		}
+	    
+		while(stdisr.ready()) {
+		    stdline_buffer = get_stream_char(stdisr,stdline_buffer,bos);
+		}
+	    
+		// Ensure that any messages still remaining in the string buffers are fired off.
+		if(eline_buffer.length() > 0) {
+		    String eline = eline_buffer.toString();
+		    //Gatherer.println("Last bit of eline: " + eline);
+		    fireMessage(type, typeAsString(type) + "> " + eline, status, bos);
+		    eline = null;
+		}
+	    
+		if(stdline_buffer.length() > 0) {
+		    String stdline = stdline_buffer.toString();
+		    //Gatherer.println("Last bit of stdline: " + stdline);
+		    fireMessage(type, typeAsString(type) + "> " + stdline, status, null);
+		    stdline = null;
+		}
+	    }
+	    else {
+		System.err.println("We've been asked to stop.");
+	    }
+	
+	
+	    if(!hasSignalledStop()) {
+		// Now display final message based on exit value
+	    
+		prcs.waitFor(); 
+
+		if(prcs.exitValue() == 0) {
+		    status = OK;
+		    fireMessage(type, typeAsString(type) + "> " + Dictionary.get("GShell.Success"), status, null);
+		}
+		else {
+		    status = ERROR;
+		    fireMessage(type, typeAsString(type) + "> " + Dictionary.get("GShell.Failure"), status, null);
+		}
+	    
+		eisr.close();
+		stdisr.close();
+	    }
+	    else {
+		// I need to somehow kill the child process. Unfortunately
+		// Thread.stop() and Process.destroy() both fail to do
+		// this. But now, thankx to the magic of Michaels 'close the
+		// stream suggestion', it works fine (no it doesn't!)
+		prcs.getInputStream().close();
+		prcs.getErrorStream().close();
+		prcs.getOutputStream().close();
+		prcs.destroy();
+		status = CANCELLED;
+	    }
+	}
+	// Exception
+	catch (Exception exception) {
+	    Gatherer.println("Exception in GShell.runLocal() - unexpected");
+	    Gatherer.printStackTrace(exception);
+	    status = ERROR;
+	}
+    }
+    
+    
+
     /** Any threaded class must include this method to allow the thread body to be run. */
     public void run() {
+
+	String col_name = args[args.length-1];		
+
 	// Determine if the user has asked for an outfile.
 	String out_name = null;
@@ -170,156 +422,62 @@
 	    }
 	}
+
+	if (Gatherer.isGsdlRemote) {
+	    if (type == IMPORT) {
+		// zip up import folder
+		Utility.zipup(col_name,"import");
+		// upload it to gsdl server
+		Utility.upload_url_zip(col_name,"import");
+
+		// upload etc/collect.cfg to server
+		Utility.zipup(col_name,Utility.CONFIG_FILE);
+		Utility.upload_url_zip(col_name,"etc");
+	    }
+	}
+
+
 	// Issue a processBegun event
 	fireProcessBegun(type, status);
-	try {
-	    String command = "";
-	    for(int i = 0; i < args.length; i++) {
-		command = command + args[i] + " ";
-	    }
-	    Gatherer.println("Command: "+command);
-	    ///ystem.err.println("Command: " + command);
-	    fireMessage(type, Dictionary.get("GShell.Command") + ": " + command, status, null);
-	    
-	    Runtime rt = Runtime.getRuntime();
-	    Process prcs = rt.exec(args);
-	    InputStreamReader eisr = new InputStreamReader( prcs.getErrorStream(), "UTF-8" );
-	    InputStreamReader stdisr = new InputStreamReader( prcs.getInputStream(), "UTF-8"  );
-	    //BufferedReader ebr = new BufferedReader( eisr );
-	    //BufferedReader stdinbr = new BufferedReader( stdinisr );
-	    // Captures the std err of a program and pipes it into std in of java
-	    
-	    StringBuffer eline_buffer = new StringBuffer();
-	    StringBuffer stdline_buffer = new StringBuffer();
-	    while(type != GShell.NEW && processRunning(prcs) && !hasSignalledStop()) {
-		// Hopefully this doesn't block if the process is trying to write to STDOUT.
-		if(eisr.ready()) {
-		    int c = eisr.read();
-		    ///atherer.println("eisr: '" + (char) c + "'");
-		    if(c == '\n' || c == '\r') {
-			if(eline_buffer.length() > 0) {
-			    String eline = eline_buffer.toString();
-			    ///atherer.println("* " + eline + " *");
-			    fireMessage(type, typeAsString(type) + "> " + eline, status, bos);
-			    eline = null;
-			    eline_buffer = new StringBuffer();
-			}
-		    }
-		    else {
-			eline_buffer.append((char)c);
-		    }
-		}
-		// Hopefully this won't block if the process is trying to write to STDERR
-		else if(stdisr.ready()) {
-		    int c = stdisr.read();
-		    ///atherer.println("eisr: '" + (char) c + "'");
-		    if(c == '\n' || c == '\r') {
-			if(stdline_buffer.length() > 0) {
-			    String stdline = stdline_buffer.toString();
-			    ///atherer.println("+ " + stdline + " +");
-			    fireMessage(type, typeAsString(type) + "> " + stdline, status, null);
-			    stdline = null;
-			    stdline_buffer = new StringBuffer();
-			}
-		    }
-		    else {
-			stdline_buffer.append((char)c);
-		    }
-		}
-		else {
-		    try {
-			sleep(100);
-		    }
-		    catch(Exception exception) {
-		    }
-		}
-	    }
-	    if(!hasSignalledStop()) {
-		// Of course, just because the process is finished doesn't mean the incoming streams are empty. Unfortunately I've got no chance of preserving order, so I'll process the error stream first, then the out stream
-		while(eisr.ready()) {
-		    int c = eisr.read();
-		    ///atherer.println("eisr: '" + (char) c + "'");
-		    if(c == '\n' || c == '\r') {
-			if(eline_buffer.length() > 0) {
-			    String eline = eline_buffer.toString();
-			    ///atherer.println("* " + eline + " *");
-			    fireMessage(type, typeAsString(type) + "> " + eline, status, bos);
-			    eline = null;
-			    eline_buffer = new StringBuffer();
-			}
-		    }
-		    else {
-			eline_buffer.append((char)c);
-		    }
-		}
-		while(stdisr.ready()) {
-		    int c = stdisr.read();
-		    ///atherer.println("eisr: '" + (char) c + "'");
-		    if(c == '\n' || c == '\r') {
-			if(stdline_buffer.length() > 0) {
-			    String stdline = stdline_buffer.toString();
-			    ///atherer.println("+ " + stdline + " +");
-			    fireMessage(type, typeAsString(type) + "> " + stdline, status, null);
-			    stdline = null;
-			    stdline_buffer = new StringBuffer();
-			}
-		    }
-		    else {
-			stdline_buffer.append((char)c);
-		    }
-		}
+	if (Gatherer.isGsdlRemote) {
+	    runRemote(args,bos);
+	}
+	else {
+	    runLocal(args,bos);
+	}
+
+	if(status == OK) {
+	    if (type == NEW) {
+		if (Gatherer.isGsdlRemote) {
+		    Utility.download_url_zip(col_name,".");
+		    Utility.unzip(col_name);
+		}
+	    }
+	    else if(type == IMPORT) {
 		
-		// Ensure that any messages still remaining in the string buffers are fired off.
-		if(eline_buffer.length() > 0) {
-		    String eline = eline_buffer.toString();
-		    ///atherer.println("Last bit of eline: " + eline);
-		    fireMessage(type, typeAsString(type) + "> " + eline, status, bos);
-		    eline = null;
-		}
+		// download the archives directory (if gsdl server is remote)			
+		if (Gatherer.isGsdlRemote) {
+		    Utility.delete(Gatherer.c_man.getCollectionArchive()); // remove current archives
+		    Utility.download_url_zip(col_name,"archives");
+		    Utility.unzip(col_name);
+		}
+
+		// extract any new metadata from the archive directory.
+		fireMessage(type, typeAsString(type) + "> " + Dictionary.get("GShell.Parsing_Metadata_Start"), status, null);
+		new GreenstoneArchiveParser(progress, this);
+		fireMessage(type, typeAsString(type) + "> " + Dictionary.get("GShell.Parsing_Metadata_Complete"), status, null);
+	    }
+
+	    else if(type == BUILD) {
 		
-		if(stdline_buffer.length() > 0) {
-		    String stdline = stdline_buffer.toString();
-		    ///atherer.println("Last bit of stdline: " + stdline);
-		    fireMessage(type, typeAsString(type) + "> " + stdline, status, null);
-		    stdline = null;
-		}
-	    }
-	    else {
-		System.err.println("We've been asked to stop.");
-	    }
-	    
-	    if(!hasSignalledStop()) {
-		// Now display final message based on exit value
-		prcs.waitFor();
-		
-		if(prcs.exitValue() == 0) {
-		    status = OK;
-		    fireMessage(type, typeAsString(type) + "> " + Dictionary.get("GShell.Success"), status, null);
-		}
-		else {
-		    status = ERROR;
-		    fireMessage(type, typeAsString(type) + "> " + Dictionary.get("GShell.Failure"), status, null);
-		}
-	    }
-	    else {
-		// I need to somehow kill the child process. Unfortunately Thread.stop() and Process.destroy() both fail to do this. But now, thankx to the magic of Michaels 'close the stream suggestion', it works fine (no it doesn't!)
-		prcs.getInputStream().close();
-		prcs.getErrorStream().close();
-		prcs.getOutputStream().close();
-		prcs.destroy();
-		status = CANCELLED;
-	    }
-	}
-	// Exception
-	catch (Exception exception) {
-	    Gatherer.println("Exception in GShell.run() - unexpected");
-	    Gatherer.printStackTrace(exception);
-	    status = ERROR;
-	}
-	// If no error occured, and this was an import process we now extract any new metadata from the archive directory.
-	if(status == OK && type == IMPORT) {
-	    fireMessage(type, typeAsString(type) + "> " + Dictionary.get("GShell.Parsing_Metadata_Start"), status, null);
-	    new GreenstoneArchiveParser(progress, this);
-	    fireMessage(type, typeAsString(type) + "> " + Dictionary.get("GShell.Parsing_Metadata_Complete"), status, null);
-	}
+		// download the building directory (if gsdl server is remote)			
+		if (Gatherer.isGsdlRemote) {
+		    Utility.delete(Gatherer.c_man.getCollectionBuild()); // remove current build dir
+		    Utility.download_url_zip(col_name,"building");
+		    Utility.unzip(col_name);
+		}
+
+	    }
+	}
+
 	if(hasSignalledStop()) {
 	    status = CANCELLED;
Index: /trunk/gli/src/org/greenstone/gatherer/util/Utility.java
===================================================================
--- /trunk/gli/src/org/greenstone/gatherer/util/Utility.java	(revision 7738)
+++ /trunk/gli/src/org/greenstone/gatherer/util/Utility.java	(revision 7739)
@@ -41,4 +41,5 @@
 import java.net.*;
 import java.util.*;
+import java.util.zip.*;
 import javax.swing.*;
 import javax.swing.tree.*;
@@ -68,10 +69,10 @@
     static final public String ARCHIVE_DIR = "archives" + File.separator;
     /** Definition of an important directory name, in this case the base dir, or the working directory of the Gatherer. */
-    static final public String BASE_DIR  = System.getProperty("user.dir") + File.separator;
+    static public String BASE_DIR  = System.getProperty("user.dir") + File.separator;
     static final public String BUILD_CFG_FILENAME = "build.cfg";
     /** Definition of an important directory name, in this case the building directory for the collection. */
     static final public String BUILD_DIR = "building" + File.separator;
     /** Definition of an important directory name, in this case the public web cache for the Gatherer. */
-    static final public String CACHE_DIR = BASE_DIR + "cache" + File.separator;
+    static public String CACHE_DIR = BASE_DIR + "cache" + File.separator;
     static final public String CFG_COLLECTIONMETA_COLLECTIONNAME = "collectionmeta\tcollectionname";
     static final public String CFG_COLLECTIONMETA_COLLECTIONEXTRA = "collectionmeta\tcollectionextra";
@@ -108,5 +109,5 @@
     static final public String GLI_EXTENSION = ".col";
     /** Definition of an important directory name, in this case the location of help documentation. */
-    static final public String HELP_DIR = BASE_DIR + "help" + File.separator;
+    static public String HELP_DIR = BASE_DIR + "help" + File.separator;
     /** Definition of an important directory name, in this case the images directory for the collection. */
     static final public String IMAGES_DIR = "images" + File.separator;
@@ -125,5 +126,7 @@
     static final public String META_DIR = "metadata" + File.separator; // Col. Copy
     /** Definition of an important directory name, in this case the location of the default metadata sets. */
-    static final public String METADATA_DIR = BASE_DIR + "metadata" + File.separator;
+    static public String METADATA_DIR = BASE_DIR + "metadata" + File.separator;
+    /** Definition of an important zip file, in this case zipped up version of metadata file stored in JAR file */
+    static final public String METADATA_ZIP = "metadata.zip";
     /** The location the gatherer expects to find metadata set information. */
     static final public String METADATA_SET_TEMPLATE = "xml/template.mds";
@@ -142,22 +145,24 @@
     static final public String PROGRAM_VERSION = "v2.51";
     /** Definition of an important directory name, in this case the location of the recycled files location. */
-    static final public String RECYCLE = BASE_DIR + "recycle" + File.separator;
+    static public String RECYCLE = BASE_DIR + "recycle" + File.separator;
     /** Definition of an important directory name, in this case the location of image and other resources. */
-    static final public String RES_DIR = BASE_DIR + "resource" + File.separator;
+    static public String RES_DIR = BASE_DIR + "resource" + File.separator;
     static final public String SERVER_EXE = "server.exe";
     /** Definition of an important directory name, in this case the location of opening (or welcome) screen html. */
-    static final public String WELCOME_DIR = BASE_DIR + "welcome" + File.separator;
+    static public String WELCOME_DIR = BASE_DIR + "welcome" + File.separator;
     static final public String WORKSPACE_TREE = "Workspace";
     static final public String XML_DIRECTORY = "xml" + File.separator;
+
     // These are out of alphabetic order to avoid forward reference error.
     /** The default icon to produce a 'help-icon' sized blank space before a menu entry. */
-    static final public ImageIcon BLANK_ICON = new ImageIcon(ClassLoader.getSystemResource("images/blank.gif"));
+    static public Class base = null;
+    static public ImageIcon BLANK_ICON = null;
     /** The default error icon image. */
-    static final public ImageIcon ERROR_ICON = new ImageIcon(ClassLoader.getSystemResource("images/error.gif"));
-    static final public ImageIcon HELP_ICON = new ImageIcon(ClassLoader.getSystemResource("images/help.gif"));
+    static public ImageIcon ERROR_ICON = null; 
+    static public ImageIcon HELP_ICON = null; 
     /** The image for a toggle button whose state is 'on'. */
-    static final public ImageIcon ON_ICON = new ImageIcon(ClassLoader.getSystemResource("images/check.gif"));
+    static public ImageIcon ON_ICON = null; 
     /** The image for a toggle button whose state is 'off'. */
-    static final public ImageIcon OFF_ICON = new ImageIcon(ClassLoader.getSystemResource("images/cross.gif"));
+    static public ImageIcon OFF_ICON = null; 
 	
     /** Decodes a string of text so its safe to use in a Greenstone configuration file. Esentially replaces "\n" with a newline.
@@ -205,5 +210,5 @@
     static public boolean delete(File file) {
 	boolean result = true;
-	// If files a directory, delete files children.
+	// If file is a directory, delete the file's children.
 	if(file.isDirectory()) {
 	    File files[] = file.listFiles();
@@ -217,4 +222,8 @@
 	}
 	return result;
+    }
+
+    static public boolean delete(String filename) {
+	return delete(new File(filename));
     }
 
@@ -469,4 +478,5 @@
 	return getSitesDir(gsdl3_path) + site_name + File.separator + COL_DIR;
     }
+
     
     /** Method which constructs a collection's top level directory
@@ -481,4 +491,20 @@
 	return getCollectDir(gsdl3_path, site_name) + coll_name + File.separator;
     }
+
+    public static String getCollectionDir() {
+	String this_col_dir;
+
+	String col_name = Gatherer.c_man.getCollection().getName();
+
+	if (Gatherer.GS3) {
+	    this_col_dir = getCollectionDir(Gatherer.config.gsdl3_path, Gatherer.config.site_name, col_name);
+	} else {
+	    this_col_dir = getCollectionDir(Gatherer.config.gsdl_path, col_name);
+	    
+	}
+
+	return this_col_dir;
+    }
+
     
     /** Method which constructs the configuration file given a certain collection.
@@ -557,13 +583,15 @@
      */
     static public String getHelpFolder() {
-	String help_folder = HELP_DIR + Gatherer.config.getLanguage() + File.separator;
-	File help_folder_file = new File(help_folder);
+
+	String help_folder = "help/" + Gatherer.config.getLanguage() + "/";
+	URL help_folder_url = base.getResource("/"+help_folder);
+
 	// If that file can't be found, default to english
-	if(!help_folder_file.exists()) {
-	    help_folder = HELP_DIR + StaticStrings.ENGLISH_LANGUAGE_STR  + File.separator;
-	}
+	if(help_folder_url==null) {
+	    help_folder = "help/" + StaticStrings.ENGLISH_LANGUAGE_STR  + "/";
+	}
+
 	return help_folder;
     }
-
 
     /** Method to retrieve an image icon with the given filename found in classpath or the resouces directory.
@@ -577,8 +605,8 @@
 	ImageIcon image = null;
 	try {
-	    image = new ImageIcon(ClassLoader.getSystemResource("images/" + Dictionary.get("Version") + "/" + filename));
+	    image = new ImageIcon(base.getResource("/images/" + Dictionary.get("Version") + "/" + filename));
 	}
 	catch(NullPointerException exception) {
-	    image = new ImageIcon(ClassLoader.getSystemResource("images/" + filename));
+	    image = new ImageIcon(base.getResource("/images/" + filename));
 	}
 	if(image == null) {
@@ -647,4 +675,448 @@
 	return col_dir + META_DIR;
     }
+
+    static public void extractFromJar(String filename, String dst_dir) 
+    {
+	try {
+	    // setup input stream for slurping out file
+	    InputStream fis = base.getResourceAsStream("/"+filename);
+	    BufferedInputStream fbis = new BufferedInputStream(fis); 
+	    DataInputStream fdbis = new DataInputStream(fbis);
+		    
+	    // set up output stream for writing to disk
+	    String ofname = dst_dir + filename;
+	    FileOutputStream fos = new FileOutputStream(ofname);
+	    BufferedOutputStream bfos = new BufferedOutputStream(fos);
+
+	    byte[] buf = new byte[1024];
+	    int len;
+	    int total_bytes = 0;
+	    while ((len = fdbis.read(buf)) >= 0) {
+		bfos.write(buf,0,len);
+		total_bytes += len;
+	    }
+
+	    fdbis.close();
+	    bfos.close();
+	}
+	catch (Exception error) {
+	    error.printStackTrace();
+	}
+    }
+
+
+    /** Method which unzips a given metadata resoure
+     * @param zip_fname The name of the zip file as a <strong>String</strong>.
+     * @param dst_dir The destination directory for unzipping, also as a <strong>String</strong>.
+     * @param use_classloader Used to determine whether or not to look in resource bundle.
+     */
+    static public void unzipFromJar(String jar_zip_fname, String dst_dir) {
+
+	File file = null;
+	if (!dst_dir.endsWith(File.separator)) {
+	    dst_dir += File.separator;
+	}
+
+	extractFromJar(jar_zip_fname,dst_dir);
+
+	String zip_ofname = dst_dir + jar_zip_fname;
+	File zip_file = new File(zip_ofname);
+
+	try {
+	    ZipFile zipfile = new ZipFile(zip_file);
+	    
+	    Enumeration e = zipfile.entries(); 
+	    while (e.hasMoreElements()) {
+		ZipEntry zipentry = (ZipEntry) e.nextElement();
+		String zentryname = dst_dir + zipentry.getName();
+		Gatherer.println("    Unzipping: " + zentryname);
+
+		if (zipentry.isDirectory()) {
+		    // Create named directory
+		    boolean success = (new File(zentryname)).mkdir();
+		    if (!success) {
+			System.err.println("Error: unable to create directory '"+zentryname+"'");
+		    }
+		}
+		else {
+		    // Write out file to disk
+
+		    // set up input stream
+		    InputStream zis = zipfile.getInputStream(zipentry); 
+		    BufferedInputStream bzis = new BufferedInputStream(zis); 
+		    DataInputStream dbzis = new DataInputStream(bzis);
+		    
+		    // set up output stream
+		    FileOutputStream fzos = new FileOutputStream(zentryname);
+		    BufferedOutputStream bfzos = new BufferedOutputStream(fzos);
+		    
+		    byte[] buf = new byte[1024];
+		    int len;
+		    while ((len = dbzis.read(buf)) >= 0) {
+			bfzos.write(buf,0,len);
+		    }
+		    
+		    dbzis.close();
+		    bfzos.close();
+		}
+	    }
+	} 
+	catch (ZipException error) {
+	    System.err.println("Error: Unable to open '"+zip_file.getAbsolutePath()+"'");
+	    Gatherer.printStackTrace(error);
+	}
+
+	catch (Exception error) {
+	    error.printStackTrace();
+	}
+    }
+    
+
+    static public void download_url_zip(String col_name, String dir)
+    {
+	try {
+	    String download_cgi  = Gatherer.cgiBase + "download";
+
+	    // Send col_name and dir arguments to download cgi
+
+	    String col_name_encoded = URLEncoder.encode(col_name,"UTF-8");
+	    String dir_encoded = URLEncoder.encode(dir,"UTF-8");
+	    String cgi_args = "c=" + col_name_encoded;
+	    cgi_args += "&dir=" + dir_encoded;
+
+	    URL download_url = new URL(download_cgi);
+
+	    System.err.println("*** download cgi = '" + download_cgi + "'");
+	    System.err.println("*** cgi args = '" + cgi_args + "'");
+
+	    URLConnection dl_connection = download_url.openConnection();
+	    dl_connection.setDoOutput(true);	    
+	    OutputStream dl_os = dl_connection.getOutputStream();
+
+	    PrintWriter dl_out = new PrintWriter(dl_os);
+	    dl_out.println(cgi_args);
+	    dl_out.close();
+
+	    // Download result from running cgi script
+	    InputStream dl_is = dl_connection.getInputStream();
+	    BufferedInputStream dl_bis = new BufferedInputStream(dl_is); 
+	    DataInputStream dl_dbis = new DataInputStream(dl_bis);
+		    
+	    // set up output stream for zip download
+	    String col_dir = Utility.getCollectDir(Gatherer.config.gsdl_path);
+	    String zip_fname = col_dir + col_name + ".zip";
+	    FileOutputStream zip_fos = new FileOutputStream(zip_fname);
+	    BufferedOutputStream zip_bfos = new BufferedOutputStream(zip_fos);
+	    
+	    byte[] buf = new byte[1024];
+	    int len;
+
+	    while ((len = dl_dbis.read(buf)) >= 0) {
+		zip_bfos.write(buf,0,len);
+	    }
+
+	    dl_dbis.close();
+	    zip_bfos.close();
+
+	}
+	catch (Exception error) {
+	    error.printStackTrace();
+	}
+    }
+
+
+    static public void upload_url_zip(String col_name, String dir)
+    {
+	final String lineEnd = "\r\n";
+	final String twoHyphens = "--";
+	final String boundary =  "*****";
+	final int maxBufferSize = 1024;
+
+	String col_dir = Utility.getCollectDir(Gatherer.config.gsdl_path);
+	String zip_fname = col_dir + col_name + ".zip";
+	String upload_cgi = Gatherer.cgiBase + "upload";
+
+	HttpURLConnection conn = null;
+		
+	try {
+	    // Send zip file to server
+
+	    File file = new File(zip_fname) ;	    
+	    FileInputStream fileInputStream = new FileInputStream(file);
+	    
+	    // open a URL connection to the Servlet 
+	    URL url = new URL(upload_cgi);
+	    	    
+	    // Open a HTTP connection to the URL
+	    conn = (HttpURLConnection) url.openConnection();
+	    
+	    conn.setDoInput(true);         // Allow Inputs
+	    conn.setDoOutput(true);        // Allow Outputs
+	    conn.setUseCaches(false);      // Don't use a cached copy.
+	    conn.setRequestMethod("POST"); // Use a post method.
+	    
+	    conn.setRequestProperty("Connection", "Keep-Alive");	    
+	    conn.setRequestProperty("Content-Type", "multipart/form-data;boundary="+boundary);
+	    
+	    DataOutputStream dos = new DataOutputStream( conn.getOutputStream() );
+
+	    dos.writeBytes(twoHyphens + boundary + lineEnd);
+	    dos.writeBytes("Content-Disposition: form-data; name=\"c\"" + lineEnd + lineEnd);
+	    dos.writeBytes(col_name + lineEnd);
+
+	    dos.writeBytes(twoHyphens + boundary + lineEnd);
+	    dos.writeBytes("Content-Disposition: form-data; name=\"dir\"" + lineEnd + lineEnd);
+	    dos.writeBytes(dir + lineEnd);
+	    
+	    dos.writeBytes(twoHyphens + boundary + lineEnd);
+	    dos.writeBytes("Content-Disposition: form-data; name=\"zip\";"
+			   + " filename=\"" + zip_fname +"\"" + lineEnd);
+	    dos.writeBytes(lineEnd);
+	    
+	    		
+	    // create a buffer of maximum size
+	           	    
+	    int bytesAvailable = fileInputStream.available();
+	    int bufferSize = Math.min(bytesAvailable, maxBufferSize);
+	    byte[] buffer = new byte[bufferSize];
+	    
+	    // read file and write it into form...
+
+	    int bytesRead = fileInputStream.read(buffer, 0, bufferSize);
+	    
+	    while (bytesRead > 0) {
+		dos.write(buffer, 0, bufferSize);
+		bytesAvailable = fileInputStream.available();
+		bufferSize = Math.min(bytesAvailable, maxBufferSize);
+		bytesRead = fileInputStream.read(buffer, 0, bufferSize);
+	    }
+	    
+	    // send multipart form data necesssary after file data...
+	    
+	    dos.writeBytes(lineEnd);
+	    dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);
+	    
+	    // close streams
+	    
+	    fileInputStream.close();
+	    dos.flush();
+	    dos.close();
+	    
+	    
+	}
+	catch (MalformedURLException ex) {
+	    System.err.println("Failed on: "+ex);
+	}
+	
+	catch (IOException ioe) {
+	    System.err.println("Failed on: "+ioe);
+	}
+	
+	// Read server response
+
+	try {
+	    InputStreamReader isr = new InputStreamReader(conn.getInputStream() );
+	    BufferedReader bisr = new BufferedReader (isr);
+	    String str;
+	    while (( str = bisr.readLine()) != null) {
+		System.err.println(str);
+	    }
+	    bisr.close();
+	    
+	}
+	catch (IOException ioex) {
+	    System.err.println("From (ServerResponse): "+ioex);
+	}
+    }
+
+    static protected void zipFunc (ZipOutputStream zos, String file_path, int prefix_strip) 
+    {
+	// Using try is required because of file io.
+	try {
+	    // Create a Zip Entry and put it into the archive (no data yet).
+
+	    // Strip off col_dir prefix
+	    String zip_path = file_path.substring(prefix_strip);
+
+	    ZipEntry fileEntry = new ZipEntry(zip_path);
+	    zos.putNextEntry(fileEntry);
+
+	    // Create a file input stream and a buffered input stream.
+	    FileInputStream fis = new FileInputStream(file_path);
+	    BufferedInputStream bis = new BufferedInputStream(fis);
+	    
+	    // Create a byte array object named data and declare byte count variable.
+	    byte[] data = new byte[1024];
+	    int byteCount;
+	    // Create a loop that reads from the buffered input stream and writes
+	    // to the zip output stream until the bis has been entirely read.
+	    while ((byteCount = bis.read(data, 0, 1024)) > -1) {
+		zos.write(data, 0, byteCount);
+	    }
+	} 
+	catch (IOException e) {
+	    e.printStackTrace();
+	}
+	
+	Gatherer.println("    Zipping up: " + file_path);
+    }
+
+    static protected void dirFunc (ZipOutputStream zos, String dir_name, int prefix_strip) 
+    {
+	File dirObj = new File(dir_name);
+
+	if (dirObj.exists() == true) {
+	    if (dirObj.isDirectory() == true) {
+		// Create an array of File objects, one for each file or directory in dirObj.
+		File [] fileList = dirObj.listFiles();
+		
+		// Loop through File array and display.
+		for (int i = 0; i < fileList.length; i++) {
+		    File file = fileList[i];
+		    if (file.isDirectory()) {
+			String dir_path = file.getPath();
+			String zip_path = dir_path.substring(prefix_strip);
+			// use of "/" here instead of File.separation intentional
+			ZipEntry dirEntry = new ZipEntry(zip_path+"/");
+
+			try {
+			    zos.putNextEntry(dirEntry);
+			} 
+			catch (IOException e) {
+			    e.printStackTrace();
+			}
+
+			dirFunc(zos,dir_path,prefix_strip);
+		    } else if (file.isFile()) {
+			// Call the zipFunc function
+			String file_path = fileList[i].getPath();
+			zipFunc(zos,file_path,prefix_strip);
+		    }
+		} 
+	    } 
+	    else { 
+		System.err.println (dir_name+" is not a directory."); 
+	    }
+	} 
+	else { 
+	    System.err.println ("Directory "+dir_name+" does not exist."); 
+	}
+    }
+    
+
+
+    static public void zipup(String col_name, String dir_or_file)
+    {
+	String col_dir = Utility.getCollectDir(Gatherer.config.gsdl_path);
+	int prefix_strip = col_dir.length();
+
+	String zip_fname = col_dir + col_name + ".zip";
+	String zip_dir_or_file = col_dir + col_name + File.separator + dir_or_file;
+	File zip_dof = new File(zip_dir_or_file);
+
+	try {
+	    FileOutputStream fos = new FileOutputStream(zip_fname);
+	    ZipOutputStream zos = new ZipOutputStream(fos);
+	    
+	    if (zip_dof.exists()) {
+		if (zip_dof.isDirectory()) {
+		    String zip_dir = zip_dir_or_file;
+		    dirFunc(zos,zip_dir,prefix_strip);
+		}
+		else {
+		    String zip_full_file = zip_dir_or_file; 
+
+		    String zip_path = zip_full_file.substring(prefix_strip);
+
+		    for (int i=1; i<zip_path.length(); i++) {
+			String ch = String.valueOf(zip_path.charAt(i));
+
+			if (ch.equals(File.separator)) {
+			    String dir_path = zip_path.substring(0,i);
+			    // use of "/" here instead of File.separation intentional
+			    ZipEntry dirEntry = new ZipEntry(dir_path+"/");
+			    zos.putNextEntry(dirEntry);
+			}
+		    }
+		    zipFunc(zos,zip_full_file,prefix_strip);
+		}
+	    }
+	    else {
+		System.err.println("Warning: " + zip_dir_or_file + " does not exist!");
+	    }
+	    
+	    // Close the file output streams for both the file and the zip.
+	    zos.flush();
+	    zos.close();
+	    fos.close();
+	} 
+	catch (IOException e) {
+	    e.printStackTrace();
+	} 
+    } 
+    
+
+    static public void unzip(String col_name)
+    {
+	String col_dir = Utility.getCollectDir(Gatherer.config.gsdl_path);
+	String zip_fname = col_dir + col_name + ".zip";
+	int zip_mode = ZipFile.OPEN_READ | ZipFile.OPEN_DELETE;
+
+	try {
+	    ZipFile zipfile = new ZipFile(new File(zip_fname), zip_mode);
+	    
+	    Enumeration e = zipfile.entries(); 
+	    while (e.hasMoreElements()) {
+		ZipEntry zipentry = (ZipEntry) e.nextElement();
+		String zentryname = col_dir + zipentry.getName();
+		Gatherer.println("    Unzipping: " + zentryname);
+
+		if (zipentry.isDirectory()) {
+		    // Create named directory
+		    boolean success = (new File(zentryname)).mkdir();
+		    if (!success) {
+			System.err.println("Error: unable to create directory '"+zentryname+"'");
+		    }
+		}
+		else {
+		    // Write out file to disk
+
+		    // set up input stream
+		    InputStream zis = zipfile.getInputStream(zipentry); 
+		    BufferedInputStream bzis = new BufferedInputStream(zis); 
+		    DataInputStream dbzis = new DataInputStream(bzis);
+		    
+		    // set up output stream
+		    FileOutputStream fzos = new FileOutputStream(zentryname);
+		    BufferedOutputStream bfzos = new BufferedOutputStream(fzos);
+		    
+		    byte[] buf = new byte[1024];
+		    int len;
+		    while ((len = dbzis.read(buf)) >= 0) {
+			bfzos.write(buf,0,len);
+		    }
+		    
+		    dbzis.close();
+		    bfzos.close();
+		}
+	    }
+	} 
+	catch (ZipException error) {
+	    System.err.println("Error: Unable to open '"+zip_fname+"'");
+	    Gatherer.printStackTrace(error);
+	}
+
+	catch (Exception error) {
+	    error.printStackTrace();
+	}
+    }
+
+
+
+
+
+    /* static private File getRecycleDirectory() {
+	return new File(RECYCLE);
+	} */
 
 
@@ -797,10 +1269,22 @@
 	if(use_classloader) {
 	    try {
-		URL url = ClassLoader.getSystemResource(filename);
-		file = new File(URLDecoder.decode(url.getFile(), ENCODING));
-		url = null;
+		// **** 
+		// URL url = ClassLoader.getSystemResource(filename);
+		// URL url = base.getResource("/"+filename);
+		System.err.println("*** looking for resource as stream: " + filename);
+		InputStream is = base.getResourceAsStream("/"+filename);
+
+		// file = new File(URLDecoder.decode(url.getFile(), ENCODING));
+		// url = null;
+
+		//FileInputStream fis   = new FileInputStream(file);		
+		return parse(is,true);
 	    }
 	    catch (Exception error) {
 		// Most likely file name.
+		/* String prefix = "";
+		if (!filename.startsWith("/")) {
+		    prefix = "/research/code/gsdl/gli/";
+		    }*/
 		file = new File("classes" + File.separator + filename);
 		//Gatherer.printStackTrace(error);
@@ -812,14 +1296,63 @@
 	return parse(file, true);
     }
+
     /** Parse in a xml document from a given file. */
     static public Document parse(File file) {
 	return parse(file, true);
     }
+
     /** Parse in a xml document from a given file. */
-    static public Document parse(File file, boolean noisey) {
+    static public Document parse(File file, boolean noisey) 
+    {
 	Document document = null;
 	try {
+	    System.err.println("file = " + file);
 	    FileInputStream fis   = new FileInputStream(file);
-	    InputStreamReader isr = new InputStreamReader(fis, ENCODING);
+	    document = parse(fis,noisey);
+	    file = null;
+	}
+	catch (Exception error) {
+	    if(noisey) {
+		error.printStackTrace();
+		Gatherer.println("Exception in Utility.parse() - Unexpected");
+	    }
+	    else {
+		Gatherer.println("Exception in Utility.parse() - Expected");
+		Gatherer.printStackTrace(error);
+	    }
+	}
+
+	return document;
+    }
+
+    /** Parse in a xml document from a given URL. */
+    static public Document parse(URL url, boolean noisey) 
+    {
+	Document document = null;
+	try {
+	    
+	    URLConnection connection = url.openConnection();
+	    InputStream is = connection.getInputStream();
+	    document = parse(is,noisey);
+	}
+	catch (Exception error) {
+	    if(noisey) {
+		error.printStackTrace();
+		Gatherer.println("Exception in Utility.parse() - Unexpected");
+	    }
+	    else {
+		Gatherer.println("Exception in Utility.parse() - Expected");
+		Gatherer.printStackTrace(error);
+	    }
+	}
+
+	return document;
+    }
+
+    /** Parse in a xml document from a given file. */
+    static public Document parse(InputStream is, boolean noisey) {
+	Document document = null;
+	try {
+	    InputStreamReader isr = new InputStreamReader(is, ENCODING);
 	    Reader r              = new BufferedReader(isr);
 	    InputSource isc       = new InputSource(r);
@@ -833,11 +1366,10 @@
 	    document = parser.getDocument();
 	    isr.close();
-	    fis.close();
+	    is.close();
 	    parser = null;
 	    isc = null;
 	    r = null;
 	    isr = null;
-	    fis = null;
-	    file = null;
+	    is = null;
 	}
 	catch (Exception error) {
