Index: /gli/branches/rtl-gli/src/org/greenstone/gatherer/remote/ActionQueue.java
===================================================================
--- /gli/branches/rtl-gli/src/org/greenstone/gatherer/remote/ActionQueue.java	(revision 18361)
+++ /gli/branches/rtl-gli/src/org/greenstone/gatherer/remote/ActionQueue.java	(revision 18361)
@@ -0,0 +1,192 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Greenstone Librarian Interface application, part of 
+ * the Greenstone digital library suite from the New Zealand Digital 
+ * Library Project at the University of Waikato, New Zealand.
+ *
+ * Author: Michael Dewsnip, NZDL Project, University of Waikato
+ *
+ * Copyright (C) 2005 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+
+package org.greenstone.gatherer.remote;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+import java.util.zip.*;
+import javax.swing.*;
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.DebugStream;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.FedoraInfo;
+import org.greenstone.gatherer.GAuthenticator;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.collection.CollectionManager;
+import org.greenstone.gatherer.shell.GShell;
+import org.greenstone.gatherer.util.UnzipTools;
+import org.greenstone.gatherer.util.Utility;
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.methods.PostMethod;
+import org.apache.commons.httpclient.methods.GetMethod;
+import org.apache.commons.httpclient.HttpException;
+import org.apache.commons.httpclient.methods.multipart.FilePart;
+import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity;
+import org.apache.commons.httpclient.methods.multipart.Part;
+import org.apache.commons.httpclient.methods.multipart.*;
+import org.apache.commons.httpclient.params.*;
+import org.apache.commons.httpclient.HttpStatus;
+
+// ----------------------------------------------------------------------------------------------------
+//   Part of the RemoteGreenstoneServer's QUEUE LAYER
+// ----------------------------------------------------------------------------------------------------
+
+// Moved here. Previously called RemoteGreenstoneServerActionQueue
+/** 
+ * A Thread that maintains a queue of RemoteGreenstoneServer Actions
+ * that are to be executed in FIFO fashion.
+*/
+class ActionQueue extends Thread
+{
+    /** The queue of waiting jobs. */
+    private ArrayList queue = null;
+    private boolean exited;
+
+    public ActionQueue()
+    {
+	super("RemoteGreenstoneServerActionQueue");
+	exited = false;
+	if (Gatherer.isGsdlRemote) {
+	    queue = new ArrayList();
+	    start();
+	}
+    }
+    
+    
+    synchronized public void addAction(RemoteGreenstoneServerAction remote_greenstone_server_action)
+    {
+	queue.add(remote_greenstone_server_action);
+	notifyAll();
+    }
+    
+    
+    synchronized public int size()
+    {
+	return queue.size();
+    }
+    
+    synchronized public RemoteGreenstoneServerAction getAction(int i)
+    {
+	return (RemoteGreenstoneServerAction)queue.get(i);
+    }
+
+    synchronized public boolean hasExited() { 
+	return exited; 
+    }
+    
+    synchronized public void clear() { 
+	queue.clear(); 
+    }
+
+    public void run()
+    {
+	boolean exit = false;
+
+	while (!exit) {
+	    RemoteGreenstoneServerAction remote_greenstone_server_action = null;
+	    
+	    // Wait until we are notify()ed by addAction that there is a new job on the queue
+	    try {
+		Gatherer.remoteGreenstoneServer.getProgressBar().setAction(null);
+		synchronized (this) {
+		    while(queue.size() <= 0) {
+			wait(); // wait for queue size to become > 0, which is done by external thread (performAction())
+		    }
+		    // Now there is at least one job on the queue, get the next in line and process it
+		    remote_greenstone_server_action = (RemoteGreenstoneServerAction) queue.get(0); //getAction(0) is already synchronized 
+		}
+	    } catch (InterruptedException exception) {
+		// It may be that GLI is exiting if we get here 
+		exit = true;
+	    }
+	    
+	    if(exit) {
+		break;
+	    }
+	    
+	    try {
+		remote_greenstone_server_action.perform();
+		
+		// No exceptions were thrown, so the action was successful
+		remote_greenstone_server_action.processed_successfully = true;
+	    }
+	    catch (RemoteGreenstoneServerAction.ActionCancelledException exception) {
+		remote_greenstone_server_action.processed_successfully = false;
+	    } 
+	    catch(java.net.ConnectException exception) {
+		if(exception.getMessage().trim().startsWith("Connection refused")) {
+		    exit = true;
+		} else {
+		    DebugStream.printStackTrace(exception);
+		}
+		JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("RemoteGreenstoneServer.Error", exception.getMessage()), Dictionary.get("RemoteGreenstoneServer.Error_Title"), JOptionPane.ERROR_MESSAGE);
+		remote_greenstone_server_action.processed_successfully = false;			
+	    }
+	    catch (FileNotFoundException exception) {
+		// FileNotFoundException happens when there's no GS server at the user-provided
+		// url (the address of gliserver.pl is wrong).
+		exit = true;
+		DebugStream.printStackTrace(exception);
+		JOptionPane.showMessageDialog(Gatherer.g_man, 
+					      Dictionary.get("RemoteGreenstoneServer.Error", 
+							     "No gliserver.pl found. " + exception.getMessage()), 
+					      Dictionary.get("RemoteGreenstoneServer.Error_Title"), 
+					      JOptionPane.ERROR_MESSAGE);
+		remote_greenstone_server_action.processed_successfully = false;
+	    }
+	    catch (Exception exception) {
+		DebugStream.printStackTrace(exception);
+		JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("RemoteGreenstoneServer.Error", exception.getMessage()), Dictionary.get("RemoteGreenstoneServer.Error_Title"), JOptionPane.ERROR_MESSAGE);
+		remote_greenstone_server_action.processed_successfully = false;
+	    }
+	    
+	    // We're done with this action, for better or worse
+	    try {
+		remote_greenstone_server_action.processed = true;
+		synchronized(remote_greenstone_server_action) {
+		    remote_greenstone_server_action.notifyAll(); // notifies RemoteGreenstoneServer.performAction()
+		}
+	    } catch (Exception exception) {
+		System.err.println("RemoteGreenstoneServerActionQueue.run() - exception: " + exception);
+	    }
+	    synchronized (this) { // remove the action just processed from the queue, since it's done.
+		queue.remove(0);
+	    }
+	}
+
+	// Out of while, means exit = true
+	// Stop the gazillion annoying error messages when the connection was simply
+	// refused or when the user pressed Cancel in the opening dialog, by clearing
+	// the action queue of subsequent actions and setting exited to true.
+	synchronized(this) {
+	    queue.clear();
+	    exited = true;
+	}
+    }
+}
Index: /gli/branches/rtl-gli/src/org/greenstone/gatherer/remote/RemoteGreenstoneServer.java
===================================================================
--- /gli/branches/rtl-gli/src/org/greenstone/gatherer/remote/RemoteGreenstoneServer.java	(revision 18360)
+++ /gli/branches/rtl-gli/src/org/greenstone/gatherer/remote/RemoteGreenstoneServer.java	(revision 18361)
@@ -37,4 +37,5 @@
 import org.greenstone.gatherer.DebugStream;
 import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.FedoraInfo;
 import org.greenstone.gatherer.GAuthenticator;
 import org.greenstone.gatherer.Gatherer;
@@ -54,103 +55,167 @@
 import org.apache.commons.httpclient.HttpStatus;
 
