Index: /main/trunk/greenstone3/src/java/org/greenstone/gsdl3/BaseGreenstoneServlet.java
===================================================================
--- /main/trunk/greenstone3/src/java/org/greenstone/gsdl3/BaseGreenstoneServlet.java	(revision 25717)
+++ /main/trunk/greenstone3/src/java/org/greenstone/gsdl3/BaseGreenstoneServlet.java	(revision 25717)
@@ -0,0 +1,16 @@
+package org.greenstone.gsdl3;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+
+import org.greenstone.util.GlobalProperties;
+
+public class BaseGreenstoneServlet extends HttpServlet
+{
+	public void init(ServletConfig config) throws ServletException
+	{
+		super.init(config);
+		GlobalProperties.loadGlobalProperties(config.getServletContext().getRealPath(""));
+	}
+}
Index: /main/trunk/greenstone3/src/java/org/greenstone/gsdl3/ClientSideServlet.java
===================================================================
--- /main/trunk/greenstone3/src/java/org/greenstone/gsdl3/ClientSideServlet.java	(revision 25716)
+++ /main/trunk/greenstone3/src/java/org/greenstone/gsdl3/ClientSideServlet.java	(revision 25717)
@@ -1,149 +1,183 @@
 package org.greenstone.gsdl3;
 
-import org.apache.log4j.*; // Actually add logging?
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
 import org.apache.commons.lang3.StringUtils;
+import org.greenstone.gsdl3.util.Dictionary;
 import org.greenstone.gsdl3.util.XSLTUtil;
-import java.io.*;
-import javax.servlet.*;
-import javax.servlet.http.*;
-import org.greenstone.gsdl3.util.Dictionary;
-import java.util.Enumeration;
 
