Index: trunk/java-client/org/nzdl/gsdl/service/NzdlMultiWayWrapper.java
===================================================================
--- trunk/java-client/org/nzdl/gsdl/service/NzdlMultiWayWrapper.java	(revision 2182)
+++ trunk/java-client/org/nzdl/gsdl/service/NzdlMultiWayWrapper.java	(revision 2182)
@@ -0,0 +1,250 @@
+/*
+ *    NzdlMultiWayWrapper.java
+ *    Copyright (C) 2001 New Zealand Digital Library Project
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+//the package we're in
+package org.nzdl.gsdl.service;
+
+import java.util.Map;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Date;
+import java.util.Hashtable;
+import java.util.Properties;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.io.Writer;
+import java.io.FileWriter;
+import org.nzdl.gsdl.util.NzdlServiceFactory;
+
+
+/**
+ *  A NzdlMultiWayWrapper multiple NzdlServices 
+ *
+ * @author Brett Sheeran (bsheeran@xtra.co.nz) (comments)
+ * @author Stuart Yeates  (say1@cs.waikato.ac.nz)
+ * @version $Revision$
+ */
+public class NzdlMultiWayWrapper
+  extends NzdlWrapper {
+
+  Hashtable services;
+   
+  /** 
+   * The bean constructor ...
+   */
+  public NzdlMultiWayWrapper() {
+    super(null);
+    services = new Hashtable();
+  }
+  /** 
+   * The normal constructor
+   */
+  public NzdlMultiWayWrapper(String [] _args,
+			     Properties _props,
+			     String _URL,
+			     String _filename,
+			     String _IOR) {
+    super(null);
+    services = new Hashtable();
+    
+    Hashtable servers = NzdlServiceFactory.findIORs(_args,_props,_URL,_filename,_IOR);
+    
+    Enumeration e = servers.keys() ;
+    for (int i = 0; e.hasMoreElements(); i++) {
+      String key = (String)  e.nextElement();
+      NzdlService server = (NzdlService) servers.get(key);
+      if (NzdlServiceFactory.logMultiple)
+	server = new NzdlLogWrapper(server, 
+				    "log.file.after.split." + key + "cache", 
+				    "AFTER:" + key + ": ");
+      services.put("" +i, server);
+    }
+  }
+
+  String findServer(String _name) {
+    int separator = _name.indexOf(':');   
+    String result = _name.substring(0,separator);
+    return result;
+  }
+  String findCollection(String _name) {
+    String result = "";
+    try {
+      int separator = _name.indexOf(':');   
+      result = _name.substring(separator+1,_name.length());
+    } catch (Throwable t) {
+      System.err.println("Throwable: "+ t);
+    }
+    return result;
+  }
+   
+  /**
+   * Allow the client to configure a CORBA server.
+   * @param key the parameter to be set.
+   * @param values what that parameter will be set to.
+   */
+  public void configure( String _key, Set _values ) {
+    Enumeration e = services.keys();
+    for (int i = 0; e.hasMoreElements(); i++) {
+      NzdlService server = (NzdlService) e.nextElement();
+      server.configure(_key,_values);
+    }
+  }
+
+  /**
+   * Obtain the set of collection names for a Greenstone library.
+   * @return A set of collection names in string format.
+   */
+  public Set getCollectionSet( ) {
+    Set results = new HashSet();
+
+    Enumeration e = services.keys();
+    for (int i = 0; e.hasMoreElements(); i++) {
+      String name = (String) e.nextElement();
+      NzdlService server = (NzdlService) services.get(name);
+      Set set = server.getCollectionSet();
+      Iterator s = set.iterator();
+      while (s.hasNext()) {
+	String coll = (String) s.next();
+	results.add("" + i + ":" + coll); 
+      }
+    }
+    return results;
+  }
+
+  /**
+   * Check if ORB knows of this collection.
+   * @param name the name of a collecion to be searched for.
+   * @return boolean <TT>true</TT> if collection is found, else <TT>false</TT>.
+   */
+  public boolean hasCollection( String _name ) {
+
+    NzdlService server = (NzdlService) services.get( findServer(_name));
+    return  server.hasCollection(findCollection(_name));
+   }
+
+  /**
+   * Check if ORB can communicate with of this collection.
+   * @param name the name of a collecion to be pinged.
+   * @return boolean <TT>true</TT> if collection returned ping, else
+   * <TT>false</TT>.
+   */
+  public boolean pingCollection( String _name ) {
+    NzdlService server = (NzdlService) services.get( findServer(_name));
+    return server.pingCollection(findCollection(_name));
+  }
+
+  /**
+   * Extract information on this collection into a
+   * {@link NzdlCollectionInfo NzdlCollectionInfo} object
+   * @param name the collection to be retrieved.
+   * @return an instance of
+   * {@link NzdlCollectionInfo NzdlCollectionInfo} containing data on a
+   * collection
+   */
+  public NzdlCollectionInfo getCollectionInfo( String _name ) {
+    NzdlService server = (NzdlService) services.get( findServer(_name));
+    NzdlCollectionInfo result = server.getCollectionInfo(findCollection(_name));
+    return result;
+  }
+
+  /**
+   * Returns the set of filters for the service object.
+   * @param name the collection name
+   * @return a set of strings that name the filters, for example
+   * BrowseFilter, QueryFilter and NullFilter.
+   */
+  public Set getFilterSet( String _name ) {
+    NzdlService server = (NzdlService) services.get( findServer(_name));
+    Set result = server.getFilterSet(findCollection(_name));
+    return result;
+  }
+
+  /**
+   * @param name the collection name
+   * @return the Set of (name, value) value pairs for all metadata 
+   * associated with a collection  
+   */
+  public Set getMetaTagSet( String _name ) {
+    NzdlService server = (NzdlService) services.get( findServer(_name));
+    Set result = server.getMetaTagSet(findCollection(_name));
+    return result;
+  }
+
+  /**
+   * Returns the Greenstone Markup Language (GML) text for a particular
+   * document from a collection.
+   * @param name the name of the collection.
+   * @param docID the document identity string
+   * @return the GML document in the form of a string.
+   */
+  public String getDocument( String _name, String _docID ) {
+    NzdlService server = (NzdlService) services.get( findServer(_name));
+    String result = server.getDocument(findCollection(_name), _docID);
+    return result;
+  }
+
+  /**
+   * Returns the set of value(s) for a metatag from a particular document.
+   * @param name collection name
+   * @param docID the document identifier.
+   * @param metaTag the metatag name such as: Title, Author, Date and Images.
+   * @return The set of value(s) for the requested metatag and document. In
+   * cases such as Title, Author, Date there will probably be only one value
+   * per document.
+   */
+  public Set getMetaData( String _name, String _docID, String _metaTag ) {
+    NzdlService server = (NzdlService) services.get( findServer(_name));
+    Set result = server.getMetaData( findCollection(_name), _docID, _metaTag );
+    return result;
+  }
+
+  /**
+   * Returns a map of value(s) for a metatag from a list of documents.
+   * @param name collection name
+   * @param docIDs a list of document identifier strings.
+   * @param metaTag the metatag name such as: Title, Author, Date and Images.
+   * @return The map of value(s) for the requested metatag and document. In
+   * cases such as Title, Author, Date there will probably be only one value
+   * per document.
+   */
+  public Map getMetaData( String _name, List _docIDs, String _metaTag ) {
+    NzdlService server = (NzdlService) services.get( findServer(_name));
+    Map result = server.getMetaData( findCollection(_name), _docIDs, _metaTag );
+    return result;
+  }
+
+  /**
+   * Services a {@link NzdlRequest NzdlRequest} to a collection and places
+   * the results into a {@link NzdlResponse NzdlResponse} object. <br>
+   * Pre:   Created instances of NzdlRequest and NzdlResponse. <br>
+   * Post: Placed the result data into NzdlResponse object.
+   * @param name the collection name.
+   * @param request an instance of NzdlRequest with query data to be serviced
+   * @param response an instance of NzdlResponse. where the results of
+   * sevciving the query will be placed
+   */
+  public void service( String _name, NzdlRequest _request, 
+		       NzdlResponse _response ) {    
+    NzdlService server = (NzdlService) services.get( findServer(_name));
+    server.service(findCollection(_name),_request,_response);
+  }
+  
+}
Index: trunk/java-client/org/nzdl/gsdl/util/NzdlServiceFactory.java
===================================================================
--- trunk/java-client/org/nzdl/gsdl/util/NzdlServiceFactory.java	(revision 2182)
+++ trunk/java-client/org/nzdl/gsdl/util/NzdlServiceFactory.java	(revision 2182)
@@ -0,0 +1,564 @@
+/*
+ *    NzdlServiceFactory.java
+ *    Copyright (C) 2001 New Zealand Digital Library Project
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+// the package we're in
+package org.nzdl.gsdl.util;
+
+// java libraries we're using
+import java.io.BufferedWriter;
+import java.io.BufferedReader;
+import java.io.DataInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.LineNumberReader;
+import java.io.Serializable;
+import java.net.URL;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.Vector;
+import java.util.Hashtable;
+
+// local libraries
+import org.nzdl.gsdl.service.NzdlCollectionInfo; 
+import org.nzdl.gsdl.service.NzdlQuery;
+import org.nzdl.gsdl.service.NzdlRequest;
+import org.nzdl.gsdl.service.NzdlResponse;
+import org.nzdl.gsdl.service.NzdlResultSet;
+import org.nzdl.gsdl.service.NzdlService;
+import org.nzdl.gsdl.service.NzdlServiceClient;
+import org.nzdl.gsdl.service.NzdlCacheWrapper;
+import org.nzdl.gsdl.service.NzdlLogWrapper;
+import org.nzdl.gsdl.service.NzdlDocSaveWrapper;
+import org.nzdl.gsdl.service.NzdlMultiWayWrapper;
+
+/**
+ * Class NzdlServiceFactory
+ *
+ * A repositry for IORs of various NZDL servers we've seen.
+ * Finds IORs from sources such as: URL, file, string, or server based
+ * list of known IORs.
+ *
+ * @author stuart yeates (say1@cs.waikato.ac.nz)
+ * @author Brett Sheeran (bsheeran@xtra.co.nz)
+ * @author Dave Nichols (daven@cs.waikato.ac.nz)
+ * @author Gordon Paynter (paynter@cs.waikato.ac.nz)
+ * @version $Revision$
+ * @see org.nzdl.gsdl.SimpleServer
+ * @see org.nzdl.gsdl.service.NzdlCollectionInfo
+ * @see org.nzdl.gsdl.service.NzdlQuery
+ * @see org.nzdl.gsdl.service.NzdlRequest
+ * @see org.nzdl.gsdl.service.NzdlResponse
+ * @see org.nzdl.gsdl.service.NzdlResultSet
+ * @see org.nzdl.gsdl.service.NzdlService
+ * @see org.nzdl.gsdl.service.NzdlServiceClient
+ * @see gnu.getopt.Getopt
+ * @see gnu.getopt.LongOpt
+ * @see <a href="http://www.nzdl.org/">The New Zealand Digital Library Project</a>
+ * @see <a href="http://www.nzdl.org/fast-cgi-bin/library?&a=p&p=gsdl">Greenstone Digital Library Software</a>
+ */
+
+
+public class NzdlServiceFactory implements Cloneable, Serializable {
+
+  /** The collection of CORBA IORs we know about */
+  protected static Properties knownIORs = null;
+  /** The name of the properties file */
+  static String propertiesFileName = "knownIORs.properties";
+  /** The name of the file we look for IOR's in */
+  public static String IORFileName = "/tmp/localcorba.objid";
+
+  /** default places wit look for IORs ... */
+  static String[] urlsCompiledIn = 
+  { 
+    "http://nikau.cs.waikato.ac.nz/~say1/gsdl/cgi-bin/getior", 
+    "http://www.nzdl.org/cgi-bin/getior"
+  };
+
+  /** Are we using a caching NzdlService ? */
+  static public boolean caching = true;
+  /** Are we logging before the cache ? */
+  static public boolean logBefore = true;
+  /** Are we logging after the cache ? */
+  static public boolean logAfter = true;
+  /** Are we saving documents ? */
+  static public boolean saveDocs = false;
+  /** Are we trying for multiple servers ? */
+  static public boolean doMultiple = false;
+  /** Are we logging after individual servers ? */
+  static public boolean logMultiple = false;
+
+  /**
+   * Get the first known-good IOR
+   * @see java.lang.String
+   * @return the string containing the IOR
+   */
+  public static String getFirstValid()  {
+    validate(); // implies checkLoaded();
+    synchronized (knownIORs) {
+      
+      Enumeration e = knownIORs.keys();
+      while (e.hasMoreElements()) {
+	String IOR = (String) e.nextElement();
+	if (attemptToInitialise(null, null, IOR) != null) {
+	  return IOR;
+	}
+      }
+      return null;
+    }
+  }
+  /**
+   * Get the all known-good IOR
+   * @see java.lang.String
+   * @return the string[] containing the IORs
+   */
+  public static String[] getAllValid()  {
+    checkLoaded();
+    Vector vec = new Vector();
+			    
+    synchronized (knownIORs) {
+      
+      Enumeration e = knownIORs.keys();
+      while (e.hasMoreElements()) {
+	String IOR = (String) e.nextElement();
+	if (attemptToInitialise(null, null, IOR) != null) {
+	  vec.add(IOR);
+	}
+      }
+    }
+    String[] strings = new Strings[vec]
+      return null;
+    
+  }
+
+  /**
+   * Check that the class has been correctly initialised
+   */
+  static protected void checkLoaded()  {
+    // if we're already initialised we can bail now and
+    // save synchronization overhead ...
+    if (knownIORs != null)
+      return;
+
+    Properties blarg = new Properties();
+    
+    // take a lock on blarg. currently it's local, but 
+    // won't be soon...
+    synchronized (blarg) {
+
+      try {
+	synchronized (Class.forName("org.nzdl.gsdl.util.NzdlServiceFactory")) {
+	  if (knownIORs != null)
+	    return;
+	  knownIORs = blarg;
+	}
+      } catch (ClassNotFoundException exception) {
+	System.err.println("Exception locking class:" + exception);
+      }
+          
+      try {
+      File file = new File(propertiesFileName);
+	if (file.exists()) {
+	  knownIORs.load(new FileInputStream(file));
+	} 
+      } catch (IOException exception) {
+	System.err.println("Exception reading properties file:" + exception);
+      }
+    }
+    getIORsfromFile(IORFileName);
+  }
+
+  /**
+   * Save the IORs back to the underlying file
+   * @see java.io.File
+   */
+  static protected void checkSave()  {
+    synchronized (knownIORs) {
+      if (knownIORs == null)
+	throw new Error("saving null property list");
+      
+      File file = new File(propertiesFileName);
+      try {
+	knownIORs.store(new FileOutputStream(file),
+			"NZDL IOR's see: org.nzdl.gsdl.util.NzdlServiceFactory");
+      } catch (IOException i) {
+	System.err.println("Error reading properties file:" + i);
+      }
+    }
+  }
+
+  /**
+   * Find a valid IOR to initialise from.
+   * @param _args the command line arguments
+   * @param _URL a URL to look for an IOR in
+   * @param _filename a local filename to look for an IOR in
+   * @param _IOR a string to look for an IOR in
+   * @see org.omg.CORBA.ORB
+   */
+  public static NzdlService findIOR(String [] _args,
+				    Properties _props, 
+				    String _URL,
+				    String _filename,
+				    String _IOR)  {
+    
+    // read our prevously seed IORs ...
+    String IOR = null;
+    NzdlService client = null;
+      
+    // try a URL from the command line
+    if ( _URL != null) {
+      String[] IORs = NzdlServiceFactory.getIORsfromURL(_URL);
+      for (int i=0;( i<IORs.length && client == null );i++) {
+	client = attemptToInitialise(_args, _props,IORs[i]);
+      }
+    }
+
+    // try an IOR from the command line
+    if (_IOR != null && client == null) {
+      IOR = NzdlServiceFactory.registerIOR(_IOR);
+      client = attemptToInitialise(_args, _props, IOR);
+    }
+    
+    // try an IOR from a file (the filename may have been 
+    // given from the commandline
+    if (client == null) {
+      String[] IORs = NzdlServiceFactory.getIORsfromFile(_filename);
+      for (int i=0;( i<IORs.length && client == null );i++) {
+	client = attemptToInitialise(_args, _props,IORs[i]);
+      }
+    }
+    
+    // try the compiled-in URLs
+    if (client == null) {
+      for (int i=0;( i<urlsCompiledIn.length && client == null );i++) {
+	String[] IORs = NzdlServiceFactory.getIORsfromURL(urlsCompiledIn[i]);
+	for (int j=0;( j<IORs.length && client == null );j++) {
+	  client = attemptToInitialise(_args, _props,IORs[j]);
+	}
+      }
+    }
+    // the knownIORs is the last resort
+    if (client == null) {
+      IOR = NzdlServiceFactory.getFirstValid();
+      client = attemptToInitialise(_args, _props, IOR);
+    }
+    return client;
+    
+  }
+  /**
+   * Connect for as many servers as possible
+   * @param _args the command line arguments
+   * @param _URL a URL to look for an IOR in
+   * @param _filename a local filename to look for an IOR in
+   * @param _IOR a string to look for an IOR in
+   * @see org.omg.CORBA.ORB
+   */
+  public static Hashtable findIORs(String [] _args,
+				   Properties _props, 
+				   String _URL,
+				   String _filename,
+				   String _IOR)  {
+    // the object we're filling ...
+    Hashtable result = new Hashtable();
+
+    // read our prevously seed IORs ...
+    String IOR = null;
+    NzdlService client = null;
+      
+      
+    // try a URL from the command line
+    if ( _URL != null) {
+      String[] IORs = NzdlServiceFactory.getIORsfromURL(_URL);
+      for (int i=0;( i<IORs.length && client == null );i++) {
+	client = attemptToInitialise(_args, _props,IORs[i]);
+	if (client != null)
+	  result.put(IORs[i],client);
+      }
+    }
+
+      System.err.println("1");
+    // try an IOR from the command line
+    if (_IOR != null) {
+      IOR = NzdlServiceFactory.registerIOR(_IOR);
+      client = attemptToInitialise(_args, _props, IOR);
+	if (client != null)
+	  result.put(IOR,client);
+    }
+    
+      System.err.println("2");
+    // try an IOR from a file (the filename may have been 
+    // given from the commandline
+    {
+      String[] IORs = NzdlServiceFactory.getIORsfromFile(_filename);
+      for (int i=0;( i<IORs.length);i++) {
+	client = attemptToInitialise(_args, _props,IORs[i]);
+	if (client != null)
+	  result.put(IORs[i],client);
+      }
+    }
+    
+      System.err.println("3");
+    // try the compiled-in URLs
+    for (int i=0;(urlsCompiledIn != null && i<urlsCompiledIn.length);i++) {
+      String[] IORs = NzdlServiceFactory.getIORsfromURL(urlsCompiledIn[i]);
+      for (int j=0;( IORs != null && j<IORs.length);j++) {
+	client = attemptToInitialise(_args, _props, IORs[j]);
+	if (client != null)
+	  result.put(IORs[j],client);
+      }
+    }
+
+    System.err.println("4");
+    // the knownIORs is the last resort
+    IOR = NzdlServiceFactory.getFirstValid();
+    client = attemptToInitialise(_args, _props, IOR);
+    if (client != null)
+      result.put(IOR,client);
+    return result;    
+  }
+
+  /**
+   * Connect to each of the ORB's described by the IORs and throw away
+   * any that can't be connected to.
+   * @see org.omg.CORBA.ORB
+   */
+ public static void validate()  {
+    checkLoaded();
+    synchronized (knownIORs) {
+
+      Properties valid = new Properties();
+      
+      if (knownIORs != null)
+	throw new Error("saving null property list");
+	
+      Enumeration e = knownIORs.keys();
+      while (e.hasMoreElements()) {
+	String IOR = (String) e.nextElement();
+	if (attemptToInitialise(null, null, IOR) != null) {
+	  valid.put(IOR,"");
+	}
+      }
+      try {
+	synchronized (Class.forName("org.nzdl.gsdl.util.NzdlServiceFactory")) {
+	  knownIORs = valid;
+	}
+      } catch (ClassNotFoundException exception) {
+	System.err.println("Exception locking class:" + exception);
+      }
+      checkSave();
+    }    
+  }
+
+  /**
+   * Register a given IOR 
+   * @see java.lang.String
+   * @param str the IOR
+   * @return the str
+   */
+ public static String registerIOR(String str)
+  {
+    checkLoaded();    
+    if (str != null)
+      synchronized (knownIORs) {
+	knownIORs.put(str,"");
+      }
+    checkSave();
+    return str;
+  }
+
+ 
+  /**
+   * Retrieve an IOR from a URL
+   * @see java.net.URL
+   * @param str the url to retrieve
+   * @return the IOR
+   */
+  public static String[] getIORsfromURL(String str)
+  {
+    checkLoaded();
+    String ior = null;
+    
+    try { 
+      System.err.println("Looking for a URL at:" + str);
+      URL url = new URL(str);
+      InputStream his = url.openStream();
+      
+      BufferedReader rdr = new BufferedReader (new InputStreamReader(his)) ;
+      return readIORsfromReader(rdr);
+    } catch (Throwable throwable) {
+      System.err.println("NzdlHosts::getIOR() unable to construct or read URL \"" +
+			 str + "\", \"" + ior + "\": " + throwable);
+      return null;
+    }
+  }
+
+  public static String[] readIORsfromReader(BufferedReader rdr) {
+    Vector vec = new Vector();
+    
+    try { 
+      String ior = rdr.readLine();
+      while (ior != null) {
+	vec.add(ior);
+	synchronized (knownIORs) {
+	  knownIORs.put(ior,"");
+	}
+	ior = rdr.readLine();
+      }
+    } catch (Throwable throwable) {
+      System.err.println("Throwable: " + throwable);
+    }
+    checkSave();
+    String[] strings = new String[vec.size()];
+    for (int i = 0; i < vec.size(); i++)
+      strings[i] = (String)vec.elementAt(i);
+    return strings;
+  }
+  
+  /**
+   * Retrieve an IOR from a file
+   * @see java.io.File
+   * @param str the file to open
+   * @return the IOR
+   */
+  public static String[] getIORsfromFile(String file) {
+    checkLoaded();
+    String ior = null;
+    if (file == null || file.equals(""))
+      file = IORFileName;
+    file = file.trim();
+    try  {
+      BufferedReader input
+	= new BufferedReader(new FileReader(file));
+      return readIORsfromReader(input);
+    } catch (java.io.IOException e) {
+      System.err.println("Error reading IOR file:\n" + e);
+    }
+    return null;
+  }   // end of getIorKey
+
+  /**
+   * Write all IORs to a flat file (for reading from c++ etc).
+   *
+   * Not used for the properties files.
+   *
+   * @see java.util.Properties
+   * @param file the file to write to
+   */
+  public static void  writeToFile(String file) {
+    checkLoaded();
+    if (file != null)
+      synchronized (knownIORs) {
+	String ior = null;
+	file = file.trim();
+	try  {
+	  BufferedWriter output
+	    = new BufferedWriter(new FileWriter(file));
+	  Enumeration e = knownIORs.keys();
+	  while (e.hasMoreElements()) {
+	    String IOR = (String) e.nextElement();
+	    output.write(IOR);
+	    output.newLine();
+	  } 
+	} catch (java.io.IOException e) {
+	  System.err.println("Error reading IOR file:\n" + e);
+	}
+      }
+  }   // end of getIorKey
+  
+
+  /**
+   * Attempt to connect to the object pointed to by an IOR
+   * @see org.omg.CORBA.ORB
+   * @param _args the command line arguments
+   * @param _props the system properties
+   * @param _IOR the IOR string
+   * @return the newly created NzdlServiceClient
+   */
+  static public NzdlService attemptToInitialise(String [] _args, 
+				      Properties _props, 
+				      String _IOR) {
+    checkLoaded();
+    NzdlService nzdl = null;
+    if (_props == null)
+      _props = System.getProperties();
+    try {
+      nzdl = new NzdlServiceClient( _args, _props, _IOR);
+    } catch (Throwable t) {
+      System.err.println ("failed to initialise using:");
+      System.err.println (_IOR);
+      return null;
+    }
+    return nzdl;
+  }
+  
+  static public NzdlService createNzdlService(String [] _args, 
+					      Properties _props, 
+					      String _URL,
+					      String _filename,
+					      String _IOR) {
+    if (_props == null)
+      _props = System.getProperties();
+
+    NzdlService nzdl = null;
+    
+    if (doMultiple)
+      nzdl = new NzdlMultiWayWrapper(_args,_props,_URL,_filename,_IOR);
+    else
+      nzdl = findIOR(_args,_props,_URL,_filename,_IOR);
+    
+    if (saveDocs)
+      nzdl = new NzdlDocSaveWrapper(nzdl);
+    
+    if (logAfter)
+      nzdl = new NzdlLogWrapper(nzdl, "log.file.after.cache", "AFTER: ");
+    
+    if (caching)
+      nzdl = new NzdlCacheWrapper(nzdl);
+
+    if (logBefore)
+      nzdl = new NzdlLogWrapper(nzdl, "log.file.before.cache", "BEFORE: ");
+    
+    return nzdl;
+  }
+    
+  /**
+   * Write the System properties to a file called "System.properties" in
+   * the current directory.
+   */
+  public static final void main( String [] args ) {
+ 
+    try {
+      File file = new File("System.properties");
+      
+      System.getProperties().store(new FileOutputStream(file),"");
+    } catch (Exception exception) {
+      System.err.println("Error locking class:" + exception);
+    }
+  } //main
+} // class
