Index: /trunk/greenstone3-extensions/gsdl-as/src/org/greenstone/p2p/AbstractClientResponse.java
===================================================================
--- /trunk/greenstone3-extensions/gsdl-as/src/org/greenstone/p2p/AbstractClientResponse.java	(revision 8905)
+++ /trunk/greenstone3-extensions/gsdl-as/src/org/greenstone/p2p/AbstractClientResponse.java	(revision 8905)
@@ -0,0 +1,68 @@
+package org.greenstone.p2p;
+
+import java.util.*;
+
+public class AbstractClientResponse implements ClientResponse
+{ private boolean success;
+  private Map     values;
+
+  public AbstractClientResponse()
+  { this.success = true;
+    this.values  = new HashMap();
+  }
+  
+  public boolean isSuccessful()
+  { return this.success;
+  }
+  
+  public void setSuccessful(boolean success)
+  { this.success = success;
+  }
+  
+  public void addValue(String label, String value)
+  { if (this.values.get(label) == null)
+    { this.setValue(label, value);
+    }
+    else
+    { Vector set = (Vector) this.values.get(label);
+      set.addElement(value);
+    }
+  }
+  
+  public void setValue(String label, String value)
+  { Vector set = new Vector();
+    set.addElement(value);
+    this.values.put(label, set);
+  }
+  
+  public Vector getValues(String label)
+  { return (Vector) this.values.get(label);
+  }
+
+  public Set getLabels()
+  { return this.values.keySet();
+  }
+
+  public String toString()
+  { Iterator keys = this.values.keySet().iterator();
+
+    StringBuffer buffer = new StringBuffer();
+
+    while (keys.hasNext())
+    { String key = keys.next().toString();
+
+      buffer.append("  " +  key + ":\n");
+
+      Vector vals = (Vector) this.values.get(key);
+      Enumeration valist = vals.elements();
+      while (valist.hasMoreElements())
+	{ String nextVal = valist.nextElement().toString();
+
+	  buffer.append("    ");
+	  buffer.append(nextVal);
+	  buffer.append("\n");
+	}
+    }
+    return buffer.toString();
+  }
+}
Index: /trunk/greenstone3-extensions/gsdl-as/src/org/greenstone/p2p/AbstractServerAction.java
===================================================================
--- /trunk/greenstone3-extensions/gsdl-as/src/org/greenstone/p2p/AbstractServerAction.java	(revision 8905)
+++ /trunk/greenstone3-extensions/gsdl-as/src/org/greenstone/p2p/AbstractServerAction.java	(revision 8905)
@@ -0,0 +1,71 @@
+package org.greenstone.p2p;
+
+import java.net.*;
+import java.util.*;
+
+public abstract class AbstractServerAction implements NameServerAction
+{ NameServer host;
+
+  public AbstractServerAction(NameServer host)
+  { this.host = host;
+  }
+
+  public abstract String getActionName();
+  
+  public void propagateAction(URL forwarder, Map parameters)
+  { Enumeration subServers = host.subServers();
+  
+    // poll all child servers
+    while (subServers.hasMoreElements())
+    { URL server = (URL) subServers.nextElement();
+      
+      if (!server.equals(forwarder))
+      { // send server the action
+        String response = this.propagateActionViaServer(server, parameters, forwarder);
+      }
+    }
+    
+    // poll upwards to parent
+    if (host.getParent() != null &&
+	!host.getParent().equals(forwarder))
+    { this.propagateActionViaServer(host.getParent(), parameters, forwarder);
+    }
+  }
+
+  public void doAction(URL forwarder, Map parameters)
+  { // start propagating the action outwards
+    this.propagateAction(forwarder, parameters);
+  
+    // now execute it on our children
+    Enumeration servers = host.servers();
+  
+    while (servers.hasMoreElements())
+    { URL server = (URL) servers.nextElement();
+      
+      if (!server.equals(forwarder))
+      { // send server the action
+        String response = this.doActionOnServer(server, parameters, forwarder);
+      }
+    }
+  }
+  
+  String propagateActionViaServer(URL server, Map paramters, URL responseTo)
+  { String actionName = this.getActionName();
+  
+    // send action to server, in a separate thread
+    // get responses
+    // forward those back
+    return "";
+  }
+  
+  String doActionOnServer(URL server, Map parameters, URL responseTo)
+  { String actionName = this.getActionName();
+  
+    // send action to the destination server (as a URL)
+    
+    // get response (as HTML)
+    
+    // forward it back...
+    return "";
+  }
+}
Index: /trunk/greenstone3-extensions/gsdl-as/src/org/greenstone/p2p/Client.java
===================================================================
--- /trunk/greenstone3-extensions/gsdl-as/src/org/greenstone/p2p/Client.java	(revision 8905)
+++ /trunk/greenstone3-extensions/gsdl-as/src/org/greenstone/p2p/Client.java	(revision 8905)
@@ -0,0 +1,40 @@
+import java.io.*;
+import java.net.*;
+
+public class Client {
+    public static String read() throws IOException {
+
+        Socket echoSocket = null;
+        PrintWriter out = null;
+        BufferedReader in = null;
+
+        try {
+            echoSocket = new Socket("taranis", 7);
+            out = new PrintWriter(echoSocket.getOutputStream(), true);
+            in = new BufferedReader(new InputStreamReader(
+                                        echoSocket.getInputStream()));
+        } catch (UnknownHostException e) {
+            System.err.println("Don't know about host: taranis.");
+            System.exit(1);
+        } catch (IOException e) {
+            System.err.println("Couldn't get I/O for "
+                               + "the connection to: taranis.");
+            System.exit(1);
+        }
+
+        BufferedReader stdIn = new BufferedReader(
+                                   new InputStreamReader(System.in));
+        String userInput;
+
+        while ((userInput = stdIn.readLine()) != null) {
+            out.println(userInput);
+            System.out.println("echo: " + in.readLine());
+        }
+
+        out.close();
+        in.close();
+        stdIn.close();
+        echoSocket.close();
+	return "";
+    }
+}
Index: /trunk/greenstone3-extensions/gsdl-as/src/org/greenstone/p2p/ClientResponse.java
===================================================================
--- /trunk/greenstone3-extensions/gsdl-as/src/org/greenstone/p2p/ClientResponse.java	(revision 8905)
+++ /trunk/greenstone3-extensions/gsdl-as/src/org/greenstone/p2p/ClientResponse.java	(revision 8905)
@@ -0,0 +1,11 @@
+package org.greenstone.p2p;
+
+import java.util.*;
+
+public interface ClientResponse
+{ boolean isSuccessful(); // obvious
+  Vector  getValues(String label); // get the values associated with a given
+                                   // label; which values are available varies
+                                   // from action to action
+  Set     getLabels();             // get the labels in this response
+}
Index: /trunk/greenstone3-extensions/gsdl-as/src/org/greenstone/p2p/DefaultServerAction.java
===================================================================
--- /trunk/greenstone3-extensions/gsdl-as/src/org/greenstone/p2p/DefaultServerAction.java	(revision 8905)
+++ /trunk/greenstone3-extensions/gsdl-as/src/org/greenstone/p2p/DefaultServerAction.java	(revision 8905)
@@ -0,0 +1,13 @@
+package org.greenstone.p2p;
+
+public class DefaultServerAction extends AbstractServerAction
+{ public static final String DEFAULT_ACTION = "default";
+
+  public DefaultServerAction(NameServer host)
+  { super(host);
+  }
+
+  public String getActionName()
+  { return DEFAULT_ACTION;
+  }
+}
Index: /trunk/greenstone3-extensions/gsdl-as/src/org/greenstone/p2p/GreenstoneClient.java
===================================================================
--- /trunk/greenstone3-extensions/gsdl-as/src/org/greenstone/p2p/GreenstoneClient.java	(revision 8905)
+++ /trunk/greenstone3-extensions/gsdl-as/src/org/greenstone/p2p/GreenstoneClient.java	(revision 8905)
@@ -0,0 +1,31 @@
+package org.greenstone.p2p;
+
+import java.util.*;
+import java.net.URL;
+
+public interface GreenstoneClient
+{ /**
+   * This interface needs to be fulfilled by a Greenstone machine wanting to
+   * register and receive messages from the Greenstone Distributed Service.
+   *
+   */
+
+  /**
+   * This method is called by a GDS server when an action (message) has a response
+   * sent in reply.  The Greenstone server that sends the action will have this
+   * method called for each response received from the GDS network.
+   *
+   * @param: <code>NameServerAction</code> - at present, </code>null</code>.
+   * This method *must* be synchronized
+   * @param: <code>ClientResponse</code> - is a simple wrapper for the Map class.
+   * 
+   */
+  public void receiveResponse(NameServerAction action, ClientResponse response);
+
+  /**
+   *
+   */
+  public void receiveMessage(String message, Map parameters);
+  public String getIdentifier();
+  public URL    getURL();
+}
Index: /trunk/greenstone3-extensions/gsdl-as/src/org/greenstone/p2p/GreenstoneInterface.java
===================================================================
--- /trunk/greenstone3-extensions/gsdl-as/src/org/greenstone/p2p/GreenstoneInterface.java	(revision 8905)
+++ /trunk/greenstone3-extensions/gsdl-as/src/org/greenstone/p2p/GreenstoneInterface.java	(revision 8905)
@@ -0,0 +1,94 @@
+
+package org.greenstone.p2p;
+
+import java.net.URL;
+import java.util.*;
+
+/**
+ * This is the class that provides a set of functions for a Greenstone server to call
+ * in order to send information/messages into a GDS network.
+ */
+
+public class GreenstoneInterface
+{ private GreenstoneClient client;
+  private URL              server;
+
+  // temporary variables which will eventually disapper - ignore!
+  private static GreenstoneClient lastClient;
+  private static NameServer       nameServer = null;
+  // end of temporary variables
+
+  /**
+   * Make a new interface with a client that will receive the responses
+   * to any messages sent.
+   *
+   * @param: the client to receive responses to messages sent through this
+   *         interface.
+   */
+  public GreenstoneInterface(GreenstoneClient client)
+  { this.client = client;
+    lastClient = this.client;
+    //    /*this.*/nameServer = null;
+  }
+
+  /**
+   *  Set up a registration for this machine with a GDS server.
+   *
+   *  The Greenstone machine should take care to store the URL of the
+   *  server for later use - don't continually reregister the same
+   *  server!
+   *
+   *  @param: <code>URL</code> the location of the GDS server to register with
+   *
+   *  @return: <code>boolean</code> whether the registration was successful or not.
+   */
+  public boolean registerWithServer(URL server)
+  { // connect to server
+    // 
+    if (/*this.*/nameServer == null) {
+      /*this.*/nameServer = new NameServer(server.toString());
+    }
+    this.server = server;
+    /*this.*/nameServer.registerServer(this.client.getURL());
+
+    return true;
+  }
+
+  /**
+   *  Method to unregister from the current GDS server for this Greenstone
+   *  machine.
+   *
+   *  @return: <code>boolean</code> whether the registration was successful or not.
+   */
+  public boolean unregisterFromServer()
+  { /*this.*/nameServer = null;
+    return true;
+  }
+
+  /**
+   *  Send a message into the GDS system through the current GDS server.
+   *
+   *  Success does not guarantee that you will receive a response.
+   *
+   *  @param: <code>String</code> the identifier for this type of message
+   *  @param: <code>Map</code> a <code>Vector</code> item is associated with
+   *          each key in this map.
+   *
+   *  @return: <code>boolean</code> whether the sending was successful or not.
+   */
+  public boolean sendMessage(String message, Map parameters)
+  { if (/*this.*/nameServer != null)
+      { /*this.*/nameServer.sendMessage(this.client.getURL(), message, parameters);
+    }
+    return false;
+  }
+
+  /**
+   *  Receive a response to a message sent from this Greenstone machine and
+   *  forward it to the current client - won't be needed in the long run, it
+   *  is here at present to provide a route for returning responses.
+   */
+  static public void receiveResponse(URL greenstoneURL, ClientResponse response)
+  { lastClient.receiveResponse(null, response);
+  }
+}
Index: /trunk/greenstone3-extensions/gsdl-as/src/org/greenstone/p2p/GreenstoneServer.java
===================================================================
--- /trunk/greenstone3-extensions/gsdl-as/src/org/greenstone/p2p/GreenstoneServer.java	(revision 8905)
+++ /trunk/greenstone3-extensions/gsdl-as/src/org/greenstone/p2p/GreenstoneServer.java	(revision 8905)
@@ -0,0 +1,20 @@
+package org.greenstone.p2p;
+
+import java.net.URL;
+
+/**
+ *  Simple class to hold the location of a Greenstone server.
+ *
+ *  This class should be subclassed and methods overridden for 
+ *  Greenstone 2, 3 or any special installations such as the
+ *  Music DL.
+ */
+
+public class GreenstoneServer
+{ private URL server;
+  
+  public GreenstoneServer(URL url)
+  { this.server = url;
+  }
+
+}
Index: /trunk/greenstone3-extensions/gsdl-as/src/org/greenstone/p2p/GreenstoneTest.java
===================================================================
--- /trunk/greenstone3-extensions/gsdl-as/src/org/greenstone/p2p/GreenstoneTest.java	(revision 8905)
+++ /trunk/greenstone3-extensions/gsdl-as/src/org/greenstone/p2p/GreenstoneTest.java	(revision 8905)
@@ -0,0 +1,70 @@
+package org.greenstone.p2p;
+
+import java.net.URL;
+import java.util.*;
+
+public class GreenstoneTest implements GreenstoneClient
+{ String name;
+  URL    url;
+  
+  public GreenstoneTest(String id, String url)
+  { try {
+      this.url = new URL(url);
+    }
+    catch (java.net.MalformedURLException malEx)
+      { this.url = null;
+      }
+    this.name = id;
+  }
+
+  public void receiveResponse(NameServerAction action, ClientResponse response)
+  {
+    System.out.println("\n----\nReceived a response:");
+    System.out.println(response.toString());
+  }
+
+  public void receiveMessage(String message, Map parameters)
+  {
+  }
+
+  public String getIdentifier()
+  { return this.name;
+  }
+
+  public URL getURL()
+  { return this.url;
+  }
+
+  /**
+   *  arg[0] => identifier for this machine
+   *  arg[1] => a url for this machine
+   *  arg[2] => a url for the GDS server
+   *
+   * e.g. run with:
+   * "java org.greenstone.p2p.GreenstoneTest localhost http://localhost http://www.nzdl.org"
+   */
+  public static void main(String args[])
+  { GreenstoneClient client = new GreenstoneTest(args[0], args[1]);
+    GreenstoneClient gsdl   = new GreenstoneTest("gsdl", "http://www.gsdl.org");
+    
+    URL server;
+    try
+      {
+	server = new URL(args[2]);
+      }
+    catch (java.net.MalformedURLException malEx)
+      { server = null;
+      }
+    
+    GreenstoneInterface gsdlIface = new GreenstoneInterface(gsdl);
+    gsdlIface.registerWithServer(server);
+
+    GreenstoneInterface iface = new GreenstoneInterface(client);
+    iface.registerWithServer(server);
+
+    Map parameters = new HashMap();
+    iface.sendMessage("ListServers", parameters);
+
+    iface.sendMessage("DocDelta", parameters);
+  }
+}
Index: /trunk/greenstone3-extensions/gsdl-as/src/org/greenstone/p2p/ListServersAction.java
===================================================================
--- /trunk/greenstone3-extensions/gsdl-as/src/org/greenstone/p2p/ListServersAction.java	(revision 8905)
+++ /trunk/greenstone3-extensions/gsdl-as/src/org/greenstone/p2p/ListServersAction.java	(revision 8905)
@@ -0,0 +1,35 @@
+package org.greenstone.p2p;
+
+import java.util.*;
+import java.net.URL;
+
+public class ListServersAction extends AbstractServerAction
+{ public String LISTSERVERS = "ListServers";
+
+  public ListServersAction(NameServer host)
+  { super(host);
+  }
+
+  public String getActionName()
+  { return LISTSERVERS;
+  }
+  
+  public void doAction(URL forwarder, Map parameters)
+  { this.propagateAction(forwarder, parameters);
+  
+    // Build a list of all servers
+    AbstractClientResponse response = new AbstractClientResponse();
+
+    Enumeration servers = this.host.servers();
+    while (servers.hasMoreElements())
+      { URL gsServer = (URL) servers.nextElement();
+	System.out.println("Adding listserver item " + gsServer);
+
+	response.addValue("Server", gsServer.toString());
+      }
+    response.setSuccessful(true);
+
+    // Send it back to the forwarder right now...
+    this.host.receiveResponse(forwarder, response);
+  }
+}
Index: /trunk/greenstone3-extensions/gsdl-as/src/org/greenstone/p2p/NameServer.java
===================================================================
--- /trunk/greenstone3-extensions/gsdl-as/src/org/greenstone/p2p/NameServer.java	(revision 8905)
+++ /trunk/greenstone3-extensions/gsdl-as/src/org/greenstone/p2p/NameServer.java	(revision 8905)
@@ -0,0 +1,124 @@
+package org.greenstone.p2p;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+
+public class NameServer
+{ ServerList list;
+  URL        parent;
+  Vector     childServers; // name servers
+  Vector     children;     // greenstone servers
+  String     identity;
+  Map        actionMap;
+ 
+  public NameServer(String identity)
+  { this.list     = new ServerList();
+    this.identity = identity;
+    this.parent   = null;
+    this.children = new Vector();
+    this.childServers = new Vector();
+
+    this.actionMap = new HashMap();
+
+    NameServerAction listServersAction = new ListServersAction(this);
+    this.addAction(listServersAction);
+    NameServerAction defaultAction = new DefaultServerAction(this);
+    this.addAction(defaultAction);
+    
+    // set up registration listener
+    // set up messaging broadcaster
+    // set up messaging listener
+  }
+
+  private void addAction(NameServerAction action)
+  { this.actionMap.put(action.getActionName(), action);
+  }
+
+  private void loadChildren(BufferedReader in)
+  { try 
+      { String child = in.readLine();
+      }
+    catch (IOException ex)
+      {
+      }
+  }
+
+  private void loadServers(BufferedReader in)
+  { try
+      { String child = in.readLine();
+      }
+    catch (IOException io)
+      {
+      }
+  }
+
+  public void sendMessage(URL origin, String actionName, Map parameters)
+  { NameServerAction action = (NameServerAction) this.actionMap.get(actionName);
+    if (action != null)
+      { action.doAction(origin, parameters);
+      }
+    else
+      { System.out.println("Sending action " + actionName + " through <default>");
+
+	// TODO: add action name to the parameter map so that it is not lost...
+	action = (NameServerAction) this.actionMap.get("Default");
+	if (action != null)
+	{ action.doAction(origin, parameters);
+	}
+      }
+    //NameServerAction action = NameServerActionFactory.createAction(action, parameters);
+    //action.doAction();
+  }
+
+  public void receiveResponse(URL responseTo, ClientResponse response)
+  { GreenstoneInterface.receiveResponse(responseTo, response);
+  }
+    
+  private void loadParent()
+  {
+  }
+
+  public String getIdentity()
+  { return this.identity;
+  }
+  
+  public void setParent(URL parent)
+  { this.parent = parent;
+  }
+  
+  public URL getParent()
+  { return this.parent;
+  }
+  
+  public void addSubServer(URL subserver)
+  { this.childServers.add(subserver);
+  }
+  
+  public void registerServer(URL child)
+  { System.out.println("Receiving registration from " + child.toString());
+    this.children.add(child);
+  }
+  
+  public Enumeration subServers()
+  { return this.childServers.elements();
+  }
+  
+  public Enumeration servers()
+  { return this.children.elements();
+  }
+
+  public static boolean pollServer(URL server)
+  { return false;
+  }
+
+  /**
+   *  
+   */
+  public static void main(String args[])
+  { NameServer server = new NameServer(args[0]);
+
+    // Load the action items
+    // Wait for signals
+  }
+}
Index: /trunk/greenstone3-extensions/gsdl-as/src/org/greenstone/p2p/NameServerAction.java
===================================================================
--- /trunk/greenstone3-extensions/gsdl-as/src/org/greenstone/p2p/NameServerAction.java	(revision 8905)
+++ /trunk/greenstone3-extensions/gsdl-as/src/org/greenstone/p2p/NameServerAction.java	(revision 8905)
@@ -0,0 +1,10 @@
+package org.greenstone.p2p;
+
+import java.util.Map;
+import java.net.URL;
+
+public interface NameServerAction
+{ public String getActionName();
+  public void   doAction(URL forwarder, Map parameters);
+  public void   propagateAction(URL forwarder, Map parameters);
+}
Index: /trunk/greenstone3-extensions/gsdl-as/src/org/greenstone/p2p/NameServerActionFactory.java
===================================================================
--- /trunk/greenstone3-extensions/gsdl-as/src/org/greenstone/p2p/NameServerActionFactory.java	(revision 8905)
+++ /trunk/greenstone3-extensions/gsdl-as/src/org/greenstone/p2p/NameServerActionFactory.java	(revision 8905)
@@ -0,0 +1,9 @@
+package org.greenstone.p2p;
+
+import java.util.Map;
+
+public class NameServerActionFactory
+{ public NameServerAction createAction(String actionName, Map parameters)
+  { return null;
+  }
+}
Index: /trunk/greenstone3-extensions/gsdl-as/src/org/greenstone/p2p/NameServerRegistrationThread.java
===================================================================
--- /trunk/greenstone3-extensions/gsdl-as/src/org/greenstone/p2p/NameServerRegistrationThread.java	(revision 8905)
+++ /trunk/greenstone3-extensions/gsdl-as/src/org/greenstone/p2p/NameServerRegistrationThread.java	(revision 8905)
@@ -0,0 +1,16 @@
+package org.greenstone.p2p;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+
+public class NameServerRegistrationThread extends Thread
+{ public void run() 
+  { /*try
+    {
+    }
+    catch (IOException ex)
+    {
+    }*/
+  }
+}
Index: /trunk/greenstone3-extensions/gsdl-as/src/org/greenstone/p2p/ServerList.java
===================================================================
--- /trunk/greenstone3-extensions/gsdl-as/src/org/greenstone/p2p/ServerList.java	(revision 8905)
+++ /trunk/greenstone3-extensions/gsdl-as/src/org/greenstone/p2p/ServerList.java	(revision 8905)
@@ -0,0 +1,19 @@
+package org.greenstone.p2p;
+
+import java.util.*;
+
+public class ServerList
+{ Map map;
+
+  public ServerList()
+  { this.map = new HashMap();
+  }
+  
+  public void addServer(GreenstoneServer server)
+  { this.map.put(server, server);
+  }
+  
+  Iterator servers()
+  { return ((Collection)this.map.values()).iterator();
+  }
+}
Index: /trunk/gsdl3/extensions/gsdl-as/src/org/greenstone/p2p/AbstractClientResponse.java
===================================================================
--- /trunk/gsdl3/extensions/gsdl-as/src/org/greenstone/p2p/AbstractClientResponse.java	(revision 8905)
+++ /trunk/gsdl3/extensions/gsdl-as/src/org/greenstone/p2p/AbstractClientResponse.java	(revision 8905)
@@ -0,0 +1,68 @@
+package org.greenstone.p2p;
+
+import java.util.*;
+
+public class AbstractClientResponse implements ClientResponse
+{ private boolean success;
+  private Map     values;
+
+  public AbstractClientResponse()
+  { this.success = true;
+    this.values  = new HashMap();
+  }
+  
+  public boolean isSuccessful()
+  { return this.success;
+  }
+  
+  public void setSuccessful(boolean success)
+  { this.success = success;
+  }
+  
+  public void addValue(String label, String value)
+  { if (this.values.get(label) == null)
+    { this.setValue(label, value);
+    }
+    else
+    { Vector set = (Vector) this.values.get(label);
+      set.addElement(value);
+    }
+  }
+  
+  public void setValue(String label, String value)
+  { Vector set = new Vector();
+    set.addElement(value);
+    this.values.put(label, set);
+  }
+  
+  public Vector getValues(String label)
+  { return (Vector) this.values.get(label);
+  }
+
+  public Set getLabels()
+  { return this.values.keySet();
+  }
+
+  public String toString()
+  { Iterator keys = this.values.keySet().iterator();
+
+    StringBuffer buffer = new StringBuffer();
+
+    while (keys.hasNext())
+    { String key = keys.next().toString();
+
+      buffer.append("  " +  key + ":\n");
+
+      Vector vals = (Vector) this.values.get(key);
+      Enumeration valist = vals.elements();
+      while (valist.hasMoreElements())
+	{ String nextVal = valist.nextElement().toString();
+
+	  buffer.append("    ");
+	  buffer.append(nextVal);
+	  buffer.append("\n");
+	}
+    }
+    return buffer.toString();
+  }
+}
Index: /trunk/gsdl3/extensions/gsdl-as/src/org/greenstone/p2p/AbstractServerAction.java
===================================================================
--- /trunk/gsdl3/extensions/gsdl-as/src/org/greenstone/p2p/AbstractServerAction.java	(revision 8905)
+++ /trunk/gsdl3/extensions/gsdl-as/src/org/greenstone/p2p/AbstractServerAction.java	(revision 8905)
@@ -0,0 +1,71 @@
+package org.greenstone.p2p;
+
+import java.net.*;
+import java.util.*;
+
+public abstract class AbstractServerAction implements NameServerAction
+{ NameServer host;
+
+  public AbstractServerAction(NameServer host)
+  { this.host = host;
+  }
+
+  public abstract String getActionName();
+  
+  public void propagateAction(URL forwarder, Map parameters)
+  { Enumeration subServers = host.subServers();
+  
+    // poll all child servers
+    while (subServers.hasMoreElements())
+    { URL server = (URL) subServers.nextElement();
+      
+      if (!server.equals(forwarder))
+      { // send server the action
+        String response = this.propagateActionViaServer(server, parameters, forwarder);
+      }
+    }
+    
+    // poll upwards to parent
+    if (host.getParent() != null &&
+	!host.getParent().equals(forwarder))
+    { this.propagateActionViaServer(host.getParent(), parameters, forwarder);
+    }
+  }
+
+  public void doAction(URL forwarder, Map parameters)
+  { // start propagating the action outwards
+    this.propagateAction(forwarder, parameters);
+  
+    // now execute it on our children
+    Enumeration servers = host.servers();
+  
+    while (servers.hasMoreElements())
+    { URL server = (URL) servers.nextElement();
+      
+      if (!server.equals(forwarder))
+      { // send server the action
+        String response = this.doActionOnServer(server, parameters, forwarder);
+      }
+    }
+  }
+  
+  String propagateActionViaServer(URL server, Map paramters, URL responseTo)
+  { String actionName = this.getActionName();
+  
+    // send action to server, in a separate thread
+    // get responses
+    // forward those back
+    return "";
+  }
+  
+  String doActionOnServer(URL server, Map parameters, URL responseTo)
+  { String actionName = this.getActionName();
+  
+    // send action to the destination server (as a URL)
+    
+    // get response (as HTML)
+    
+    // forward it back...
+    return "";
+  }
+}
Index: /trunk/gsdl3/extensions/gsdl-as/src/org/greenstone/p2p/Client.java
===================================================================
--- /trunk/gsdl3/extensions/gsdl-as/src/org/greenstone/p2p/Client.java	(revision 8905)
+++ /trunk/gsdl3/extensions/gsdl-as/src/org/greenstone/p2p/Client.java	(revision 8905)
@@ -0,0 +1,40 @@
+import java.io.*;
+import java.net.*;
+
+public class Client {
+    public static String read() throws IOException {
+
+        Socket echoSocket = null;
+        PrintWriter out = null;
+        BufferedReader in = null;
+
+        try {
+            echoSocket = new Socket("taranis", 7);
+            out = new PrintWriter(echoSocket.getOutputStream(), true);
+            in = new BufferedReader(new InputStreamReader(
+                                        echoSocket.getInputStream()));
+        } catch (UnknownHostException e) {
+            System.err.println("Don't know about host: taranis.");
+            System.exit(1);
+        } catch (IOException e) {
+            System.err.println("Couldn't get I/O for "
+                               + "the connection to: taranis.");
+            System.exit(1);
+        }
+
+        BufferedReader stdIn = new BufferedReader(
+                                   new InputStreamReader(System.in));
+        String userInput;
+
+        while ((userInput = stdIn.readLine()) != null) {
+            out.println(userInput);
+            System.out.println("echo: " + in.readLine());
+        }
+
+        out.close();
+        in.close();
+        stdIn.close();
+        echoSocket.close();
+	return "";
+    }
+}
Index: /trunk/gsdl3/extensions/gsdl-as/src/org/greenstone/p2p/ClientResponse.java
===================================================================
--- /trunk/gsdl3/extensions/gsdl-as/src/org/greenstone/p2p/ClientResponse.java	(revision 8905)
+++ /trunk/gsdl3/extensions/gsdl-as/src/org/greenstone/p2p/ClientResponse.java	(revision 8905)
@@ -0,0 +1,11 @@
+package org.greenstone.p2p;
+
+import java.util.*;
+
+public interface ClientResponse
+{ boolean isSuccessful(); // obvious
+  Vector  getValues(String label); // get the values associated with a given
+                                   // label; which values are available varies
+                                   // from action to action
+  Set     getLabels();             // get the labels in this response
+}
Index: /trunk/gsdl3/extensions/gsdl-as/src/org/greenstone/p2p/DefaultServerAction.java
===================================================================
--- /trunk/gsdl3/extensions/gsdl-as/src/org/greenstone/p2p/DefaultServerAction.java	(revision 8905)
+++ /trunk/gsdl3/extensions/gsdl-as/src/org/greenstone/p2p/DefaultServerAction.java	(revision 8905)
@@ -0,0 +1,13 @@
+package org.greenstone.p2p;
+
+public class DefaultServerAction extends AbstractServerAction
+{ public static final String DEFAULT_ACTION = "default";
+
+  public DefaultServerAction(NameServer host)
+  { super(host);
+  }
+
+  public String getActionName()
+  { return DEFAULT_ACTION;
+  }
+}
Index: /trunk/gsdl3/extensions/gsdl-as/src/org/greenstone/p2p/GreenstoneClient.java
===================================================================
--- /trunk/gsdl3/extensions/gsdl-as/src/org/greenstone/p2p/GreenstoneClient.java	(revision 8905)
+++ /trunk/gsdl3/extensions/gsdl-as/src/org/greenstone/p2p/GreenstoneClient.java	(revision 8905)
@@ -0,0 +1,31 @@
+package org.greenstone.p2p;
+
+import java.util.*;
+import java.net.URL;
+
+public interface GreenstoneClient
+{ /**
+   * This interface needs to be fulfilled by a Greenstone machine wanting to
+   * register and receive messages from the Greenstone Distributed Service.
+   *
+   */
+
+  /**
+   * This method is called by a GDS server when an action (message) has a response
+   * sent in reply.  The Greenstone server that sends the action will have this
+   * method called for each response received from the GDS network.
+   *
+   * @param: <code>NameServerAction</code> - at present, </code>null</code>.
+   * This method *must* be synchronized
+   * @param: <code>ClientResponse</code> - is a simple wrapper for the Map class.
+   * 
+   */
+  public void receiveResponse(NameServerAction action, ClientResponse response);
+
+  /**
+   *
+   */
+  public void receiveMessage(String message, Map parameters);
+  public String getIdentifier();
+  public URL    getURL();
+}
Index: /trunk/gsdl3/extensions/gsdl-as/src/org/greenstone/p2p/GreenstoneInterface.java
===================================================================
--- /trunk/gsdl3/extensions/gsdl-as/src/org/greenstone/p2p/GreenstoneInterface.java	(revision 8905)
+++ /trunk/gsdl3/extensions/gsdl-as/src/org/greenstone/p2p/GreenstoneInterface.java	(revision 8905)
@@ -0,0 +1,94 @@
+
+package org.greenstone.p2p;
+
+import java.net.URL;
+import java.util.*;
+
+/**
+ * This is the class that provides a set of functions for a Greenstone server to call
+ * in order to send information/messages into a GDS network.
+ */
+
+public class GreenstoneInterface
+{ private GreenstoneClient client;
+  private URL              server;
+
+  // temporary variables which will eventually disapper - ignore!
+  private static GreenstoneClient lastClient;
+  private static NameServer       nameServer = null;
+  // end of temporary variables
+
+  /**
+   * Make a new interface with a client that will receive the responses
+   * to any messages sent.
+   *
+   * @param: the client to receive responses to messages sent through this
+   *         interface.
+   */
+  public GreenstoneInterface(GreenstoneClient client)
+  { this.client = client;
+    lastClient = this.client;
+    //    /*this.*/nameServer = null;
+  }
+
+  /**
+   *  Set up a registration for this machine with a GDS server.
+   *
+   *  The Greenstone machine should take care to store the URL of the
+   *  server for later use - don't continually reregister the same
+   *  server!
+   *
+   *  @param: <code>URL</code> the location of the GDS server to register with
+   *
+   *  @return: <code>boolean</code> whether the registration was successful or not.
+   */
+  public boolean registerWithServer(URL server)
+  { // connect to server
+    // 
+    if (/*this.*/nameServer == null) {
+      /*this.*/nameServer = new NameServer(server.toString());
+    }
+    this.server = server;
+    /*this.*/nameServer.registerServer(this.client.getURL());
+
+    return true;
+  }
+
+  /**
+   *  Method to unregister from the current GDS server for this Greenstone
+   *  machine.
+   *
+   *  @return: <code>boolean</code> whether the registration was successful or not.
+   */
+  public boolean unregisterFromServer()
+  { /*this.*/nameServer = null;
+    return true;
+  }
+
+  /**
+   *  Send a message into the GDS system through the current GDS server.
+   *
+   *  Success does not guarantee that you will receive a response.
+   *
+   *  @param: <code>String</code> the identifier for this type of message
+   *  @param: <code>Map</code> a <code>Vector</code> item is associated with
+   *          each key in this map.
+   *
+   *  @return: <code>boolean</code> whether the sending was successful or not.
+   */
+  public boolean sendMessage(String message, Map parameters)
+  { if (/*this.*/nameServer != null)
+      { /*this.*/nameServer.sendMessage(this.client.getURL(), message, parameters);
+    }
+    return false;
+  }
+
+  /**
+   *  Receive a response to a message sent from this Greenstone machine and
+   *  forward it to the current client - won't be needed in the long run, it
+   *  is here at present to provide a route for returning responses.
+   */
+  static public void receiveResponse(URL greenstoneURL, ClientResponse response)
+  { lastClient.receiveResponse(null, response);
+  }
+}
Index: /trunk/gsdl3/extensions/gsdl-as/src/org/greenstone/p2p/GreenstoneServer.java
===================================================================
--- /trunk/gsdl3/extensions/gsdl-as/src/org/greenstone/p2p/GreenstoneServer.java	(revision 8905)
+++ /trunk/gsdl3/extensions/gsdl-as/src/org/greenstone/p2p/GreenstoneServer.java	(revision 8905)
@@ -0,0 +1,20 @@
+package org.greenstone.p2p;
+
+import java.net.URL;
+
+/**
+ *  Simple class to hold the location of a Greenstone server.
+ *
+ *  This class should be subclassed and methods overridden for 
+ *  Greenstone 2, 3 or any special installations such as the
+ *  Music DL.
+ */
+
+public class GreenstoneServer
+{ private URL server;
+  
+  public GreenstoneServer(URL url)
+  { this.server = url;
+  }
+
+}
Index: /trunk/gsdl3/extensions/gsdl-as/src/org/greenstone/p2p/GreenstoneTest.java
===================================================================
--- /trunk/gsdl3/extensions/gsdl-as/src/org/greenstone/p2p/GreenstoneTest.java	(revision 8905)
+++ /trunk/gsdl3/extensions/gsdl-as/src/org/greenstone/p2p/GreenstoneTest.java	(revision 8905)
@@ -0,0 +1,70 @@
+package org.greenstone.p2p;
+
+import java.net.URL;
+import java.util.*;
+
+public class GreenstoneTest implements GreenstoneClient
+{ String name;
+  URL    url;
+  
+  public GreenstoneTest(String id, String url)
+  { try {
+      this.url = new URL(url);
+    }
+    catch (java.net.MalformedURLException malEx)
+      { this.url = null;
+      }
+    this.name = id;
+  }
+
+  public void receiveResponse(NameServerAction action, ClientResponse response)
+  {
+    System.out.println("\n----\nReceived a response:");
+    System.out.println(response.toString());
+  }
+
+  public void receiveMessage(String message, Map parameters)
+  {
+  }
+
+  public String getIdentifier()
+  { return this.name;
+  }
+
+  public URL getURL()
+  { return this.url;
+  }
+
+  /**
+   *  arg[0] => identifier for this machine
+   *  arg[1] => a url for this machine
+   *  arg[2] => a url for the GDS server
+   *
+   * e.g. run with:
+   * "java org.greenstone.p2p.GreenstoneTest localhost http://localhost http://www.nzdl.org"
+   */
+  public static void main(String args[])
+  { GreenstoneClient client = new GreenstoneTest(args[0], args[1]);
+    GreenstoneClient gsdl   = new GreenstoneTest("gsdl", "http://www.gsdl.org");
+    
+    URL server;
+    try
+      {
+	server = new URL(args[2]);
+      }
+    catch (java.net.MalformedURLException malEx)
+      { server = null;
+      }
+    
+    GreenstoneInterface gsdlIface = new GreenstoneInterface(gsdl);
+    gsdlIface.registerWithServer(server);
+
+    GreenstoneInterface iface = new GreenstoneInterface(client);
+    iface.registerWithServer(server);
+
+    Map parameters = new HashMap();
+    iface.sendMessage("ListServers", parameters);
+
+    iface.sendMessage("DocDelta", parameters);
+  }
+}
Index: /trunk/gsdl3/extensions/gsdl-as/src/org/greenstone/p2p/ListServersAction.java
===================================================================
--- /trunk/gsdl3/extensions/gsdl-as/src/org/greenstone/p2p/ListServersAction.java	(revision 8905)
+++ /trunk/gsdl3/extensions/gsdl-as/src/org/greenstone/p2p/ListServersAction.java	(revision 8905)
@@ -0,0 +1,35 @@
+package org.greenstone.p2p;
+
+import java.util.*;
+import java.net.URL;
+
+public class ListServersAction extends AbstractServerAction
+{ public String LISTSERVERS = "ListServers";
+
+  public ListServersAction(NameServer host)
+  { super(host);
+  }
+
+  public String getActionName()
+  { return LISTSERVERS;
+  }
+  
+  public void doAction(URL forwarder, Map parameters)
+  { this.propagateAction(forwarder, parameters);
+  
+    // Build a list of all servers
+    AbstractClientResponse response = new AbstractClientResponse();
+
+    Enumeration servers = this.host.servers();
+    while (servers.hasMoreElements())
+      { URL gsServer = (URL) servers.nextElement();
+	System.out.println("Adding listserver item " + gsServer);
+
+	response.addValue("Server", gsServer.toString());
+      }
+    response.setSuccessful(true);
+
+    // Send it back to the forwarder right now...
+    this.host.receiveResponse(forwarder, response);
+  }
+}
Index: /trunk/gsdl3/extensions/gsdl-as/src/org/greenstone/p2p/NameServer.java
===================================================================
--- /trunk/gsdl3/extensions/gsdl-as/src/org/greenstone/p2p/NameServer.java	(revision 8905)
+++ /trunk/gsdl3/extensions/gsdl-as/src/org/greenstone/p2p/NameServer.java	(revision 8905)
@@ -0,0 +1,124 @@
+package org.greenstone.p2p;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+
+public class NameServer
+{ ServerList list;
+  URL        parent;
+  Vector     childServers; // name servers
+  Vector     children;     // greenstone servers
+  String     identity;
+  Map        actionMap;
+ 
+  public NameServer(String identity)
+  { this.list     = new ServerList();
+    this.identity = identity;
+    this.parent   = null;
+    this.children = new Vector();
+    this.childServers = new Vector();
+
+    this.actionMap = new HashMap();
+
+    NameServerAction listServersAction = new ListServersAction(this);
+    this.addAction(listServersAction);
+    NameServerAction defaultAction = new DefaultServerAction(this);
+    this.addAction(defaultAction);
+    
+    // set up registration listener
+    // set up messaging broadcaster
+    // set up messaging listener
+  }
+
+  private void addAction(NameServerAction action)
+  { this.actionMap.put(action.getActionName(), action);
+  }
+
+  private void loadChildren(BufferedReader in)
+  { try 
+      { String child = in.readLine();
+      }
+    catch (IOException ex)
+      {
+      }
+  }
+
+  private void loadServers(BufferedReader in)
+  { try
+      { String child = in.readLine();
+      }
+    catch (IOException io)
+      {
+      }
+  }
+
+  public void sendMessage(URL origin, String actionName, Map parameters)
+  { NameServerAction action = (NameServerAction) this.actionMap.get(actionName);
+    if (action != null)
+      { action.doAction(origin, parameters);
+      }
+    else
+      { System.out.println("Sending action " + actionName + " through <default>");
+
+	// TODO: add action name to the parameter map so that it is not lost...
+	action = (NameServerAction) this.actionMap.get("Default");
+	if (action != null)
+	{ action.doAction(origin, parameters);
+	}
+      }
+    //NameServerAction action = NameServerActionFactory.createAction(action, parameters);
+    //action.doAction();
+  }
+
+  public void receiveResponse(URL responseTo, ClientResponse response)
+  { GreenstoneInterface.receiveResponse(responseTo, response);
+  }
+    
+  private void loadParent()
+  {
+  }
+
+  public String getIdentity()
+  { return this.identity;
+  }
+  
+  public void setParent(URL parent)
+  { this.parent = parent;
+  }
+  
+  public URL getParent()
+  { return this.parent;
+  }
+  
+  public void addSubServer(URL subserver)
+  { this.childServers.add(subserver);
+  }
+  
+  public void registerServer(URL child)
+  { System.out.println("Receiving registration from " + child.toString());
+    this.children.add(child);
+  }
+  
+  public Enumeration subServers()
+  { return this.childServers.elements();
+  }
+  
+  public Enumeration servers()
+  { return this.children.elements();
+  }
+
+  public static boolean pollServer(URL server)
+  { return false;
+  }
+
+  /**
+   *  
+   */
+  public static void main(String args[])
+  { NameServer server = new NameServer(args[0]);
+
+    // Load the action items
+    // Wait for signals
+  }
+}
Index: /trunk/gsdl3/extensions/gsdl-as/src/org/greenstone/p2p/NameServerAction.java
===================================================================
--- /trunk/gsdl3/extensions/gsdl-as/src/org/greenstone/p2p/NameServerAction.java	(revision 8905)
+++ /trunk/gsdl3/extensions/gsdl-as/src/org/greenstone/p2p/NameServerAction.java	(revision 8905)
@@ -0,0 +1,10 @@
+package org.greenstone.p2p;
+
+import java.util.Map;
+import java.net.URL;
+
+public interface NameServerAction
+{ public String getActionName();
+  public void   doAction(URL forwarder, Map parameters);
+  public void   propagateAction(URL forwarder, Map parameters);
+}
Index: /trunk/gsdl3/extensions/gsdl-as/src/org/greenstone/p2p/NameServerActionFactory.java
===================================================================
--- /trunk/gsdl3/extensions/gsdl-as/src/org/greenstone/p2p/NameServerActionFactory.java	(revision 8905)
+++ /trunk/gsdl3/extensions/gsdl-as/src/org/greenstone/p2p/NameServerActionFactory.java	(revision 8905)
@@ -0,0 +1,9 @@
+package org.greenstone.p2p;
+
+import java.util.Map;
+
+public class NameServerActionFactory
+{ public NameServerAction createAction(String actionName, Map parameters)
+  { return null;
+  }
+}
Index: /trunk/gsdl3/extensions/gsdl-as/src/org/greenstone/p2p/NameServerRegistrationThread.java
===================================================================
--- /trunk/gsdl3/extensions/gsdl-as/src/org/greenstone/p2p/NameServerRegistrationThread.java	(revision 8905)
+++ /trunk/gsdl3/extensions/gsdl-as/src/org/greenstone/p2p/NameServerRegistrationThread.java	(revision 8905)
@@ -0,0 +1,16 @@
+package org.greenstone.p2p;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+
+public class NameServerRegistrationThread extends Thread
+{ public void run() 
+  { /*try
+    {
+    }
+    catch (IOException ex)
+    {
+    }*/
+  }
+}
Index: /trunk/gsdl3/extensions/gsdl-as/src/org/greenstone/p2p/ServerList.java
===================================================================
--- /trunk/gsdl3/extensions/gsdl-as/src/org/greenstone/p2p/ServerList.java	(revision 8905)
+++ /trunk/gsdl3/extensions/gsdl-as/src/org/greenstone/p2p/ServerList.java	(revision 8905)
@@ -0,0 +1,19 @@
+package org.greenstone.p2p;
+
+import java.util.*;
+
+public class ServerList
+{ Map map;
+
+  public ServerList()
+  { this.map = new HashMap();
+  }
+  
+  public void addServer(GreenstoneServer server)
+  { this.map.put(server, server);
+  }
+  
+  Iterator servers()
+  { return ((Collection)this.map.values()).iterator();
+  }
+}
Index: /trunk/gsdl3/packages/gsdl-as/src/org/greenstone/p2p/AbstractClientResponse.java
===================================================================
--- /trunk/gsdl3/packages/gsdl-as/src/org/greenstone/p2p/AbstractClientResponse.java	(revision 8905)
+++ /trunk/gsdl3/packages/gsdl-as/src/org/greenstone/p2p/AbstractClientResponse.java	(revision 8905)
@@ -0,0 +1,68 @@
+package org.greenstone.p2p;
+
+import java.util.*;
+
+public class AbstractClientResponse implements ClientResponse
+{ private boolean success;
+  private Map     values;
+
+  public AbstractClientResponse()
+  { this.success = true;
+    this.values  = new HashMap();
+  }
+  
+  public boolean isSuccessful()
+  { return this.success;
+  }
+  
+  public void setSuccessful(boolean success)
+  { this.success = success;
+  }
+  
+  public void addValue(String label, String value)
+  { if (this.values.get(label) == null)
+    { this.setValue(label, value);
+    }
+    else
+    { Vector set = (Vector) this.values.get(label);
+      set.addElement(value);
+    }
+  }
+  
+  public void setValue(String label, String value)
+  { Vector set = new Vector();
+    set.addElement(value);
+    this.values.put(label, set);
+  }
+  
+  public Vector getValues(String label)
+  { return (Vector) this.values.get(label);
+  }
+
+  public Set getLabels()
+  { return this.values.keySet();
+  }
+
+  public String toString()
+  { Iterator keys = this.values.keySet().iterator();
+
+    StringBuffer buffer = new StringBuffer();
+
+    while (keys.hasNext())
+    { String key = keys.next().toString();
+
+      buffer.append("  " +  key + ":\n");
+
+      Vector vals = (Vector) this.values.get(key);
+      Enumeration valist = vals.elements();
+      while (valist.hasMoreElements())
+	{ String nextVal = valist.nextElement().toString();
+
+	  buffer.append("    ");
+	  buffer.append(nextVal);
+	  buffer.append("\n");
+	}
+    }
+    return buffer.toString();
+  }
+}
Index: /trunk/gsdl3/packages/gsdl-as/src/org/greenstone/p2p/AbstractServerAction.java
===================================================================
--- /trunk/gsdl3/packages/gsdl-as/src/org/greenstone/p2p/AbstractServerAction.java	(revision 8905)
+++ /trunk/gsdl3/packages/gsdl-as/src/org/greenstone/p2p/AbstractServerAction.java	(revision 8905)
@@ -0,0 +1,71 @@
+package org.greenstone.p2p;
+
+import java.net.*;
+import java.util.*;
+
+public abstract class AbstractServerAction implements NameServerAction
+{ NameServer host;
+
+  public AbstractServerAction(NameServer host)
+  { this.host = host;
+  }
+
+  public abstract String getActionName();
+  
+  public void propagateAction(URL forwarder, Map parameters)
+  { Enumeration subServers = host.subServers();
+  
+    // poll all child servers
+    while (subServers.hasMoreElements())
+    { URL server = (URL) subServers.nextElement();
+      
+      if (!server.equals(forwarder))
+      { // send server the action
+        String response = this.propagateActionViaServer(server, parameters, forwarder);
+      }
+    }
+    
+    // poll upwards to parent
+    if (host.getParent() != null &&
+	!host.getParent().equals(forwarder))
+    { this.propagateActionViaServer(host.getParent(), parameters, forwarder);
+    }
+  }
+
+  public void doAction(URL forwarder, Map parameters)
+  { // start propagating the action outwards
+    this.propagateAction(forwarder, parameters);
+  
+    // now execute it on our children
+    Enumeration servers = host.servers();
+  
+    while (servers.hasMoreElements())
+    { URL server = (URL) servers.nextElement();
+      
+      if (!server.equals(forwarder))
+      { // send server the action
+        String response = this.doActionOnServer(server, parameters, forwarder);
+      }
+    }
+  }
+  
+  String propagateActionViaServer(URL server, Map paramters, URL responseTo)
+  { String actionName = this.getActionName();
+  
+    // send action to server, in a separate thread
+    // get responses
+    // forward those back
+    return "";
+  }
+  
+  String doActionOnServer(URL server, Map parameters, URL responseTo)
+  { String actionName = this.getActionName();
+  
+    // send action to the destination server (as a URL)
+    
+    // get response (as HTML)
+    
+    // forward it back...
+    return "";
+  }
+}
Index: /trunk/gsdl3/packages/gsdl-as/src/org/greenstone/p2p/Client.java
===================================================================
--- /trunk/gsdl3/packages/gsdl-as/src/org/greenstone/p2p/Client.java	(revision 8905)
+++ /trunk/gsdl3/packages/gsdl-as/src/org/greenstone/p2p/Client.java	(revision 8905)
@@ -0,0 +1,40 @@
+import java.io.*;
+import java.net.*;
+
+public class Client {
+    public static String read() throws IOException {
+
+        Socket echoSocket = null;
+        PrintWriter out = null;
+        BufferedReader in = null;
+
+        try {
+            echoSocket = new Socket("taranis", 7);
+            out = new PrintWriter(echoSocket.getOutputStream(), true);
+            in = new BufferedReader(new InputStreamReader(
+                                        echoSocket.getInputStream()));
+        } catch (UnknownHostException e) {
+            System.err.println("Don't know about host: taranis.");
+            System.exit(1);
+        } catch (IOException e) {
+            System.err.println("Couldn't get I/O for "
+                               + "the connection to: taranis.");
+            System.exit(1);
+        }
+
+        BufferedReader stdIn = new BufferedReader(
+                                   new InputStreamReader(System.in));
+        String userInput;
+
+        while ((userInput = stdIn.readLine()) != null) {
+            out.println(userInput);
+            System.out.println("echo: " + in.readLine());
+        }
+
+        out.close();
+        in.close();
+        stdIn.close();
+        echoSocket.close();
+	return "";
+    }
+}
Index: /trunk/gsdl3/packages/gsdl-as/src/org/greenstone/p2p/ClientResponse.java
===================================================================
--- /trunk/gsdl3/packages/gsdl-as/src/org/greenstone/p2p/ClientResponse.java	(revision 8905)
+++ /trunk/gsdl3/packages/gsdl-as/src/org/greenstone/p2p/ClientResponse.java	(revision 8905)
@@ -0,0 +1,11 @@
+package org.greenstone.p2p;
+
+import java.util.*;
+
+public interface ClientResponse
+{ boolean isSuccessful(); // obvious
+  Vector  getValues(String label); // get the values associated with a given
+                                   // label; which values are available varies
+                                   // from action to action
+  Set     getLabels();             // get the labels in this response
+}
Index: /trunk/gsdl3/packages/gsdl-as/src/org/greenstone/p2p/DefaultServerAction.java
===================================================================
--- /trunk/gsdl3/packages/gsdl-as/src/org/greenstone/p2p/DefaultServerAction.java	(revision 8905)
+++ /trunk/gsdl3/packages/gsdl-as/src/org/greenstone/p2p/DefaultServerAction.java	(revision 8905)
@@ -0,0 +1,13 @@
+package org.greenstone.p2p;
+
+public class DefaultServerAction extends AbstractServerAction
+{ public static final String DEFAULT_ACTION = "default";
+
+  public DefaultServerAction(NameServer host)
+  { super(host);
+  }
+
+  public String getActionName()
+  { return DEFAULT_ACTION;
+  }
+}
Index: /trunk/gsdl3/packages/gsdl-as/src/org/greenstone/p2p/GreenstoneClient.java
===================================================================
--- /trunk/gsdl3/packages/gsdl-as/src/org/greenstone/p2p/GreenstoneClient.java	(revision 8905)
+++ /trunk/gsdl3/packages/gsdl-as/src/org/greenstone/p2p/GreenstoneClient.java	(revision 8905)
@@ -0,0 +1,31 @@
+package org.greenstone.p2p;
+
+import java.util.*;
+import java.net.URL;
+
+public interface GreenstoneClient
+{ /**
+   * This interface needs to be fulfilled by a Greenstone machine wanting to
+   * register and receive messages from the Greenstone Distributed Service.
+   *
+   */
+
+  /**
+   * This method is called by a GDS server when an action (message) has a response
+   * sent in reply.  The Greenstone server that sends the action will have this
+   * method called for each response received from the GDS network.
+   *
+   * @param: <code>NameServerAction</code> - at present, </code>null</code>.
+   * This method *must* be synchronized
+   * @param: <code>ClientResponse</code> - is a simple wrapper for the Map class.
+   * 
+   */
+  public void receiveResponse(NameServerAction action, ClientResponse response);
+
+  /**
+   *
+   */
+  public void receiveMessage(String message, Map parameters);
+  public String getIdentifier();
+  public URL    getURL();
+}
Index: /trunk/gsdl3/packages/gsdl-as/src/org/greenstone/p2p/GreenstoneInterface.java
===================================================================
--- /trunk/gsdl3/packages/gsdl-as/src/org/greenstone/p2p/GreenstoneInterface.java	(revision 8905)
+++ /trunk/gsdl3/packages/gsdl-as/src/org/greenstone/p2p/GreenstoneInterface.java	(revision 8905)
@@ -0,0 +1,94 @@
+
+package org.greenstone.p2p;
+
+import java.net.URL;
+import java.util.*;
+
+/**
+ * This is the class that provides a set of functions for a Greenstone server to call
+ * in order to send information/messages into a GDS network.
+ */
+
+public class GreenstoneInterface
+{ private GreenstoneClient client;
+  private URL              server;
+
+  // temporary variables which will eventually disapper - ignore!
+  private static GreenstoneClient lastClient;
+  private static NameServer       nameServer = null;
+  // end of temporary variables
+
+  /**
+   * Make a new interface with a client that will receive the responses
+   * to any messages sent.
+   *
+   * @param: the client to receive responses to messages sent through this
+   *         interface.
+   */
+  public GreenstoneInterface(GreenstoneClient client)
+  { this.client = client;
+    lastClient = this.client;
+    //    /*this.*/nameServer = null;
+  }
+
+  /**
+   *  Set up a registration for this machine with a GDS server.
+   *
+   *  The Greenstone machine should take care to store the URL of the
+   *  server for later use - don't continually reregister the same
+   *  server!
+   *
+   *  @param: <code>URL</code> the location of the GDS server to register with
+   *
+   *  @return: <code>boolean</code> whether the registration was successful or not.
+   */
+  public boolean registerWithServer(URL server)
+  { // connect to server
+    // 
+    if (/*this.*/nameServer == null) {
+      /*this.*/nameServer = new NameServer(server.toString());
+    }
+    this.server = server;
+    /*this.*/nameServer.registerServer(this.client.getURL());
+
+    return true;
+  }
+
+  /**
+   *  Method to unregister from the current GDS server for this Greenstone
+   *  machine.
+   *
+   *  @return: <code>boolean</code> whether the registration was successful or not.
+   */
+  public boolean unregisterFromServer()
+  { /*this.*/nameServer = null;
+    return true;
+  }
+
+  /**
+   *  Send a message into the GDS system through the current GDS server.
+   *
+   *  Success does not guarantee that you will receive a response.
+   *
+   *  @param: <code>String</code> the identifier for this type of message
+   *  @param: <code>Map</code> a <code>Vector</code> item is associated with
+   *          each key in this map.
+   *
+   *  @return: <code>boolean</code> whether the sending was successful or not.
+   */
+  public boolean sendMessage(String message, Map parameters)
+  { if (/*this.*/nameServer != null)
+      { /*this.*/nameServer.sendMessage(this.client.getURL(), message, parameters);
+    }
+    return false;
+  }
+
+  /**
+   *  Receive a response to a message sent from this Greenstone machine and
+   *  forward it to the current client - won't be needed in the long run, it
+   *  is here at present to provide a route for returning responses.
+   */
+  static public void receiveResponse(URL greenstoneURL, ClientResponse response)
+  { lastClient.receiveResponse(null, response);
+  }
+}
Index: /trunk/gsdl3/packages/gsdl-as/src/org/greenstone/p2p/GreenstoneServer.java
===================================================================
--- /trunk/gsdl3/packages/gsdl-as/src/org/greenstone/p2p/GreenstoneServer.java	(revision 8905)
+++ /trunk/gsdl3/packages/gsdl-as/src/org/greenstone/p2p/GreenstoneServer.java	(revision 8905)
@@ -0,0 +1,20 @@
+package org.greenstone.p2p;
+
+import java.net.URL;
+
+/**
+ *  Simple class to hold the location of a Greenstone server.
+ *
+ *  This class should be subclassed and methods overridden for 
+ *  Greenstone 2, 3 or any special installations such as the
+ *  Music DL.
+ */
+
+public class GreenstoneServer
+{ private URL server;
+  
+  public GreenstoneServer(URL url)
+  { this.server = url;
+  }
+
+}
Index: /trunk/gsdl3/packages/gsdl-as/src/org/greenstone/p2p/GreenstoneTest.java
===================================================================
--- /trunk/gsdl3/packages/gsdl-as/src/org/greenstone/p2p/GreenstoneTest.java	(revision 8905)
+++ /trunk/gsdl3/packages/gsdl-as/src/org/greenstone/p2p/GreenstoneTest.java	(revision 8905)
@@ -0,0 +1,70 @@
+package org.greenstone.p2p;
+
+import java.net.URL;
+import java.util.*;
+
+public class GreenstoneTest implements GreenstoneClient
+{ String name;
+  URL    url;
+  
+  public GreenstoneTest(String id, String url)
+  { try {
+      this.url = new URL(url);
+    }
+    catch (java.net.MalformedURLException malEx)
+      { this.url = null;
+      }
+    this.name = id;
+  }
+
+  public void receiveResponse(NameServerAction action, ClientResponse response)
+  {
+    System.out.println("\n----\nReceived a response:");
+    System.out.println(response.toString());
+  }
+
+  public void receiveMessage(String message, Map parameters)
+  {
+  }
+
+  public String getIdentifier()
+  { return this.name;
+  }
+
+  public URL getURL()
+  { return this.url;
+  }
+
+  /**
+   *  arg[0] => identifier for this machine
+   *  arg[1] => a url for this machine
+   *  arg[2] => a url for the GDS server
+   *
+   * e.g. run with:
+   * "java org.greenstone.p2p.GreenstoneTest localhost http://localhost http://www.nzdl.org"
+   */
+  public static void main(String args[])
+  { GreenstoneClient client = new GreenstoneTest(args[0], args[1]);
+    GreenstoneClient gsdl   = new GreenstoneTest("gsdl", "http://www.gsdl.org");
+    
+    URL server;
+    try
+      {
+	server = new URL(args[2]);
+      }
+    catch (java.net.MalformedURLException malEx)
+      { server = null;
+      }
+    
+    GreenstoneInterface gsdlIface = new GreenstoneInterface(gsdl);
+    gsdlIface.registerWithServer(server);
+
+    GreenstoneInterface iface = new GreenstoneInterface(client);
+    iface.registerWithServer(server);
+
+    Map parameters = new HashMap();
+    iface.sendMessage("ListServers", parameters);
+
+    iface.sendMessage("DocDelta", parameters);
+  }
+}
Index: /trunk/gsdl3/packages/gsdl-as/src/org/greenstone/p2p/ListServersAction.java
===================================================================
--- /trunk/gsdl3/packages/gsdl-as/src/org/greenstone/p2p/ListServersAction.java	(revision 8905)
+++ /trunk/gsdl3/packages/gsdl-as/src/org/greenstone/p2p/ListServersAction.java	(revision 8905)
@@ -0,0 +1,35 @@
+package org.greenstone.p2p;
+
+import java.util.*;
+import java.net.URL;
+
+public class ListServersAction extends AbstractServerAction
+{ public String LISTSERVERS = "ListServers";
+
+  public ListServersAction(NameServer host)
+  { super(host);
+  }
+
+  public String getActionName()
+  { return LISTSERVERS;
+  }
+  
+  public void doAction(URL forwarder, Map parameters)
+  { this.propagateAction(forwarder, parameters);
+  
+    // Build a list of all servers
+    AbstractClientResponse response = new AbstractClientResponse();
+
+    Enumeration servers = this.host.servers();
+    while (servers.hasMoreElements())
+      { URL gsServer = (URL) servers.nextElement();
+	System.out.println("Adding listserver item " + gsServer);
+
+	response.addValue("Server", gsServer.toString());
+      }
+    response.setSuccessful(true);
+
+    // Send it back to the forwarder right now...
+    this.host.receiveResponse(forwarder, response);
+  }
+}
Index: /trunk/gsdl3/packages/gsdl-as/src/org/greenstone/p2p/NameServer.java
===================================================================
--- /trunk/gsdl3/packages/gsdl-as/src/org/greenstone/p2p/NameServer.java	(revision 8905)
+++ /trunk/gsdl3/packages/gsdl-as/src/org/greenstone/p2p/NameServer.java	(revision 8905)
@@ -0,0 +1,124 @@
+package org.greenstone.p2p;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+
+public class NameServer
+{ ServerList list;
+  URL        parent;
+  Vector     childServers; // name servers
+  Vector     children;     // greenstone servers
+  String     identity;
+  Map        actionMap;
+ 
+  public NameServer(String identity)
+  { this.list     = new ServerList();
+    this.identity = identity;
+    this.parent   = null;
+    this.children = new Vector();
+    this.childServers = new Vector();
+
+    this.actionMap = new HashMap();
+
+    NameServerAction listServersAction = new ListServersAction(this);
+    this.addAction(listServersAction);
+    NameServerAction defaultAction = new DefaultServerAction(this);
+    this.addAction(defaultAction);
+    
+    // set up registration listener
+    // set up messaging broadcaster
+    // set up messaging listener
+  }
+
+  private void addAction(NameServerAction action)
+  { this.actionMap.put(action.getActionName(), action);
+  }
+
+  private void loadChildren(BufferedReader in)
+  { try 
+      { String child = in.readLine();
+      }
+    catch (IOException ex)
+      {
+      }
+  }
+
+  private void loadServers(BufferedReader in)
+  { try
+      { String child = in.readLine();
+      }
+    catch (IOException io)
+      {
+      }
+  }
+
+  public void sendMessage(URL origin, String actionName, Map parameters)
+  { NameServerAction action = (NameServerAction) this.actionMap.get(actionName);
+    if (action != null)
+      { action.doAction(origin, parameters);
+      }
+    else
+      { System.out.println("Sending action " + actionName + " through <default>");
+
+	// TODO: add action name to the parameter map so that it is not lost...
+	action = (NameServerAction) this.actionMap.get("Default");
+	if (action != null)
+	{ action.doAction(origin, parameters);
+	}
+      }
+    //NameServerAction action = NameServerActionFactory.createAction(action, parameters);
+    //action.doAction();
+  }
+
+  public void receiveResponse(URL responseTo, ClientResponse response)
+  { GreenstoneInterface.receiveResponse(responseTo, response);
+  }
+    
+  private void loadParent()
+  {
+  }
+
+  public String getIdentity()
+  { return this.identity;
+  }
+  
+  public void setParent(URL parent)
+  { this.parent = parent;
+  }
+  
+  public URL getParent()
+  { return this.parent;
+  }
+  
+  public void addSubServer(URL subserver)
+  { this.childServers.add(subserver);
+  }
+  
+  public void registerServer(URL child)
+  { System.out.println("Receiving registration from " + child.toString());
+    this.children.add(child);
+  }
+  
+  public Enumeration subServers()
+  { return this.childServers.elements();
+  }
+  
+  public Enumeration servers()
+  { return this.children.elements();
+  }
+
+  public static boolean pollServer(URL server)
+  { return false;
+  }
+
+  /**
+   *  
+   */
+  public static void main(String args[])
+  { NameServer server = new NameServer(args[0]);
+
+    // Load the action items
+    // Wait for signals
+  }
+}
Index: /trunk/gsdl3/packages/gsdl-as/src/org/greenstone/p2p/NameServerAction.java
===================================================================
--- /trunk/gsdl3/packages/gsdl-as/src/org/greenstone/p2p/NameServerAction.java	(revision 8905)
+++ /trunk/gsdl3/packages/gsdl-as/src/org/greenstone/p2p/NameServerAction.java	(revision 8905)
@@ -0,0 +1,10 @@
+package org.greenstone.p2p;
+
+import java.util.Map;
+import java.net.URL;
+
+public interface NameServerAction
+{ public String getActionName();
+  public void   doAction(URL forwarder, Map parameters);
+  public void   propagateAction(URL forwarder, Map parameters);
+}
Index: /trunk/gsdl3/packages/gsdl-as/src/org/greenstone/p2p/NameServerActionFactory.java
===================================================================
--- /trunk/gsdl3/packages/gsdl-as/src/org/greenstone/p2p/NameServerActionFactory.java	(revision 8905)
+++ /trunk/gsdl3/packages/gsdl-as/src/org/greenstone/p2p/NameServerActionFactory.java	(revision 8905)
@@ -0,0 +1,9 @@
+package org.greenstone.p2p;
+
+import java.util.Map;
+
+public class NameServerActionFactory
+{ public NameServerAction createAction(String actionName, Map parameters)
+  { return null;
+  }
+}
Index: /trunk/gsdl3/packages/gsdl-as/src/org/greenstone/p2p/NameServerRegistrationThread.java
===================================================================
--- /trunk/gsdl3/packages/gsdl-as/src/org/greenstone/p2p/NameServerRegistrationThread.java	(revision 8905)
+++ /trunk/gsdl3/packages/gsdl-as/src/org/greenstone/p2p/NameServerRegistrationThread.java	(revision 8905)
@@ -0,0 +1,16 @@
+package org.greenstone.p2p;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+
+public class NameServerRegistrationThread extends Thread
+{ public void run() 
+  { /*try
+    {
+    }
+    catch (IOException ex)
+    {
+    }*/
+  }
+}
Index: /trunk/gsdl3/packages/gsdl-as/src/org/greenstone/p2p/ServerList.java
===================================================================
--- /trunk/gsdl3/packages/gsdl-as/src/org/greenstone/p2p/ServerList.java	(revision 8905)
+++ /trunk/gsdl3/packages/gsdl-as/src/org/greenstone/p2p/ServerList.java	(revision 8905)
@@ -0,0 +1,19 @@
+package org.greenstone.p2p;
+
+import java.util.*;
+
+public class ServerList
+{ Map map;
+
+  public ServerList()
+  { this.map = new HashMap();
+  }
+  
+  public void addServer(GreenstoneServer server)
+  { this.map.put(server, server);
+  }
+  
+  Iterator servers()
+  { return ((Collection)this.map.values()).iterator();
+  }
+}