-public class ClientSideServlet extends HttpServlet {
-	
-public void init(ServletConfig config) throws ServletException {
-	super.init(config);	
-}	
-	
-public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {   
-   
-   String query_string = request.getQueryString();
-   PrintWriter w = response.getWriter();
+public class ClientSideServlet extends BaseGreenstoneServlet
+{
+	public void init(ServletConfig config) throws ServletException
+	{
+		super.init(config);
+	}
 
-	if(query_string == null)
-		displayParamError(response);
-	
+	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
+	{
+		String query_string = request.getQueryString();
+		PrintWriter w = response.getWriter();
+
+		if (query_string == null)
+			displayParamError(response);
+
 		String[] parts = StringUtils.split(query_string, "&");
-	
+
 		String[] keys = null; // Array of keys to look up
 		String lang = "";
-		String interface_name = "";	
-		String command = "";	
+		String interface_name = "";
+		String command = "";
 		String params = "";
-		
-		for(String part : parts) {		
-		
+
+		for (String part : parts)
+		{
+
 			String[] nameval = StringUtils.split(part, '=');
 
-			if(nameval.length != 2) {
+			if (nameval.length != 2)
+			{
 				displayParamError(response);
 				return;
-			}			
-			
+			}
+
 			String name = nameval[0];
 			String value = nameval[1];
-			
-			if(name.equals("k"))
+
+			if (name.equals("k"))
 				keys = StringUtils.split(value, ",");
-			else if(name.equals("l"))
+			else if (name.equals("l"))
 				lang = value;
-			else if(name.equals("i"))
+			else if (name.equals("i"))
 				interface_name = value;
-			else if(name.equals("c"))
+			else if (name.equals("c"))
 				// Alternative commands
 				command = value;
-			else if(name.equals("p"))
+			else if (name.equals("p"))
 				params = value;
 		}
-		
-		if(keys == null && command.equals("") && params.equals("")) {
+
+		if (keys == null && command.equals("") && params.equals(""))
+		{
 			// Not satisfiable
 			displayParamError(response);
-			return;	
+			return;
 		}
-		
+
 		String bundle = "<?xml version=\"1.0\" encoding=\"iso-8859-1\" ?>\r\n<textBundle>\r\n";
-		
-		if(!command.equals("") && !params.equals("")) {
-		
+
+		if (!command.equals("") && !params.equals(""))
+		{
+
 			// Alternative commands other than dictionary lookup
-			String[] parameters = StringUtils.split(params, "|");			
-			String result = null;		
-			
-			if(command.equals("getNumberedItem") && parameters.length == 2) {
+			String[] parameters = StringUtils.split(params, "|");
+			String result = null;
+
+			if (command.equals("getNumberedItem") && parameters.length == 2)
+			{
 				result = XSLTUtil.getNumberedItem(parameters[0], Integer.parseInt(parameters[1]));
-			} else if(command.equals("exists") && parameters.length == 2) {
+			}
+			else if (command.equals("exists") && parameters.length == 2)
+			{
 				result = XSLTUtil.exists(parameters[0], parameters[1]) ? "true" : "false";
-			} else if(command.equals("isImage") && parameters.length == 1) {
-				result = (XSLTUtil.isImage(parameters[0])) ? "true" : "false";	
 			}
-			
-			if(result != null) {
+			else if (command.equals("isImage") && parameters.length == 1)
+			{
+				result = (XSLTUtil.isImage(parameters[0])) ? "true" : "false";
+			}
+
+			if (result != null)
+			{
 				bundle += "	<method name=\"" + command + "\" parameters=\"" + params + "\" return=\"" + result + "\" />\r\n";
-			} else { displayParamError(response); return; }
-		} else {
-		
-		for(String key : keys) {
-		
-			String original_key = key;
-			String[] theParts = StringUtils.split(key, "|");
-			String[] args = null;
-			
-			if(theParts.length > 1)
-				args = StringUtils.split(theParts[1], ";");
-		
-			key = theParts[0];
-		
-			// Straight from XSLTUtils.java (src), with some modifications
-			if(key.equals("null")) {
-				bundle += "	<item key=\"" + key + "\" value=\"\" />\r\n";
-				continue;
 			}
-				
-			Dictionary dict = new Dictionary("interface_"+interface_name, lang);
-			String result = dict.get(key, args);
-			
-			if (result == null) {
-				String sep_interface_dir = interface_name + File.separatorChar + lang + File.separatorChar + "interface"; 
-				dict = new Dictionary(sep_interface_dir, lang);
-				result = dict.get(key, args);  
-			 }
+			else
+			{
+				displayParamError(response);
+				return;
+			}
+		}
+		else
+		{
 
-			if (result == null && !interface_name.equals("default")) { // not found, try the default interface
-			    dict = new Dictionary("interface_default", lang);
-			    result = dict.get(key, args);
+			for (String key : keys)
+			{
+
+				String original_key = key;
+				String[] theParts = StringUtils.split(key, "|");
+				String[] args = null;
+
+				if (theParts.length > 1)
+					args = StringUtils.split(theParts[1], ";");
+
+				key = theParts[0];
+
+				// Straight from XSLTUtils.java (src), with some modifications
+				if (key.equals("null"))
+				{
+					bundle += "	<item key=\"" + key + "\" value=\"\" />\r\n";
+					continue;
+				}
+
+				Dictionary dict = new Dictionary("interface_" + interface_name, lang);
+				String result = dict.get(key, args);
+
+				if (result == null)
+				{
+					String sep_interface_dir = interface_name + File.separatorChar + lang + File.separatorChar + "interface";
+					dict = new Dictionary(sep_interface_dir, lang);
+					result = dict.get(key, args);
+				}
+
+				if (result == null && !interface_name.equals("default"))
+				{ // not found, try the default interface
+					dict = new Dictionary("interface_default", lang);
+					result = dict.get(key, args);
+				}
+
+				if (result == null)
+				{ // not found
+					result = "_" + original_key + "_";
+				}
+
+				bundle += "	<item key=\"" + encode(original_key) + "\" value=\"" + encode(result) + "\" />\r\n";
 			}
-			    
-		    if (result == null) { // not found
-			    result = "_" + original_key + "_";
-		    } 
+		}
 
-			bundle += "	<item key=\"" + encode(original_key) + "\" value=\"" + encode(result) + "\" />\r\n";
-		} }
-		
 		bundle += "</textBundle>";
-		
-		response.setContentType("text/xml");   			
+
+		response.setContentType("text/xml");
 
 		w.print(bundle);
 		w.close();
+	}
+
+	private String encode(String s)
+	{
+		s = StringUtils.replace(s, "&", "&amp;");
+		s = StringUtils.replace(s, "<", "&lt;");
+		s = StringUtils.replace(s, ">", "&gt;");
+		return s;
+	}
+
+	private void displayParamError(HttpServletResponse response)
+	{
+
+		try
+		{
+			PrintWriter w = response.getWriter();
+			w.write("Invalid parameters supplied! Need key (k=), interface name (i=) and language (l=). If you specified a method call, it must be on the list of supported method calls, and you must specify a command (c=) and parameters (p=).");
+			w.close();
+		}
+		catch (Exception ex)
+		{ /* Should log here */
+		}
+
+	}
+
 }
-
-private String encode(String s) {
-	s = StringUtils.replace(s, "&", "&amp;");
-	s = StringUtils.replace(s, "<", "&lt;");
-	s = StringUtils.replace(s, ">", "&gt;");
-	return s;
-}
-
-private void displayParamError(HttpServletResponse response) {
-
-	try {
-	PrintWriter w = response.getWriter();
-	w.write("Invalid parameters supplied! Need key (k=), interface name (i=) and language (l=). If you specified a method call, it must be on the list of supported method calls, and you must specify a command (c=) and parameters (p=).");
-	w.close();
-	} catch (Exception ex) { /* Should log here */ }
-	
-}
-	
-}
Index: /main/trunk/greenstone3/src/java/org/greenstone/gsdl3/FileLoaderServlet.java
===================================================================
--- /main/trunk/greenstone3/src/java/org/greenstone/gsdl3/FileLoaderServlet.java	(revision 25716)
+++ /main/trunk/greenstone3/src/java/org/greenstone/gsdl3/FileLoaderServlet.java	(revision 25717)
@@ -1,5 +1,9 @@
 package org.greenstone.gsdl3;
 
-import java.io.*;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.PrintWriter;
 import java.nio.channels.FileChannel;
 import java.util.Iterator;
@@ -7,6 +11,8 @@
 import java.util.Map;
 
-import javax.servlet.*;
-import javax.servlet.http.*;
+import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
 
 import org.apache.commons.fileupload.FileItem;
@@ -48,5 +54,5 @@
 							storageLocation = current.getString();
 						}
-						
+
 						if (current.getFieldName().equals("ajaxUpload") && current.getString().equals("true"))
 						{
@@ -65,10 +71,10 @@
 
 						uploadedFile = file;
-						
-						if(!json.toString().equals("["))
+
+						if (!json.toString().equals("["))
 						{
 							json.append(",");
 						}
-						
+
 						json.append("{");
 						json.append("\"name\":\"" + file.getName() + "\",");
@@ -82,6 +88,6 @@
 				}
 				json.append("]");
-				
-				if(ajaxUpload)
+
+				if (ajaxUpload)
 				{
 					response.setContentType("application/json");
@@ -89,5 +95,5 @@
 					writer.write(json.toString());
 					writer.flush();
-					
+
 					return;
 				}
@@ -141,6 +147,6 @@
 			Map<String, String[]> queryMap = request.getParameterMap();
 			Iterator<String> queryIter = queryMap.keySet().iterator();
-			
-			while(queryIter.hasNext())
+
+			while (queryIter.hasNext())
 			{
 				String q = queryIter.next();
@@ -149,12 +155,12 @@
 					String fileLocation = queryMap.get(q)[0];
 					File fileToGet = new File(GlobalProperties.getGSDL3Home() + File.separator + fileLocation);
-	
+
 					if (fileToGet.exists())
 					{
 						response.setContentType("application/octet-stream");
-						response.addHeader("Content-Disposition","attachment;filename=" + fileToGet.getName());
+						response.addHeader("Content-Disposition", "attachment;filename=" + fileToGet.getName());
 						FileInputStream fis = new FileInputStream(fileToGet);
 						ServletOutputStream sos = response.getOutputStream();
-	
+
 						byte[] buffer = new byte[4096];
 						int len;
@@ -166,5 +172,5 @@
 						fis.close();
 						sos.close();
-						
+
 						return;
 					}
Index: /main/trunk/greenstone3/src/java/org/greenstone/gsdl3/LibraryServlet.java
===================================================================
--- /main/trunk/greenstone3/src/java/org/greenstone/gsdl3/LibraryServlet.java	(revision 25716)
+++ /main/trunk/greenstone3/src/java/org/greenstone/gsdl3/LibraryServlet.java	(revision 25717)
@@ -1,33 +1,46 @@
 package org.greenstone.gsdl3;
 
-import org.greenstone.gsdl3.comms.*;
-import org.greenstone.gsdl3.core.*;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.Serializable;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import javax.servlet.http.HttpSessionBindingEvent;
+import javax.servlet.http.HttpSessionBindingListener;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.log4j.Logger;
+import org.greenstone.gsdl3.action.PageAction;
+import org.greenstone.gsdl3.comms.Communicator;
+import org.greenstone.gsdl3.comms.SOAPCommunicator;
+import org.greenstone.gsdl3.core.DefaultReceptionist;
+import org.greenstone.gsdl3.core.MessageRouter;
+import org.greenstone.gsdl3.core.Receptionist;
 import org.greenstone.gsdl3.service.Authentication;
-import org.greenstone.gsdl3.util.*;
-import org.greenstone.gsdl3.action.PageAction; // used to get the default action
+import org.greenstone.gsdl3.util.GSConstants;
+import org.greenstone.gsdl3.util.GSParams;
+import org.greenstone.gsdl3.util.GSXML;
+import org.greenstone.gsdl3.util.UserContext;
+import org.greenstone.gsdl3.util.XMLConverter;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.w3c.dom.Node;
 import org.w3c.dom.NodeList;
-import java.io.*;
-
-import javax.servlet.*;
-import javax.servlet.http.*;
-
-import java.util.Enumeration;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.lang.reflect.Type;
-import java.util.Hashtable;
-import org.apache.log4j.*;
 
 import com.google.gson.Gson;
 import com.google.gson.reflect.TypeToken;
-
-// Apache Commons
-import org.apache.commons.lang3.*;
 
 /**
@@ -45,7 +58,6 @@
  * @see Receptionist
  */
-public class LibraryServlet extends HttpServlet
+public class LibraryServlet extends BaseGreenstoneServlet
 {
-
 	/** the receptionist to send messages to */
 	protected Receptionist recept = null;
@@ -110,5 +122,4 @@
 
 		String library_name = config.getInitParameter(GSConstants.LIBRARY_NAME);
-		String gsdl3_home = config.getInitParameter(GSConstants.GSDL3_HOME);
 		String interface_name = config.getInitParameter(GSConstants.INTERFACE_NAME);
 
Index: /main/trunk/greenstone3/src/java/org/greenstone/gsdl3/OAIServer.java
===================================================================
--- /main/trunk/greenstone3/src/java/org/greenstone/gsdl3/OAIServer.java	(revision 25716)
+++ /main/trunk/greenstone3/src/java/org/greenstone/gsdl3/OAIServer.java	(revision 25717)
@@ -19,20 +19,28 @@
 package org.greenstone.gsdl3;
 
-import org.greenstone.gsdl3.comms.*;
-import org.greenstone.gsdl3.core.*;
-import org.greenstone.gsdl3.util.*;
-import org.greenstone.gsdl3.action.PageAction; // used to get the default action
-import org.w3c.dom.*;
-import java.io.*;
-import javax.servlet.*;
-import javax.servlet.http.*;
-import java.util.Enumeration;
+import java.io.IOException;
+import java.io.PrintWriter;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.Map;
-import java.util.Map.Entry;
-import java.io.File;
-
-import org.apache.log4j.*;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.log4j.Logger;
+import org.greenstone.gsdl3.comms.Communicator;
+import org.greenstone.gsdl3.comms.SOAPCommunicator;
+import org.greenstone.gsdl3.core.MessageRouter;
+import org.greenstone.gsdl3.core.OAIReceptionist;
+import org.greenstone.gsdl3.util.GSConstants;
+import org.greenstone.gsdl3.util.GSParams;
+import org.greenstone.gsdl3.util.GSXML;
+import org.greenstone.gsdl3.util.OAIXML;
+import org.greenstone.gsdl3.util.XMLConverter;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
 
 /** a servlet to serve the OAI metadata harvesting - we are using servlets instead
@@ -48,392 +56,446 @@
 /**
  * OAI server configuration instructions *
- *
+ * 
  */
-public class OAIServer extends HttpServlet {
-  
-  /** the receptionist to send messages to */
-  protected OAIReceptionist recept=null;
-  /** the default language - is specified by setting a servlet param,
-   * otherwise DEFAULT_LANG is used*/
-  protected String default_lang= null;
-  /** The default default - used if a default lang is not specified
-   * in the servlet params */
-  protected final String DEFAULT_LANG = "en";
-
-  /** a converter class to parse XML and create Docs
-   * This is only used for generating internal requests passed to MessageRouter.
-   * The response message is generated by parsing an existing xml skeleton file (web/WEB-INF/oaixml/oaiversion2.xml, for example).
-   */
-  protected XMLConverter converter=null;
-  /** container Document to create XML Nodes (but only request to the oai receptionist,
-   *  not response (which is created in OAIXML.java) created by converter class */
-  protected Document doc=null;
-  
-  /** A HashSet which contains all the legal verbs. */
-  protected HashSet<String> verb_set = null;
-  /** A HashSet which contains all the legal oai keys in the key/value argument pair. */
-  protected HashSet<String> param_set = null;
-  /** The name of the site with which we will finally be dealing, whether it is a local site or a remote site through a communicator.*/
-  protected String site = "";
-  
-  // do we output the stylesheet processing instruction?
-  protected boolean use_oai_stylesheet = true;
-  protected String oai_stylesheet = "interfaces/oai/oai2.xsl";
-
-    // there is no getQueryString() method in the HttpServletRequest returned from doPost, 
-    // since that is actually of type apache RequestFacade, and doesn't define such a method
-    protected String queryString = null;
-
-  static Logger logger = Logger.getLogger(org.greenstone.gsdl3.OAIServer.class.getName());
-  
-  /** initialise the servlet
-   */
-  public void init(ServletConfig config) throws ServletException {
-    // always call super.init, i.e., HttpServlet.;
-    super.init(config);
-    this.default_lang = config.getInitParameter(GSConstants.DEFAULT_LANG);
-    
-    initVerbs();
-    initParams();
-    
-    String site_name = config.getInitParameter(GSConstants.SITE_NAME);
-    String remote_site_name = null;
-    String remote_site_type = null;
-    String remote_site_address = null;
-    
-    if (site_name == null) {
-      // no local site, try for communicator (remote site)
-      remote_site_name = config.getInitParameter("remote_site_name");
-      remote_site_type = config.getInitParameter("remote_site_type");
-      remote_site_address = config.getInitParameter("remote_site_address");
-      if (remote_site_name == null || remote_site_type == null || remote_site_address == null) {
-        System.err.println("initialisation paramters not all set!");
-        System.err.println("if site_name is not set, then you must have remote_site_name, remote_site_type and remote_site_address set");
-        System.exit(1);
-      }
-    }
-    
-    if (this.default_lang == null) {
-      // choose english
-      this.default_lang = DEFAULT_LANG;
-    }
-    
-    // the receptionist -the servlet will talk to this
-    this.recept = new OAIReceptionist();
-    
-    // the receptionist uses a MessageRouter or Communicator to send its requests to. We either create a MessageRouter here for the designated site (if site_name set), or we create a Communicator for a remote site. The is given to teh Receptionist, and the servlet never talks to it again.directly.
-    if (site_name != null) {
-      //this site_name could consist of comma separated more than one site name.
-      String mr_name = (String)config.getInitParameter("messagerouter_class");
-      MessageRouter message_router = null;
-      if (mr_name == null) { // just use the normal MR *********
-        message_router = new MessageRouter();
-      } else { // try the specified one
-        try {
-          message_router = (MessageRouter)Class.forName("org.greenstone.gsdl3.core."+mr_name).newInstance();
-        } catch (Exception e) { // cant use this new one, so use normal one
-          System.err.println("OAIServlet configure exception when trying to use a new MessageRouter "+mr_name+": "+e.getMessage());
-          e.printStackTrace();
-          message_router = new MessageRouter();
-        }
-      }
-      
-      message_router.setSiteName(site_name);
-      // lots of work is done in this step; see MessageRouter.java
-      message_router.configure();
-      this.recept.setSiteName(site_name);
-      this.recept.setMessageRouter(message_router);
-      
-    } else {      
-      // talking to a remote site, create a communicator
-      Communicator communicator = null;
-      // we need to create the XML to configure the communicator
-      Element site_elem = this.doc.createElement(GSXML.SITE_ELEM);
-      site_elem.setAttribute(GSXML.TYPE_ATT, remote_site_type);
-      site_elem.setAttribute(GSXML.NAME_ATT, remote_site_name);
-      site_elem.setAttribute(GSXML.ADDRESS_ATT, remote_site_address);
-      
-      if (remote_site_type.equals(GSXML.COMM_TYPE_SOAP_JAVA)) {
-        communicator = new SOAPCommunicator();
-      } else {
-        System.err.println("OAIServlet.init Error: invalid Communicator type: "+remote_site_type);
-        System.exit(1);
-      }
-      
-      if (!communicator.configure(site_elem)) {
-        System.err.println("OAIServlet.init Error: Couldn't configure communicator");
-        System.exit(1);
-      }
-      this.recept.setSiteName(remote_site_name);
-      this.recept.setMessageRouter(communicator);
-    }
-    // used for composing internal xml requests, but not xml responses.
-    // the converter may be used to get pretty xml, though.    
-    this.converter = new XMLConverter();
-    this.doc = this.converter.newDOM();
-
-    // Read in OAIConfig.xml (residing web/WEB-INF/classes/) and 
-    //use it to configure the receptionist. The init() is also called in which
-    //the resumption token file is read in and all expired tokens cleared.
-    Element oai_config = OAIXML.getOAIConfigXML();
-      if (oai_config == null) {
-        logger.error("Fail to parse oai config file OAIConfig.xml.");
-        return;
-      }   
-    // pass it to the receptionist
-    this.recept.configure(oai_config);
-    
-    // also, we have something we want to get from here - useOAIStylesheet
-    this.configure(oai_config);
-  }//end of init()
-  
-  private void configure(Element oai_config) {
-    Element use_stylesheet_elem = (Element)GSXML.getChildByTagName(oai_config, OAIXML.USE_STYLESHEET);
-    if (use_stylesheet_elem != null) {
-      String value = GSXML.getNodeText(use_stylesheet_elem);
-      if (value.equals("no")) {
-	this.use_oai_stylesheet = false;
-      }
-    }
-    if (this.use_oai_stylesheet) {
-      // now see if there is a custom stylesheet specified
-      Element stylesheet_elem = (Element)GSXML.getChildByTagName(oai_config, OAIXML.STYLESHEET);
-      if (stylesheet_elem != null) {
-	String value = GSXML.getNodeText(stylesheet_elem);
-	if (!value.equals("")) {
-	  oai_stylesheet = value;
-	}
-      }
-      
-    }
-  }
-  private void initVerbs() {
-    verb_set = new HashSet<String>();
-    verb_set.add(OAIXML.GET_RECORD);
-    verb_set.add(OAIXML.LIST_RECORDS);
-    verb_set.add(OAIXML.LIST_IDENTIFIERS);
-    verb_set.add(OAIXML.LIST_SETS);
-    verb_set.add(OAIXML.LIST_METADATA_FORMATS);
-    verb_set.add(OAIXML.IDENTIFY);
-  }
-  
-  private void initParams() {
-    param_set = new HashSet<String>();
-    param_set.add(OAIXML.METADATA_PREFIX);
-    param_set.add(OAIXML.FROM);
-    param_set.add(OAIXML.UNTIL);
-    param_set.add(OAIXML.SET);
-    param_set.add(OAIXML.RESUMPTION_TOKEN);
-    param_set.add(OAIXML.IDENTIFIER);
-  }
-  private void logUsageInfo(HttpServletRequest request){
-    String usageInfo = "";
-    
-    String query = (queryString == null) ? request.getQueryString() : queryString;
-
-    //logged info = general-info + session-info
-    usageInfo =
-      request.getContextPath()+" "+ //session id
-      request.getServletPath()+" "+ //serlvet
-      "["+query+"]" +" "+ //the query string
-      "["+usageInfo.trim()+"]" +" "+ // params stored in a session
-      request.getRemoteAddr()+" "+   //remote address
-      request.getHeader("user-agent")+" "; //the remote brower info
-    
-    logger.info(usageInfo);   
-  }
-  /** return true if the url is in the form of baseURL?verb=..., 
-   */
-  private boolean validate(String query, String verb) {
-    //Here in OAIServer, only the verbs are validated. All the validation for individual verb
-    // is taken in their doXXX() methods.
-    if(query == null || !query.startsWith(OAIXML.VERB+"=")) {
-      return false;
-    }
-    if (!verb_set.contains(verb)) {
-      return false;
-    }
-    return true;
-  }
-  private String getVerb(String query) {
-    if (query == null) return "";
-    int verb_start_index = query.indexOf("=") + 1;// first occurence of '='
-    int verb_end_index = query.indexOf("&");
-    if(verb_end_index == -1) {
-      return query.substring(verb_start_index);
-    }
-    return query.substring(verb_start_index, verb_end_index);
-  }
-
-  public void doGet(HttpServletRequest request, HttpServletResponse response)
-    throws ServletException, IOException {
-    logUsageInfo(request);
-    //out.println("url="+request.getRequestURL());// /oaiserver    
-    //out.println("query="+request.getQueryString());// is /greenstone3
-
-    // oai always requires the content type be text/xml
-    request.setCharacterEncoding("UTF-8");
-    response.setContentType("text/xml;charset=UTF-8");
-    PrintWriter out = response.getWriter();
-    
-    //
-    String lang = request.getParameter(GSParams.LANGUAGE);
-    if (lang==null || lang.equals("")) {
-      // use the default
-      lang = this.default_lang;
-    }
-    //we don't get the baseURL from the http request because what we get might be different from the one known publicly due to local network redirection.
-    //For example, puka.cs.waikato.ac.nz vs www.greenstone.org
-    //String base_url = request.getRequestURL().toString();
-    // if called by doPost (if this was originally a POST request), var queryString would have been set
-    String query = (queryString == null) ? request.getQueryString() : queryString;
-    queryString = null; // reset member variable, else no doGet will work as long as the server remains running
-
-    String[] pairs = (query==null)? null : query.split("&");//split into key/value pairs
-    String verb = getVerb(query);
-    Element xml_response = OAIXML.createBasicResponse(verb, pairs);
-    Element verb_elem = null;
-    
-    if (validate(query, verb) == false) {
-      if (verb_set.contains(verb) == false) {
-        logger.error(OAIXML.BAD_VERB + ": " + query);
-        verb_elem = OAIXML.createErrorElement(OAIXML.BAD_VERB, OAIXML.ILLEGAL_OAI_VERB);
-      } else {
-        //must be something else other than bad verbs caused an error, so bad argument
-        logger.error(OAIXML.BAD_ARGUMENT + ": " + query);
-        verb_elem = OAIXML.createErrorElement(OAIXML.BAD_ARGUMENT, "");
-      } 
-      xml_response.appendChild(verb_elem);
-
-      out.println("<?xml version='1.0' encoding='UTF-8' ?>");
-      if (this.use_oai_stylesheet) {
-	out.println("<?xml-stylesheet type='text/xsl' href='"+this.oai_stylesheet+"' ?>\n");
-      }
-      out.println(this.converter.getPrettyString(xml_response));
-      return;
-    }//end of if(validate
-    
-    // The query is valid, we can now
-    // compose the request message to the receptionist
-    Element xml_message = this.doc.createElement(GSXML.MESSAGE_ELEM);
-    Element xml_request = this.doc.createElement(GSXML.REQUEST_ELEM);
-    // The type attribute is set to be 'oaiService' from OAIServer to OAIReceptionist.
-    //xml_request.setAttribute(GSXML.TYPE_ATT, OAIXML.OAI_SERVICE);
-    xml_request.setAttribute(GSXML.LANG_ATT, lang);
-    xml_request.setAttribute(GSXML.TO_ATT, verb);
-    addParams(xml_request, pairs);
-    
-    //xml_request.setAttribute(GSXML.OUTPUT_ATT, output);????
-    xml_message.appendChild(xml_request);
-         
-    Node xml_result = this.recept.process (xml_message);
-    if (xml_result == null) {
-      logger.info("xml_result is null");
-      verb_elem = OAIXML.createErrorElement("Internal error", "");
-      xml_response.appendChild(verb_elem);
-    } else {
-    
-      /** All response elements are in the form (with a corresponding verb name):
-       *                                        <message>
-                                                  <response>
-                                                    <verb>
-                                                    ...
-       *                                              <resumptionToken>
-       *                                              .. this is optional!
-       *                                              </resumptionToken>
-       *                                            </verb>
-       *                                          </response>       
-       *                                        </message>
-       */
-      Node res = GSXML.getChildByTagName(xml_result, OAIXML.RESPONSE);
-      if(res == null) {
-        logger.info("response element in xml_result is null");
-        verb_elem = OAIXML.createErrorElement("Internal error", "");
-      } else {
-        verb_elem = GSXML.getFirstElementChild(res);
-      }
-      
-      if(OAIXML.oai_version.equals(OAIXML.OAI_VERSION2) ||
-         verb_elem.getTagName().equals(OAIXML.ERROR)) {
-        xml_response.appendChild(xml_response.getOwnerDocument().importNode(verb_elem, true));
-      } else {
-        GSXML.copyAllChildren(xml_response, verb_elem);
-      }
-    }
-    out.println("<?xml version='1.0' encoding='UTF-8' ?>");
-    if (this.use_oai_stylesheet) {
-      out.println("<?xml-stylesheet type='text/xsl' href='"+this.oai_stylesheet+"' ?>\n");
-    }
-    out.println (this.converter.getPrettyString (xml_response));
-    return; 
-  }
-  /** append parameter elements to the request sent to the receptionist*/
-  public void addParams(Element request, String[] pairs) {
-    // no params apart from the verb
-    if (pairs == null || pairs.length < 2) return ;
-    
-      /**the request xml is composed in the form: <request>
-       *                                            <param name=.../>
-       *                                            <param name=.../>
-       *                                          </request>
-       *(No paramList element in between).
-       */    
-    for (int i=1; i<pairs.length; i++) {
-      //the first pair in pairs is the verb=xxx
-      int index = pairs[i].indexOf("=");
-      if(index != -1){ //just a double check
-        Element param = this.doc.createElement(OAIXML.PARAM);
-        param.setAttribute(OAIXML.NAME, pairs[i].substring(0, index));
-        param.setAttribute(OAIXML.VALUE, OAIXML.oaiDecode(pairs[i].substring(index + 1)));
-        request.appendChild(param);
-      }
-    } 
-  }
-
-  // For OAI version 2.0, validation tests indicated that POST needs to be supported. Some
-  // modification was required in order to ensure that the request is passed intact to doGet()
-  public void doPost(HttpServletRequest request,
-    HttpServletResponse response)
-    throws ServletException, IOException {
-
-      // the post method returns a wrapper of type RequestFacade by apache and there
-      // is no getQueryString() method defined for it. Therefore, need to work this out
-      // manually before calling doGet(request, response) so that doGet can work as before.
-      
-      queryString = "";
-      Iterator parameter_entries = request.getParameterMap().entrySet().iterator();
-      while(parameter_entries.hasNext()) {	  
-	  Map.Entry param_entry = (Map.Entry)parameter_entries.next();
-	  String[] paramVals = (String[]) param_entry.getValue();
-	  if(paramVals != null) {
-	      if(paramVals.length > 0) {
-		  logger.error("POST request received: " + param_entry.getKey() + " - " + paramVals[0]);
-		  queryString = queryString + "&" + param_entry.getKey() + "=" + paramVals[0];
-	      }
-	  }	  
-      }
-      if(queryString.length() > 0) {
-	  queryString = queryString.substring(1);
-	  //queryString = OAIXML.oaiEncode(queryString);
-      }
-      if(queryString.equals("")) {
-	  queryString = null;
-      }
-    doGet(request,response);    
-  }
+public class OAIServer extends BaseGreenstoneServlet
+{
+
+	/** the receptionist to send messages to */
+	protected OAIReceptionist recept = null;
+	/**
+	 * the default language - is specified by setting a servlet param, otherwise
+	 * DEFAULT_LANG is used
+	 */
+	protected String default_lang = null;
+	/**
+	 * The default default - used if a default lang is not specified in the
+	 * servlet params
+	 */
+	protected final String DEFAULT_LANG = "en";
+
+	/**
+	 * a converter class to parse XML and create Docs This is only used for
+	 * generating internal requests passed to MessageRouter. The response
+	 * message is generated by parsing an existing xml skeleton file
+	 * (web/WEB-INF/oaixml/oaiversion2.xml, for example).
+	 */
+	protected XMLConverter converter = null;
+	/**
+	 * container Document to create XML Nodes (but only request to the oai
+	 * receptionist, not response (which is created in OAIXML.java) created by
+	 * converter class
+	 */
+	protected Document doc = null;
+
+	/** A HashSet which contains all the legal verbs. */
+	protected HashSet<String> verb_set = null;
+	/**
+	 * A HashSet which contains all the legal oai keys in the key/value argument
+	 * pair.
+	 */
+	protected HashSet<String> param_set = null;
+	/**
+	 * The name of the site with which we will finally be dealing, whether it is
+	 * a local site or a remote site through a communicator.
+	 */
+	protected String site = "";
+
+	// do we output the stylesheet processing instruction?
+	protected boolean use_oai_stylesheet = true;
+	protected String oai_stylesheet = "interfaces/oai/oai2.xsl";
+
+	// there is no getQueryString() method in the HttpServletRequest returned from doPost, 
+	// since that is actually of type apache RequestFacade, and doesn't define such a method
+	protected String queryString = null;
+
+	static Logger logger = Logger.getLogger(org.greenstone.gsdl3.OAIServer.class.getName());
+
+	/**
+	 * initialise the servlet
+	 */
+	public void init(ServletConfig config) throws ServletException
+	{
+		// always call super.init, i.e., HttpServlet.;
+		super.init(config);
+		this.default_lang = config.getInitParameter(GSConstants.DEFAULT_LANG);
+
+		initVerbs();
+		initParams();
+
+		String site_name = config.getInitParameter(GSConstants.SITE_NAME);
+		String remote_site_name = null;
+		String remote_site_type = null;
+		String remote_site_address = null;
+
+		if (site_name == null)
+		{
+			// no local site, try for communicator (remote site)
+			remote_site_name = config.getInitParameter("remote_site_name");
+			remote_site_type = config.getInitParameter("remote_site_type");
+			remote_site_address = config.getInitParameter("remote_site_address");
+			if (remote_site_name == null || remote_site_type == null || remote_site_address == null)
+			{
+				System.err.println("initialisation paramters not all set!");
+				System.err.println("if site_name is not set, then you must have remote_site_name, remote_site_type and remote_site_address set");
+				System.exit(1);
+			}
+		}
+
+		if (this.default_lang == null)
+		{
+			// choose english
+			this.default_lang = DEFAULT_LANG;
+		}
+
+		// the receptionist -the servlet will talk to this
+		this.recept = new OAIReceptionist();
+
+		// the receptionist uses a MessageRouter or Communicator to send its requests to. We either create a MessageRouter here for the designated site (if site_name set), or we create a Communicator for a remote site. The is given to teh Receptionist, and the servlet never talks to it again.directly.
+		if (site_name != null)
+		{
+			//this site_name could consist of comma separated more than one site name.
+			String mr_name = (String) config.getInitParameter("messagerouter_class");
+			MessageRouter message_router = null;
+			if (mr_name == null)
+			{ // just use the normal MR *********
+				message_router = new MessageRouter();
+			}
+			else
+			{ // try the specified one
+				try
+				{
+					message_router = (MessageRouter) Class.forName("org.greenstone.gsdl3.core." + mr_name).newInstance();
+				}
+				catch (Exception e)
+				{ // cant use this new one, so use normal one
+					System.err.println("OAIServlet configure exception when trying to use a new MessageRouter " + mr_name + ": " + e.getMessage());
+					e.printStackTrace();
+					message_router = new MessageRouter();
+				}
+			}
+
+			message_router.setSiteName(site_name);
+			// lots of work is done in this step; see MessageRouter.java
+			message_router.configure();
+			this.recept.setSiteName(site_name);
+			this.recept.setMessageRouter(message_router);
+
+		}
+		else
+		{
+			// talking to a remote site, create a communicator
+			Communicator communicator = null;
+			// we need to create the XML to configure the communicator
+			Element site_elem = this.doc.createElement(GSXML.SITE_ELEM);
+			site_elem.setAttribute(GSXML.TYPE_ATT, remote_site_type);
+			site_elem.setAttribute(GSXML.NAME_ATT, remote_site_name);
+			site_elem.setAttribute(GSXML.ADDRESS_ATT, remote_site_address);
+
+			if (remote_site_type.equals(GSXML.COMM_TYPE_SOAP_JAVA))
+			{
+				communicator = new SOAPCommunicator();
+			}
+			else
+			{
+				System.err.println("OAIServlet.init Error: invalid Communicator type: " + remote_site_type);
+				System.exit(1);
+			}
+
+			if (!communicator.configure(site_elem))
+			{
+				System.err.println("OAIServlet.init Error: Couldn't configure communicator");
+				System.exit(1);
+			}
+			this.recept.setSiteName(remote_site_name);
+			this.recept.setMessageRouter(communicator);
+		}
+		// used for composing internal xml requests, but not xml responses.
+		// the converter may be used to get pretty xml, though.    
+		this.converter = new XMLConverter();
+		this.doc = this.converter.newDOM();
+
+		// Read in OAIConfig.xml (residing web/WEB-INF/classes/) and 
+		//use it to configure the receptionist. The init() is also called in which
+		//the resumption token file is read in and all expired tokens cleared.
+		Element oai_config = OAIXML.getOAIConfigXML();
+		if (oai_config == null)
+		{
+			logger.error("Fail to parse oai config file OAIConfig.xml.");
+			return;
+		}
+		// pass it to the receptionist
+		this.recept.configure(oai_config);
+
+		// also, we have something we want to get from here - useOAIStylesheet
+		this.configure(oai_config);
+	}//end of init()
+
+	private void configure(Element oai_config)
+	{
+		Element use_stylesheet_elem = (Element) GSXML.getChildByTagName(oai_config, OAIXML.USE_STYLESHEET);
+		if (use_stylesheet_elem != null)
+		{
+			String value = GSXML.getNodeText(use_stylesheet_elem);
+			if (value.equals("no"))
+			{
+				this.use_oai_stylesheet = false;
+			}
+		}
+		if (this.use_oai_stylesheet)
+		{
+			// now see if there is a custom stylesheet specified
+			Element stylesheet_elem = (Element) GSXML.getChildByTagName(oai_config, OAIXML.STYLESHEET);
+			if (stylesheet_elem != null)
+			{
+				String value = GSXML.getNodeText(stylesheet_elem);
+				if (!value.equals(""))
+				{
+					oai_stylesheet = value;
+				}
+			}
+
+		}
+	}
+
+	private void initVerbs()
+	{
+		verb_set = new HashSet<String>();
+		verb_set.add(OAIXML.GET_RECORD);
+		verb_set.add(OAIXML.LIST_RECORDS);
+		verb_set.add(OAIXML.LIST_IDENTIFIERS);
+		verb_set.add(OAIXML.LIST_SETS);
+		verb_set.add(OAIXML.LIST_METADATA_FORMATS);
+		verb_set.add(OAIXML.IDENTIFY);
+	}
+
+	private void initParams()
+	{
+		param_set = new HashSet<String>();
+		param_set.add(OAIXML.METADATA_PREFIX);
+		param_set.add(OAIXML.FROM);
+		param_set.add(OAIXML.UNTIL);
+		param_set.add(OAIXML.SET);
+		param_set.add(OAIXML.RESUMPTION_TOKEN);
+		param_set.add(OAIXML.IDENTIFIER);
+	}
+
+	private void logUsageInfo(HttpServletRequest request)
+	{
+		String usageInfo = "";
+
+		String query = (queryString == null) ? request.getQueryString() : queryString;
+
+		//logged info = general-info + session-info
+		usageInfo = request.getContextPath() + " " + //session id
+		request.getServletPath() + " " + //serlvet
+		"[" + query + "]" + " " + //the query string
+		"[" + usageInfo.trim() + "]" + " " + // params stored in a session
+		request.getRemoteAddr() + " " + //remote address
+		request.getHeader("user-agent") + " "; //the remote brower info
+
+		logger.info(usageInfo);
+	}
+
+	/**
+	 * return true if the url is in the form of baseURL?verb=...,
+	 */
+	private boolean validate(String query, String verb)
+	{
+		//Here in OAIServer, only the verbs are validated. All the validation for individual verb
+		// is taken in their doXXX() methods.
+		if (query == null || !query.startsWith(OAIXML.VERB + "="))
+		{
+			return false;
+		}
+		if (!verb_set.contains(verb))
+		{
+			return false;
+		}
+		return true;
+	}
+
+	private String getVerb(String query)
+	{
+		if (query == null)
+			return "";
+		int verb_start_index = query.indexOf("=") + 1;// first occurence of '='
+		int verb_end_index = query.indexOf("&");
+		if (verb_end_index == -1)
+		{
+			return query.substring(verb_start_index);
+		}
+		return query.substring(verb_start_index, verb_end_index);
+	}
+
+	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
+	{
+		logUsageInfo(request);
+		//out.println("url="+request.getRequestURL());// /oaiserver    
+		//out.println("query="+request.getQueryString());// is /greenstone3
+
+		// oai always requires the content type be text/xml
+		request.setCharacterEncoding("UTF-8");
+		response.setContentType("text/xml;charset=UTF-8");
+		PrintWriter out = response.getWriter();
+
+		//
+		String lang = request.getParameter(GSParams.LANGUAGE);
+		if (lang == null || lang.equals(""))
+		{
+			// use the default
+			lang = this.default_lang;
+		}
+		//we don't get the baseURL from the http request because what we get might be different from the one known publicly due to local network redirection.
+		//For example, puka.cs.waikato.ac.nz vs www.greenstone.org
+		//String base_url = request.getRequestURL().toString();
+		// if called by doPost (if this was originally a POST request), var queryString would have been set
+		String query = (queryString == null) ? request.getQueryString() : queryString;
+		queryString = null; // reset member variable, else no doGet will work as long as the server remains running
+
+		String[] pairs = (query == null) ? null : query.split("&");//split into key/value pairs
+		String verb = getVerb(query);
+		Element xml_response = OAIXML.createBasicResponse(verb, pairs);
+		Element verb_elem = null;
+
+		if (validate(query, verb) == false)
+		{
+			if (verb_set.contains(verb) == false)
+			{
+				logger.error(OAIXML.BAD_VERB + ": " + query);
+				verb_elem = OAIXML.createErrorElement(OAIXML.BAD_VERB, OAIXML.ILLEGAL_OAI_VERB);
+			}
+			else
+			{
+				//must be something else other than bad verbs caused an error, so bad argument
+				logger.error(OAIXML.BAD_ARGUMENT + ": " + query);
+				verb_elem = OAIXML.createErrorElement(OAIXML.BAD_ARGUMENT, "");
+			}
+			xml_response.appendChild(verb_elem);
+
+			out.println("<?xml version='1.0' encoding='UTF-8' ?>");
+			if (this.use_oai_stylesheet)
+			{
+				out.println("<?xml-stylesheet type='text/xsl' href='" + this.oai_stylesheet + "' ?>\n");
+			}
+			out.println(this.converter.getPrettyString(xml_response));
+			return;
+		}//end of if(validate
+
+		// The query is valid, we can now
+		// compose the request message to the receptionist
+		Element xml_message = this.doc.createElement(GSXML.MESSAGE_ELEM);
+		Element xml_request = this.doc.createElement(GSXML.REQUEST_ELEM);
+		// The type attribute is set to be 'oaiService' from OAIServer to OAIReceptionist.
+		//xml_request.setAttribute(GSXML.TYPE_ATT, OAIXML.OAI_SERVICE);
+		xml_request.setAttribute(GSXML.LANG_ATT, lang);
+		xml_request.setAttribute(GSXML.TO_ATT, verb);
+		addParams(xml_request, pairs);
+
+		//xml_request.setAttribute(GSXML.OUTPUT_ATT, output);????
+		xml_message.appendChild(xml_request);
+
+		Node xml_result = this.recept.process(xml_message);
+		if (xml_result == null)
+		{
+			logger.info("xml_result is null");
+			verb_elem = OAIXML.createErrorElement("Internal error", "");
+			xml_response.appendChild(verb_elem);
+		}
+		else
+		{
+
+			/**
+			 * All response elements are in the form (with a corresponding verb
+			 * name): <message> <response> <verb> ... <resumptionToken> .. this
+			 * is optional! </resumptionToken> </verb> </response> </message>
+			 */
+			Node res = GSXML.getChildByTagName(xml_result, OAIXML.RESPONSE);
+			if (res == null)
+			{
+				logger.info("response element in xml_result is null");
+				verb_elem = OAIXML.createErrorElement("Internal error", "");
+			}
+			else
+			{
+				verb_elem = GSXML.getFirstElementChild(res);
+			}
+
+			if (OAIXML.oai_version.equals(OAIXML.OAI_VERSION2) || verb_elem.getTagName().equals(OAIXML.ERROR))
+			{
+				xml_response.appendChild(xml_response.getOwnerDocument().importNode(verb_elem, true));
+			}
+			else
+			{
+				GSXML.copyAllChildren(xml_response, verb_elem);
+			}
+		}
+		out.println("<?xml version='1.0' encoding='UTF-8' ?>");
+		if (this.use_oai_stylesheet)
+		{
+			out.println("<?xml-stylesheet type='text/xsl' href='" + this.oai_stylesheet + "' ?>\n");
+		}
+		out.println(this.converter.getPrettyString(xml_response));
+		return;
+	}
+
+	/** append parameter elements to the request sent to the receptionist */
+	public void addParams(Element request, String[] pairs)
+	{
+		// no params apart from the verb
+		if (pairs == null || pairs.length < 2)
+			return;
+
+		/**
+		 * the request xml is composed in the form: <request> <param name=.../>
+		 * <param name=.../> </request> (No paramList element in between).
+		 */
+		for (int i = 1; i < pairs.length; i++)
+		{
+			//the first pair in pairs is the verb=xxx
+			int index = pairs[i].indexOf("=");
+			if (index != -1)
+			{ //just a double check
+				Element param = this.doc.createElement(OAIXML.PARAM);
+				param.setAttribute(OAIXML.NAME, pairs[i].substring(0, index));
+				param.setAttribute(OAIXML.VALUE, OAIXML.oaiDecode(pairs[i].substring(index + 1)));
+				request.appendChild(param);
+			}
+		}
+	}
+
+	// For OAI version 2.0, validation tests indicated that POST needs to be supported. Some
+	// modification was required in order to ensure that the request is passed intact to doGet()
+	public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
+	{
+
+		// the post method returns a wrapper of type RequestFacade by apache and there
+		// is no getQueryString() method defined for it. Therefore, need to work this out
+		// manually before calling doGet(request, response) so that doGet can work as before.
+
+		queryString = "";
+		Iterator parameter_entries = request.getParameterMap().entrySet().iterator();
+		while (parameter_entries.hasNext())
+		{
+			Map.Entry param_entry = (Map.Entry) parameter_entries.next();
+			String[] paramVals = (String[]) param_entry.getValue();
+			if (paramVals != null)
+			{
+				if (paramVals.length > 0)
+				{
+					logger.error("POST request received: " + param_entry.getKey() + " - " + paramVals[0]);
+					queryString = queryString + "&" + param_entry.getKey() + "=" + paramVals[0];
+				}
+			}
+		}
+		if (queryString.length() > 0)
+		{
+			queryString = queryString.substring(1);
+			//queryString = OAIXML.oaiEncode(queryString);
+		}
+		if (queryString.equals(""))
+		{
+			queryString = null;
+		}
+		doGet(request, response);
+	}
 }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Index: /main/trunk/greenstone3/src/java/org/greenstone/gsdl3/service/GS2Browse.java
===================================================================
--- /main/trunk/greenstone3/src/java/org/greenstone/gsdl3/service/GS2Browse.java	(revision 25716)
+++ /main/trunk/greenstone3/src/java/org/greenstone/gsdl3/service/GS2Browse.java	(revision 25717)
@@ -20,23 +20,17 @@
 
 // Greenstone classes
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.StringTokenizer;
+
+import org.apache.log4j.Logger;
+import org.greenstone.gsdl3.util.DBInfo;
+import org.greenstone.gsdl3.util.GS2MacroResolver;
+import org.greenstone.gsdl3.util.GSFile;
+import org.greenstone.gsdl3.util.GSXML;
 import org.greenstone.gsdl3.util.OID;
-import org.greenstone.gsdl3.util.GSXML;
-import org.greenstone.gsdl3.util.GSFile;
-import org.greenstone.gsdl3.util.MacroResolver;
-import org.greenstone.gsdl3.util.GS2MacroResolver;
 import org.greenstone.gsdl3.util.SimpleCollectionDatabase;
-import org.greenstone.gsdl3.util.DBInfo;
-// XML classes
-import org.w3c.dom.Document;
 import org.w3c.dom.Element;
-import org.w3c.dom.NodeList;
-
-// General Java classes
-import java.util.ArrayList;
-import java.util.StringTokenizer;
-import java.util.Set;
-import java.util.Iterator;
-
-import org.apache.log4j.*;
 
 /**
Index: /main/trunk/greenstone3/src/java/org/greenstone/server/Server3.java
===================================================================
--- /main/trunk/greenstone3/src/java/org/greenstone/server/Server3.java	(revision 25716)
+++ /main/trunk/greenstone3/src/java/org/greenstone/server/Server3.java	(revision 25717)
@@ -45,5 +45,5 @@
 	public void reload()
 	{
-		GlobalProperties.reload(); // properties file may have changed, so reload it
+		GlobalProperties.loadGlobalProperties(null); // properties file may have changed, so reload it
 	}
 
Index: /main/trunk/greenstone3/src/java/org/greenstone/util/GlobalProperties.java
===================================================================
--- /main/trunk/greenstone3/src/java/org/greenstone/util/GlobalProperties.java	(revision 25716)
+++ /main/trunk/greenstone3/src/java/org/greenstone/util/GlobalProperties.java	(revision 25717)
@@ -32,17 +32,9 @@
 
 	static Logger logger = Logger.getLogger(org.greenstone.util.GlobalProperties.class.getName());
-	private static Properties properties = null;
+	private static Properties properties = new Properties();
 	private static String properties_filename = "global.properties";
 	private static String gsdl3_home = null;
 	private static String gsdl3_web_address = null;
-        private static String full_gsdl3_web_address = null;
-
-	// Note, that if the servlet is reloadable, then it is reloaded each time the file is changed.
-	static
-	{
-		//load in the properties
-		properties = new Properties();
-		reload();
-	}
+	private static String full_gsdl3_web_address = null;
 
 	/** get the value of the property 'key'. returns null if not found */
@@ -76,14 +68,13 @@
 	}
 
-        public static String getFullGSDL3WebAddress()
+	public static String getFullGSDL3WebAddress()
 	{
 		return full_gsdl3_web_address;
 	}
 
-	public static void reload()
+	public static void loadGlobalProperties(String optionalGS3Home)
 	{
 		try
 		{
-
 			InputStream in = Class.forName("org.greenstone.util.GlobalProperties").getClassLoader().getResourceAsStream(properties_filename);
 			if (in != null)
@@ -97,5 +88,11 @@
 				logger.error("couldn't load global properties!");
 			}
+
 			gsdl3_home = properties.getProperty("gsdl3.home");
+			if ((gsdl3_home == null || gsdl3_home.length() > 0) && optionalGS3Home != null && optionalGS3Home.length() > 0)
+			{
+				gsdl3_home = optionalGS3Home;
+			}
+
 			// make sure the path separators are correct
 			File gs3_file = new File(gsdl3_home);