+
 public class RemoteGreenstoneServer
 {
+    // A PasswordAuthentication object is created whenever it is required
+    static private PasswordAuthentication remote_greenstone_server_authentication = null;
+    // static private PasswordAuthentication remote_greenstone_server_authentication = new PasswordAuthentication(System.getProperty("user.name"), new char[] { });
+
+    private ActionQueue remote_greenstone_server_action_queue;
+    private RemoteGreenstoneServer.ProgressBar progress_bar;
+
+    public RemoteGreenstoneServer() {
+	// Create the progress_bar first since ActionQueue uses it in its thread 
+	// (the thread will start immediately).
+	progress_bar = new RemoteGreenstoneServer.ProgressBar();
+	remote_greenstone_server_action_queue = new ActionQueue();
+    }
+
     // ----------------------------------------------------------------------------------------------------
     //   PUBLIC LAYER
     // ----------------------------------------------------------------------------------------------------
-
-
-    static public String deleteCollection(String collection_name)
-    {
-	return performAction(new RemoteGreenstoneServerDeleteCollectionAction(collection_name));
-    }
-
-
-    static public String deleteCollectionFile(String collection_name, File collection_file)
-    {
-	return performAction(new RemoteGreenstoneServerDeleteCollectionFileAction(collection_name, collection_file));
-    }
-
-
-    static public String downloadCollection(String collection_name)
-    {
-	return performAction(new RemoteGreenstoneServerDownloadCollectionAction(collection_name));
-    }
-
-
-    static public String downloadCollectionArchives(String collection_name)
-    {
-	return performAction(new RemoteGreenstoneServerDownloadCollectionArchivesAction(collection_name));
-    }
-
-
-    static public String downloadCollectionConfigurations()
-    {
-	return performAction(new RemoteGreenstoneServerDownloadCollectionConfigurationsAction());
-    }
-
-
-    static public String downloadCollectionFile(String collection_name, File collection_file)
-    {
-	return performAction(new RemoteGreenstoneServerDownloadCollectionFileAction(collection_name, collection_file));
+    public String deleteCollection(String collection_name)
+    {
+	return performAction(new RemoteGreenstoneServerAction.DeleteCollectionAction(collection_name));
+    }
+
+
+    public String deleteCollectionFile(String collection_name, File collection_file)
+    {
+	return performAction(new RemoteGreenstoneServerAction.DeleteCollectionFileAction(collection_name, collection_file));
+    }
+
+
+    public String downloadCollection(String collection_name)
+    {
+	return performAction(new RemoteGreenstoneServerAction.DownloadCollectionAction(collection_name));
+    }
+
+
+    public String downloadCollectionArchives(String collection_name)
+    {
+	return performAction(new RemoteGreenstoneServerAction.DownloadCollectionArchivesAction(collection_name));
+    }
+
+
+    public String downloadCollectionConfigurations()
+    {
+	return performAction(new RemoteGreenstoneServerAction.DownloadCollectionConfigurationsAction());
+    }
+
+
+    public String downloadCollectionFile(String collection_name, File collection_file)
+    {
+	return performAction(new RemoteGreenstoneServerAction.DownloadCollectionFileAction(collection_name, collection_file));
     }
     
     // get web.xml from the server -- for a remote gli of GS3
-    static public String downloadWebXMLFile()
-    {
-	return performAction(new RemoteGreenstoneServerDownloadWebXMLFileAction());
-    }
-
-    static public String getScriptOptions(String script_name, String script_arguments)
-    {
-	return performAction(new RemoteGreenstoneServerGetScriptOptionsAction(script_name, script_arguments));
+    public String downloadWebXMLFile()
+    {
+	return performAction(new RemoteGreenstoneServerAction.DownloadWebXMLFileAction());
+    }
+
+    public String getScriptOptions(String script_name, String script_arguments)
+    {
+	return performAction(new RemoteGreenstoneServerAction.GetScriptOptionsAction(script_name, script_arguments));
     }
     
     //get all available site names from the server -- for a remote gli of GS3
-    static public String getSiteNames()
-    {
-	return performAction(new RemoteGreenstoneServerGetSiteNamesAction());
-    }
-
-    static public String moveCollectionFile(String collection_name, File source_collection_file, File target_collection_file)
-    {
-	return performAction(new RemoteGreenstoneServerMoveCollectionFileAction(collection_name, source_collection_file, target_collection_file));
-    }
-
-
-    static public String newCollectionDirectory(String collection_name, File new_collection_directory)
-    {
-	return performAction(new RemoteGreenstoneServerNewCollectionDirectoryAction(collection_name, new_collection_directory));
-    }
-
-
-    static public String runScript(String collection_name, String script_name, String script_arguments, GShell shell)
-    {
-	return performAction(new RemoteGreenstoneServerRunScriptAction(collection_name, script_name, script_arguments, shell));
-    }
-
-
-    static public String uploadCollectionFile(String collection_name, File collection_file)
-    {
-	return performAction(new RemoteGreenstoneServerUploadCollectionFilesAction(collection_name, new File[] { collection_file }));
-    }
-
-
-    static public String uploadCollectionFiles(String collection_name, File[] collection_files)
-    {
-	return performAction(new RemoteGreenstoneServerUploadCollectionFilesAction(collection_name, collection_files));
-    }
-
-
-    static public String uploadFilesIntoCollection(String collection_name, File[] source_files, File target_collection_directory)
-    {
-	return performAction(new RemoteGreenstoneServerUploadFilesIntoCollectionAction(collection_name, source_files, target_collection_directory));
-    }
-
-
-    // ----------------------------------------------------------------------------------------------------
-
-
-    static public void exit()
+    public String getSiteNames()
+    {
+	return performAction(new RemoteGreenstoneServerAction.GetSiteNamesAction());
+    }
+
+    public String moveCollectionFile(String collection_name, File source_collection_file, File target_collection_file)
+    {
+	return performAction(new RemoteGreenstoneServerAction.MoveCollectionFileAction(
+                             collection_name, source_collection_file, target_collection_file));
+    }
+
+
+    public String newCollectionDirectory(String collection_name, File new_collection_directory)
+    {
+	return performAction(new RemoteGreenstoneServerAction.NewCollectionDirectoryAction(
+                             collection_name, new_collection_directory));
+    }
+
+
+    public String runScript(String collection_name, String script_name, String script_arguments, GShell shell)
+    {
+	return performAction(new RemoteGreenstoneServerAction.RunScriptAction(
+                             collection_name, script_name, script_arguments, shell));
+    }
+
+
+    public String uploadCollectionFile(String collection_name, File collection_file)
+    {
+	return performAction(new RemoteGreenstoneServerAction.UploadCollectionFilesAction(
+                             collection_name, new File[] { collection_file }));
+    }
+
+
+    public String uploadCollectionFiles(String collection_name, File[] collection_files)
+    {
+	return performAction(new RemoteGreenstoneServerAction.UploadCollectionFilesAction(collection_name, collection_files));
+    }
+
+
+    public String uploadFilesIntoCollection(String collection_name, File[] source_files, File target_collection_directory)
+    {
+	return performAction(new RemoteGreenstoneServerAction.UploadFilesIntoCollectionAction(
+                             collection_name, source_files, target_collection_directory));
+    }
+
+    public boolean exists(String collection_name, File collection_file)
+    {
+	String result = performAction(new RemoteGreenstoneServerAction.ExistsAction(collection_name, collection_file));
+	if(result.indexOf("exists") != -1) {
+	    return true;
+	}
+	else if(result.indexOf("does not exist") != -1) {
+	    return false;
+	}
+	return false;
+    }
+
+    public int getGreenstoneVersion()
+    {
+	// returns message "Greenstone version is: <version number of the Greenstone remote server>"
+	String result = performAction(new RemoteGreenstoneServerAction.VersionAction());
+	int index = result.indexOf(":"); 
+	if(index != -1) {
+	    result = result.substring(index+1).trim(); // skip the space after colon, must remove surrounding spaces
+	}
+	int greenstoneVersion = Integer.parseInt(result);
+	return greenstoneVersion;
+    }
+
+    /** For constructing the preview command (the library URL) with */
+    public String getLibraryURL(String serverHomeURL)
+    {
+	// returns message "Greenstone library URL suffix is: <e.g. /greenstone3/library or /gsdl/cgi-bin/library>"
+	String libSuffix = performAction(new RemoteGreenstoneServerAction.LibraryURLSuffixAction());
+	int index = libSuffix.indexOf(":"); 
+	if(index != -1) {
+	    libSuffix = libSuffix.substring(index+1).trim(); // skip the space after colon and remove surrounding spaces
+	}
+	
+	// serverHomeURL is of the form, http://domain/other/stuff. We want the prefix upto & including domain
+	// and prepend that to the libraryURLSuffix
+	index = -1;
+	for(int i = 0; i < 3; i++) {
+	    index = serverHomeURL.indexOf("/", index+1);
+	    if(index == -1) { // shouldn't happen, but if it does, we'll be in an infinite loop
+		break; 
+	    }
+	}
+	serverHomeURL = serverHomeURL.substring(0, index);
+	return serverHomeURL + libSuffix;
+    }
+
+    // ----------------------------------------------------------------------------------------------------
+
+
+    public void exit()
     {
 	System.err.println("Exiting, number of jobs on queue: " + remote_greenstone_server_action_queue.size());
@@ -167,5 +232,5 @@
 	}
     }
-
+    
 
     // ----------------------------------------------------------------------------------------------------
@@ -175,25 +240,40 @@
 
     /** Returns null if we cannot wait for the action to finish, "" if the action failed, or the action output. */
-    static private String performAction(RemoteGreenstoneServerAction remote_greenstone_server_action)
-    {
+    private String performAction(RemoteGreenstoneServerAction remote_greenstone_server_action)
+    {
+	// Check for whether the queue thread stopped running because 
+	// the user cancelled out. If so, exit GLI.
+	if(remote_greenstone_server_action_queue.hasExited()) {
+	    remote_greenstone_server_action_queue.clear();
+	    //remote_greenstone_server_action_queue = null;
+	    Gatherer.exit();
+	    return "";
+	}
+
 	// Add the action to the queue
 	remote_greenstone_server_action_queue.addAction(remote_greenstone_server_action);
+	String threadName = Thread.currentThread().getName();
 
 	// If we're running in the GUI thread we must return immediately
 	// We cannot wait for the action to complete because this will block any GUI updates
 	if (SwingUtilities.isEventDispatchThread()) {
-	    System.err.println("WARNING: In event dispatch thread, returning immediately...");
+	    System.err.println(threadName 
+			       + "\tACTION QUEUED: In event dispatch thread, returning immediately...\n\t" 
+			       + remote_greenstone_server_action);
 	    return null;
 	}
 
 	// Otherwise wait until the action is processed
-	while (!remote_greenstone_server_action.processed) {
+	try {
 	    synchronized (remote_greenstone_server_action) {
-		try {
+		while(!remote_greenstone_server_action.processed) {
+		    //System.err.println("Waiting for action to complete...: " + remote_greenstone_server_action);
 		    DebugStream.println("Waiting for action to complete...");
-		    remote_greenstone_server_action.wait(500);
+		    remote_greenstone_server_action.wait(); // wait to be notified when the action has been processed 
 		}
-		catch (InterruptedException exception) {}
-	    }
+	    }
+	} catch (Exception e) {
+	    System.err.println("RemoteGreenstoneServer.performAction() - exception: " + e);
+	    e.printStackTrace();
 	}
 
@@ -207,92 +287,12 @@
 
 
-    static private RemoteGreenstoneServerActionQueue remote_greenstone_server_action_queue = new RemoteGreenstoneServerActionQueue();
-
-
-    static private class RemoteGreenstoneServerActionQueue
-	extends Thread
-    {
-	/** The queue of waiting jobs. */
-	private ArrayList queue = null;
-
-
-	public RemoteGreenstoneServerActionQueue()
-	{
-	    if (Gatherer.isGsdlRemote) {
-		queue = new ArrayList();
-		start();
-	    }
-	}
-
-
-	synchronized public void addAction(RemoteGreenstoneServerAction remote_greenstone_server_action)
-	{
-	    queue.add(remote_greenstone_server_action);
-	    notifyAll();
-	}
-
-
-	public int size()
-	{
-	    return queue.size();
-	}
-
-
-	public void run()
-	{
-	    while (true) {
-		// If there are jobs on the queue, get the next in line and process it
-		if (queue.size() > 0) {
-		    RemoteGreenstoneServerAction remote_greenstone_server_action = (RemoteGreenstoneServerAction) queue.get(0);
-
-		    try {
-			remote_greenstone_server_action.perform();
-
-			// No exceptions were thrown, so the action was successful
-			remote_greenstone_server_action.processed_successfully = true;
-		    }
-		    catch (RemoteGreenstoneServerActionCancelledException exception) {
-			remote_greenstone_server_action.processed_successfully = false;
-		    }
-		    catch (Exception exception) {
-			DebugStream.printStackTrace(exception);
-			JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("RemoteGreenstoneServer.Error", exception.getMessage()), Dictionary.get("RemoteGreenstoneServer.Error_Title"), JOptionPane.ERROR_MESSAGE);
-			remote_greenstone_server_action.processed_successfully = false;
-		    }
-
-		    // We're done with this action, for better or worse
-		    remote_greenstone_server_action.processed = true;
-		    queue.remove(0);
-		}
-
-		// Otherwise the queue is empty
-		else {
-		    progress_bar.setAction(null);
-
-		    // Wait until we are notify()ed by addAction that there is a new job on the queue
-		    synchronized (this) {
-			try {
-			    wait();
-			}
-			catch (InterruptedException exception) { }
-		    }
-		}
-	    }
-	}
-    }
-
-
     // ----------------------------------------------------------------------------------------------------
     //   PROGRESS BAR
     // ----------------------------------------------------------------------------------------------------
 
-
-    static private RemoteGreenstoneServerProgressBar progress_bar = new RemoteGreenstoneServerProgressBar();
-
-
-    static private class RemoteGreenstoneServerProgressBar
+    static class ProgressBar
 	extends JProgressBar
     {
-	public RemoteGreenstoneServerProgressBar()
+	public ProgressBar()
 	{
 	    setBackground(Configuration.getColor("coloring.collection_tree_background", false));
@@ -302,6 +302,6 @@
 	}
 
-
-	public void setAction(String action)
+	/** synchronized to avoid conflicts since several threads access this */
+	synchronized public void setAction(String action)
 	{
 	    if (action != null) {
@@ -326,7 +326,7 @@
 	}
     }
-
-
-    static public RemoteGreenstoneServerProgressBar getProgressBar()
+    
+    /** synchronized to avoid conflicts since several threads access this */
+    synchronized public RemoteGreenstoneServer.ProgressBar getProgressBar()
     {
 	return progress_bar;
@@ -335,517 +335,6 @@
 
     // ----------------------------------------------------------------------------------------------------
-    //   ACTIONS
-    // ----------------------------------------------------------------------------------------------------
-
-
-    static private abstract class RemoteGreenstoneServerAction
-    {
-	public String action_output = null;
-	public boolean processed = false;
-	public boolean processed_successfully;
-
-	abstract public void perform()
-	    throws Exception;
-    }
-
-
-    static private class RemoteGreenstoneServerActionCancelledException
-	extends Exception
-    {
-    }
-
-
-    /**
-     * --------------------------------------------------------------------------------------------
-     *    DELETE COLLECTION
-     * --------------------------------------------------------------------------------------------
-     */
-    static private class RemoteGreenstoneServerDeleteCollectionAction
-	extends RemoteGreenstoneServerAction
-    {
-	private String collection_name;
-
-	public RemoteGreenstoneServerDeleteCollectionAction(String collection_name)
-	{
-	    this.collection_name = collection_name;
-	}
-
-	public void perform()
-	    throws Exception
-	{
-	    progress_bar.setAction("Deleting collection " + collection_name + "...");
-
-	    String delete_collection_command = "cmd=delete-collection";
-	    delete_collection_command += "&c=" + URLEncoder.encode(collection_name, "UTF-8");
-	    action_output = sendCommandToServer(delete_collection_command, null);
-	}
-    }
-
-
-    /**
-     * --------------------------------------------------------------------------------------------
-     *    DELETE COLLECTION FILE
-     * --------------------------------------------------------------------------------------------
-     */
-    static private class RemoteGreenstoneServerDeleteCollectionFileAction
-	extends RemoteGreenstoneServerAction
-    {
-	private String collection_name;
-	private File collection_file;
-
-	public RemoteGreenstoneServerDeleteCollectionFileAction(String collection_name, File collection_file)
-	{
-	    this.collection_name = collection_name;
-	    this.collection_file = collection_file;
-	}
-
-	public void perform()
-	    throws Exception
-	{
-	    String collection_directory_path = CollectionManager.getCollectionDirectoryPath(collection_name);
-	    String collection_file_relative_path = getPathRelativeToDirectory(collection_file, collection_directory_path);
-	    collection_file_relative_path = collection_file_relative_path.replaceAll((Utility.isWindows() ? "\\\\" : "\\/"), "|");
-	    progress_bar.setAction("Deleting collection file " + collection_file_relative_path + "...");
-
-	    String delete_collection_file_command = "cmd=delete-collection-file";
-	    delete_collection_file_command += "&c=" + URLEncoder.encode(collection_name, "UTF-8");
-	    delete_collection_file_command += "&file=" + URLEncoder.encode(collection_file_relative_path, "UTF-8");
-	    action_output = sendCommandToServer(delete_collection_file_command, null);
-	}
-    }
-
-
-    /**
-     * --------------------------------------------------------------------------------------------
-     *    DOWNLOAD COLLECTION
-     * --------------------------------------------------------------------------------------------
-     */
-    static private class RemoteGreenstoneServerDownloadCollectionAction
-	extends RemoteGreenstoneServerAction
-    {
-	private String collection_name;
-
-	public RemoteGreenstoneServerDownloadCollectionAction(String collection_name)
-	{
-	    this.collection_name = collection_name;
-	}
-
-	public void perform()
-	    throws Exception
-	{
-	    progress_bar.setAction("Downloading remote collection " + collection_name + "...");
-
-	    String download_collection_command = "cmd=download-collection";
-	    download_collection_command += "&c=" + URLEncoder.encode(collection_name, "UTF-8");
-	    String zip_file_path = Gatherer.getCollectDirectoryPath() + collection_name + ".zip";
-	    action_output = downloadFile(download_collection_command, zip_file_path);
-
-	    // Delete the existing (local) collection directory
-	    Utility.delete(new File(CollectionManager.getCollectionDirectoryPath(collection_name)));
-
-	    // Unzip the collection just downloaded
-	    UnzipTools.unzipFile(zip_file_path, Gatherer.getCollectDirectoryPath());
-	}
-    }
-
-
-    /**
-     * --------------------------------------------------------------------------------------------
-     *    DOWNLOAD COLLECTION ARCHIVES
-     * --------------------------------------------------------------------------------------------
-     */
-    static private class RemoteGreenstoneServerDownloadCollectionArchivesAction
-	extends RemoteGreenstoneServerAction
-    {
-	private String collection_name;
-
-	public RemoteGreenstoneServerDownloadCollectionArchivesAction(String collection_name)
-	{
-	    this.collection_name = collection_name;
-	}
-
-	public void perform()
-	    throws Exception
-	{
-	    progress_bar.setAction("Downloading collection archives for " + collection_name + "...");
-
-	    String download_collection_archives_command = "cmd=download-collection-archives";
-	    download_collection_archives_command += "&c=" + URLEncoder.encode(collection_name, "UTF-8");
-	    String zip_file_path = Gatherer.getCollectDirectoryPath() + collection_name + "-archives.zip";
-	    action_output = downloadFile(download_collection_archives_command, zip_file_path);
-
-	    // Delete the existing (local) collection archives
-	    Utility.delete(new File(CollectionManager.getLoadedCollectionArchivesDirectoryPath()));
-
-	    // Unzip the collection archives just downloaded
-	    UnzipTools.unzipFile(zip_file_path, Gatherer.getCollectDirectoryPath());
-	}
-    }
-
-
-    /**
-     * --------------------------------------------------------------------------------------------
-     *    DOWNLOAD COLLECTION CONFIGURATIONS
-     * --------------------------------------------------------------------------------------------
-     */
-    static private class RemoteGreenstoneServerDownloadCollectionConfigurationsAction
-	extends RemoteGreenstoneServerAction
-    {
-	public RemoteGreenstoneServerDownloadCollectionConfigurationsAction()
-	{
-	}
-
-	public void perform()
-	    throws Exception
-	{
-	    progress_bar.setAction("Downloading collection configurations...");
-
-	    // Delete the existing (local) collect directory
-	    Utility.delete(new File(Gatherer.getCollectDirectoryPath()));
-	    new File(Gatherer.getCollectDirectoryPath()).mkdirs();
-
-	    String download_collection_configurations_command = "cmd=download-collection-configurations";
-	    String zip_file_path = Gatherer.getCollectDirectoryPath() + "collections.zip";
-	    action_output = downloadFile(download_collection_configurations_command, zip_file_path);
-
-	    // Unzip the collection configurations just downloaded
-	    UnzipTools.unzipFile(zip_file_path, Gatherer.getCollectDirectoryPath());
-	}
-    }
-
-
-    /**
-     * --------------------------------------------------------------------------------------------
-     *    DOWNLOAD COLLECTION FILE
-     * --------------------------------------------------------------------------------------------
-     */
-    static private class RemoteGreenstoneServerDownloadCollectionFileAction
-	extends RemoteGreenstoneServerAction
-    {
-	private String collection_name;
-	private File collection_file;
-
-	public RemoteGreenstoneServerDownloadCollectionFileAction(String collection_name, File collection_file)
-	{
-	    this.collection_name = collection_name;
-	    this.collection_file = collection_file;
-	}
-
-	public void perform()
-	    throws Exception
-	{
-	    String collection_directory_path = CollectionManager.getCollectionDirectoryPath(collection_name);
-	    String collection_file_relative_path = getPathRelativeToDirectory(collection_file, collection_directory_path);
-	    collection_file_relative_path = collection_file_relative_path.replaceAll((Utility.isWindows() ? "\\\\" : "\\/"), "|");
-	    progress_bar.setAction("Downloading collection file " + collection_file_relative_path + "...");
-
-	    String download_collection_file_command = "cmd=download-collection-file";
-	    download_collection_file_command += "&c=" + URLEncoder.encode(collection_name, "UTF-8");
-	    download_collection_file_command += "&file=" + URLEncoder.encode(collection_file_relative_path, "UTF-8");
-	    String zip_file_name = collection_name + "-" + collection_file.getName() + ".zip";
-	    String zip_file_path = collection_directory_path + zip_file_name;
-	    action_output = downloadFile(download_collection_file_command, zip_file_path);
-
-	    // Unzip the collection file just downloaded
-	    UnzipTools.unzipFile(zip_file_path, collection_directory_path);
-	}
-    }
-
-    /**
-     * --------------------------------------------------------------------------------------------
-     *    DOWNLOAD web.xml FILE --for a remote GS3
-     * --------------------------------------------------------------------------------------------
-     */
-    static private class RemoteGreenstoneServerDownloadWebXMLFileAction
-	extends RemoteGreenstoneServerAction
-    {
-	public RemoteGreenstoneServerDownloadWebXMLFileAction()
-	{}
-
-	public void perform()
-	    throws Exception
-	{
-	    String web_xml_directory_path=(Configuration.gli_user_directory_path);
-	    String download_web_xml_file_command = "cmd=download-web-xml-file";
-	    download_web_xml_file_command += "&file=" + URLEncoder.encode("web.xml", "UTF-8");
-	    String zip_file_name = "web-xml.zip";
-	    String zip_file_path = web_xml_directory_path + zip_file_name;
-	    action_output = downloadFile(download_web_xml_file_command, zip_file_path);
-
-	    // Unzip the web.xml file just downloaded
-	    UnzipTools.unzipFile(zip_file_path,web_xml_directory_path);
-	}
-    }
-
-    /**
-     * --------------------------------------------------------------------------------------------
-     *    GET SCRIPT OPTIONS
-     * --------------------------------------------------------------------------------------------
-     */
-    static private class RemoteGreenstoneServerGetScriptOptionsAction
-	extends RemoteGreenstoneServerAction
-    {
-	private String script_name;
-	private String script_arguments;
-
-	public RemoteGreenstoneServerGetScriptOptionsAction(String script_name, String script_arguments)
-	{
-	    this.script_name = script_name;
-	    this.script_arguments = script_arguments;
-	}
-
-	public void perform()
-	    throws Exception
-	{
-	    progress_bar.setAction("Getting options for " + script_name + "...");
-
-	    String get_script_options_command = "cmd=get-script-options";
-	    get_script_options_command += "&script=" + script_name;
-	    get_script_options_command += "&xml=";
-	    get_script_options_command += "&language=" + Configuration.getLanguage();
-	    get_script_options_command += script_arguments;
-	    action_output = sendCommandToServer(get_script_options_command, null);
-	}
-    }
-
-    /**
-     * --------------------------------------------------------------------------------------------
-     *    GET ALL NAMES OF SITES // for a remote GS3 
-     * --------------------------------------------------------------------------------------------
-     */
-    static private class RemoteGreenstoneServerGetSiteNamesAction
-	extends RemoteGreenstoneServerAction
-    {
-	public RemoteGreenstoneServerGetSiteNamesAction()
-	{}
-
-	public void perform()
-	    throws Exception
-	{
-	    progress_bar.setAction("Getting names of sites ...");
-
-	    String get_script_options_command = "cmd=get-site-names";
-	    action_output = sendCommandToServer(get_script_options_command, null);
-	}
-    }
-
-    /**
-     * --------------------------------------------------------------------------------------------
-     *    MOVE COLLECTION FILE
-     * --------------------------------------------------------------------------------------------
-     */
-    static private class RemoteGreenstoneServerMoveCollectionFileAction
-	extends RemoteGreenstoneServerAction
-    {
-	private String collection_name;
-	private File source_collection_file;
-	private File target_collection_file;
-
-	public RemoteGreenstoneServerMoveCollectionFileAction(String collection_name, File source_collection_file, File target_collection_file)
-	{
-	    this.collection_name = collection_name;
-	    this.source_collection_file = source_collection_file;
-	    this.target_collection_file = target_collection_file;
-	}
-
-	public void perform()
-	    throws Exception
-	{
-	    String collection_directory_path = CollectionManager.getCollectionDirectoryPath(collection_name);
-	    String source_collection_file_relative_path = getPathRelativeToDirectory(source_collection_file, collection_directory_path);
-	    source_collection_file_relative_path = source_collection_file_relative_path.replaceAll((Utility.isWindows() ? "\\\\" : "\\/"), "|");
-	    String target_collection_file_relative_path = getPathRelativeToDirectory(target_collection_file, collection_directory_path);
-	    target_collection_file_relative_path = target_collection_file_relative_path.replaceAll((Utility.isWindows() ? "\\\\" : "\\/"), "|");
-	    progress_bar.setAction("Moving file " + source_collection_file_relative_path + " -> " + target_collection_file_relative_path + "...");
-
-	    String move_collection_file_command = "cmd=move-collection-file";
-	    move_collection_file_command += "&c=" + URLEncoder.encode(collection_name, "UTF-8");
-	    move_collection_file_command += "&source=" + URLEncoder.encode(source_collection_file_relative_path, "UTF-8");
-	    move_collection_file_command += "&target=" + URLEncoder.encode(target_collection_file_relative_path, "UTF-8");
-	    action_output = sendCommandToServer(move_collection_file_command, null);
-	}
-    }
-
-
-    /**
-     * --------------------------------------------------------------------------------------------
-     *    NEW COLLECTION DIRECTORY
-     * --------------------------------------------------------------------------------------------
-     */
-    static private class RemoteGreenstoneServerNewCollectionDirectoryAction
-	extends RemoteGreenstoneServerAction
-    {
-	private String collection_name;
-	private File new_collection_directory;
-
-	public RemoteGreenstoneServerNewCollectionDirectoryAction(String collection_name, File new_collection_directory)
-	{
-	    this.collection_name = collection_name;
-	    this.new_collection_directory = new_collection_directory;
-	}
-
-	public void perform()
-	    throws Exception
-	{
-	    String collection_directory_path = CollectionManager.getCollectionDirectoryPath(collection_name);
-	    String new_collection_directory_relative_path = getPathRelativeToDirectory(new_collection_directory, collection_directory_path);
-	    new_collection_directory_relative_path = new_collection_directory_relative_path.replaceAll((Utility.isWindows() ? "\\\\" : "\\/"), "|");
-	    progress_bar.setAction("Creating new directory " + new_collection_directory_relative_path + "...");
-
-	    String new_collection_directory_command = "cmd=new-collection-directory";
-	    new_collection_directory_command += "&c=" + URLEncoder.encode(collection_name, "UTF-8");
-	    new_collection_directory_command += "&directory=" + URLEncoder.encode(new_collection_directory_relative_path, "UTF-8");
-	    action_output = sendCommandToServer(new_collection_directory_command, null);
-	}
-    }
-
-
-    /**
-     * --------------------------------------------------------------------------------------------
-     *    RUN SCRIPT
-     * --------------------------------------------------------------------------------------------
-     */
-    static private class RemoteGreenstoneServerRunScriptAction
-	extends RemoteGreenstoneServerAction
-    {
-	private String collection_name;
-	private String script_name;
-	private String script_arguments;
-	private GShell shell;
-
-	public RemoteGreenstoneServerRunScriptAction(String collection_name, String script_name, String script_arguments, GShell shell)
-	{
-	    this.collection_name = collection_name;
-	    this.script_name = script_name;
-	    this.script_arguments = script_arguments;
-	    this.shell = shell;
-	}
-
-	public void perform()
-	    throws Exception
-	{
-	    progress_bar.setAction("Running " + script_name + "...");
-
-	    String run_script_command = "cmd=run-script";
-	    run_script_command += "&c=" + URLEncoder.encode(collection_name, "UTF-8");
-	    run_script_command += "&script=" + script_name;
-	    run_script_command += "&language=" + Configuration.getLanguage();
-	    run_script_command += script_arguments;
-	    action_output = sendCommandToServer(run_script_command, shell);
-	}
-    }
-
-
-    /**
-     * --------------------------------------------------------------------------------------------
-     *    UPLOAD COLLECTION FILE
-     * --------------------------------------------------------------------------------------------
-     */
-    static private class RemoteGreenstoneServerUploadCollectionFilesAction
-	extends RemoteGreenstoneServerAction
-    {
-	private String collection_name;
-	private File[] collection_files;
-
-
-	public RemoteGreenstoneServerUploadCollectionFilesAction(String collection_name, File[] collection_files)
-	{
-	    this.collection_name = collection_name;
-	    this.collection_files = collection_files;
-	}
-
-
-	public void perform()
-	    throws Exception
-	{
-	    progress_bar.setAction("Uploading collection files...");
-
-	    // Determine the file paths relative to the collection directory
-	    String collection_directory_path = CollectionManager.getCollectionDirectoryPath(collection_name);
-	    String[] collection_file_relative_paths = new String[collection_files.length];
-	    for (int i = 0; i < collection_files.length; i++) {
-		collection_file_relative_paths[i] = getPathRelativeToDirectory(collection_files[i], collection_directory_path);
-	    }
-
-	    // Zip up the files to send to the server
-	    String zip_file_name = collection_name + "-" + System.currentTimeMillis() + ".zip";
-	    String zip_file_path = collection_directory_path + zip_file_name;
-	    ZipTools.zipFiles(zip_file_path, collection_directory_path, collection_file_relative_paths);
-
-	    // Upload the zip file
-	    String upload_collection_file_command = "cmd=upload-collection-file";
-	    upload_collection_file_command += "&c=" + URLEncoder.encode(collection_name, "UTF-8");
-	    upload_collection_file_command += "&file=" + URLEncoder.encode(zip_file_name, "UTF-8");
-	    upload_collection_file_command += "&directory=";
-	    upload_collection_file_command += "&zip=true";
-	    action_output = uploadFile(upload_collection_file_command, zip_file_path);
-	}
-    }
-
-
-    /**
-     * --------------------------------------------------------------------------------------------
-     *    UPLOAD FILES INTO COLLECTION
-     * --------------------------------------------------------------------------------------------
-     */
-    static private class RemoteGreenstoneServerUploadFilesIntoCollectionAction
-	extends RemoteGreenstoneServerAction
-    {
-	private String collection_name;
-	private File[] source_files;
-	private File target_collection_directory;
-
-
-	public RemoteGreenstoneServerUploadFilesIntoCollectionAction(String collection_name, File[] source_files, File target_collection_directory)
-	{
-	    this.collection_name = collection_name;
-	    this.source_files = source_files;
-	    this.target_collection_directory = target_collection_directory;
-	}
-
-
-	public void perform()
-	    throws Exception
-	{
-	    String collection_directory_path = CollectionManager.getCollectionDirectoryPath(collection_name);
-	    String target_collection_directory_relative_path = getPathRelativeToDirectory(target_collection_directory, collection_directory_path);
-	    target_collection_directory_relative_path = target_collection_directory_relative_path.replaceAll((Utility.isWindows() ? "\\\\" : "\\/"), "|");
-	    progress_bar.setAction("Uploading files into collection...");
-
-	    String zip_file_name = collection_name + "-" + System.currentTimeMillis() + ".zip";
-	    String zip_file_path = Gatherer.getCollectDirectoryPath() + zip_file_name;
-	    DebugStream.println("Zip file path: " + zip_file_path);
-
-	    String base_directory_path = source_files[0].getParentFile().getAbsolutePath();
-	    DebugStream.println("Base directory path: " + base_directory_path);
-	    String[] source_file_relative_paths = new String[source_files.length];
-	    for (int i = 0; i < source_files.length; i++) {
-		DebugStream.println("Source file path: " + source_files[i]);
-		source_file_relative_paths[i] = getPathRelativeToDirectory(source_files[i], base_directory_path);
-	    }
-
-	    ZipTools.zipFiles(zip_file_path, base_directory_path, source_file_relative_paths);
-
-	    String upload_collection_file_command = "cmd=upload-collection-file";
-	    upload_collection_file_command += "&c=" + URLEncoder.encode(collection_name, "UTF-8");
-	    upload_collection_file_command += "&file=" + URLEncoder.encode(zip_file_name, "UTF-8");
-	    upload_collection_file_command += "&directory=" + URLEncoder.encode(target_collection_directory_relative_path, "UTF-8");
-	    upload_collection_file_command += "&zip=true";
-	    action_output = uploadFile(upload_collection_file_command, zip_file_path);
-	}
-    }
-
-
-    // ----------------------------------------------------------------------------------------------------
     //   AUTHENTICATION LAYER
     // ----------------------------------------------------------------------------------------------------
-
-
-    static private PasswordAuthentication remote_greenstone_server_authentication = null;
-    // static private PasswordAuthentication remote_greenstone_server_authentication = new PasswordAuthentication(System.getProperty("user.name"), new char[] { });
-
-    static public void set_remote_greenstone_server_authentication_to_null(){
-	remote_greenstone_server_authentication = null;
-    }
 
     static private class RemoteGreenstoneServerAuthenticateTask
@@ -856,9 +345,14 @@
 	    remote_greenstone_server_authentication = new RemoteGreenstoneServerAuthenticator().getAuthentication();
 	}
-
+    
 
 	static private class RemoteGreenstoneServerAuthenticator
 	    extends GAuthenticator
 	{
+	    public PasswordAuthentication getAuthentication(String username, String password)
+	    {
+		return getPasswordAuthentication(username,password);
+	    }
+
 	    public PasswordAuthentication getAuthentication()
 	    {
@@ -875,8 +369,11 @@
  	}
     }
-
-
-    static private void authenticateUser()
-	throws RemoteGreenstoneServerActionCancelledException
+    
+    public void set_remote_greenstone_server_authentication_to_null() {
+	remote_greenstone_server_authentication = null;
+    }
+
+    private void authenticateUser()
+	throws RemoteGreenstoneServerAction.ActionCancelledException
     {
 	// If we don't have any authentication information then ask for it now
@@ -887,4 +384,5 @@
 	    }
 	    catch (Exception exception) {
+		System.err.println("Exception occurred when authenticating the user: " + exception);
 		DebugStream.printStackTrace(exception);
 	    }
@@ -892,11 +390,11 @@
 	    // If it is still null then the user has cancelled the authentication, so the action is cancelled
 	    if (remote_greenstone_server_authentication == null) {
-		throw new RemoteGreenstoneServerActionCancelledException();
-	    }
-	}
-    }
-
-
-    static public String getUsername()
+		throw new RemoteGreenstoneServerAction.ActionCancelledException();
+	    }
+	}
+    }
+
+
+    public String getUsername()
     {
 	if (remote_greenstone_server_authentication != null) {
@@ -914,5 +412,5 @@
 
     /** Returns the command output if the action completed, throws some kind of exception otherwise. */
-    static private String downloadFile(String gliserver_args, String file_path)
+    String downloadFile(String gliserver_args, String file_path)
 	throws Exception
     {
@@ -938,5 +436,5 @@
 		if (JOptionPane.showConfirmDialog(Gatherer.g_man, Dictionary.get("RemoteGreenstoneServer.Steal_Lock_Message", command_output.substring("ERROR: Collection is locked by: ".length())), Dictionary.get("RemoteGreenstoneServer.Error_Title"), JOptionPane.YES_NO_OPTION) == JOptionPane.NO_OPTION) {
 		    // The user has decided to cancel the action
-		    throw new RemoteGreenstoneServerActionCancelledException();
+		    throw new RemoteGreenstoneServerAction.ActionCancelledException();
 		}
 
@@ -955,10 +453,21 @@
     }
 
-
-    /** Returns the command output if the action completed, throws some kind of exception otherwise. */
-    static private String sendCommandToServer(String gliserver_args, GShell shell)
+    /** Returns true or false depending on whether authentication is required for the cmd 
+     * string embedded in the given gliserver_args. No authentication is required for either 
+     * of the commands greenstone-server-version and get-library-url-suffix. */
+    private boolean isAuthenticationRequired(String gliserver_args) {
+	return ((gliserver_args.indexOf("greenstone-server-version") == -1) 
+		&& (gliserver_args.indexOf("get-library-url-suffix") == -1));
+    }
+
+
+    /** Returns the command output if the action completed, throws some kind of exception otherwise. 
+     *  Package access, so that RemoteGreenstoneServerAction.java can call this.
+     */
+    String sendCommandToServer(String gliserver_args, GShell shell)
 	throws Exception
     {
 	while (true) {
+	    
 	    // Check that Configuration.gliserver_url is set
 	    if (Configuration.gliserver_url == null) {
@@ -967,9 +476,10 @@
 
 	    // Ask for authentication information (if necessary), then perform the action
-	    authenticateUser();
+	    if(isAuthenticationRequired(gliserver_args)) {
+		authenticateUser();
+	    }
 	    String gliserver_url_string = Configuration.gliserver_url.toString();
 	    String command_output = sendCommandToServerInternal(gliserver_url_string, gliserver_args, shell);
-	    // System.err.println("Command output: " + command_output);
-
+	    
 	    // Check the first line to see if authentication has failed; if so, go around the loop again
 	    if (command_output.startsWith("ERROR: Authentication failed:")) {
@@ -982,5 +492,5 @@
 		if (JOptionPane.showConfirmDialog(Gatherer.g_man, Dictionary.get("RemoteGreenstoneServer.Steal_Lock_Message", command_output.substring("ERROR: Collection is locked by: ".length())), Dictionary.get("RemoteGreenstoneServer.Error_Title"), JOptionPane.YES_NO_OPTION) == JOptionPane.NO_OPTION) {
 		    // The user has decided to cancel the action
-		    throw new RemoteGreenstoneServerActionCancelledException();
+		    throw new RemoteGreenstoneServerAction.ActionCancelledException();
 		}
 
@@ -990,8 +500,11 @@
 	    }
 	    // Handle other types of errors by throwing an exception
-	    else if (command_output.startsWith("ERROR: ")) {
+	    else if (command_output.startsWith("ERROR: ")) { 
 		throw new Exception(command_output.substring("ERROR: ".length()));
-	    }
-
+	    } else if (command_output.indexOf("ERROR: ") != -1) { // check if ERROR occurs anywhere else in the output
+		throw new Exception(command_output);
+	    }
+
+	    
 	    // There were no exceptions thrown so the action must have succeeded
 	    return command_output;
@@ -1001,5 +514,5 @@
 
     /** Returns the command output if the action completed, throws some kind of exception otherwise. */
-    static private String uploadFile(String gliserver_args, String file_path)
+    String uploadFile(String gliserver_args, String file_path)
 	throws Exception
     {
@@ -1026,5 +539,5 @@
 		if (JOptionPane.showConfirmDialog(Gatherer.g_man, Dictionary.get("RemoteGreenstoneServer.Steal_Lock_Message", command_output.substring("ERROR: Collection is locked by: ".length())), Dictionary.get("RemoteGreenstoneServer.Error_Title"), JOptionPane.YES_NO_OPTION) == JOptionPane.NO_OPTION) {
 		    // The user has decided to cancel the action
-		    throw new RemoteGreenstoneServerActionCancelledException();
+		    throw new RemoteGreenstoneServerAction.ActionCancelledException();
 		}
 
@@ -1050,5 +563,5 @@
 
     /** Returns the command output if the action completed, throws some kind of exception otherwise. */
-    static private String downloadFileInternal(String download_cgi, String cgi_args, String file_path)
+    private String downloadFileInternal(String download_cgi, String cgi_args, String file_path)
 	throws Exception
     {
@@ -1106,5 +619,5 @@
 
     /** Returns the command output if the action completed, throws some kind of exception otherwise. */
-    static private String sendCommandToServerInternal(String gliserver_url_string, String cgi_args, GShell shell)
+    private String sendCommandToServerInternal(String gliserver_url_string, String cgi_args, GShell shell)
 	throws Exception
     {
@@ -1113,6 +626,8 @@
 
 	// Add username and password, and a timestamp
-	cgi_args += "&un=" + remote_greenstone_server_authentication.getUserName();
-        cgi_args += "&pw=" + new String(remote_greenstone_server_authentication.getPassword());
+	if(isAuthenticationRequired(cgi_args)) {
+	    cgi_args += "&un=" + remote_greenstone_server_authentication.getUserName();
+	    cgi_args += "&pw=" + new String(remote_greenstone_server_authentication.getPassword());
+	}
 	cgi_args += "&ts=" + System.currentTimeMillis();
 	if (Gatherer.GS3){
@@ -1132,5 +647,5 @@
 		shell.fireMessage(gliserver_output_line);
 		if (shell.hasSignalledStop()) {
-		    throw new RemoteGreenstoneServerActionCancelledException();
+		    throw new RemoteGreenstoneServerAction.ActionCancelledException();
 		}
 	    }
@@ -1143,75 +658,68 @@
     }
 
-
+	       
     /** Returns the command output if the action completed, throws some kind of exception otherwise. */
-    static private String uploadFileInternal(String upload_cgi, String cgi_args, String file_path)
+    private String uploadFileInternal(String upload_cgi, String cgi_args, String file_path)
 	throws Exception
     {
+	System.err.println("gliserver URL: " + upload_cgi);
+	System.err.println("gliserver args: " + cgi_args);
+
 	//For a remote GS3
 	//GS3 is running on Tomcat, and Tomcat requires a connection timeout to be set up at the client
-	//side while uploading files. As HttpURLConection couldn't set the connection timeout, HttpClient.jar 
+	//side while uploading files. As HttpURLConnection couldn't set the connection timeout, HttpClient.jar 
 	//from Jakarta is applied to solve this problem only for uploading files. 
-	if (Gatherer.GS3){
-	    System.err.println("gliserver URL: " + upload_cgi);
-	    System.err.println("gliserver args: " + cgi_args);
-
-	// Setup the POST method
-	PostMethod httppost = new PostMethod(upload_cgi+"?"+cgi_args);
-
-	//read the zip file into a byte array
-	InputStream in = new FileInputStream (file_path);
-	File f = new File (file_path); // in order to get the length of the bytes array
-	ByteArrayOutputStream out = new ByteArrayOutputStream ((int)f.length());
-	int r = 0; // amount read
-	byte[] buf = new byte[1024];
-	while((r = in.read(buf, 0, buf.length)) != -1) {
-	    out.write(buf, 0, r);
-	}
-	in.close();
-	byte[] result = out.toByteArray();
-
-	// construct the multipartrequest form
-	PartSource partSource = new ByteArrayPartSource("zipFile", result);
-        FilePart filePart = new FilePart("uploaded_file", partSource);
-
-	String[] cgi_array=cgi_args.split("&");// get parameter-value paires from cgi_args string
-	Part[] parts=new Part[cgi_array.length+5];
-	parts[0]=filePart;
-	parts[1]= new StringPart("un", remote_greenstone_server_authentication.getUserName());
-	parts[2]= new StringPart("pw", new String(remote_greenstone_server_authentication.getPassword()));
-	parts[3]= new StringPart("ts", String.valueOf(System.currentTimeMillis()));
-	parts[4]= new StringPart("site", Configuration.site_name);
-	// find all parameters of cgi-agrs and add them into Part[]
-	for (int i=0; i<cgi_array.length;i++){
-	    parts[5+i]=new StringPart(cgi_array[i].substring(0,cgi_array[i].indexOf("=")),cgi_array[i].substring(cgi_array[i].indexOf("=")+1,cgi_array[i].length()));
-	}
-	// set MutilartRequestEntity on the POST method
-        httppost.setRequestEntity(new MultipartRequestEntity(parts, httppost.getParams()));
-	//set up the HttpClient connection
-	HttpClient client=new HttpClient();	
-        client.getParams().setBooleanParameter(HttpMethodParams.USE_EXPECT_CONTINUE, false);
-	client.getParams().setConnectionManagerTimeout(200000); //set the connection timeout
-	// get the output of the command from the server
- 	client.executeMethod(httppost);
-	String command_output = ""; 
-	try{
-	    client.executeMethod(httppost);
-	    if (httppost.getStatusCode() == HttpStatus.SC_OK) {
-		command_output = httppost.getStatusLine().toString();
-	    } else {
-		command_output = httppost.getStatusLine().toString();
-		System.out.println("Unexpected failure: " + httppost.getStatusLine().toString());
-	    }
-	}catch(IOException e){
-	    e.printStackTrace();
-	}finally{
-	    httppost.releaseConnection();
-	}
-	return command_output;
+	if (Gatherer.GS3) {
+
+	    // Setup the POST method
+	    PostMethod httppost = new PostMethod(upload_cgi+"?"+cgi_args); // cgi_args: QUERY_STRING on perl server side
+	    		    
+	    // construct the multipartrequest form
+	    String[] cgi_array=cgi_args.split("&");// get parameter-value pairs from cgi_args string
+	    Part[] parts=new Part[cgi_array.length+5];
+	    
+	    // The FilePart: consisting of the (cgi-arg) name and (optional) filename in the Content-Disposition 
+	    // of the POST request Header (see CGI.pm), and the actual zip file itself. It uses the defaults:
+	    // Content-Type: application/octet-stream; charset=ISO-8859-1,Content-Transfer-Encoding: binary
+	    parts[0]= new FilePart("uploaded_file", "zipFile", new File(file_path));
+
+	    parts[1]= new StringPart("un", remote_greenstone_server_authentication.getUserName());
+	    parts[2]= new StringPart("pw", new String(remote_greenstone_server_authentication.getPassword()));
+	    parts[3]= new StringPart("ts", String.valueOf(System.currentTimeMillis()));
+	    parts[4]= new StringPart("site", Configuration.site_name);
+	    // find all parameters of cgi-args and add them into Part[]
+	    for (int i=0; i<cgi_array.length;i++){
+		parts[5+i]=new StringPart(cgi_array[i].substring(0,cgi_array[i].indexOf("=")),cgi_array[i].substring(cgi_array[i].indexOf("=")+1,cgi_array[i].length()));
+	    }
+
+	    // set MultipartRequestEntity on the POST method
+	    httppost.setRequestEntity(new MultipartRequestEntity(parts, httppost.getParams()));
+
+	    // See file gli/request.txt for the multipart request that's been generated:
+	    //httppost.getRequestEntity().writeRequest(new FileOutputStream("request.txt", true)); // true: appends
+	    
+	    //set up the HttpClient connection
+	    HttpClient client=new HttpClient();	
+	    client.getParams().setBooleanParameter(HttpMethodParams.USE_EXPECT_CONTINUE, false);
+	    client.getParams().setConnectionManagerTimeout(200000); //set the connection timeout
+	    // get the output of the command from the server
+	    String command_output = ""; 
+	    try{
+		client.executeMethod(httppost);
+		if (httppost.getStatusCode() == HttpStatus.SC_OK) {
+		    command_output = httppost.getStatusLine().toString();
+		} else {
+		    command_output = httppost.getStatusLine().toString();
+		    System.out.println("Unexpected failure: " + httppost.getStatusLine().toString());
+		}
+	    }catch(IOException e){
+		e.printStackTrace();
+	    }finally{
+		httppost.releaseConnection();
+	    }
+	    return command_output;
 	}
 
 	//For a remote GS2
-	System.err.println("gliserver URL: " + upload_cgi);
-	System.err.println("gliserver args: " + cgi_args);
 	// Add username and password, and a timestamp
 	cgi_args += "&un=" + remote_greenstone_server_authentication.getUserName();
@@ -1282,5 +790,5 @@
 
 
-    static public String getPathRelativeToDirectory(File file, String directory_path)
+    public String getPathRelativeToDirectory(File file, String directory_path)
     {
 	String file_path = file.getAbsolutePath();
Index: /gli/branches/rtl-gli/src/org/greenstone/gatherer/remote/RemoteGreenstoneServerAction.java
===================================================================
--- /gli/branches/rtl-gli/src/org/greenstone/gatherer/remote/RemoteGreenstoneServerAction.java	(revision 18361)
+++ /gli/branches/rtl-gli/src/org/greenstone/gatherer/remote/RemoteGreenstoneServerAction.java	(revision 18361)
@@ -0,0 +1,641 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Greenstone Librarian Interface application, part of 
+ * the Greenstone digital library suite from the New Zealand Digital 
+ * Library Project at the University of Waikato, New Zealand.
+ *
+ * Author: Michael Dewsnip, NZDL Project, University of Waikato
+ *
+ * Copyright (C) 2005 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+*/
+
+package org.greenstone.gatherer.remote;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+import java.util.zip.*;
+import javax.swing.*;
+import java.io.ByteArrayOutputStream;
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.DebugStream;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.FedoraInfo;
+import org.greenstone.gatherer.GAuthenticator;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.collection.CollectionManager;
+import org.greenstone.gatherer.shell.GShell;
+import org.greenstone.gatherer.util.UnzipTools;
+import org.greenstone.gatherer.util.Utility;
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.methods.PostMethod;
+import org.apache.commons.httpclient.methods.GetMethod;
+import org.apache.commons.httpclient.HttpException;
+import org.apache.commons.httpclient.methods.multipart.FilePart;
+import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity;
+import org.apache.commons.httpclient.methods.multipart.Part;
+import org.apache.commons.httpclient.methods.multipart.*;
+import org.apache.commons.httpclient.params.*;
+import org.apache.commons.httpclient.HttpStatus;
+
+
+// Code moved here from RemoteGreenstoneServer.java
+// ----------------------------------------------------------------------------------------------------
+//   ACTIONS
+// ----------------------------------------------------------------------------------------------------
+/** RemoteGreenstoneServer Actions that can go into the remote GS server's  ActionQueue.
+ * Contains many package access inner classes that are Actions.   
+*/
+public abstract class RemoteGreenstoneServerAction
+{
+    public String action_output = null;
+    public boolean processed = false;
+    public boolean processed_successfully;
+    
+    protected RemoteGreenstoneServer remote = null;
+    protected RemoteGreenstoneServer.ProgressBar progress_bar = null;
+
+    public RemoteGreenstoneServerAction() {
+	remote = Gatherer.remoteGreenstoneServer;
+	progress_bar = remote.getProgressBar();
+    }
+
+    abstract public void perform()
+	throws Exception;
+
+    /*
+      protected String sendCommandToServer(String gliserver_args, GShell shell) 
+      throws Exception
+      {
+      return Gatherer.remoteGreenstoneServer.sendCommandToServer(gliserver_args, shell);
+      }
+      
+      protected void setAction(String action) {
+      Gatherer.remoteGreenstoneServer.progress_bar.setAction(action);
+    }*/
+    
+    static class ActionCancelledException
+	extends Exception
+    {
+    }
+
+    /**
+     * --------------------------------------------------------------------------------------------
+     *    DELETE COLLECTION
+     * --------------------------------------------------------------------------------------------
+     */
+    static class DeleteCollectionAction
+	extends RemoteGreenstoneServerAction
+    {
+	private String collection_name;
+
+	public DeleteCollectionAction(String collection_name)
+	{
+	    this.collection_name = collection_name;
+	}
+
+	public void perform()
+	    throws Exception
+	{
+	    progress_bar.setAction("Deleting collection " + collection_name + "...");
+
+	    String delete_collection_command = "cmd=delete-collection";
+	    delete_collection_command += "&c=" + URLEncoder.encode(collection_name, "UTF-8");
+	    action_output = remote.sendCommandToServer(delete_collection_command, null);
+	}
+    }
+
+
+    /**
+     * --------------------------------------------------------------------------------------------
+     *    DELETE COLLECTION FILE
+     * --------------------------------------------------------------------------------------------
+     */
+    static class DeleteCollectionFileAction
+	extends RemoteGreenstoneServerAction
+    {
+	private String collection_name;
+	private File collection_file;
+
+	public DeleteCollectionFileAction(String collection_name, File collection_file)
+	{
+	    this.collection_name = collection_name;
+	    this.collection_file = collection_file;
+	}
+
+	public void perform()
+	    throws Exception
+	{
+	    String collection_directory_path = CollectionManager.getCollectionDirectoryPath(collection_name);
+	    String collection_file_relative_path = remote.getPathRelativeToDirectory(collection_file, collection_directory_path);
+	    collection_file_relative_path = collection_file_relative_path.replaceAll((Utility.isWindows() ? "\\\\" : "\\/"), "|");
+	    progress_bar.setAction("Deleting collection file " + collection_file_relative_path + "...");
+
+	    String delete_collection_file_command = "cmd=delete-collection-file";
+	    delete_collection_file_command += "&c=" + URLEncoder.encode(collection_name, "UTF-8");
+	    delete_collection_file_command += "&file=" + URLEncoder.encode(collection_file_relative_path, "UTF-8");
+	    action_output = remote.sendCommandToServer(delete_collection_file_command, null);
+	}
+    }
+
+
+    /**
+     * --------------------------------------------------------------------------------------------
+     *    DOWNLOAD COLLECTION
+     * --------------------------------------------------------------------------------------------
+     */
+    static class DownloadCollectionAction
+	extends RemoteGreenstoneServerAction
+    {
+	private String collection_name;
+
+	public DownloadCollectionAction(String collection_name)
+	{
+	    this.collection_name = collection_name;
+	}
+
+	public void perform()
+	    throws Exception
+	{
+	    progress_bar.setAction("Downloading remote collection " + collection_name + "...");
+
+	    String download_collection_command = "cmd=download-collection";
+	    download_collection_command += "&c=" + URLEncoder.encode(collection_name, "UTF-8");
+	    String zip_file_path = Gatherer.getCollectDirectoryPath() + collection_name + ".zip";
+	    action_output = remote.downloadFile(download_collection_command, zip_file_path);
+
+	    // Delete the existing (local) collection directory
+	    Utility.delete(new File(CollectionManager.getCollectionDirectoryPath(collection_name)));
+
+	    // Unzip the collection just downloaded
+	    UnzipTools.unzipFile(zip_file_path, Gatherer.getCollectDirectoryPath());
+	}
+    }
+
+
+    /**
+     * --------------------------------------------------------------------------------------------
+     *    DOWNLOAD COLLECTION ARCHIVES
+     * --------------------------------------------------------------------------------------------
+     */
+    static class DownloadCollectionArchivesAction
+	extends RemoteGreenstoneServerAction
+    {
+	private String collection_name;
+
+	public DownloadCollectionArchivesAction(String collection_name)
+	{
+	    this.collection_name = collection_name;
+	}
+
+	public void perform()
+	    throws Exception
+	{
+	    progress_bar.setAction("Downloading collection archives for " + collection_name + "...");
+
+	    String download_collection_archives_command = "cmd=download-collection-archives";
+	    download_collection_archives_command += "&c=" + URLEncoder.encode(collection_name, "UTF-8");
+	    String zip_file_path = Gatherer.getCollectDirectoryPath() + collection_name + "-archives.zip";
+	    action_output = remote.downloadFile(download_collection_archives_command, zip_file_path);
+
+	    // Delete the existing (local) collection archives
+	    Utility.delete(new File(CollectionManager.getLoadedCollectionArchivesDirectoryPath()));
+
+	    // Unzip the collection archives just downloaded
+	    UnzipTools.unzipFile(zip_file_path, Gatherer.getCollectDirectoryPath());
+	}
+    }
+
+
+    /**
+     * --------------------------------------------------------------------------------------------
+     *    DOWNLOAD COLLECTION CONFIGURATIONS
+     * --------------------------------------------------------------------------------------------
+     */
+    static class DownloadCollectionConfigurationsAction
+	extends RemoteGreenstoneServerAction
+    {
+	public DownloadCollectionConfigurationsAction()
+	{
+	}
+
+	public void perform()
+	    throws Exception
+	{
+	    progress_bar.setAction("Downloading collection configurations...");
+
+	    // Delete the existing (local) collect directory
+	    Utility.delete(new File(Gatherer.getCollectDirectoryPath()));
+	    new File(Gatherer.getCollectDirectoryPath()).mkdirs();
+
+	    String download_collection_configurations_command = "cmd=download-collection-configurations";
+	    String zip_file_path = Gatherer.getCollectDirectoryPath() + "collections.zip";
+	    action_output = remote.downloadFile(download_collection_configurations_command, zip_file_path);
+
+	    // Unzip the collection configurations just downloaded
+	    UnzipTools.unzipFile(zip_file_path, Gatherer.getCollectDirectoryPath());
+	}
+    }
+
+     /**
+     * --------------------------------------------------------------------------------------------
+     *    DISCOVERING WHAT VERSION THE REMOTE GREENSTONE SERVER IS (2 or 3)
+     * --------------------------------------------------------------------------------------------
+     */
+
+    static class VersionAction
+	extends RemoteGreenstoneServerAction
+    {
+	public void perform()
+	    throws Exception
+	{
+	    action_output = remote.sendCommandToServer("cmd=greenstone-server-version", null);
+	}	
+    }
+
+    static class LibraryURLSuffixAction
+	extends RemoteGreenstoneServerAction
+    {
+	public void perform()
+	    throws Exception
+	{
+	    action_output = remote.sendCommandToServer("cmd=get-library-url-suffix", null);
+	}	
+    }
+    
+    /**
+     * --------------------------------------------------------------------------------------------
+     *    CHECKING IF A FILE/FOLDER EXISTS ON SERVER SIDE
+     * --------------------------------------------------------------------------------------------
+     */
+    static class ExistsAction 
+	extends RemoteGreenstoneServerAction
+    {
+	private String collection_name;
+	private File collection_file;
+	
+	public ExistsAction(String collection_name, File collection_file)
+	{
+	    this.collection_name = collection_name;
+	    this.collection_file = collection_file;
+	}
+	
+	public void perform()
+	    throws Exception
+	{
+	    String collection_directory_path = CollectionManager.getCollectionDirectoryPath(collection_name);
+	    String collection_file_relative_path = remote.getPathRelativeToDirectory(collection_file, collection_directory_path);
+	    collection_file_relative_path = collection_file_relative_path.replaceAll((Utility.isWindows() ? "\\\\" : "\\/"), "|");
+	    File file = new File(collection_directory_path, collection_file_relative_path);
+
+	    String file_exists_command = "cmd=file-exists";
+	    file_exists_command += "&c=" + URLEncoder.encode(collection_name, "UTF-8");
+	    file_exists_command += "&file=" + URLEncoder.encode(collection_file_relative_path, "UTF-8");
+	    // returns either "File <filename> exists" or "File <filename> does not exist"
+	    // for the file/folder collection_file
+	    action_output = remote.sendCommandToServer(file_exists_command, null);
+	}	
+    }
+    
+
+    /**
+     * --------------------------------------------------------------------------------------------
+     *    DOWNLOAD COLLECTION FILE
+     * --------------------------------------------------------------------------------------------
+     */
+    static class DownloadCollectionFileAction
+	extends RemoteGreenstoneServerAction
+    {
+	private String collection_name;
+	private File collection_file;
+
+	public DownloadCollectionFileAction(String collection_name, File collection_file)
+	{
+	    this.collection_name = collection_name;
+	    this.collection_file = collection_file;
+	}
+
+	public void perform()
+	    throws Exception
+	{
+	    String collection_directory_path = CollectionManager.getCollectionDirectoryPath(collection_name);
+	    String collection_file_relative_path = remote.getPathRelativeToDirectory(collection_file, collection_directory_path);
+	    collection_file_relative_path = collection_file_relative_path.replaceAll((Utility.isWindows() ? "\\\\" : "\\/"), "|");
+	    progress_bar.setAction("Downloading collection file " + collection_file_relative_path + "...");
+
+	    String download_collection_file_command = "cmd=download-collection-file";
+	    download_collection_file_command += "&c=" + URLEncoder.encode(collection_name, "UTF-8");
+	    download_collection_file_command += "&file=" + URLEncoder.encode(collection_file_relative_path, "UTF-8");
+	    String zip_file_name = collection_name + "-" + collection_file.getName() + ".zip";
+	    String zip_file_path = collection_directory_path + zip_file_name;
+	    action_output = remote.downloadFile(download_collection_file_command, zip_file_path);
+
+	    // Unzip the collection file just downloaded
+	    UnzipTools.unzipFile(zip_file_path, collection_directory_path);
+	}
+    }
+
+    /**
+     * --------------------------------------------------------------------------------------------
+     *    DOWNLOAD web.xml FILE --for a remote GS3
+     * --------------------------------------------------------------------------------------------
+     */
+    static class DownloadWebXMLFileAction
+	extends RemoteGreenstoneServerAction
+    {
+	public DownloadWebXMLFileAction()
+	{}
+
+	public void perform()
+	    throws Exception
+	{
+	    String web_xml_directory_path=(Configuration.gli_user_directory_path);
+	    String download_web_xml_file_command = "cmd=download-web-xml-file";
+	    download_web_xml_file_command += "&file=" + URLEncoder.encode("web.xml", "UTF-8");
+	    String zip_file_name = "web-xml.zip";
+	    String zip_file_path = web_xml_directory_path + zip_file_name;
+	    action_output = remote.downloadFile(download_web_xml_file_command, zip_file_path);
+
+	    // Unzip the web.xml file just downloaded
+	    UnzipTools.unzipFile(zip_file_path,web_xml_directory_path);
+	}
+    }
+
+    /**
+     * --------------------------------------------------------------------------------------------
+     *    GET SCRIPT OPTIONS
+     * --------------------------------------------------------------------------------------------
+     */
+    static class GetScriptOptionsAction
+	extends RemoteGreenstoneServerAction
+    {
+	private String script_name;
+	private String script_arguments;
+
+	public GetScriptOptionsAction(String script_name, String script_arguments)
+	{
+	    this.script_name = script_name;
+	    this.script_arguments = script_arguments;
+	}
+
+	public void perform()
+	    throws Exception
+	{
+	    progress_bar.setAction("Getting options for " + script_name + "...");
+
+	    String get_script_options_command = "cmd=get-script-options";
+	    get_script_options_command += "&script=" + script_name;
+	    get_script_options_command += "&xml=";
+	    get_script_options_command += "&language=" + Configuration.getLanguage();
+	    get_script_options_command += script_arguments;
+	    action_output = remote.sendCommandToServer(get_script_options_command, null);
+	}
+    }
+
+    /**
+     * --------------------------------------------------------------------------------------------
+     *    GET ALL NAMES OF SITES // for a remote GS3 
+     * --------------------------------------------------------------------------------------------
+     */
+    static class GetSiteNamesAction
+	extends RemoteGreenstoneServerAction
+    {
+	public GetSiteNamesAction()
+	{}
+
+	public void perform()
+	    throws Exception
+	{
+	    progress_bar.setAction("Getting names of sites ...");
+
+	    String get_script_options_command = "cmd=get-site-names";
+	    action_output = remote.sendCommandToServer(get_script_options_command, null);
+	}
+    }
+
+    /**
+     * --------------------------------------------------------------------------------------------
+     *    MOVE COLLECTION FILE
+     * --------------------------------------------------------------------------------------------
+     */
+    static class MoveCollectionFileAction
+	extends RemoteGreenstoneServerAction
+    {
+	private String collection_name;
+	private File source_collection_file;
+	private File target_collection_file;
+
+	public MoveCollectionFileAction(String collection_name, File source_collection_file, File target_collection_file)
+	{
+	    this.collection_name = collection_name;
+	    this.source_collection_file = source_collection_file;
+	    this.target_collection_file = target_collection_file;
+	}
+
+	public void perform()
+	    throws Exception
+	{
+	    String collection_directory_path = CollectionManager.getCollectionDirectoryPath(collection_name);
+	    String source_collection_file_relative_path = remote.getPathRelativeToDirectory(
+                                                          source_collection_file, collection_directory_path);
+	    source_collection_file_relative_path = source_collection_file_relative_path.replaceAll((Utility.isWindows() ? "\\\\" : "\\/"), "|");
+	    String target_collection_file_relative_path = remote.getPathRelativeToDirectory(
+                                                          target_collection_file, collection_directory_path);
+	    target_collection_file_relative_path = target_collection_file_relative_path.replaceAll((Utility.isWindows() ? "\\\\" : "\\/"), "|");
+	    progress_bar.setAction("Moving file " + source_collection_file_relative_path + " -> " + target_collection_file_relative_path + "...");
+
+	    String move_collection_file_command = "cmd=move-collection-file";
+	    move_collection_file_command += "&c=" + URLEncoder.encode(collection_name, "UTF-8");
+	    move_collection_file_command += "&source=" + URLEncoder.encode(source_collection_file_relative_path, "UTF-8");
+	    move_collection_file_command += "&target=" + URLEncoder.encode(target_collection_file_relative_path, "UTF-8");
+	    action_output = remote.sendCommandToServer(move_collection_file_command, null);
+	}
+    }
+
+
+    /**
+     * --------------------------------------------------------------------------------------------
+     *    NEW COLLECTION DIRECTORY
+     * --------------------------------------------------------------------------------------------
+     */
+    static class NewCollectionDirectoryAction
+	extends RemoteGreenstoneServerAction
+    {
+	private String collection_name;
+	private File new_collection_directory;
+
+	public NewCollectionDirectoryAction(String collection_name, File new_collection_directory)
+	{
+	    this.collection_name = collection_name;
+	    this.new_collection_directory = new_collection_directory;
+	}
+
+	public void perform()
+	    throws Exception
+	{
+	    String collection_directory_path = CollectionManager.getCollectionDirectoryPath(collection_name);
+	    String new_collection_directory_relative_path = remote.getPathRelativeToDirectory(
+                                                            new_collection_directory, collection_directory_path);
+	    new_collection_directory_relative_path = new_collection_directory_relative_path.replaceAll((Utility.isWindows() ? "\\\\" : "\\/"), "|");
+	    progress_bar.setAction("Creating new directory " + new_collection_directory_relative_path + "...");
+
+	    String new_collection_directory_command = "cmd=new-collection-directory";
+	    new_collection_directory_command += "&c=" + URLEncoder.encode(collection_name, "UTF-8");
+	    new_collection_directory_command += "&directory=" + URLEncoder.encode(new_collection_directory_relative_path, "UTF-8");
+	    action_output = remote.sendCommandToServer(new_collection_directory_command, null);
+	}
+    }
+
+
+    /**
+     * --------------------------------------------------------------------------------------------
+     *    RUN SCRIPT
+     * --------------------------------------------------------------------------------------------
+     */
+    static class RunScriptAction
+	extends RemoteGreenstoneServerAction
+    {
+	private String collection_name;
+	private String script_name;
+	private String script_arguments;
+	private GShell shell;
+
+	public RunScriptAction(String collection_name, String script_name, String script_arguments, GShell shell)
+	{
+	    this.collection_name = collection_name;
+	    this.script_name = script_name;
+	    this.script_arguments = script_arguments;
+	    this.shell = shell;
+	}
+
+	public void perform()
+	    throws Exception
+	{
+	    progress_bar.setAction("Running " + script_name + "...");
+
+	    String run_script_command = "cmd=run-script";
+	    run_script_command += "&c=" + URLEncoder.encode(collection_name, "UTF-8");
+	    run_script_command += "&script=" + script_name;
+	    run_script_command += "&language=" + Configuration.getLanguage();
+	    run_script_command += script_arguments;
+	    action_output = remote.sendCommandToServer(run_script_command, shell);
+	}
+    }
+
+
+    /**
+     * --------------------------------------------------------------------------------------------
+     *    UPLOAD COLLECTION FILE
+     * --------------------------------------------------------------------------------------------
+     */
+    static class UploadCollectionFilesAction
+	extends RemoteGreenstoneServerAction
+    {
+	private String collection_name;
+	private File[] collection_files;
+
+
+	public UploadCollectionFilesAction(String collection_name, File[] collection_files)
+	{
+	    this.collection_name = collection_name;
+	    this.collection_files = collection_files;
+	}
+
+
+	public void perform()
+	    throws Exception
+	{
+	    progress_bar.setAction("Uploading collection files...");
+
+	    // Determine the file paths relative to the collection directory
+	    String collection_directory_path = CollectionManager.getCollectionDirectoryPath(collection_name);
+	    String[] collection_file_relative_paths = new String[collection_files.length];
+	    for (int i = 0; i < collection_files.length; i++) {
+		collection_file_relative_paths[i] = remote.getPathRelativeToDirectory(collection_files[i], collection_directory_path);
+	    }
+
+	    // Zip up the files to send to the server
+	    String zip_file_name = collection_name + "-" + System.currentTimeMillis() + ".zip";
+	    String zip_file_path = collection_directory_path + zip_file_name;
+	    ZipTools.zipFiles(zip_file_path, collection_directory_path, collection_file_relative_paths);
+	    
+	    // Upload the zip file
+	    String upload_collection_file_command = "cmd=upload-collection-file";
+	    upload_collection_file_command += "&c=" + URLEncoder.encode(collection_name, "UTF-8");
+	    upload_collection_file_command += "&file=" + URLEncoder.encode(zip_file_name, "UTF-8");
+	    upload_collection_file_command += "&directory=";
+	    upload_collection_file_command += "&zip=true";
+	    action_output = remote.uploadFile(upload_collection_file_command, zip_file_path);
+	}
+    }
+
+
+    /**
+     * --------------------------------------------------------------------------------------------
+     *    UPLOAD FILES INTO COLLECTION
+     * --------------------------------------------------------------------------------------------
+     */
+    static class UploadFilesIntoCollectionAction
+	extends RemoteGreenstoneServerAction
+    {
+	private String collection_name;
+	private File[] source_files;
+	private File target_collection_directory;
+
+
+	public UploadFilesIntoCollectionAction(String collection_name, File[] source_files, File target_collection_directory)
+	{
+	    this.collection_name = collection_name;
+	    this.source_files = source_files;
+	    this.target_collection_directory = target_collection_directory;
+	}
+
+
+	public void perform()
+	    throws Exception
+	{
+	    String collection_directory_path = CollectionManager.getCollectionDirectoryPath(collection_name);
+	    String target_collection_directory_relative_path = remote.getPathRelativeToDirectory(
+                                                               target_collection_directory, collection_directory_path);
+	    target_collection_directory_relative_path = target_collection_directory_relative_path.replaceAll((Utility.isWindows() ? "\\\\" : "\\/"), "|");
+	    progress_bar.setAction("Uploading files into collection...");
+	   
+	    String zip_file_name = collection_name + "-" + System.currentTimeMillis() + ".zip";
+	    String zip_file_path = Gatherer.getCollectDirectoryPath() + zip_file_name;
+	    DebugStream.println("Zip file path: " + zip_file_path);
+
+	    String base_directory_path = source_files[0].getParentFile().getAbsolutePath();
+	    DebugStream.println("Base directory path: " + base_directory_path);
+	    String[] source_file_relative_paths = new String[source_files.length];
+	    for (int i = 0; i < source_files.length; i++) {
+		DebugStream.println("Source file path: " + source_files[i]);
+		source_file_relative_paths[i] = remote.getPathRelativeToDirectory(source_files[i], base_directory_path);
+	    }
+	    
+	    ZipTools.zipFiles(zip_file_path, base_directory_path, source_file_relative_paths);
+
+	    String upload_collection_file_command = "cmd=upload-collection-file";
+	    upload_collection_file_command += "&c=" + URLEncoder.encode(collection_name, "UTF-8");
+	    upload_collection_file_command += "&file=" + URLEncoder.encode(zip_file_name, "UTF-8");
+	    upload_collection_file_command += "&directory=" + URLEncoder.encode(target_collection_directory_relative_path, "UTF-8");
+	    upload_collection_file_command += "&zip=true";
+	    action_output = remote.uploadFile(upload_collection_file_command, zip_file_path);
+	}
+    }
+}
