Index: test/dtdxml.xml
===================================================================
--- test/dtdxml.xml	(nonexistent)
+++ test/dtdxml.xml	(revision 1292)
@@ -0,0 +1,25 @@
+<?xml version="1.0"?>
+<!DOCTYPE PARENT [
+<!ELEMENT PARENT (CHILD*)>
+<!ELEMENT CHILD (MARK?,NAME+)>
+<!ELEMENT MARK EMPTY>
+<!ELEMENT NAME (LASTNAME+,FIRSTNAME+)*>
+<!ELEMENT LASTNAME (#PCDATA)>
+<!ELEMENT FIRSTNAME (#PCDATA)>
+<!ATTLIST MARK
+            NUMBER ID #REQUIRED
+            LISTED CDATA #FIXED "yes"
+            TYPE (natural|adopted) "natural">
+<!ENTITY STATEMENT "This is well-formed XML">
+]>
+<PARENT>
+&STATEMENT;
+<CHILD>
+<MARK NUMBER="1" LISTED="yes" TYPE="natural"/>
+<NAME>
+<LASTNAME>child</LASTNAME>
+<FIRSTNAME>second</FIRSTNAME>
+</NAME>
+</CHILD>
+</PARENT>
+

Property changes on: test/dtdxml.xml
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Author Date Id Revision
\ No newline at end of property
Index: test/edu/ucsb/nceas/metacattest/ReplicationServerListTest.java
===================================================================
--- test/edu/ucsb/nceas/metacattest/ReplicationServerListTest.java	(nonexistent)
+++ test/edu/ucsb/nceas/metacattest/ReplicationServerListTest.java	(revision 1292)
@@ -0,0 +1,308 @@
+/**
+ *  '$RCSfile$'
+ *  Copyright: 2000 Regents of the University of California and the
+ *              National Center for Ecological Analysis and Synthesis
+ *  Purpose: To test the ReplicationServerList class by JUnit
+ *    Authors: @Jing Tao@
+ *    Release: @release@
+ *
+ *   '$Author$'
+ *     '$Date$'
+ * '$Revision$'
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+package edu.ucsb.nceas.metacattest;
+
+import edu.ucsb.nceas.metacat.*;
+//import edu.ucsb.nceas.morpho.framework.*;
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestResult;
+import junit.framework.TestSuite;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+
+
+/**
+ * A JUnit test for testing Step class processing
+ */
+public class ReplicationServerListTest extends TestCase
+{
+  private static String metacatReplicationURL=
+                                   MetaCatUtil.getOption("junitreplicationurl");
+  private ReplicationServerList serverList = null;
+  /**
+   * Constructor to build the test
+   *
+   * @param name the name of the test method
+   */
+  public ReplicationServerListTest(String name)
+  {
+    super(name);
+  }
+
+  /**
+   * Constructor to build the test
+   *
+   * @param name the name of the test method
+   * @param list the ReplicationServerList will be passed int
+   */
+  public ReplicationServerListTest(String name, ReplicationServerList list)
+  {
+    super(name);
+    serverList=list;
+  }
+ 
+  /**
+   * Establish a testing framework by initializing appropriate objects
+   */
+  public void setUp()
+ {
+   
+ }
+
+  /**
+   * Release any objects after tests are complete
+   */
+  public void tearDown()
+  {
+    //DBConnectionPool will be release
+    DBConnectionPool.release();
+  }
+
+  /**
+   * Create a suite of tests to be run together
+   */
+  public static Test suite()
+  {
+     //Get DBConnection pool, this is only for junit test.
+    //Because DBConnection is singleton class. So there is only one DBConnection
+    //pool in the program
+    try
+    {
+      DBConnectionPool pool = DBConnectionPool.getInstance();
+    }//try
+    catch (Exception e)
+    {
+      MetaCatUtil.debugMessage("Error in ReplicationServerList() to get" +
+                        " DBConnection pool"+e.getMessage(), 30);
+    }//catch
+    
+    TestSuite suite = new TestSuite();
+    suite.addTest(new ReplicationServerListTest("initialize"));
+    
+    try
+    {
+  
+    //Add two server into xml_replication table
+    URL dev = new URL(metacatReplicationURL+"?action=servercontrol&server=dev"+
+                        "&subaction=add&replicate=1&datareplicate=1&hub=1");
+    URL epsilon = new URL(metacatReplicationURL+"?action=servercontrol"+
+             "&server=epsilon&subaction=add&replicate=0&datareplicate=1&hub=0");
+    InputStream input = dev.openStream();
+    input.close();
+    input = epsilon.openStream();
+    input.close();
+    
+    //create a new server list
+    ReplicationServerList list = new ReplicationServerList();
+    
+    //Doing test test cases
+    suite.addTest(new ReplicationServerListTest("testSize", list));
+    
+    suite.addTest(new ReplicationServerListTest("testServerAt0", list));
+    suite.addTest(new ReplicationServerListTest("testServerAt1", list));
+    
+    suite.addTest(new ReplicationServerListTest
+                                              ("testNonEmptyServerList", list));
+    
+    suite.addTest(new ReplicationServerListTest("testServerIsNotInList", list));
+    suite.addTest(new ReplicationServerListTest("testServerIsInList", list));
+    
+    suite.addTest(new ReplicationServerListTest
+                                              ("testGetLastCheckedDate", list));
+    
+    suite.addTest(new ReplicationServerListTest
+                                        ("testGetReplicationValueFalse", list));
+    
+    suite.addTest(new ReplicationServerListTest
+                                         ("testGetReplicationValueTrue", list));
+    suite.addTest(new ReplicationServerListTest
+                                    ("testGetDataReplicationValueFalse", list));
+    
+    suite.addTest(new ReplicationServerListTest("testGetHubValueTrue", list));
+    suite.addTest(new ReplicationServerListTest("testGetHubValueFalse", list));
+    
+    //Delete this two server
+    URL deleteDev = new URL(metacatReplicationURL+"?action=servercontrol" +
+                                        "&server=dev&subaction=delete");
+    URL deleteEpsilon = new URL(metacatReplicationURL+"?action=servercontrol" +
+                                        "&server=epsilon&subaction=delete");
+    input = deleteDev.openStream();
+    input.close();
+    input = deleteEpsilon.openStream();
+    input.close();                                   
+    }//try
+    catch (Exception e)
+    {
+      MetaCatUtil.debugMessage("Error in ReplicationServerListTest.suite: "+
+                                e.getMessage(), 10);
+    }//catch
+    
+ 
+    
+                              
+    return suite;
+  }
+  
+
+
+  /**
+   * Run an initial test that always passes to check that the test
+   * harness is working.
+   */
+  public void initialize()
+  {
+    assert(1 == 1);
+  }
+
+   
+  /**
+   * Test the a empty server list is empty
+   */
+  public void testEmptyServerList()
+  {
+    
+    assert(serverList.isEmpty());
+  }
+  
+  /**
+   * Test the a non-empty server list is non-empty
+   */
+  public void testNonEmptyServerList()
+  {
+    
+    assert(!serverList.isEmpty());
+  }
+  
+  /**
+   * Test the size() method
+   */
+  public void testSize()
+  {
+    int size = serverList.size();
+    assert(size ==2);
+  }
+  
+  /**
+   * Test the method serverAt(0)
+   */
+  public void testServerAt0()
+  {
+    ReplicationServer server = serverList.serverAt(0);
+    String serverName = server.getServerName();
+    assert(serverName.equals("dev"));
+  }
+  
+  /**
+   * Test the method serverAt(1)
+   */
+  public void testServerAt1()
+  {
+    ReplicationServer server = serverList.serverAt(1);
+    String serverName = server.getServerName();
+    assert(serverName.equals("epsilon"));
+  }
+   
+  
+  /**
+   * Test the a given server is not in the server list
+   */
+  public void testServerIsNotInList()
+  {
+    assert(!serverList.isGivenServerInList("localhost"));
+  }
+  
+  /**
+   * Test the a given server is in the server list
+   */
+  public void testServerIsInList()
+  {
+    assert(serverList.isGivenServerInList("dev"));
+  }
+  
+  /**
+   * Test the method getLastCheckedDate
+   */
+  public void testGetLastCheckedDate()
+  {
+    String lastCheckedDate = serverList.getLastCheckedDate("dev");
+    assert(lastCheckedDate.equals("0001-01-01 BC"));
+  }
+  
+  /**
+   * Test the method getReplicationValue(resulst is true)
+   */
+  public void testGetReplicationValueTrue()
+  {
+    assert(serverList.getReplicationValue("dev"));
+  }
+  
+  /**
+   * Test the method getReplicationValue(result is false)
+   */
+  public void testGetReplicationValueFalse()
+  {
+    assert(!serverList.getReplicationValue("epsilon"));
+  }
+  
+  /**
+   * Test the method getDataReplicationValue(result is true)
+   */
+  public void testGetDataReplicationValueTrue()
+  {
+    assert(serverList.getDataReplicationValue("dev"));
+  }
+  
+  /**
+   * Test the method getDataReplicationValue(result is false)
+   */
+  public void testGetDataReplicationValueFalse()
+  {
+    assert(!serverList.getDataReplicationValue("epsilon"));
+  }
+
+  /**
+   * Test the method getHubValue(result is true)
+   */
+  public void testGetHubValueTrue()
+  {
+    assert(serverList.getHubValue("dev"));
+  }
+  
+  /**
+   * Test the method getHubValue(result is false)
+   */
+  public void testGetHubValueFalse()
+  {
+    assert(!serverList.getHubValue("epsilon"));
+  }  
+
+   
+}//ReplicationServerListTest

Property changes on: test/edu/ucsb/nceas/metacattest/ReplicationServerListTest.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Author Date Id Revision
\ No newline at end of property
Index: lib/replControl.html
===================================================================
--- lib/replControl.html	(revision 1291)
+++ lib/replControl.html	(revision 1292)
@@ -32,7 +32,7 @@
   </HEAD> 
   <FRAMESET COLS="*" FRAMEBORDER=0 BORDER=0>
 
-    <FRAMESET ROWS="*,200"  FRAMEBORDER=0 BORDER=0>
+    <FRAMESET ROWS="*,150"  FRAMEBORDER=0 BORDER=0>
     
     <FRAME SRC="replMain.html" BORDER=0 NAME="top">
 
Index: lib/metacat.properties
===================================================================
--- lib/metacat.properties	(revision 1291)
+++ lib/metacat.properties	(revision 1292)
@@ -14,8 +14,9 @@
 maximumConnectionAge=120000
 maximumConnectionTime=60000
 maximumUsageNumber=100
-runDBConnectionRecycleThread=on
+runDBConnectionRecycleThread=off
 cycleTimeOfDBConnection=30000
+forcereplicationwaitingtime=@forcereplicationwaitingtime@
 config-dir=@config-dir@
 default-style=@default-style@
 xmlcatalogfile=/opt/tomcat/webapps/xmltodb/catalog.txt
@@ -39,14 +40,10 @@
 deltaT=60
 replicationpath=@replication-path@
 replicationlog=@replication-log@
-replication=@replication@
-replicationsenddata=@replicationsenddata@
-replicationacceptdata=@replicationacceptdata@
 dtdPath=@config-dir@/dtd/
 dtdURL=@server@@html-path@/dtd/
 datafilepath=@datafilepath@
 certPath=@install-dir@/
 context=@context@
-hub=super1
 debuglevel=@debuglevel@
 datafileflag=datafile
Index: lib/replMain.html
===================================================================
--- lib/replMain.html	(revision 1291)
+++ lib/replMain.html	(revision 1292)
@@ -97,7 +97,9 @@
       <input type="radio" name="subaction" value="delete"> Remove this server<br>
       <input type="radio" name="subaction" value="add"> Add this server<br>
       <input size="30" name="server" >  <br>
-      Replicate To server (1 or 0)?: <input size="2" name="replicate"> <br>
+      Replicate xml doc To server (1 or 0)?: <input size="2" name="replicate"> <br>
+      Replicate data file To server (1 or 0)?: <input size="2" name="datareplicate"> <br>
+      Localhost is a hub to server (1 or 0)?: <input size="2" name="hub"> <br>
       Download certificate from<br>
       <input type="text" size="30" name="certificate">
       <br><br>
Index: src/xmltables_postgres.sql
===================================================================
--- src/xmltables_postgres.sql	(revision 1291)
+++ src/xmltables_postgres.sql	(revision 1292)
@@ -48,11 +48,13 @@
   serverid INT8 default nextval('xml_replication_id_seq'), 
   server VARCHAR(512),
   last_checked DATE,
-  replicate INT8, 
+  replicate INT8,
+  datareplicate INT8,
+  hub INT8,
   CONSTRAINT xml_replication_pk PRIMARY KEY (serverid)
 );  
 
-INSERT INTO xml_replication (serverid, server, replicate) VALUES ('1', 'localhost', '0');
+INSERT INTO xml_replication (server, replicate, datareplicate, hub) VALUES ('localhost', '0', '0', '0');
 
 /* 
  * Nodes -- table to store XML Nodes (both elements and attributes)
Index: src/xmltables.sql
===================================================================
--- src/xmltables.sql	(revision 1291)
+++ src/xmltables.sql	(revision 1292)
@@ -52,7 +52,9 @@
   serverid      NUMBER(20),
   server        VARCHAR2(512),
   last_checked  DATE,
-  replicate     NUMBER(1), 
+  replicate     NUMBER(1),
+  datareplicate NUMBER(1),
+  hub NUMBER(1),
   CONSTRAINT xml_replication_pk PRIMARY KEY (serverid)
 );  
   
@@ -66,8 +68,8 @@
 END;
 /
 
-INSERT INTO xml_replication (serverid, server, replicate)
- VALUES ('1', 'localhost', '0');
+INSERT INTO xml_replication (server, replicate, datareplicate, hub)
+ VALUES ('localhost', '0', '0', '0');
 
 /* 
  * Nodes -- table to store XML Nodes (both elements and attributes)
Index: src/edu/ucsb/nceas/metacat/ReplicationServer.java
===================================================================
--- src/edu/ucsb/nceas/metacat/ReplicationServer.java	(nonexistent)
+++ src/edu/ucsb/nceas/metacat/ReplicationServer.java	(revision 1292)
@@ -0,0 +1,145 @@
+/**
+ *  '$RCSfile$'
+ *    Purpose: A class represent a server in xml_replcation table
+ *  Copyright: 2000 Regents of the University of California and the
+ *             National Center for Ecological Analysis and Synthesis
+ *    Authors: Jing Tao
+ *    Release: @release@
+ *
+ *   '$Author$'
+ *     '$Date$'
+ * '$Revision$'
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+package edu.ucsb.nceas.metacat;
+
+/**
+ * A class express a entry in xml_replication. It include server name,
+ * lastChechedDate, replication or not, dataReplication or not, hub or not
+ */
+ 
+public class ReplicationServer
+{
+  private String serverName = null; //server name
+  private String lastCheckedDate = null; //string of last 
+  private boolean replication = false; //replciate xml document or not
+  private boolean dataReplication = false; //replciate data file or not
+                                           //it is relative to replcation
+                                           //if replication is false, it should
+                                           //be false
+  private boolean hub = false; //it is hub or not. Hub means the localhost can
+                               //replcate documents to the server if the 
+                               //document's home server is not localhost
+  /**
+   * Consturctor of ReplicationServer
+   */
+  public ReplicationServer()
+  {
+    this.serverName = null;
+    this.lastCheckedDate = null;
+    this.replication = false;
+    this.dataReplication = false;
+    this.hub = false;
+  }//constructor
+  
+  /**
+   * Get server name
+   */
+  public String getServerName()
+  {
+    return this.serverName;
+  }//getServerName
+  
+  /**
+   * Set a sting as server name
+   * @param myServerName, the string will set to object's serverName
+   */
+  public void setServerName(String myServerName)
+  {
+    this.serverName = myServerName;
+  }//setServerName
+  
+  /**
+   * Get last checked date
+   */
+  public String getLastCheckedDate()
+  {
+    return this.lastCheckedDate;
+  }//getLastCheckedDate
+  
+  /**
+   * Set a string as last checked date
+   * @Param myLastCheckedDate, the string will set to object's lastCheckedDate
+   */
+  public void setLastCheckedDate(String myLastCheckedDate)
+  {
+    this.lastCheckedDate = myLastCheckedDate;
+  }//setLastCheckedDate
+   
+  /**
+   * Get replication xml or not option
+   */
+  public boolean getReplication()
+  {
+    return this.replication;
+  }//getReplication
+  
+  /**
+   * Set replication option
+   * @param myReplication, the option will set to object's replication
+   */
+  public void setReplication(boolean myReplication)
+  {
+    this.replication = myReplication;
+  }//setReplication
+  
+  /**
+   * Get datareplication xml or not option
+   */
+  public boolean getDataReplication()
+  {
+    return this.dataReplication;
+  }//getDataReplication
+  
+  /**
+   * Set data replication option
+   * @param myDataReplication, the option will set to object's datareplication
+   */
+  public void setDataReplication(boolean myDataReplication)
+  {
+    this.dataReplication = myDataReplication;
+  }//setDataReplication   
+   
+  /**
+   * Get hub option
+   */
+  public boolean getHub()
+  {
+    return this.hub;
+  }//getHub
+  
+  /**
+   * Set hub option
+   * @param myHub, the option will set to object's hub option
+   */
+  public void setHub(boolean myHub)
+  {
+    this.hub = myHub;
+  }//setHub     
+  
+}//class ReplicationServer
+

Property changes on: src/edu/ucsb/nceas/metacat/ReplicationServer.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Author Date Id Revision
\ No newline at end of property
Index: src/edu/ucsb/nceas/metacat/MetacatReplication.java
===================================================================
--- src/edu/ucsb/nceas/metacat/MetacatReplication.java	(revision 1291)
+++ src/edu/ucsb/nceas/metacat/MetacatReplication.java	(revision 1292)
@@ -88,15 +88,7 @@
     Hashtable params = new Hashtable();
     Enumeration paramlist = request.getParameterNames();
     
-    //First check if administrate conifgure the replcation feature on
-    //This configuration is set in build.xml file
-    //If it is not on, reject any request.
-    if (!(util.getOption("replication")).equals("on"))
-    {
-     (response.getWriter()).println("MetaCat is not set to handle replication");
-      (response.getWriter()).close();
-      return;
-    }
+   
     
 // NOT NEEDED - doesn't provide enough security because of possible IP spoofing
 // REPLACED with running replication comminications over HTTPS
@@ -121,7 +113,7 @@
            !action.equals("getall") ) {
 
         server = ((String[])params.get("server"))[0];
-        if ( getServerCode(server) == 0 ) {
+        if ( getServerCodeForServerName(server) == 0 ) {
           System.out.println("Action \"" + action + 
                              "\" rejected for server: " + server);
           return;
@@ -144,11 +136,9 @@
     }
     else if ( action.equals("forcereplicatedatafile") ) 
     {
-     
-      //OutputStream out=response.getOutputStream();
       //read a specific docid from remote host, and store it into local host
       handleForceReplicateDataFileRequest(params);
-      //out.close();
+     
     }
     else
     {
@@ -244,7 +234,10 @@
     DBConnection dbConn = null;
     int serialNumber = -1;
     PreparedStatement pstmt = null;
-
+    String replicate =null;
+    String server = null;
+    String dataReplicate = null;
+    String hub = null;
     try {
       //conn = util.openDBConnection();
       dbConn=DBConnectionPool.
@@ -253,13 +246,19 @@
       
       // add server to server list
       if ( subaction.equals("add") ) {
-        String replicate = ((String[])params.get("replicate"))[0];
-        String server = ((String[])params.get("server"))[0];
+        replicate = ((String[])params.get("replicate"))[0];
+        server = ((String[])params.get("server"))[0];
+        //Get data replication value
+        dataReplicate = ((String[])params.get("datareplicate"))[0];
+        //Get hub value
+        hub = ((String[])params.get("hub"))[0];
+        
         pstmt = dbConn.prepareStatement("INSERT INTO xml_replication " +
-                                      "(server, last_checked, replicate) " +
+                  "(server, last_checked, replicate, datareplicate, hub) " +
                                       "VALUES ('" + server + "', to_date(" +
                                       "'01/01/00', 'MM/DD/YY'), '" +
-                                      replicate + "')");
+                                      replicate +"', '" +dataReplicate+"', '"
+                                      + hub +"')");
         pstmt.execute();
         pstmt.close();
         dbConn.commit();
@@ -267,7 +266,9 @@
         response.setContentType("text/html");
         out.println("<html><body><table border=\"1\">");
         out.println("<tr><td><b>server</b></td><td><b>last_checked</b></td><td>");
-        out.println("<b>replicate</b></td></tr>");
+        out.println("<b>replicate</b></td>");
+        out.println("<td><b>datareplicate</b></td>");
+        out.println("<td><b>hub</b></td></tr>");
         pstmt = dbConn.prepareStatement("SELECT * FROM xml_replication");
         //increase dbconnection usage
         dbConn.increaseUsageCount(1);
@@ -278,7 +279,10 @@
         while(tablehasrows) {
           out.println("<tr><td>" + rs.getString(2) + "</td><td>");
           out.println(rs.getString(3) + "</td><td>");
-          out.println(rs.getString(4) + "</td></tr>");
+          out.println(rs.getString(4) + "</td><td>");
+          out.println(rs.getString(5) + "</td><td>");
+          out.println(rs.getString(6) + "</td></tr>");
+          
           tablehasrows = rs.next();
         }
         out.println("</table></body></html>");
@@ -290,7 +294,7 @@
         
       // delete server from server list
       } else if ( subaction.equals("delete") ) {
-        String server = ((String[])params.get("server"))[0];
+        server = ((String[])params.get("server"))[0];
         pstmt = dbConn.prepareStatement("DELETE FROM xml_replication " +
                                       "WHERE server LIKE '" + server + "'");
         pstmt.execute();
@@ -300,7 +304,10 @@
         response.setContentType("text/html");
         out.println("<html><body><table border=\"1\">");
         out.println("<tr><td><b>server</b></td><td><b>last_checked</b></td><td>");
-        out.println("<b>replicate</b></td></tr>");
+        out.println("<b>replicate</b></td>");
+        out.println("<td><b>datareplicate</b></td>");
+        out.println("<td><b>hub</b></td></tr>");
+  
         pstmt = dbConn.prepareStatement("SELECT * FROM xml_replication");
         //increase dbconnection usage
         dbConn.increaseUsageCount(1);
@@ -311,7 +318,9 @@
         {
           out.println("<tr><td>" + rs.getString(2) + "</td><td>");
           out.println(rs.getString(3) + "</td><td>");
-          out.println(rs.getString(4) + "</td></tr>");
+          out.println(rs.getString(4) + "</td><td>");
+          out.println(rs.getString(5) + "</td><td>");
+          out.println(rs.getString(6) + "</td></tr>");
           tablehasrows = rs.next();
         }
         out.println("</table></body></html>");
@@ -321,7 +330,9 @@
         response.setContentType("text/html");
         out.println("<html><body><table border=\"1\">");
         out.println("<tr><td><b>server</b></td><td><b>last_checked</b></td><td>");
-        out.println("<b>replicate</b></td></tr>");
+        out.println("<b>replicate</b></td>");
+        out.println("<td><b>datareplicate</b></td>");
+        out.println("<td><b>hub</b></td></tr>");
         pstmt = dbConn.prepareStatement("SELECT * FROM xml_replication");
         pstmt.execute();
         ResultSet rs = pstmt.getResultSet();
@@ -329,10 +340,18 @@
         while(tablehasrows) {
           out.println("<tr><td>" + rs.getString(2) + "</td><td>");
           out.println(rs.getString(3) + "</td><td>");
-          out.println(rs.getString(4) + "</td></tr>");
+          out.println(rs.getString(4) + "</td><td>");
+          out.println(rs.getString(5) + "</td><td>");
+          out.println(rs.getString(6) + "</td></tr>");
           tablehasrows = rs.next();
         }
         out.println("</table></body></html>");
+      } 
+      else
+      {
+       
+        out.println("<error>Unkonwn subaction</error>");
+       
       }
       pstmt.close();
       //conn.close();
@@ -445,11 +464,11 @@
         //serverCode = MetacatReplication.getServerCode(server);
         //override = true; //we are now overriding the default action
       }
-      MetacatReplication.replLog("force replication request from " + server); 
-      util.debugMessage("Force replication docid: "+docid, 20);
-      util.debugMessage("Force replication action: "+dbaction, 20);
-      // sending back read request to server
-     
+      MetacatReplication.replLog("force replication request from " + server);
+      MetaCatUtil.debugMessage("Force replication request from: "+ server, 34);
+      MetaCatUtil.debugMessage("Force replication docid: "+docid, 34);
+      MetaCatUtil.debugMessage("Force replication action: "+dbaction, 34);
+      // sending back read request to remote server
       URL u = new URL("https://" + server + "?server="
                 +util.getLocalReplicationServerName()
                 +"&action=read&docid=" + docid);
@@ -467,32 +486,35 @@
       XMLReader docinfoParser = ReplicationHandler.initParser(dih);
       docinfoParser.parse(new InputSource(new StringReader(docInfoStr)));
       Hashtable docinfoHash = dih.getDocInfo();
+      
+      // Get user owner of this docid
       String user = (String)docinfoHash.get("user_owner");
-      
+      // Get home server of this docid
       String homeServer=(String)docinfoHash.get("home_server");
-      util.debugMessage("homeServer: "+homeServer,20);
-      // write the document here
-      //Connection conn = util.openDBConnection();
+      MetaCatUtil.debugMessage("homeServer: "+homeServer, 34);
+    
+      // Get DBConnection from pool
       dbConn=DBConnectionPool.
               getDBConnection("MetacatReplication.handleForceReplicateRequest");
       serialNumber=dbConn.getCheckOutSerialNumber();
+      // write the document to local database
       DocumentImpl.writeReplication(dbConn, 
                   new StringReader(xmldoc), null, null, dbaction, docid, user, 
-                  null, homeServer, false);
+                  null, homeServer, false, server);
               
-       
-      //conn.close();
-
       MetacatReplication.replLog("document " + docid + " added to DB with " +
                                  "action " + dbaction);
-    } catch(Exception e) {
+    }//try
+    catch(Exception e) 
+    {
       
       System.out.println("ERROR in MetacatReplication.handleForceReplicate" +
                          "Request(): " + e.getMessage());
        e.printStackTrace();
-    }
+    }//catch
     finally
     {
+      // Return the checked out DBConnection
       DBConnectionPool.returnDBConnection(dbConn, serialNumber);
     }//finally
   }
@@ -504,33 +526,32 @@
    */
   private void handleForceReplicateDataFileRequest(Hashtable params)
   {
-    //check if the metacat was configured to handle replication 
-    if (!(util.getOption("replicationacceptdata")).equals("on"))
-    {
-      return;
-    }
+    
     //make sure there is some parameters
     if(params.isEmpty())
     {
       return;
     }
-    String server = ((String[])params.get("server"))[0]; // the server that
-    //docid should include rev number
-    String docid = ((String[])params.get("docid"))[0]; // sent the document
-    if (docid==null)
+    // Get remote server 
+    String server = ((String[])params.get("server"))[0]; 
+    // the docid should include rev number
+    String docid = ((String[])params.get("docid"))[0]; 
+    // Make sure there is a docid and server
+    if (docid==null || server==null || server.equals(""))
     {
-      util.debugMessage("Didn't specify docid for replication", 20);
+      MetaCatUtil.debugMessage("Didn't specify docid or server for replication"
+                              , 20);
       return;
     }
-    //docid was switch to two parts
+    
+    // Overide or not
     boolean override = false;
-    int serverCode = 1;
+    // dbaction - update or insert
     String dbaction=null;
-    //Connection conn=null;
-    
+   
     try 
     {
-      //docid was switch to two parts
+      //docid was switch to two parts uinque code and rev
       String uniqueCode=MetaCatUtil.getDocIdFromString(docid);
       int rev=MetaCatUtil.getVersionFromString(docid);
       if(params.containsKey("dbaction")) 
@@ -541,9 +562,11 @@
       {
         dbaction = "update";
       }
-      //serverCode = MetacatReplication.getServerCode(server);
+      
       MetacatReplication.replLog("force replication request from " + server); 
-      
+      MetaCatUtil.debugMessage("Force replication request from: "+ server, 34);
+      MetaCatUtil.debugMessage("Force replication docid: "+docid, 34);
+      MetaCatUtil.debugMessage("Force replication action: "+dbaction, 34);
       // get the document info from server
       URL docinfourl = new URL("https://" + server + 
                                "?server="+util.getLocalReplicationServerName()
@@ -563,7 +586,7 @@
       String docType = (String)docinfoHash.get("doctype");
       
       String docHomeServer= (String)docinfoHash.get("home_server");
-      MetaCatUtil.debugMessage("docHomeServer of data file: "+docHomeServer);
+      MetaCatUtil.debugMessage("docHomeServer of datafile: "+docHomeServer, 34);
       
       
       
@@ -586,8 +609,8 @@
         String datafilePath = util.getOption("datafilepath");
         //register data file into xml_documents table and wite data file
         //into file system
-        DocumentImpl.writeDataFile(url.openStream(), datafilePath, docName,
-                              docType, docid, user,docHomeServer);
+        DocumentImpl.writeDataFileInReplication(url.openStream(), datafilePath, 
+                            docName, docType, docid, user,docHomeServer,server);
      }
     
   
@@ -598,7 +621,8 @@
     {
       
       //util.returnConnection(conn);
-      util.debugMessage("ERROR in MetacatReplication.handleForceReplicate" +
+      util.debugMessage
+              ("ERROR in MetacatReplication.handleForceDataFileReplicate" +
                          "Request(): " + e.getMessage(), 30);
     }
   }
@@ -612,11 +636,10 @@
   private void handleGetLockRequest(PrintWriter out, Hashtable params,
                                     HttpServletResponse response)
   {
-    //Connection conn = null;
+
     try
     {
-      /*conn = MetacatReplication.getDBConnection("MetacatReplication." +
-                                                "handleGetLockRequest");*/
+    
       String docid = ((String[])params.get("docid"))[0];
       String remoteRev = ((String[])params.get("updaterev"))[0];
       DocumentImpl requestDoc = new DocumentImpl(docid);
@@ -671,11 +694,10 @@
   {
     String docid = ((String[])(params.get("docid")))[0];
     StringBuffer sb = new StringBuffer();
-    //Connection conn = null;
+  
     try
     {
-      /*conn = MetacatReplication.getDBConnection("MetacatReplication." +
-                                              "handleGetDocumentInfoRequest");*/
+      
       DocumentImpl doc = new DocumentImpl(docid);
       sb.append("<documentinfo><docid>").append(docid);
       sb.append("</docid><docname>").append(doc.getDocname());
@@ -692,7 +714,7 @@
       sb.append("</rev></documentinfo>");
       response.setContentType("text/xml");
       out.println(sb.toString());
-      //conn.close();
+      
     }
     catch (Exception e)
     {
@@ -710,13 +732,9 @@
                             Hashtable params, HttpServletResponse response)
                                  
   {
-    //check the metacat was configured to handle data replication
-    if (!(util.getOption("replicationsenddata")).equals("on"))
-    {
-      return;
-    }
-    
+    // File path for data file    
     String filepath = util.getOption("datafilepath");
+    // Request docid
     String docId = ((String[])(params.get("docid")))[0];
     //check if the doicd is null
     if (docId==null)
@@ -752,73 +770,73 @@
     {
           filepath += "/";
     }
-    String filename = filepath + docId;      //MIME type
+    // Get file aboslute file name
+    String filename = filepath + docId;      
     
-    String contentType = null;//getServletContext().getMimeType(filename);
+    //MIME type
+    String contentType = null;
+    if (filename.endsWith(".xml")) 
+    {
+        contentType="text/xml";
+    } 
+    else if (filename.endsWith(".css")) 
+    {
+        contentType="text/css";
+    } 
+    else if (filename.endsWith(".dtd")) 
+    {
+        contentType="text/plain";
+    } 
+    else if (filename.endsWith(".xsd")) 
+    {
+        contentType="text/xml";
+    } 
+    else if (filename.endsWith("/")) 
+    {
+        contentType="text/html";
+    } 
+    else 
+    {
+        File f = new File(filename);
+        if ( f.isDirectory() ) 
+        {
+           contentType="text/html";
+        } 
+        else
+        {
+           contentType="application/octet-stream";
+        }
+     }
    
-    if (contentType == null) 
-    {
-       if (filename.endsWith(".xml")) 
-       {
-          contentType="text/xml";
-       } 
-       else if (filename.endsWith(".css")) 
-       {
-          contentType="text/css";
-       } 
-       else if (filename.endsWith(".dtd")) 
-       {
-          contentType="text/plain";
-       } 
-       else if (filename.endsWith(".xsd")) 
-       {
-          contentType="text/xml";
-       } 
-       else if (filename.endsWith("/")) 
-       {
-          contentType="text/html";
-       } 
-       else 
-       {
-          File f = new File(filename);
-          if ( f.isDirectory() ) 
-          {
-             contentType="text/html";
-          } 
-          else
-          {
-             contentType="application/octet-stream";
-          }
-       }
-   }
-  
+   // Set the mime type
    response.setContentType(contentType);
-   // if we decide to use "application/octet-stream" for all data returns
-   // response.setContentType("application/octet-stream");
+   
+   // Get the content of the file
    FileInputStream fin = null;
    try 
    {
-      
+      // FileInputStream to metacat
       fin = new FileInputStream(filename);
-      
-      byte[] buf = new byte[4 * 1024]; // 4K buffer
+      // 4K buffer
+      byte[] buf = new byte[4 * 1024];
+      // Read data from file input stream to byte array
       int b = fin.read(buf);
+      // Write to outStream from byte array
       while (b != -1) 
       {
-        
         outPut.write(buf, 0, b);
         b = fin.read(buf);
       }
-    
+      // close file input stream
       fin.close();
    
-   }  
+   }//try
    catch(Exception e)
    {
       System.out.println("error getting data file from MetacatReplication." +
                          "handlGetDataFileRequest " + e.getMessage());
       e.printStackTrace(System.out);
-   }
+   }//catch
   
 }
   
@@ -829,7 +847,7 @@
   private void handleGetDocumentRequest(PrintWriter out, Hashtable params, 
                                         HttpServletResponse response)
   {
-    //Connection dbConn = null;
+  
     try
     {
       //try to open a https stream to test if the request server's public key
@@ -844,16 +862,16 @@
       {
         response.setContentType("text/xml");
         out.println("<error>Couldn't pass the trust test</error>");
+        out.close();
         return;
       }
       
       String docid = ((String[])(params.get("docid")))[0];
-      /*conn = MetacatReplication.getDBConnection("MetacatReplication." +
-                                                "handleGetDocumentRequest");*/
+      
       DocumentImpl di = new DocumentImpl(docid);
       response.setContentType("text/xml");
       out.print(di.toString());
-      //conn.close();
+   
       MetacatReplication.replLog("document " + docid + " sent");
     
     }
@@ -863,7 +881,7 @@
                           +"handlGetDocumentRequest " + e.getMessage(), 30);
       //e.printStackTrace(System.out);
       response.setContentType("text/xml");
-      out.println("<error>e.getMessage()</error>");
+      out.println("<error>"+e.getMessage()+"</error>");
     }
     
   }
@@ -886,14 +904,36 @@
   private void handleUpdateRequest(PrintWriter out, Hashtable params, 
                                     HttpServletResponse response)
   {
+    // Checked out DBConnection 
     DBConnection dbConn = null;
+    // DBConenction serial number when checked it out
     int serialNumber = -1;
     PreparedStatement pstmt = null;
+    // Server list to store server info of xml_replication table
+    ReplicationServerList serverList = null;
+  
     try
     {
+      // Check out a DBConnection from pool
+      dbConn=DBConnectionPool.
+                  getDBConnection("MetacatReplication.handleUpdateRequest");
+      serialNumber=dbConn.getCheckOutSerialNumber();
+      // Create a server list from xml_replication table
+      serverList = new ReplicationServerList();
+      
+      // Get remote server name from param
+      String server = ((String[])params.get("server"))[0];
+      // If no servr name in param, return a error
+      if ( server == null || server.equals(""))
+      {
+        response.setContentType("text/xml");
+        out.println("<error>Request didn't specify server name</error>");
+        out.close();
+        return;
+      }//if
+      
       //try to open a https stream to test if the request server's public key
       //in the key store, this is security issue
-      String server = ((String[])params.get("server"))[0];
       URL u = new URL("https://" + server + "?server="
                 +util.getLocalReplicationServerName()
                 +"&action=test");
@@ -903,46 +943,70 @@
       {
         response.setContentType("text/xml");
         out.println("<error>Couldn't pass the trust test</error>");
+        out.close();
         return;
       }
       
+      
+      // Check if local host configure to replicate xml documents to remote
+      // server. If not send back a error message
+      if (!serverList.getReplicationValue(server))
+      {
+        response.setContentType("text/xml");
+        out.println
+        ("<error>Configuration not allow to replicate document to you</error>");
+        out.close();
+        return;
+      }//if
+      
+      // Store the sql command
       StringBuffer docsql = new StringBuffer();
+      // Stroe the docid list
       StringBuffer doclist = new StringBuffer();
+      // Store the deleted docid list
+      StringBuffer delsql = new StringBuffer();
+      // Store the data set file
       Vector packageFiles = new Vector();
       
-      //get all docs that reside on this server
+      // Append local server's name and replication servlet to doclist
       doclist.append("<?xml version=\"1.0\"?><replication>");
       doclist.append("<server>").append(util.getOption("server"));
       doclist.append(util.getOption("replicationpath"));
       doclist.append("</server><updates>");
       
+      // Get correct docid that reside on this server according the requesting
+      // server's replicate and data replicate value in xml_replication table
       docsql.append("select docid, rev, doctype from xml_documents ");
-      if (!(util.getOption("hub")).equals("super"))
+      // If the localhost is not a hub to the remote server, only replicate
+      // the docid' which home server is local host (server_location =1)
+      if (!serverList.getHubValue(server))
       {
         docsql.append("where server_location = 1");
       }
+      MetaCatUtil.debugMessage("Doc sql: "+docsql.toString(), 30);
       
-      //get any deleted documents
-      StringBuffer delsql = new StringBuffer();
+      // Get any deleted documents
       delsql.append("select distinct docid from ");
       delsql.append("xml_revisions where docid not in (select docid from ");
       delsql.append("xml_documents) ");
-      if (!(util.getOption("hub")).equals("super"))
+      // If the localhost is not a hub to the remote server, only replicate
+      // the docid' which home server is local host (server_location =1)
+      if (!serverList.getHubValue(server))
       {
         delsql.append("and server_location = 1");
       }
-     
-      /*conn = MetacatReplication.getDBConnection("MetacatReplication." +
-                                                "handleUpdateRequest");*/
-      dbConn=DBConnectionPool.
-                  getDBConnection("MetacatReplication.handleUpdateRequest");
-      serialNumber=dbConn.getCheckOutSerialNumber();
+      MetaCatUtil.debugMessage("Deleted sql: "+delsql.toString(), 30);
+      
+      
+      
+      // Get docid list of local host
       pstmt = dbConn.prepareStatement(docsql.toString());
       pstmt.execute();
       ResultSet rs = pstmt.getResultSet();
       boolean tablehasrows = rs.next();
       //If metacat configed to replicate data file
-      if ((util.getOption("replicationsenddata")).equals("on"))
+      //if ((util.getOption("replicationsenddata")).equals("on"))
+      if (serverList.getDataReplicationValue(server))
       {
         while(tablehasrows)
         {
@@ -949,10 +1013,12 @@
           String recordDoctype = rs.getString(3);
           Vector packagedoctypes = MetaCatUtil.getOptionList(
                                      MetaCatUtil.getOption("packagedoctype"));
+          //if this is a package file, put it at the end
+          //because if a package file is read before all of the files it
+          //refers to are loaded then there is an error
           if(!packagedoctypes.contains(recordDoctype))
-          {   //if this is a package file, put it at the end
-              //because if a package file is read before all of the files it
-              //refers to are loaded then there is an error
+          {   
+              //If this is not data file
               if (!recordDoctype.equals("BIN"))
               {
                 //for non-data file document
@@ -961,7 +1027,7 @@
                 doclist.append("</docid><rev>").append(rs.getInt(2));
                 doclist.append("</rev>");
                 doclist.append("</updatedDocument>");
-              }
+              }//if
               else
               {
                 //for data file document, in datafile attributes
@@ -974,8 +1040,8 @@
                 doclist.append(MetaCatUtil.getOption("datafileflag"));
                 doclist.append("</datafile>");
                 doclist.append("</updatedDocument>");
-              } 
-          }
+              }//else 
+          }//if packagedoctpes
           else
           { //the package files are saved to be put into the xml later.
               Vector v = new Vector();
@@ -982,7 +1048,7 @@
               v.add(new String(rs.getString(1)));
               v.add(new Integer(rs.getInt(2)));
               packageFiles.add(new Vector(v));
-          }
+          }//esle
           tablehasrows = rs.next();
         }//while
       }//if
@@ -1058,7 +1124,7 @@
                          "handleupdaterequest: " + e.getMessage(), 30);
       //e.printStackTrace(System.out);
       response.setContentType("text/xml");
-      out.println("<error>e.getMessage()</error>");
+      out.println("<error>"+e.getMessage()+"</error>");
     }
     finally
     {
@@ -1076,11 +1142,8 @@
         DBConnectionPool.returnDBConnection(dbConn, serialNumber);
       }//finally
     }//finally
-        
-                        
-      
-    
-  }
+ 
+  }//handlUpdateRequest
   
   /**
    * Returns the xml_catalog table encoded in xml
@@ -1150,6 +1213,10 @@
       System.out.println("error in MetacatReplication.handleGetCatalogRequest:"+ 
                           e.getMessage());
       e.printStackTrace(System.out);
+      if(printFlag)
+      {
+        out.println("<error>"+e.getMessage()+"</error>");
+      }
     }
     finally
     {
@@ -1222,7 +1289,7 @@
    * @return the servername or null if the specified serverCode does not
    *         exist.
    */
-  public static String getServer(int serverCode)
+  public static String getServerNameForServerCode(int serverCode)
   {
     //System.out.println("serverid: " + serverCode);
     DBConnection dbConn = null;
@@ -1283,7 +1350,7 @@
    * @return integer > 0 representing the code of the server, 0 if the server
    *  does not exist.
    */
-  public static int getServerCode(String server) throws Exception
+  public static int getServerCodeForServerName(String server) throws Exception
   {
     DBConnection dbConn = null;
     int serialNumber = -1;
@@ -1333,6 +1400,169 @@
   }
   
   /**
+   * Method to get a host server information for given docid
+   * @param conn a connection to the database
+   */
+  public static Hashtable getHomeServerInfoForDocId(String docId)
+  {
+    Hashtable sl = new Hashtable();
+    DBConnection dbConn = null;
+    int serialNumber = -1;
+    //MetaCatUtil ut=new MetaCatUtil();
+    docId=MetaCatUtil.getDocIdFromString(docId);
+    PreparedStatement pstmt=null;
+    int serverLocation;
+    try
+    {
+      //get conection
+      dbConn=DBConnectionPool.
+                  getDBConnection("ReplicationHandler.getHomeServer");
+      serialNumber=dbConn.getCheckOutSerialNumber();
+      //get a server location from xml_document table
+      pstmt=dbConn.prepareStatement("select server_location from xml_documents "
+                                            +"where docid = ?");
+      pstmt.setString(1, docId);
+      pstmt.execute();
+      ResultSet serverName = pstmt.getResultSet();
+      //get a server location
+      if(serverName.next())
+      {
+        serverLocation=serverName.getInt(1);
+        pstmt.close();
+      }
+      else
+      {
+        pstmt.close();
+        //ut.returnConnection(conn);
+        return null;
+      }
+      pstmt=dbConn.prepareStatement("select server, last_checked, replicate " +
+                        "from xml_replication where serverid = ?");
+      //increase usage count
+      dbConn.increaseUsageCount(1);
+      pstmt.setInt(1, serverLocation);
+      pstmt.execute();
+      ResultSet rs = pstmt.getResultSet();
+      boolean tableHasRows = rs.next();
+      if (tableHasRows)
+      {
+        
+          String server = rs.getString(1);
+          String last_checked = rs.getString(2);
+          if(!server.equals("localhost"))
+          {
+            sl.put(server, last_checked);
+          }
+        
+      }
+      else
+      {
+        pstmt.close();
+        //ut.returnConnection(conn);
+        return null;
+      }
+      pstmt.close();
+    }
+    catch(Exception e)
+    {
+      System.out.println("error in replicationHandler.getHomeServer(): " +
+                         e.getMessage());
+    }
+    finally
+    {
+      try
+      {
+        pstmt.close();
+        //ut.returnConnection(conn);
+      }
+      catch (Exception ee)
+      {
+        MetaCatUtil.debugMessage("Eror irn rplicationHandler.getHomeServer() "+
+                          "to close pstmt: "+ee.getMessage(), 30);
+      }
+      finally
+      {
+        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
+      }
+    
+    }//finally
+    return sl;
+  }
+  
+  /**
+   * Returns a home server location  given a accnum
+   * @param accNum , given accNum for a document
+   * 
+   */
+  public static int getHomeServerCodeForDocId(String accNum) throws Exception
+  {
+    DBConnection dbConn = null;
+    int serialNumber = -1;
+    PreparedStatement pstmt = null;
+    int serverCode = 1;
+    //MetaCatUtil ut = new MetaCatUtil();
+    String docId=MetaCatUtil.getDocIdFromString(accNum);
+
+    try 
+    {
+
+      // Get DBConnection
+      dbConn=DBConnectionPool.
+                  getDBConnection("ReplicationHandler.getServerLocation");
+      serialNumber=dbConn.getCheckOutSerialNumber();
+      pstmt=dbConn.prepareStatement("SELECT server_location FROM xml_documents " 
+                              + "WHERE docid LIKE '" + docId + "'");
+      pstmt.execute();
+      ResultSet rs = pstmt.getResultSet();
+      boolean tablehasrows = rs.next();
+      //If a document is find, return the server location for it
+      if ( tablehasrows ) 
+      {  
+        serverCode = rs.getInt(1);
+        pstmt.close();
+        //conn.close();
+        return serverCode;
+      }
+      //if couldn't find in xml_documents table, we think server code is 1
+      //(this is new document)
+      else
+      {
+        pstmt.close();
+        //conn.close();
+        return serverCode;
+      }
+      
+    } 
+    catch(Exception e) 
+    {
+      
+      throw e;
+
+    } 
+    finally 
+    {
+      try 
+      {
+        pstmt.close();
+        //conn.close();
+        
+      } 
+      catch(Exception ee) 
+      {
+        MetaCatUtil.debugMessage("Erorr in Replication.getServerLocation "+
+                     "to close pstmt"+ee.getMessage(), 30);
+      }
+      finally
+      {
+        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
+      }//finally
+    }//finally
+   //return serverCode;
+  }
+  
+  
+  
+  /**
    * This method returns the content of a url
    * @param u the url to return the content from
    * @return a string representing the content of the url
Index: src/edu/ucsb/nceas/metacat/DBQuery.java
===================================================================
--- src/edu/ucsb/nceas/metacat/DBQuery.java	(revision 1291)
+++ src/edu/ucsb/nceas/metacat/DBQuery.java	(revision 1292)
@@ -824,6 +824,13 @@
     ResultSet rs=null;
     String docIdInSubjectField=null;
     String docIdInObjectField=null;
+    
+    // Check the parameter
+    if (dataPackageDocid == null || dataPackageDocid.equals(""))
+    {
+      return docIdList;
+    }//if
+    
     //the query stirng
     String query="SELECT subject, object from xml_relation where docId = ?";
     try
@@ -865,7 +872,7 @@
     }//try
     catch (SQLException e)
     {
-      util.debugMessage("Error in getDocidListForDataPackage: "
+      MetaCatUtil.debugMessage("Error in getDocidListForDataPackage: "
                             +e.getMessage(), 30);
     }//catch
     finally
@@ -876,7 +883,7 @@
       }//try
       catch (SQLException ee)
       {
-        util.debugMessage("Error in getDocidListForDataPackage: "
+        MetaCatUtil.debugMessage("Error in getDocidListForDataPackage: "
                             +ee.getMessage(), 30);
       }//catch     
       finally
@@ -892,13 +899,20 @@
    * @param dataPackageDocid, the string in docId field of xml_relation table
    */
   private Vector getOldVersionDocidListForDataPackage(String dataPackageDocid)
-                                 throws SQLException, McdbException,Exception
   {
    
     Vector docIdList=new Vector();//return value
     Vector tripleList=null;
     String xml=null;
-   
+    
+     // Check the parameter
+    if (dataPackageDocid == null || dataPackageDocid.equals(""))
+    {
+      return docIdList;
+    }//if
+    
+    try
+    {
       //initial a documentImpl object 
       DocumentImpl packageDocument = 
                   new DocumentImpl(dataPackageDocid);
@@ -925,9 +939,14 @@
           docIdList.add(((Triple)(tripleList.get(i))).getObject());
         }
       }//for
+    }//try
+    catch (Exception e)
+    {
+      MetaCatUtil.debugMessage("Error in getOldVersionAllDocumentImpl: "
+                            +e.getMessage(), 30);
+    }//catch
   
-    
-    
+    // return result
     return docIdList;
   }//getDocidListForPackageInXMLRevisions()  
   
@@ -1010,6 +1029,7 @@
    * If the return value is -5, means no value in rev field for this docid
    */
   private int getCurrentRevFromXMLDoumentsTable(String docId)
+                                                throws SQLException
   {
     int rev=-5;
     PreparedStatement pStmt = null;
@@ -1037,12 +1057,13 @@
       {
         rev=-5;
       }
-      pStmt.close();
+     
     }//try
     catch (SQLException e)
     {
-      util.debugMessage("Error in getCurrentRevFromXMLDoumentsTable: "
+      MetaCatUtil.debugMessage("Error in getCurrentRevFromXMLDoumentsTable: "
                             +e.getMessage(), 30);
+      throw e;
     }//catch
     finally
     {
@@ -1089,10 +1110,12 @@
 
   
   /**
-   *transfer a docid vetor to a documentImpl vector. The documentImpl vetor 
-   *only inlcudes current version
-   *@param docIdList, a vetor hold a docid list for a data package. In docid,
-   *there is not version number in it.
+   * Transfer a docid vetor to a documentImpl vector. The documentImpl vetor 
+   * only inlcudes current version. If a DocumentImple object
+   * couldn't find for a docid, then the String of this docid was added to vetor
+   * rather than DocumentImple object.
+   * @param docIdList, a vetor hold a docid list for a data package. In docid,
+   * there is not version number in it.
    */  
   
   private Vector getCurrentAllDocumentImpl( Vector docIdList)
@@ -1102,40 +1125,59 @@
     Vector documentImplList=new Vector();
     int rev=0; 
     
-    /*if (conn == null || conn.isClosed())
+    // Check the parameter
+    if (docIdList.isEmpty())
     {
-      dbConn = util.openDBConnection();
-    }
-    else
-    {
-      dbConn=conn;
-    }*/
+      return documentImplList;
+    }//if
+  
     //for every docid in vector
     for (int i=0;i<docIdList.size();i++)
     {
-      //get newest version for this docId
-      rev=getCurrentRevFromXMLDoumentsTable((String)docIdList.elementAt(i));
+      try
+      {
+        //get newest version for this docId
+        rev=getCurrentRevFromXMLDoumentsTable((String)docIdList.elementAt(i));
+      
+        // There is no record for this docId in xml_documents table
+        if (rev ==-5)
+        {
+          // Rather than put DocumentImple object, put a String Object(docid)
+          // into the documentImplList
+          documentImplList.add((String)docIdList.elementAt(i));
+          // Skip other code
+          continue;
+        }
      
-      String docidPlusVersion=((String)docIdList.elementAt(i))
+        String docidPlusVersion=((String)docIdList.elementAt(i))
                         +util.getOption("accNumSeparator")+rev;
-      //create new documentImpl object
-      DocumentImpl documentImplObject = 
+      
+      
+        //create new documentImpl object
+        DocumentImpl documentImplObject = 
                                     new DocumentImpl(docidPlusVersion);
-      //add them to vector                            
-      documentImplList.add(documentImplObject);
-      
+       //add them to vector                            
+        documentImplList.add(documentImplObject);
+      }//try
+      catch (Exception e)
+      {
+        MetaCatUtil.debugMessage("Error in getCurrentAllDocumentImpl: "
+                            +e.getMessage(), 30);
+        // continue the for loop
+        continue;
+      }
     }//for
     return documentImplList;
   }
   
   /**
-   *transfer a docid vetor to a documentImpl vector. The documentImpl vetor 
-   *does not inlcude old version
-   *@param docIdList, a vetor hold a docid list for a data package. In docid,
-   *there is version number in it.
+   * Transfer a docid vetor to a documentImpl vector. If a DocumentImple object
+   * couldn't find for a docid, then the String of this docid was added to vetor
+   * rather than DocumentImple object.
+   * @param docIdList, a vetor hold a docid list for a data package. In docid,
+   *t here is version number in it.
    */    
   private Vector getOldVersionAllDocumentImpl( Vector docIdList)
-                              throws McdbException,Exception
   {
     //Connection dbConn=null;
     Vector documentImplList=new Vector();
@@ -1143,28 +1185,49 @@
     String uniqueId=null;
     int rev=0; 
     
-    /*if (conn == null || conn.isClosed())
+    // Check the parameter
+    if (docIdList.isEmpty())
     {
-      dbConn = util.openDBConnection();
-    }
-    else
-    {
-      dbConn=conn;
-    }*/
+      return documentImplList;
+    }//if
+    
     //for every docid in vector
     for (int i=0;i<docIdList.size();i++)
     {
       
         String docidPlusVersion=(String)(docIdList.elementAt(i));
-        //create new documentImpl object
-        DocumentImpl documentImplObject = 
+        
+        try
+        {
+          //create new documentImpl object
+          DocumentImpl documentImplObject = 
                                     new DocumentImpl(docidPlusVersion);
-        //add them to vector                            
-        documentImplList.add(documentImplObject);
+          //add them to vector                            
+          documentImplList.add(documentImplObject);
+        }//try
+        catch (McdbDocNotFoundException notFoundE)
+        {
+          MetaCatUtil.debugMessage("Error in DBQuery.getOldVersionAllDocument"+
+                                  "Imple" + notFoundE.getMessage(), 30);
+          // Rather than add a DocumentImple object into vetor, a String object
+          // - the doicd was added to the vector
+          documentImplList.add(docidPlusVersion);
+          // Continue the for loop
+          continue;
+        }//catch
+        catch (Exception e)
+        {
+          MetaCatUtil.debugMessage("Error in DBQuery.getOldVersionAllDocument"+
+                                  "Imple" + e.getMessage(), 30);
+          // Continue the for loop
+          continue;
+        }//catch
+          
       
     }//for
     return documentImplList;
-  }
+  }//getOldVersionAllDocumentImple
+  
   /**
    *put a data file into a zip output stream
    *@param docImpl, docmentImpl object which will be sent to zip output stream
@@ -1221,18 +1284,7 @@
     byte[] byteString=null;
     InputStream source;
     DBTransform xmlToHtml;
-    //Connection dbConn;
-
-    //get the connection to the database
-    /*if (conn == null || conn.isClosed())
-    {
-      dbConn = util.openDBConnection();
-    }
-    else
-    {
-      dbConn=conn;
-    }*/
-
+  
     //create a DBTransform ojbect
     xmlToHtml = new DBTransform();
     //head of html
@@ -1239,7 +1291,20 @@
     htmlDoc.append("<html><head></head><body>");
     for (int i=0; i<docImplList.size(); i++)
     {
-      if ((((DocumentImpl)docImplList.elementAt(i)).getDoctype()).
+      // If this String object, this means it is missed data file
+      if ((((docImplList.elementAt(i)).getClass()).toString())
+                                             .equals("class java.lang.String"))
+      {
+        
+        htmlDoc.append("<a href=\"");
+        String dataFileid =(String)docImplList.elementAt(i);
+        htmlDoc.append("./data/").append(dataFileid).append("\">");
+        htmlDoc.append("Data File: ");
+        htmlDoc.append(dataFileid).append("</a><br>");
+        htmlDoc.append("<br><hr><br>");
+        
+      }//if
+      else if ((((DocumentImpl)docImplList.elementAt(i)).getDoctype()).
                                                          compareTo("BIN")!=0)
       { //this is an xml file so we can transform it.
         //transform each file individually then concatenate all of the
@@ -1262,7 +1327,6 @@
       else
       { //this is a data file so we should link to it in the html
         htmlDoc.append("<a href=\"");
-        String dataFileName = null;
         String dataFileid =((DocumentImpl)docImplList.elementAt(i)).getDocID();
         htmlDoc.append("./data/").append(dataFileid).append("\">");
         htmlDoc.append("Data File: ");
@@ -1291,7 +1355,7 @@
    * @param groups, the group of the user
    */
   public ZipOutputStream getZippedPackage(String docIdString, 
-                    ServletOutputStream out, String user, String[] groups)
+        ServletOutputStream out, String user, String[] groups, String passWord)
                     throws ClassNotFoundException, IOException, SQLException, 
                       McdbException, NumberFormatException, Exception
   { 
@@ -1307,32 +1371,24 @@
     
     String docId=null;
     int version=-5;
+    // Docid without revision
     docId=MetaCatUtil.getDocIdFromString(docIdString);
+    // revision number
     version=MetaCatUtil.getVersionFromString(docIdString);
  
-    //get the connection to the database
-    /*if (conn == null || conn.isClosed())
-    {
-      dbConn = util.openDBConnection();
-    }
-    else
-    {
-      dbConn=conn;
-    }*/
-
     //check if the reqused docId is a data package id
     if (!isDataPackageId(docId))//if it is not, throw a exception
     {
       Exception e = new Exception("The request the doc id " +docIdString+
                                     " is not a data package id");
-      //dbConn.close();
       throw e;
     }
+    // Check the permission of user
     else if(!hasPermissionToExportPackage(docId, user, groups))
     {
+      
       Exception e = new Exception("User " + user + " does not have permission"
                        +" to export the data package " + docIdString);
-      //dbConn.close();
       throw e;
     }
     else //it is a packadge id
@@ -1339,11 +1395,13 @@
     { 
       //store the package id
       packageId=docId;
-      //If it is for current version
-      if ((version ==-1)||version==getCurrentRevFromXMLDoumentsTable(packageId))
+      //get current version in database
+      int currentVersion = getCurrentRevFromXMLDoumentsTable(packageId);
+      //If it is for current version (-1 means user didn't specify revision)
+      if ((version ==-1)||version==currentVersion)
       { 
         //get current version number
-        version=getCurrentRevFromXMLDoumentsTable(packageId);
+        version=currentVersion;
         //get package zip entry name
         //it should be docId.revsion.package
         rootName=packageId+util.getOption("accNumSeparator")+version+
@@ -1354,6 +1412,11 @@
         documentImplList=getCurrentAllDocumentImpl(docIdList);
        
       }//if
+      else if (version > currentVersion || version < -1)
+      {
+        throw new Exception ("The user specified docid: "+docId+"."+version
+                                              +" doesn't exist");
+      }//else if
       else  //for an old version
       {
        
@@ -1365,37 +1428,80 @@
         documentImplList=getOldVersionAllDocumentImpl(docIdList);
       }//else  
       
+      // Make sure documentImplist is not empty
+      if (documentImplList.isEmpty())
+      {
+        throw new Exception ("Couldn't find component for data package: "
+                                              + packageId);
+      }//if
       
-      zOut = new ZipOutputStream(out);
-
+     
+       zOut = new ZipOutputStream(out);
       //put every element into zip output stream
       for (int i=0; i < documentImplList.size(); i++ )
       {
-        //create a docmentImpls object (represent xml doc) base on the docId
-        docImpls=(DocumentImpl)documentImplList.elementAt(i);
-        
-        //checking if the user has the permission to read the documents
-        if (docImpls.hasReadPermission(user,groups,docImpls.getDocID()))
-        { 
+        // if the object in the vetor is String, this means we couldn't find
+        // the document locally, we need find it remote
+       if ((((documentImplList.elementAt(i)).getClass()).toString())
+                                             .equals("class java.lang.String"))
+        {
+          // Get String object from vetor
+          String documentId = (String) documentImplList.elementAt(i);
+          MetaCatUtil.debugMessage("docid: "+documentId, 30);
+          // Get doicd without revision
+          String docidWithoutRevision = 
+                                     MetaCatUtil.getDocIdFromString(documentId);
+          MetaCatUtil.debugMessage("docidWithoutRevsion: "
+                                                     +docidWithoutRevision, 30);
+          // Get revision
+          String revision = MetaCatUtil.getRevisionStringFromString(documentId);
+          MetaCatUtil.debugMessage("revsion from docIdentifier: "+revision, 30);
+          // Zip entry string
+          String zipEntryPath = rootName+"/data/"; 
+          // Create a RemoteDocument object
+          RemoteDocument remoteDoc = 
+                          new RemoteDocument(docidWithoutRevision,revision,user, 
+                                                     passWord, zipEntryPath);
+          // Here we only read data file from remote metacat
+          String docType = remoteDoc.getDocType();
+          if (docType!=null)
+          {
+            if (docType.equals("BIN"))
+            {
+              // Put remote document to zip output
+              remoteDoc.readDocumentFromRemoteServerByZip(zOut);
+              // Add String object to htmlDocumentImplList
+              String elementInHtmlList = remoteDoc.getDocIdWithoutRevsion()+
+               MetaCatUtil.getOption("accNumSeparator")+remoteDoc.getRevision();
+              htmlDocumentImplList.add(elementInHtmlList);
+            }//if
+          }//if
+         
+        }//if
+        else
+        {
+          //create a docmentImpls object (represent xml doc) base on the docId
+          docImpls=(DocumentImpl)documentImplList.elementAt(i);
+          //checking if the user has the permission to read the documents
+          if (docImpls.hasReadPermission(user,groups,docImpls.getDocID()))
+          {  
             //if the docImpls is metadata 
-          if ((docImpls.getDoctype()).compareTo("BIN")!=0)  
-          {
+            if ((docImpls.getDoctype()).compareTo("BIN")!=0)  
+            {
               //add metadata into zip output stream
               addDocToZipOutputStream(docImpls, zOut, rootName);
               //add the documentImpl into the vetor which will be used in html
               htmlDocumentImplList.add(docImpls);
            
+            }//if
+            else 
+            {
+              //it is data file 
+              addDataFileToZipOutputStream(docImpls, zOut, rootName);
+              htmlDocumentImplList.add(docImpls);
+            }//else
           }//if
-          
-          else 
-          {
-           
-           //it is data file 
-           addDataFileToZipOutputStream(docImpls, zOut, rootName);
-           htmlDocumentImplList.add(docImpls);
-          }//else
-        }//if
-
+        }//else
       }//for
 
       //add html summary file
Index: src/edu/ucsb/nceas/metacat/MetaCatUtil.java
===================================================================
--- src/edu/ucsb/nceas/metacat/MetaCatUtil.java	(revision 1291)
+++ src/edu/ucsb/nceas/metacat/MetaCatUtil.java	(revision 1292)
@@ -380,7 +380,6 @@
    *              1) str1.str2(no version)  version =-1;
    *              2) str1.str2.str3, in this case version = str3;
    *              3) other, vresion =-2
-   * @param the sperator char
    */
   public static int getVersionFromString(String str)
                                 throws NumberFormatException
@@ -408,7 +407,8 @@
     {
       version=-2;
     }
-    else if (dotNumber == 2) //the case for str1.str2.str3
+    else if (dotNumber == 2 && (indexOfLastDot != (str.length() -1))) 
+     //the case for str1.str2.str3
     {
        versionString=str.substring((indexOfLastDot+1), str.length());
        version=Integer.parseInt(versionString);
@@ -421,7 +421,55 @@
     return version;  
   }//getVersionFromString
   
-   /**
+  
+  /** 
+   * Utility method to get version string from a given string
+   * @param string, the given string should be these two format:
+   *              1) str1.str2(no version)  version=null;
+   *              2) str1.str2.str3, in this case version = str3;
+   *              3) other, vresion =null;
+   */
+  public static String getRevisionStringFromString(String str)
+                                throws NumberFormatException
+  {
+    // String to store the version
+    String versionString=null;
+    int dotNumber = 0;//count how many dots in given string
+    int indexOfLastDot = 0;
+    
+    //assume that seperator is one charactor string
+    char seperator=getOption("accNumSeparator").charAt(0);
+    
+    for (int i=0; i<str.length(); i++)
+    {
+      if ( str.charAt(i)==seperator)
+      {
+        dotNumber++;//count how many dots
+        indexOfLastDot=i;//keep the last dot postion
+      }
+    }//for
+    
+    //The string formatt is wrong, because it has more than two or less than
+    //one seperator
+    if ( dotNumber>2 || dotNumber < 1)
+    {
+      versionString = null;
+    }
+    else if (dotNumber == 2 && (indexOfLastDot != (str.length() -1))) 
+    {
+      //the case for str1.str2.str3
+      // indexOfLastDot != (str.length() -1) means get rid of str1.str2.
+      versionString=str.substring((indexOfLastDot+1), str.length());
+    }
+    else if (dotNumber == 1) //the case for str1.str2 or str1.str2.
+    {
+      versionString=null;
+    }
+    
+    return versionString;  
+  }//getVersionFromString
+   
+  /**
    * Method to get the name of local replication server
    */
    public static String getLocalReplicationServerName()
Index: src/edu/ucsb/nceas/metacat/MetaCatServlet.java
===================================================================
--- src/edu/ucsb/nceas/metacat/MetaCatServlet.java	(revision 1291)
+++ src/edu/ucsb/nceas/metacat/MetaCatServlet.java	(revision 1292)
@@ -317,9 +317,9 @@
         }
       } else if (action.equals("export")) {
         
-        handleExportAction(params, response, username, groupnames);
+        handleExportAction(params, response, username, groupnames, password);
       } else if (action.equals("read")) {
-        handleReadAction(params, response, username, groupnames);
+        handleReadAction(params, response, username,password, groupnames);
       } else if (action.equals("insert") || action.equals("update")) {
         PrintWriter out = response.getWriter();
         if ( (username != null) &&  !username.equals("public") ) {
@@ -364,6 +364,10 @@
         PrintWriter out = response.getWriter();
         handleGetMaxDocidAction(out, params, response);
         out.close();
+      } else if (action.equals("getrevisionanddoctype")) {
+        PrintWriter out = response.getWriter();
+        handleGetRevisionAndDocTypeAction(out, params);
+        out.close();
       } else if (action.equals("login") || action.equals("logout")) {
       } else if (action.equals("protocoltest")) {
         String testURL = "metacat://dev.nceas.ucsb.edu/NCEAS.897766.9";
@@ -699,10 +703,12 @@
    * @param user the username sent the request
    * @param groups the user's groupnames
    */
-  private void handleExportAction(Hashtable params,
-                    HttpServletResponse response, String user, String[] groups)
+  private void handleExportAction(Hashtable params, 
+    HttpServletResponse response, String user, String[] groups, String passWord)
   {
+    // Output stream
     ServletOutputStream out = null;
+    // Zip output stream
     ZipOutputStream zOut = null;
     DocumentImpl docImpls=null;
     DBQuery queryObj=null;
@@ -713,27 +719,44 @@
     try
     {
       // read the params
-      if (params.containsKey("docid")) {
+      if (params.containsKey("docid")) 
+      {
         docs = (String[])params.get("docid");
-      }
-
-   
-      queryObj = new DBQuery(saxparser);//"saxparser" have to use though
-                                              //it is not standard
+      }//if
+      // Create a DBuery to handle export
+      queryObj = new DBQuery(saxparser);
+      // Get the docid
       docId=docs[0];
+      // Make sure the client specify docid
+      if (docId == null || docId.equals(""))
+      {
+        response.setContentType("text/xml"); //MIME type
+        // Get a printwriter
+        PrintWriter pw = response.getWriter();
+        // Send back message
+        pw.println("<?xml version=\"1.0\"?>");
+        pw.println("<error>");
+        pw.println("You didn't specify requested docid");
+        pw.println("</error>");
+        // Close printwriter 
+        pw.close();
+        return;
+      }//if
+      // Get output stream
       out = response.getOutputStream();
       response.setContentType("application/zip"); //MIME type
       zOut = new ZipOutputStream(out);
-      zOut =queryObj.getZippedPackage(docId, out, user, groups);
+      zOut =queryObj.getZippedPackage(docId, out, user, groups, passWord);
       zOut.finish(); //terminate the zip file
       zOut.close();  //close the zip stream
       
-    } 
+    }//try 
     catch (Exception e)
     {
       try
       {
         response.setContentType("text/xml"); //MIME type
+        // Send error message back
         if (out != null)
         {
             PrintWriter pw = new PrintWriter(out);
@@ -741,29 +764,30 @@
             pw.println("<error>");
             pw.println(e.getMessage());
             pw.println("</error>");
+            // Close printwriter
             pw.close();
-        }
-
+            // Close output stream
+            out.close();
+        }//if
+        // Close zip output stream 
         if ( zOut != null )
         {
           zOut.close();
-        }
-      }
+        }//if
+      }//try
       catch (IOException ioe)
       {
         MetaCatUtil.debugMessage("Problem with the servlet output " +
-                           "in MetacatServlet.handleReadAction: " +
+                           "in MetacatServlet.handleExportAction: " +
                            ioe.getMessage(), 30);
-        
+      }//catch
 
-      }
-
-      MetaCatUtil.debugMessage("Error in MetacatServlet.handleReadAction: " +
+      MetaCatUtil.debugMessage("Error in MetacatServlet.handleExportAction: " +
                          e.getMessage(), 30);
+      e.printStackTrace(System.out);
       
     }//catch
-   
-
+ 
   }//handleExportAction
   
   // READ SECTION
@@ -779,10 +803,12 @@
    * @param groups the user's groupnames
    */
   private void handleReadAction(Hashtable params, HttpServletResponse response,
-                                String user, String[] groups) 
+                                String user, String passWord, String[] groups) 
   {
     ServletOutputStream out = null;
     ZipOutputStream zout = null;
+    PrintWriter pw = null;
+    boolean zip = false;
     
     try {
       String[] docs = new String[0];
@@ -789,7 +815,7 @@
       String docid = "";
       String qformat = "";
       String abstrpath = null;
-      boolean zip = false;
+      
       // read the params
       if (params.containsKey("docid")) {
         docs = (String[])params.get("docid");
@@ -857,24 +883,116 @@
       }
       
   
-    } catch (Exception e) {
+    }
+    // To handle doc not found exception
+    catch (McdbDocNotFoundException notFoundE)
+    {
+      // the docid which didn't be found
+      String notFoundDocId = notFoundE.getUnfoundDocId();
+      String notFoundRevision = notFoundE.getUnfoundRevision();
+      MetaCatUtil.debugMessage("Missed id: "+ notFoundDocId, 30);
+      MetaCatUtil.debugMessage("Missed rev: "+ notFoundRevision, 30);
+      try
+      {
+        // read docid from remote server
+        readFromRemoteMetaCat(response, notFoundDocId, notFoundRevision,
+                                              user, passWord, out, zip, zout);
+        // Close zout outputstream
+        if ( zout != null)
+        {
+          zout.close();
+        }
+        // close output stream
+        if (out != null)
+        {
+          out.close();
+        }
+        
+      }//try
+      catch ( Exception exc)
+      {
+        MetaCatUtil.debugMessage("Erorr in MetacatServlet.hanldReadAction: "+
+                                      exc.getMessage(), 30);
+        try
+        {
+          if (out != null) 
+          {
+            response.setContentType("text/xml");
+            // Send back error message by printWriter
+            pw = new PrintWriter(out);
+            pw.println("<?xml version=\"1.0\"?>");
+            pw.println("<error>");
+            pw.println(notFoundE.getMessage());
+            pw.println("</error>");
+            pw.close();
+            out.close();
+            
+          }
+          else
+          {
+           response.setContentType("text/xml"); //MIME type
+           // Send back error message if out = null
+           if (pw == null)
+           {
+             // If pw is null, open the respnose
+            pw = response.getWriter();
+           }
+           pw.println("<?xml version=\"1.0\"?>");
+           pw.println("<error>");
+           pw.println(notFoundE.getMessage());
+           pw.println("</error>");
+           pw.close();
+        }
+        // close zout
+        if ( zout != null ) 
+        { 
+          zout.close(); 
+        }
+        }//try
+        catch (IOException ie)
+        {
+          MetaCatUtil.debugMessage("Problem with the servlet output " +
+                           "in MetacatServlet.handleReadAction: " +
+                           ie.getMessage(), 30);
+        }//cathch
+      }//catch
+    }// catch McdbDocNotFoundException
+    catch (Exception e) 
+    {
       try {
-        response.setContentType("text/xml"); //MIME type
-        //PrintWriter pw = response.getWriter();
+       
         if (out != null) {
-            PrintWriter pw = new PrintWriter(out);
+            response.setContentType("text/xml"); //MIME type
+            pw = new PrintWriter(out);
             pw.println("<?xml version=\"1.0\"?>");
             pw.println("<error>");
             pw.println(e.getMessage());
             pw.println("</error>");
             pw.close();
+            out.close();
         }
-        //if ( out != null ) { out.close(); }
+        else
+        {
+           response.setContentType("text/xml"); //MIME type
+           // Send back error message if out = null
+           if ( pw == null)
+           {
+            pw = response.getWriter();
+           }
+           pw.println("<?xml version=\"1.0\"?>");
+           pw.println("<error>");
+           pw.println(e.getMessage());
+           pw.println("</error>");
+           pw.close();
+          
+        }
+        // Close zip output stream
         if ( zout != null ) { zout.close(); }
+        
       } catch (IOException ioe) {
-        System.out.println("Problem with the servlet output " +
+        MetaCatUtil.debugMessage("Problem with the servlet output " +
                            "in MetacatServlet.handleReadAction: " +
-                           ioe.getMessage());
+                           ioe.getMessage(), 30);
         ioe.printStackTrace(System.out);
         
       }
@@ -910,12 +1028,15 @@
      
       if ( doc.getRootNodeID() == 0 ) {
         // this is data file
-        ServletOutputStream out = response.getOutputStream(); 
         String filepath = util.getOption("datafilepath");
         if(!filepath.endsWith("/")) {
           filepath += "/";
         }
-        String filename = filepath + docid;      //MIME type
+        String filename = filepath + docid;
+        FileInputStream fin = null;
+        fin = new FileInputStream(filename);
+        
+        //MIME type
         String contentType = getServletContext().getMimeType(filename);
         if (contentType == null) {
           if (filename.endsWith(".xml")) {
@@ -940,9 +1061,10 @@
         response.setContentType(contentType);
         // if we decide to use "application/octet-stream" for all data returns
         // response.setContentType("application/octet-stream");
-        FileInputStream fin = null;
+       
         try {
-          fin = new FileInputStream(filename);
+          
+          ServletOutputStream out = response.getOutputStream(); 
           byte[] buf = new byte[4 * 1024]; // 4K buffer
           int b = fin.read(buf);
           while (b != -1) {
@@ -974,7 +1096,9 @@
         }
       
       }
-    } catch (Exception except) {
+    }
+    catch (Exception except) 
+    {
       throw except;
     
     }
@@ -1080,12 +1204,13 @@
           if(!filepath.endsWith("/")) {
             filepath += "/";
           }
-          String filename = filepath + doc.getDocname();
-          zentry = new ZipEntry(filename);
-          zout.putNextEntry(zentry);
+          String filename = filepath + docid;
           FileInputStream fin = null;
+          fin = new FileInputStream(filename);
           try {
-            fin = new FileInputStream(filename);
+            
+            zentry = new ZipEntry(docid);
+            zout.putNextEntry(zentry);
             byte[] buf = new byte[4 * 1024]; // 4K buffer
             int b = fin.read(buf);
             while (b != -1) {
@@ -1144,6 +1269,34 @@
    
     }
   }
+  /**
+   * If metacat couldn't find a data file or document locally, it will read this
+   * docid from its home server. This is for the replication feature
+   */
+  private void readFromRemoteMetaCat(HttpServletResponse response, String docid, 
+                     String rev, String user, String password, 
+                     ServletOutputStream out, boolean zip, ZipOutputStream zout)
+                        throws Exception
+ {
+   // Create a object of RemoteDocument, "" is for zipEntryPath
+   RemoteDocument remoteDoc = 
+                        new RemoteDocument (docid, rev,user, password, "");
+   // If it is zip format
+   if (zip)
+   {
+     remoteDoc.readDocumentFromRemoteServerByZip(zout);
+   }//if 
+   else
+   {
+     if (out == null)
+     {
+       out = response.getOutputStream();
+     }//if
+     response.setContentType("application/octet-stream");
+     remoteDoc.readDocumentFromRemoteServer(out);
+   }//else (not zip)                   
+ }//readFromRemoteMetaCat
+  
   // END OF READ SECTION
     
   // INSERT/UPDATE SECTION
@@ -1202,10 +1355,12 @@
                   getDBConnection("MetaCatServlet.handleInsertOrUpdateAction");
           serialNumber=dbConn.getCheckOutSerialNumber();
           
+          
           // write the document to the database
           try 
           {
             String accNumber = docid[0];
+            MetaCatUtil.debugMessage(""+ doAction + " " + accNumber +"...", 10);
             if (accNumber.equals("")) 
             {
               accNumber = null;
@@ -1431,6 +1586,53 @@
  
   // OTHER ACTION HANDLERS
   
+  /**
+   * Handle "getrevsionanddoctype" action
+   * Given a docid, return it's current revision and doctype from data base
+   * The output is String look like "rev;doctype"
+   */
+  private void handleGetRevisionAndDocTypeAction(PrintWriter out, 
+                                                              Hashtable params)
+  {
+    // To store doc parameter
+    String [] docs = new String[10];
+    // Store a single doc id
+    String givenDocId = null;
+    // Get docid from parameters
+    if (params.containsKey("docid")) 
+    {
+      docs = (String[])params.get("docid");
+    }
+    // Get first docid form string array
+    givenDocId = docs[0];
+   
+    try 
+    {
+      // Make sure there is a docid
+      if (givenDocId == null || givenDocId.equals(""))
+      {
+        throw new Exception("User didn't specify docid!");
+      }//if
+      
+      // Create a DBUtil object
+      DBUtil dbutil = new DBUtil();
+      // Get a rev and doctype
+      String revAndDocType = 
+                dbutil.getCurrentRevisionAndDocTypeForGivenDocument(givenDocId);
+      out.println(revAndDocType);
+
+    }//try 
+    catch (Exception e) 
+    {
+      // Handle exception
+      out.println("<?xml version=\"1.0\"?>");
+      out.println("<error>");
+      out.println(e.getMessage());
+      out.println("</error>");
+    }//catch 
+    
+  }//handleGetRevisionAndDocTypeAction
+  
   /** 
    * Handle "getaccesscontrol" action.
    * Read Access Control List from db connection in XML format
@@ -1691,18 +1893,21 @@
                            ise.getMessage());
       }
     }  
-
-    if ( action.equals("upload")) {
-      if (username != null &&  !username.equals("public")) {
-        handleUploadAction(request, response, params, fileList, 
-                           username, groupnames);
-      } else {
-        try {
+    
+    // Get the out stream
+    try {
           out = response.getWriter();
         } catch (IOException ioe2) {
           util.debugMessage("Fatal Error: couldn't get response "+
                                                               "output stream.");
         }
+    
+    if ( action.equals("upload")) {
+      if (username != null &&  !username.equals("public")) {
+        handleUploadAction(request, out, params, fileList, 
+                           username, groupnames);
+      } else {
+       
         out.println("<?xml version=\"1.0\"?>");
         out.println("<error>");
         out.println("Permission denied for " + action);
@@ -1709,11 +1914,11 @@
         out.println("</error>");
       }
     } else {
-      try {
+      /*try {
         out = response.getWriter();
       } catch (IOException ioe2) {
         System.err.println("Fatal Error: couldn't get response output stream.");
-      }
+      }*/
       out.println("<?xml version=\"1.0\"?>");
       out.println("<error>");
       out.println("Error: action not registered.  Please report this error.");
@@ -1727,16 +1932,16 @@
    * registering it in the Metacat db
    */
   private void handleUploadAction(HttpServletRequest request,
-                                  HttpServletResponse response, 
+                                  PrintWriter out, 
                                   Hashtable params, Hashtable fileList, 
                                   String username, String[] groupnames)
   {
-    PrintWriter out = null;
+    //PrintWriter out = null;
     //Connection conn = null;
     String action = null;
     String docid = null;
   
-    response.setContentType("text/xml");
+    /*response.setContentType("text/xml");
     try 
     {
       out = response.getWriter();
@@ -1744,7 +1949,7 @@
     catch (IOException ioe2) 
     {
       System.err.println("Fatal Error: couldn't get response output stream.");
-    }
+    }*/
 
     if (params.containsKey("docid")) 
     {
@@ -1764,6 +1969,7 @@
   
         try 
         {
+           //MetaCatUtil.debugMessage("Upload datafile " + docid +"...", 10);
            //If document get lock data file grant
            if (DocumentImpl.getDataFileLockGrant(docid))
            {
@@ -1775,34 +1981,15 @@
               dataDirectory.mkdirs();
               File newFile = new File(dataDirectory, docid);
               long size = filePart.writeTo(newFile);
-              if ((util.getOption("replicationsenddata")).equals("on"))
-              {
-                // force replcation data file if metacat was configured
-                if (ReplicationHandler.getServerLocation(docid)==1)
-                {//local host document
-                  //conn=util.getConnection();
-                  ForceReplicationHandler frh = new ForceReplicationHandler
-             (docid, "insert", false, ReplicationHandler.buildServerList());
-                  //conn.close();
-                }//if
-                else
-                {
-                  //if it is super hub, replication to server list
-                  if ((util.getOption("hub")).equals("super"))
-                  {
-                    ForceReplicationHandler frh = new ForceReplicationHandler
-                    (docid,true, ReplicationHandler.buildServerList());
-                    //conn.close();
-                  }//if
-                  else
-                  {
-                    //only replicate to home host of the document
-                    String id=util.getDocIdFromString(docid);
-                    ForceReplicationHandler frh = new ForceReplicationHandler
-                    (docid, true, ReplicationHandler.getHomeServer(id));
-                  }//else
-                }//else
-              }//if
+              
+              // Force replication this data file
+              // To data file, "insert" and update is same
+              // The fourth parameter is null. Because it is notification server 
+              // and this method is in MetaCatServerlet. It is original command, 
+              // not get force replication info from another metacat
+              ForceReplicationHandler frh = new ForceReplicationHandler
+                                                (docid, "insert", false, null);
+             
               // set content type and other response header fields first
               out.println("<?xml version=\"1.0\"?>");
               out.println("<success>");
Index: src/edu/ucsb/nceas/metacat/DocumentImpl.java
===================================================================
--- src/edu/ucsb/nceas/metacat/DocumentImpl.java	(revision 1291)
+++ src/edu/ucsb/nceas/metacat/DocumentImpl.java	(revision 1292)
@@ -91,6 +91,8 @@
   private long rootnodeid;
   private ElementNode rootNode = null;
   private TreeSet nodeRecordList = null;
+  //private static 
+  //ReplicationServerList serverList = new ReplicationServerList();
   
   /**
    * Constructor used to create a document and read the document information
@@ -412,6 +414,13 @@
         deleteXMLDocuments(docIdWithoutRev);
         ac = new AccessionNumber(accnum, "update");
       }
+      // local server has newer version, then notify the remote server
+      else if ( userSpecifyRev < revInDataBase && revInDataBase > 0)
+      {
+        throw new Exception("Local server: "+MetaCatUtil.getOption("server")+
+                 " has newer revision of doc: "+docIdWithoutRev+"."
+                  +revInDataBase+". Please notify it.");
+      }
       //other situation
       else
       {
@@ -442,13 +451,19 @@
       sql.append(sqlDateString).append(",");
       sql.append(sqlDateString).append(",");
       sql.append("'0')");
+      // Set auto commit fasle
+      dbconn.setAutoCommit(false);
       pstmt = dbconn.prepareStatement(sql.toString());
       pstmt.execute();
+      // Commit the insert
+      dbconn.commit();
       pstmt.close();
       //dbconn.close();
     } 
     finally 
     {
+      // Set DBConnection auto commit true
+      dbconn.setAutoCommit(true);
       pstmt.close();
       DBConnectionPool.returnDBConnection(dbconn, serialNumber);
     }    
@@ -456,8 +471,7 @@
   
  /**
    * This method will register a data file entry in xml_documents and save a
-   * data file input Stream into file system.. It is only used in force 
-   * replication
+   * data file input Stream into file system.. It is only used in replication
    *
    * @param  input, the input stream which contain the file content.
    * @param  , the input stream which contain the file content
@@ -467,15 +481,18 @@
    *               includes a revision number for this revision of the document 
    *               (e.g., knb.1.1)
    * @param user the user that owns the document
-   * @param serverCode the serverid from xml_replication on which this document
-   *        resides.
+   * @param docHomeServer, the home server of the docid
+   * @param notificationServer, the server to notify force replication info to 
+   *                            local metacat
    */
- public static void writeDataFile(InputStream input, String filePath, 
-                                  String docname, String doctype, String accnum, 
-                                  String user, String docHomeServer)
+ public static void writeDataFileInReplication(InputStream input, 
+                 String filePath, String docname, String doctype, String accnum, 
+                   String user, String docHomeServer, String notificationServer)
                      throws SQLException, AccessionNumberException, Exception
  {
-   int serverCode=-2;
+    int serverCode=-2;
+   
+    
     if (filePath==null||filePath.equals(""))
     {
       throw new 
@@ -486,45 +503,46 @@
       throw new Exception("Please specify the stored file name");
     }
     
-    //get server code for the home server
-    serverCode=getServerCode(docHomeServer);
-    //if the server is not in the xml replication table, insert it.
-    if (serverCode==-1)
-    {
-      insertServerIntoReplicationTable(docHomeServer);
-      //get server code again
-      serverCode=getServerCode(docHomeServer);
-    }
+   
     
-    //make sure user have file lock grant(local metacat means have it too)
-    //if (getDataFileLockGrant(accnum))
-    //{
-      //register data file into xml_documents table
-      registerDocumentInReplication(docname, doctype, accnum, user, serverCode);
-      //write inputstream into file system.
-      File dataDirectory = new File(filePath);
-      File newFile = new File(dataDirectory, accnum); 
+    // If server is not int the xml replication talbe, insert it into 
+    // xml_replication table
+    //serverList.addToServerListIfItIsNot(docHomeServer);
+    insertServerIntoReplicationTable(docHomeServer);
+    
+    // Get server code again
+    serverCode = getServerCode(docHomeServer);
+    
+    
+    //register data file into xml_documents table
+    registerDocumentInReplication(docname, doctype, accnum, user, serverCode);
+    //write inputstream into file system.
+    File dataDirectory = new File(filePath);
+    File newFile = new File(dataDirectory, accnum); 
        
-      // create a buffered byte output stream
-      // that uses a default-sized output buffer
-      FileOutputStream fos = new FileOutputStream(newFile);
-      BufferedOutputStream outPut = new BufferedOutputStream(fos);
+    // create a buffered byte output stream
+    // that uses a default-sized output buffer
+    FileOutputStream fos = new FileOutputStream(newFile);
+    BufferedOutputStream outPut = new BufferedOutputStream(fos);
 
-      BufferedInputStream bis = null;
-      bis = new BufferedInputStream(input);
-      byte[] buf = new byte[4 * 1024]; // 4K buffer
-      int b = bis.read(buf);
+    BufferedInputStream bis = null;
+    bis = new BufferedInputStream(input);
+    byte[] buf = new byte[4 * 1024]; // 4K buffer
+    int b = bis.read(buf);
        
-      while (b != -1) 
-      {
+    while (b != -1) 
+    {
         outPut.write(buf, 0, b);
         b = bis.read(buf);
-      }
-      bis.close();
-	    outPut.close();
-	    fos.close();
-    
-    //}//if
+    }
+    bis.close();
+	  outPut.close();
+	  fos.close();
+      
+    // Force replicate data file
+    ForceReplicationHandler forceReplication = new ForceReplicationHandler
+                                    (accnum, false, notificationServer);
+  
  }
   
 
@@ -579,7 +597,7 @@
       //saying that he/she needs to download a new copy of the file and
       //merge the differences manually.
       
-      String server = MetacatReplication.getServer(serverCode);
+      String server=MetacatReplication.getServerNameForServerCode(serverCode);
       MetacatReplication.replLog("attempting to lock " + accnum);
       URL u = new URL("https://" + server + "?server=" +
         MetaCatUtil.getLocalReplicationServerName()+"&action=getlock&updaterev=" 
@@ -967,8 +985,12 @@
                             "the latest revision number.");
         }
       }
-      throw new Exception("the requested docid '" + docid.toString() + 
-                        "' does not exist");
+      // Get miss docid and rev, throw to McdDocNotFoundException
+      String missDocId = MetaCatUtil.getDocIdFromString(docid.toString());
+      String missRevision = 
+                  MetaCatUtil.getRevisionStringFromString(docid.toString());
+      throw new McdbDocNotFoundException("the requested docid '" + 
+                docid.toString() + "' does not exist", missDocId, missRevision);
     }//try
     finally
     {
@@ -978,7 +1000,7 @@
   }
 
   private void getDocumentInfo(String docid) throws McdbException, 
-                                                    AccessionNumberException
+                                        AccessionNumberException, Exception
   {
     getDocumentInfo(new DocumentIdentifier(docid));
   }
@@ -988,7 +1010,8 @@
    *
    * @param docid the id of the document to look up
    */
-  private void getDocumentInfo(DocumentIdentifier docid) throws McdbException 
+  private void getDocumentInfo(DocumentIdentifier docid) throws McdbException
+                                                          , Exception
   {
     DBConnection dbconn = null;
     int serialNumber = -1;
@@ -1002,19 +1025,21 @@
         table = "xml_revisions";
       }
     }
-    catch(Exception e)
+    // catch a McdbDocNotFoundException throw it
+    catch (McdbDocNotFoundException notFound)
     {
-      System.out.println("error in DocumentImpl.getDocumentInfo: " + 
-                          e.getMessage());
+      throw notFound;
     }
-    
-    //deal with the key words here.
-    
-    if(docid.getRev().equals("all"))
+    catch(Exception e)
     {
       
+      MetaCatUtil.debugMessage("error in DocumentImpl.getDocumentInfo: " + 
+                          e.getMessage(), 30);
+      throw e;
     }
     
+
+    
     try 
     {
       dbconn=DBConnectionPool.getDBConnection("DocumentImpl.getDocumentInfo");
@@ -1124,7 +1149,8 @@
     }
 
     if (this.docname == null) {
-      throw new McdbDocNotFoundException("Document not found: " + docid);
+      throw new McdbDocNotFoundException("Document not found: " + docid,
+                                 docid.getIdentifier(), docid.getRev());
     }
   }
 
@@ -1270,7 +1296,7 @@
 
         // Save the old document publicaccessentry in a backup table
         DocumentImpl.archiveDocRevision(connection, docid, user );
-        DocumentImpl thisdoc = new DocumentImpl(docid);
+        DocumentImpl thisdoc = new DocumentImpl(docid, false);
         int thisrev = thisdoc.getRev();
         
         //if the updated vesion is not greater than current one,
@@ -1474,7 +1500,7 @@
   
       DocumentIdentifier id = new DocumentIdentifier(accnum);
       String updaterev = id.getRev();
-      String server = MetacatReplication.getServer(serverCode);
+      String server=MetacatReplication.getServerNameForServerCode(serverCode);
       MetacatReplication.replLog("attempting to lock " + accnum);
       URL u = new URL("https://" + server + "?server="+
         MetaCatUtil.getLocalReplicationServerName()+"&action=getlock&updaterev=" 
@@ -1505,22 +1531,11 @@
                 
         
         
-        //If Metacat is super hub, tell all servers in its server list to get 
-        //the new document, ture mean it is xml document
-        if ((MetaCatUtil.getOption("hub")).equals("super"))
-        {
-          ForceReplicationHandler frh = new ForceReplicationHandler(accnum, 
-                true, ReplicationHandler.buildServerList());
-        }
-        else
-        {
-          //after inserting the document locally, tell the document's homeserver
-          //to come get a copy from here.
-         
-          ForceReplicationHandler frh = new ForceReplicationHandler(accnum, 
-                true, ReplicationHandler.getHomeServer(docid));
-        }
-        return (accnum);
+        // Force replication the docid
+        ForceReplicationHandler frh = new ForceReplicationHandler
+                                                          (accnum, true, null);
+        return(accnum);
+   
       }
 
       else if(openingtag.equals("<filelocked>"))
@@ -1574,16 +1589,14 @@
       throw e;
     }
     
-    //force replicate out the new document to each server in our server list.
-    if(serverCode == 1)
-    { 
+    // Force replicate out the new document to each server in our server list.
+    // Start the thread to replicate this new document out to the other servers
+    // true mean it is xml document
+    // null is because no metacat notify the force replication.
+    ForceReplicationHandler frh = new ForceReplicationHandler
+                                                  (accnum, action, true, null);
       
-      //start the thread to replicate this new document out to the other servers
-      //true mean it is xml document
-      ForceReplicationHandler frh = new ForceReplicationHandler
-                (accnum, action, true,ReplicationHandler.buildServerList());
-      
-    }
+   
     MetaCatUtil.debugMessage("Conn Usage count after writting: "
                                                       +conn.getUsageCount(),50); 
     return(accnum);
@@ -1602,41 +1615,74 @@
    * @param groups the groups to which user belongs
    * @param homeServer the name of server which the document origanlly create
    * @param validate, if the xml document is valid or not
+   * @param notifyServer, the server which notify local server the force 
+   *                       replication command
    */
 
   public static String writeReplication(DBConnection conn, Reader xml, 
             String pub, Reader dtd, String action, String accnum, String user,
-            String[] groups,String homeServer, boolean validate)
+     String[] groups,String homeServer, boolean validate, String notifyServer)
                 throws Exception
   {
+    // Docid without revision
+    String docid=MetaCatUtil.getDocIdFromString(accnum);
+    // Revision specified by user (int)
+    int userSpecifyRev=MetaCatUtil.getVersionFromString(accnum);
+    // Revision for this docid in current database
+    int revInDataBase=getLatestRevisionNumber(docid);
+    // String to store the revision
+    String rev = null;
    
-    String docid=MetaCatUtil.getDocIdFromString(accnum);
-    String rev=(new Integer(MetaCatUtil.getVersionFromString(accnum))).
-                                                                    toString();
     
-    //check if xml_documents table has the document or not
-    //if not, set action to insert
-    if (getLatestRevisionNumber(docid)==-1)
+    //revIndataBase=-1, there is no record in xml_documents table
+    //the document is a new one for local server, inert it into table
+    //user specified rev should be great than 0
+    if (revInDataBase==-1 && userSpecifyRev>0 )
     {
-      action="INSERT";
+        // rev equals user specified
+        rev=(new Integer(userSpecifyRev)).toString();
+        // action should be INSERT
+        action = "INSERT";
     }
-    
-    int serverCode=-2;
-    //get server code for the home server
-    serverCode=getServerCode(homeServer);
-    //if the server is not in the xml replication table, insert it.
-    if (serverCode==-1)
+    //rev is greater the last revsion number and revInDataBase isn't -1
+    // it is a updated  file
+    else if (userSpecifyRev>revInDataBase && revInDataBase>0)
     {
-      insertServerIntoReplicationTable(homeServer);
-      //get server code again
-      serverCode=getServerCode(homeServer);
+       // rev equals user specified
+       rev=(new Integer(userSpecifyRev)).toString();
+       // action should be update
+       action = "UPDATE";
     }
-      
-    MetaCatUtil.debugMessage("action: " + action + " servercode: " + 
-                             serverCode, 10);
+    // local server has newer version, then notify the remote server
+    else if ( userSpecifyRev < revInDataBase && revInDataBase > 0)
+    {
+      throw new Exception("Local server: "+MetaCatUtil.getOption("server")+
+                " has newer revision of doc: "+docid+"."+revInDataBase
+                 +". Please notify it.");
+    }
+    //other situation
+    else
+    {
+        
+        throw new Exception("The docid"+docid+"'s revision number couldn't be "
+                    +userSpecifyRev);
+    }
+    // Variable to store homeserver code
+    int serverCode=-2;
+    
+     // If server is not int the xml replication talbe, insert it into
+    // xml_replication table
+    //serverList.addToServerListIfItIsNot(homeServer);
+    insertServerIntoReplicationTable(homeServer);
+    // Get server code again
+    serverCode = getServerCode(homeServer);
+    
+    
+    MetaCatUtil.debugMessage("Document "+docid+"."+rev+" "+action+ " into local"
+                               +" metacat with servercode: "+ serverCode, 10);
                         
   
-
+    // insert into xml_nodes and xml_index table
     try 
     { 
       
@@ -1653,6 +1699,11 @@
       conn.setAutoCommit(true);
       throw e;
     }
+    
+    //Force replication to other server
+    ForceReplicationHandler forceReplication = new ForceReplicationHandler
+                                  (accnum, action, true, notifyServer);
+    
 
     return(accnum);
   }
@@ -2220,28 +2271,54 @@
    * Insert a server into xml_replcation table
    * @param server, the name of server 
    */
-  private static void  insertServerIntoReplicationTable(String server)
+  private static synchronized void 
+                                insertServerIntoReplicationTable(String server)
   {
     PreparedStatement pStmt=null;
     DBConnection dbConn = null;
     int serialNumber = -1;
-    int replicate = 1;
-    //MetaCatUtil util = new MetaCatUtil();
+    
+    // Initial value for the server
+    int replicate = 0;
+    int dataReplicate = 0;
+    int hub = 0;
+   
     try
     {
-       //dbConn=util.openDBConnection();
-       //check out DBConnection
+       // Get DBConnection
        dbConn=DBConnectionPool.
                 getDBConnection("DocumentImpl.insertServIntoReplicationTable");
        serialNumber=dbConn.getCheckOutSerialNumber();
-       pStmt = dbConn.prepareStatement("INSERT INTO xml_replication " +
-                                      "(server, last_checked, replicate) " +
-                                      "VALUES ('" + server + "', to_date(" +
-                                      "'01/01/00', 'MM/DD/YY'), '" +
-                                      replicate + "')");
+      
+      // Compare the server to dabase
+      pStmt = dbConn.prepareStatement
+      ("SELECT serverid FROM xml_replication WHERE server='" + server +"'");
+      pStmt.execute();
+      ResultSet rs = pStmt.getResultSet();
+      boolean hasRow = rs.next();
+      // Close preparedstatement and result set
+      pStmt.close();
+      rs.close();
+      
+      // If the server is not in the table, and server is not local host,
+      // insert it
+      if ( !hasRow 
+         && !server.equals(MetaCatUtil.getLocalReplicationServerName()))
+      {
+        // Set auto commit false
+        dbConn.setAutoCommit(false);
+        pStmt = dbConn.prepareStatement("INSERT INTO xml_replication " +
+                      "(server, last_checked, replicate, datareplicate, hub) " +
+                       "VALUES ('" + server + "', to_date(" +
+                       "'01/01/00', 'MM/DD/YY'), '" +
+                       replicate +"', '"+dataReplicate+"','"+ hub + "')");
         pStmt.execute();
+        dbConn.commit();
+        // Increase usage number
+        dbConn.increaseUsageCount(1);
         pStmt.close();
-        dbConn.commit();
+        
+      }
     }//try
     catch (Exception e)
     {
@@ -2253,7 +2330,10 @@
      
       try
       {
+        // Set auto commit true
+        dbConn.setAutoCommit(true);
         pStmt.close();
+        
       }//try
       catch (Exception ee)
       {
Index: src/edu/ucsb/nceas/metacat/ReplicationHandler.java
===================================================================
--- src/edu/ucsb/nceas/metacat/ReplicationHandler.java	(revision 1291)
+++ src/edu/ucsb/nceas/metacat/ReplicationHandler.java	(revision 1292)
@@ -56,13 +56,13 @@
 {
   int serverCheckCode = 1;
   MetaCatUtil util = new MetaCatUtil();
-  Hashtable serverList = new Hashtable(); 
-  //Connection conn;
+  ReplicationServerList serverList = null; 
   PrintWriter out;
   
   public ReplicationHandler(PrintWriter o)
   {
     this.out = o;
+    serverList = new ReplicationServerList();
   }
   
   public ReplicationHandler(PrintWriter o, int serverCheckCode)
@@ -69,6 +69,7 @@
   {
     this.out = o;
     this.serverCheckCode = serverCheckCode;
+    serverList = new ReplicationServerList();
   }
   
   /**
@@ -82,39 +83,13 @@
     //xml_documents with an update_date > last_checked
     try
     {
-      //try
-      //{ //this connection is prone to error for some reason so we 
-        //try to connect it three times before quiting.
-        //conn = util.openDBConnection();
-      //}
-      //catch(SQLException sqle)
-      //{
-        /*try
-        {
-          conn = util.openDBConnection();
-        }
-        catch(SQLException sqlee)
-        {
-          try
-          {
-            conn = util.openDBConnection();
-          }
-          catch(SQLException sqleee)
-          {*/
-            //System.out.println("error getting db connection in " + 
-                               //"ReplicationHandler.run: " +
-                               //sqle.getMessage());
-          //}
-        //}
-      //}
-      serverList = buildServerList();
       //if serverList is null, metacat don't need to replication
       if (serverList==null||serverList.isEmpty())
       {
         return;
       }
-      updateCatalog(serverList);
-      update(serverList);
+      updateCatalog();
+      update();
       //conn.close();
     }//try
     catch (Exception e)
@@ -121,6 +96,7 @@
     {
       MetaCatUtil.debugMessage("Error in replicationHandler.run():"
                                                     +e.getMessage(), 30);
+      e.printStackTrace();
     }//catch
   }
   
@@ -127,7 +103,7 @@
   /**
    * Method that uses revision taging for replication instead of update_date.
    */
-  private void update(Hashtable serverList)
+  private void update()
   {
     /*
      Pseudo-algorithm
@@ -145,17 +121,11 @@
     
     DBConnection dbConn = null;
     int serialNumber = -1;
-    /*try
-    {
-      conn = util.getConnection();
-    }
-    catch (Exception e)
-    {
-      util.debugMessage("There is problem to get conncetion: "+e.getMessage());
-    }*/
-    
-    Enumeration keys;
-    String server;
+   
+    ReplicationServer replServer = null; // Variable to store the 
+                                        // ReplicationServer got from 
+                                        // Server list
+    String server; // Variable to store server name
     String update;
     ReplMessageHandler message = new ReplMessageHandler();
     Vector responses = new Vector();
@@ -162,7 +132,7 @@
     PreparedStatement pstmt = null;
     ResultSet rs;
     boolean tablehasrows;
-    boolean flag=false;
+    boolean flag=false; // If a document need to update
     boolean dataFile=false;
     String action = new String();
     XMLReader parser;
@@ -170,21 +140,39 @@
     
     try
     {
+      // Get DBConnection from pool
       dbConn=DBConnectionPool.
                   getDBConnection("ReplicationHandler.update");
       serialNumber=dbConn.getCheckOutSerialNumber();
-      MetaCatUtil.debugMessage("init parser");
+      MetaCatUtil.debugMessage("init parser", 50);
       parser = initParser(message);
-      keys = serverList.keys();
-      while(keys.hasMoreElements())
+      //Check for every server in server list
+      for (int i=0; i<serverList.size(); i++)
       {
-        server = (String)(keys.nextElement());
+        // Get ReplicationServer object from server list
+        replServer = serverList.serverAt(i);
+        // Get server name from ReplicationServer object
+        server = replServer.getServerName();
         MetacatReplication.replLog("full update started to: " + server);
+        // Send command to that server to get updated docid information
         u = new URL("https://" + server + "?server="
         +util.getLocalReplicationServerName()+"&action=update");
-        //System.out.println("Sending Message: " + u.toString());
-        String result = MetacatReplication.getURLContent(u);
-        //check if result have error or not
+        MetaCatUtil.debugMessage("Sending infomation " +u.toString(), 50);
+        // Get information from remote server
+        String result = null;
+        try
+        {
+          result = MetacatReplication.getURLContent(u);
+        }//try
+        catch (Exception e)
+        {
+          
+          MetaCatUtil.debugMessage("Error in get docid information from "+
+                                server+" :"+e.getMessage(), 30);
+          continue;
+        }//catch
+        MetaCatUtil.debugMessage("docid: "+server+" "+result, 50);
+        //check if result have error or not, if has skip it.
         if (result.indexOf("error")!=-1)
         {
           continue;
@@ -193,19 +181,18 @@
       }
       
       //make sure that there is updated file list
-      //If response is null, mecat don't need do anything
+      //If response is null, metacat don't need do anything
        if (responses==null||responses.isEmpty())
       {
         return;
       }
+     
       
-      //String srvr = util.getOption("servletpath");
+      MetaCatUtil.debugMessage("Responses from remote metacat about updated "+
+                   "document information: "+ responses.toString(), 30);
       
-      //System.out.println("responses (from srvr): " + responses.toString());
-      
       for(int i=0; i<responses.size(); i++)
       { //check each server for updated files
-        //System.out.println("parsing responses");
         parser.parse(new InputSource(
                      new StringReader(
                      (String)(responses.elementAt(i)))));
@@ -215,10 +202,10 @@
         //d is the list of deleted documents
         Vector d = new Vector(message.getDeletesVect());
         //System.out.println("d: " + d.toString());
+        MetaCatUtil.debugMessage("Update vector size: "+ v.size(), 40);
+        MetaCatUtil.debugMessage("Delete vector size: "+ d.size(),40);
         //check the revs in u to see if there are any newer ones than
         //in the local DB.
-        MetaCatUtil.debugMessage("Update vector size: "+ v.size(), 20);
-        MetaCatUtil.debugMessage("Delete vector size: "+ d.size(),20);
         for(int j=0; j<v.size(); j++)
         {
           //initial dataFile is false
@@ -233,24 +220,30 @@
             dataFile=true;
           }
           //System.out.println("w: " + w.toString());
+          // Get docid
           String docid = (String)w.elementAt(0);
           MetaCatUtil.debugMessage("docid: " + docid, 40);
+          // Get revision number
           int rev = Integer.parseInt((String)w.elementAt(1));
           MetaCatUtil.debugMessage("rev: " + rev, 40);
-          String docServer = (String)w.elementAt(2);
+          // Get remote server name (it is may not be doc homeserver because
+          // the new hub feature
+          String remoteServer = (String)w.elementAt(2);
           
-    
-         pstmt = dbConn.prepareStatement("select rev from xml_documents where "+
-                                        "docid like '" + docid + "'");
+          // Choose revision number from local host
+          pstmt = dbConn.prepareStatement("select rev from xml_documents where "
+                                            + "docid like '" + docid + "'");
           pstmt.execute();
           rs = pstmt.getResultSet();
           tablehasrows = rs.next();
           if(tablehasrows)
           { //check the revs for an update because this document is in the
-            //local DB, it just might be out of date.
+            //local DB, it might be out of date.
             int localrev = rs.getInt(1);
             if(localrev == rev)
             {
+              // Local meatacat has the same rev to remote host, don't need 
+              // update and flag set false
               flag = false;
             }
             else if(localrev < rev)
@@ -265,13 +258,20 @@
             flag = true;
           }
           
+          // Close result set
+          rs.close();
+          // Close preparedstatement
+          pstmt.close();
+          
           // this is non-data file
           if(flag && !dataFile)
           { //if the document needs to be updated or inserted, this is executed
-            u = new URL("https://" + docServer + "?server="+
+            u = new URL("https://" + remoteServer + "?server="+
               util.getLocalReplicationServerName()+"&action=read&docid="+docid);
             //System.out.println("Sending message: " + u.toString());
+            // Get docid content
             String newxmldoc = MetacatReplication.getURLContent(u);
+            // If couldn't get skip it
             if ( newxmldoc.indexOf("error")!= -1)
             {
               continue;
@@ -278,25 +278,27 @@
             }
             MetaCatUtil.debugMessage("xml documnet:", 50);
             MetaCatUtil.debugMessage(newxmldoc, 50);
+            
+            // Try get the docid info from remote server
             DocInfoHandler dih = new DocInfoHandler();
             XMLReader docinfoParser = initParser(dih);
-            URL docinfoUrl = new URL("https://" + docServer + 
+            URL docinfoUrl = new URL("https://" + remoteServer + 
                   "?server="+util.getLocalReplicationServerName()+
                   "&action=getdocumentinfo&docid="+docid);
-            //System.out.println("Sending message: " + docinfoUrl.toString());
+            MetaCatUtil.debugMessage("Sending message: " + 
+                                                  docinfoUrl.toString(), 50);
             String docInfoStr = MetacatReplication.getURLContent(docinfoUrl);
             docinfoParser.parse(new InputSource(new StringReader(docInfoStr)));
             Hashtable docinfoHash = dih.getDocInfo();
+            // Get home server of the docid
             String docHomeServer = (String)docinfoHash.get("home_server");
-            //int serverCode = MetacatReplication.getServerCode(docServer);
-            //System.out.println("updating doc: " + docid +" action: "+ action);
+                
             //docid should include rev number too
             String accnum=docid+util.getOption("accNumSeparator")+
                                               (String)docinfoHash.get("rev");
-            //System.out.println("accnum: "+accnum);
             try
             {
-             
+              // Write the document into local host
               String newDocid = DocumentImpl.writeReplication(dbConn, 
                               new StringReader(newxmldoc),
                               (String)docinfoHash.get("public_access"),
@@ -306,11 +308,12 @@
                               (String)docinfoHash.get("user_owner"),
                               null, /* null for groups[] */
                               docHomeServer, 
-                              false /* validate */);
+                              false /* validate */,
+                              remoteServer);
               //increase usage
               dbConn.increaseUsageCount(1);
               MetacatReplication.replLog("wrote doc " + docid + " from " + 
-                                         docServer);
+                                         remoteServer);
               /*System.out.println("wrote doc " + docid + " from " + 
                                  docServer);*/
             }
@@ -322,62 +325,70 @@
             }
           }//if for non-data file
           
-           // this is for data file and metacat is configured to accetp datafile
-          if(flag && dataFile 
-                   && (util.getOption("replicationacceptdata")).equals("on"))
+           // this is for data file
+          if(flag && dataFile)
           { 
             //if the document needs to be updated or inserted, this is executed
-            //String newxmldoc = MetacatReplication.getURLContent(u);
+            
+            // Try get docid info from remote server
             DocInfoHandler dih = new DocInfoHandler();
             XMLReader docinfoParser = initParser(dih);
-            URL docinfoUrl = new URL("https://" + docServer + 
+            URL docinfoUrl = new URL("https://" + remoteServer + 
                   "?server="+util.getLocalReplicationServerName()+
                   "&action=getdocumentinfo&docid="+docid);
-            //System.out.println("Sending message: " + docinfoUrl.toString());
+            
             String docInfoStr = MetacatReplication.getURLContent(docinfoUrl);
             docinfoParser.parse(new InputSource(new StringReader(docInfoStr)));
             Hashtable docinfoHash = dih.getDocInfo();
+            // Get doicd owner
             String user = (String)docinfoHash.get("user_owner");
+            // Get docid name (such as acl or dataset)
             String docName = (String)docinfoHash.get("docname");
+            // Get doc type (eml public id) 
             String docType = (String)docinfoHash.get("doctype");
+            // Get docid home sever. it might be different to remoteserver
+            // becuause of hub feature
             String docHomeServer = (String)docinfoHash.get("home_server");
-          
-            //int serverCode = MetacatReplication.getServerCode(docServer);
+         
             //System.out.println("updating doc: " + docid +" action: "+ action);
             //docid should include rev number too
             String accnum=docid+util.getOption("accNumSeparator")+
                                               (String)docinfoHash.get("rev");
             String datafilePath = util.getOption("datafilepath");
-            u = new URL("https://" + docServer + "?server="+
+            // Get data file content
+            u = new URL("https://" + remoteServer + "?server="+
                                         util.getLocalReplicationServerName()+
                                             "&action=readdata&docid="+accnum);
-            //System.out.println("accnum: "+accnum);
+           
             try
             {
-              
               //register data file into xml_documents table and wite data file
               //into file system
               if (u.openStream() != null)
               {
-              DocumentImpl.writeDataFile(u.openStream(), datafilePath, 
-                                  docName,docType, accnum, user,docHomeServer);
+                DocumentImpl.writeDataFileInReplication(u.openStream(), 
+                                                        datafilePath, 
+                                                        docName,docType, 
+                                                        accnum, user,
+                                                        docHomeServer,
+                                                        remoteServer);
               
-              MetacatReplication.replLog("wrote doc " + docid + " from " + 
-                                         docServer);
-              }
+                MetacatReplication.replLog("wrote doc " + docid + " from " + 
+                                         remoteServer);
+              }//if
               else
               {
+                // If get null, skip it
                 continue;
-              }
-              /*System.out.println("wrote doc " + docid + " from " + 
-                                 docServer);*/
-            }
+              }//else
+            
+            }//try
             catch(Exception e)
             {
               System.out.println("error writing document in " + 
                                  "ReplicationHandler.update: " + docid +
                                  ": " + e.getMessage());
-            }
+            }//catch
           }//for datafile
         }//for update docs
         
@@ -397,12 +408,16 @@
             MetacatReplication.replLog("doc " + docid + " deleted");
           }
         }//for delete docs
-        
-        //updated last_checked
-        keys = serverList.keys();
-        while(keys.hasMoreElements())
-        {
-          server = (String)(keys.nextElement()); 
+      }//for
+      
+      //updated last_checked
+      for (int i=0;i<serverList.size(); i++)
+      {
+          // Get ReplicationServer object from server list
+          replServer = serverList.serverAt(i);
+          // Get server name from ReplicationServer object
+          server = replServer.getServerName();
+          // Get time from remote server
           URL dateurl = new URL("https://" + server + "?server="+
           util.getLocalReplicationServerName()+"&action=gettime");
           String datexml = MetacatReplication.getURLContent(dateurl);
@@ -421,10 +436,9 @@
             dbConn.increaseUsageCount(1);
             pstmt.executeUpdate();
             dbConn.commit();
-            System.out.println("last_checked updated to " + datestr + " on " +
-                            server);
-          }
-        }//wile
+            MetaCatUtil.debugMessage("last_checked updated to "+datestr+" on " 
+                                      + server, 45);
+          }//if
       }//for
     }//try
     catch(Exception e)
@@ -437,7 +451,9 @@
     {
       try
       {
-        pstmt.close();
+        
+          pstmt.close();
+       
       }//try
       catch(Exception ee) 
       {
@@ -454,51 +470,42 @@
   /**
    * updates xml_catalog with entries from other servers.
    */
-  private void updateCatalog(Hashtable serverList)
+  private void updateCatalog()
   {
+    // DConnection
     DBConnection dbConn = null;
+    // DBConnection checkout serial number
     int serialNumber = -1;
+    // ReplicationServer object in server list
+    ReplicationServer replServer = null;
     PreparedStatement pstmt = null;
     try
     {
-      /*try
-      { 
-        conn = util.openDBConnection();
-      }
-      catch(SQLException sqle)
-      {
-        try
-        {
-          conn = util.openDBConnection();
-        }
-        catch(SQLException sqlee)
-        {
-          try
-          {
-            conn = util.openDBConnection();
-          }
-          catch(SQLException sqleee)
-          {
-            System.out.println("error getting db connection in " + 
-                               "ReplicationHandler.update: " +
-                               sqleee.getMessage());
-          }
-        }
-      }*/
-      
+
       dbConn=DBConnectionPool.
                   getDBConnection("ReplicationHandler.updateCatalog");
       serialNumber=dbConn.getCheckOutSerialNumber();
       String server;
-      Enumeration keys = serverList.keys();
-      while(keys.hasMoreElements())
-      { //go through each server
-        server = (String)(keys.nextElement());
+      
+      // Go through each ReplicationServer object in sererlist
+      for (int j=0; j<serverList.size(); j++)
+      { 
+        // Get ReplicationServer object from server list
+        replServer = serverList.serverAt(j);
+        // Get server name from the ReplicationServer object
+        server = replServer.getServerName();
+        // Try to get catalog
         URL u = new URL("https://" + server + "?server="+
         util.getLocalReplicationServerName()+"&action=getcatalog");
-        //System.out.println("sending message " + u.toString());
+        MetaCatUtil.debugMessage("sending message " + u.toString(), 50);
         String catxml = MetacatReplication.getURLContent(u);
-        //System.out.println("catxml: " + catxml);
+        
+        // Make sure there are not error, no empty string
+        if (catxml.indexOf("error")!=-1 || catxml==null||catxml.equals(""))
+        {
+          continue;
+        }
+        MetaCatUtil.debugMessage("catxml: " + catxml, 50);
         CatalogMessageHandler cmh = new CatalogMessageHandler();
         XMLReader catparser = initParser(cmh);
         catparser.parse(new InputSource(new StringReader(catxml)));
@@ -505,8 +512,20 @@
         //parse the returned catalog xml and put it into a vector
         Vector remoteCatalog = cmh.getCatalogVect();
         
+        // Makse sure remoteCatalog is not empty
+        if (remoteCatalog.isEmpty())
+        {
+          continue;
+        }
+        
         String localcatxml = MetacatReplication.getCatalogXML();
-        //System.out.println("localcatxml: " + localcatxml);
+        
+        // Make sure local catalog is no empty
+        if (localcatxml==null||localcatxml.equals(""))
+        {
+          continue;
+        }
+        
         cmh = new CatalogMessageHandler();
         catparser = initParser(cmh);
         catparser.parse(new InputSource(new StringReader(localcatxml)));
@@ -520,7 +539,7 @@
         for(int i=0; i<localCatalog.size(); i++)
         {
           Vector v = new Vector((Vector)localCatalog.elementAt(i));
-          //System.out.println("v1: " + v.toString());
+          MetaCatUtil.debugMessage("v1: " + v.toString(), 50);
           publicId.add(new String((String)v.elementAt(3)));
           //System.out.println("adding " + (String)v.elementAt(3));
         }
@@ -532,7 +551,8 @@
           //System.out.println("i: " + i);
           //System.out.println("remoteCatalog.size(): " + remoteCatalog.size());
           //System.out.println("publicID: " + publicId.toString());
-          //System.out.println("v.elementAt(3): " + (String)v.elementAt(3));
+          MetaCatUtil.debugMessage
+                              ("v.elementAt(3): " + (String)v.elementAt(3), 50);
           if(!publicId.contains(v.elementAt(3)))
           { //so we don't have this public id in our local table so we need to
             //add it.
@@ -555,7 +575,7 @@
           }
         }
       }
-      //conn.close();
+     
     }
     catch(Exception e)
     {
@@ -565,19 +585,7 @@
     }//catch
     finally
     {
-      try
-      {
-        pstmt.close();
-      }//try
-      catch (SQLException ee)
-      {
-        MetaCatUtil.debugMessage("Error in ReplicationHandler.updateCatalog "+
-                      "to close pstmt: "+ee.getMessage(), 30);
-      }//catch
-      finally
-      {
-        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
-      }//finally
+      DBConnectionPool.returnDBConnection(dbConn, serialNumber);
     }//finall
   }
   
@@ -674,292 +682,9 @@
     }//finally
     return false;
   }
-  
-  /**
-   * Checks to see if a document is already in the DB.  Returns
-   * "UPDATE" if it is, "INSERT" if it isn't
-   */
-  private static String getAction(String docid)
-  {
-    DBConnection dbConn = null;
-    int serialNumber = -1;
-    PreparedStatement pstmt = null;
-    try
-    {
-      dbConn=DBConnectionPool.
-                  getDBConnection("ReplicationHandler.getAction");
-      serialNumber=dbConn.getCheckOutSerialNumber();
-      //MetaCatUtil util = new MetaCatUtil();
-      StringBuffer sql = new StringBuffer();
-      sql.append("select docid from xml_documents where docid like '");
-      sql.append(docid).append("'");
-      //Connection conn = util.openDBConnection();
-      pstmt = dbConn.prepareStatement(sql.toString());
-      pstmt.execute();
-      ResultSet rs = pstmt.getResultSet();
 
-      if(rs.next())
-      {
-        pstmt.close();
-        //conn.close();
-        return "UPDATE";
-      }
-      else
-      {
-        pstmt.close();
-        //conn.close();
-        return "INSERT";
-      }
-    }
-    catch(Exception e)
-    {
-      System.out.println("error in replicationHandler.getAction: " + 
-                          e.getMessage());
-    }
-    finally
-    {
-      try
-      {
-        pstmt.close();
-      }
-      catch (SQLException sqlE)
-      {
-        MetaCatUtil.debugMessage("error in replicationHandler.getAction: " + 
-                     "to close pstmt: "+ sqlE.getMessage(), 30);
-      }
-      finally
-      {
-        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
-      }
-    }//finally
-    return "";
-  }
   
   /**
-   * Method to query xml_replication and build a hashtable of each server
-   * and it's last update time.
-   * @param conn a connection to the database
-   */
-  public static Hashtable buildServerList()
-  {
-    DBConnection dbConn = null;
-    int serialNumber = -1;
-    Hashtable sl = new Hashtable();
-    PreparedStatement pstmt = null;   
-    try
-    {
-      dbConn=DBConnectionPool.
-                  getDBConnection("ReplicationHandler.buildServerList");
-      serialNumber=dbConn.getCheckOutSerialNumber();
-      pstmt = dbConn.prepareStatement("select server, last_checked, replicate "+
-                                    "from xml_replication");
-      pstmt.execute();
-      ResultSet rs = pstmt.getResultSet();
-      boolean tableHasRows = rs.next();
-      while(tableHasRows)
-      {
-        if(rs.getInt(3) == 1)
-        {//only put the server in the list if the replicate flag is true
-          String server = rs.getString(1);
-          String last_checked = rs.getString(2);
-          if(!server.equals("localhost"))
-          {
-            sl.put(server, last_checked);
-          }
-        }
-        tableHasRows = rs.next();   
-      }
-      pstmt.close();
-    }
-    catch(Exception e)
-    {
-      System.out.println("error in replicationHandler.buildServerList(): " +
-                         e.getMessage());
-    }
-    finally
-    {
-      try
-      {
-        pstmt.close();
-      }//try
-      catch (SQLException sqlE)
-      {
-        MetaCatUtil.debugMessage("Error in ReplicationHandler.buildServerList: "
-                                +sqlE.getMessage());
-      }//catch
-      finally
-      {
-        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
-      }//finally
-    }//finally
-     
-    return sl;
-  }
-   /**
-   * Method to get a host server information for given docid
-   * @param conn a connection to the database
-   */
-  public static Hashtable getHomeServer(String docId)
-  {
-    Hashtable sl = new Hashtable();
-    DBConnection dbConn = null;
-    int serialNumber = -1;
-    //MetaCatUtil ut=new MetaCatUtil();
-    docId=MetaCatUtil.getDocIdFromString(docId);
-    PreparedStatement pstmt=null;
-    int serverLocation;
-    try
-    {
-      //get conection
-      dbConn=DBConnectionPool.
-                  getDBConnection("ReplicationHandler.getHomeServer");
-      serialNumber=dbConn.getCheckOutSerialNumber();
-      //get a server location from xml_document table
-      pstmt=dbConn.prepareStatement("select server_location from xml_documents "
-                                            +"where docid = ?");
-      pstmt.setString(1, docId);
-      pstmt.execute();
-      ResultSet serverName = pstmt.getResultSet();
-      //get a server location
-      if(serverName.next())
-      {
-        serverLocation=serverName.getInt(1);
-        pstmt.close();
-      }
-      else
-      {
-        pstmt.close();
-        //ut.returnConnection(conn);
-        return null;
-      }
-      pstmt=dbConn.prepareStatement("select server, last_checked, replicate " +
-                        "from xml_replication where serverid = ?");
-      //increase usage count
-      dbConn.increaseUsageCount(1);
-      pstmt.setInt(1, serverLocation);
-      pstmt.execute();
-      ResultSet rs = pstmt.getResultSet();
-      boolean tableHasRows = rs.next();
-      if (tableHasRows)
-      {
-        
-          String server = rs.getString(1);
-          String last_checked = rs.getString(2);
-          if(!server.equals("localhost"))
-          {
-            sl.put(server, last_checked);
-          }
-        
-      }
-      else
-      {
-        pstmt.close();
-        //ut.returnConnection(conn);
-        return null;
-      }
-      pstmt.close();
-    }
-    catch(Exception e)
-    {
-      System.out.println("error in replicationHandler.getHomeServer(): " +
-                         e.getMessage());
-    }
-    finally
-    {
-      try
-      {
-        pstmt.close();
-        //ut.returnConnection(conn);
-      }
-      catch (Exception ee)
-      {
-        MetaCatUtil.debugMessage("Eror irn rplicationHandler.getHomeServer() "+
-                          "to close pstmt: "+ee.getMessage(), 30);
-      }
-      finally
-      {
-        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
-      }
-    
-    }//finally
-    return sl;
-  }
-  
-  /**
-   * Returns a server location  given a accnum
-   * @param accNum , given accNum for a document
-   * 
-   */
-  public static int getServerLocation(String accNum) throws Exception
-  {
-    DBConnection dbConn = null;
-    int serialNumber = -1;
-    PreparedStatement pstmt = null;
-    int serverCode = 1;
-    //MetaCatUtil ut = new MetaCatUtil();
-    String docId=MetaCatUtil.getDocIdFromString(accNum);
-
-    try 
-    {
-
-      //conn = ut.openDBConnection();
-      //get conection
-      dbConn=DBConnectionPool.
-                  getDBConnection("ReplicationHandler.getServerLocation");
-      serialNumber=dbConn.getCheckOutSerialNumber();
-      pstmt=dbConn.prepareStatement("SELECT server_location FROM xml_documents " 
-                              + "WHERE docid LIKE '" + docId + "'");
-      pstmt.execute();
-      ResultSet rs = pstmt.getResultSet();
-      boolean tablehasrows = rs.next();
-      //If a document is find, return the server location for it
-      if ( tablehasrows ) 
-      {  
-        serverCode = rs.getInt(1);
-        pstmt.close();
-        //conn.close();
-        return serverCode;
-      }
-      //if couldn't find in xml_documents table, we think server code is 1
-      //(this is new document)
-      else
-      {
-        pstmt.close();
-        //conn.close();
-        return serverCode;
-      }
-      
-    } 
-    catch(Exception e) 
-    {
-      
-      throw e;
-
-    } 
-    finally 
-    {
-      try 
-      {
-        pstmt.close();
-        //conn.close();
-        
-      } 
-      catch(Exception ee) 
-      {
-        MetaCatUtil.debugMessage("Erorr in Replication.getServerLocation "+
-                     "to close pstmt"+ee.getMessage(), 30);
-      }
-      finally
-      {
-        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
-      }//finally
-    }//finally
-   //return serverCode;
-  }
-  
-  
-  
-  /**
    * Method to initialize the message parser
    */
   public static XMLReader initParser(DefaultHandler dh)
Index: src/edu/ucsb/nceas/metacat/DBUtil.java
===================================================================
--- src/edu/ucsb/nceas/metacat/DBUtil.java	(revision 1291)
+++ src/edu/ucsb/nceas/metacat/DBUtil.java	(revision 1292)
@@ -470,5 +470,174 @@
 
     return accnum;
   }
-
+  
+  /**
+   * To a given docid, found a dataset docid which conatains the the given doicd
+   * This will be done by searching xml_relation table
+   * If couldn't find, null will be return
+   * @param givenDocId, the docid which we want to find
+   */
+  public static String findDataSetDocIdForGivenDocument(String givenDocId)
+  {
+    // Prepared statement for sql
+    PreparedStatement pStmt = null;
+    // Result set
+    ResultSet resultSet = null;
+    // String to store the data set docid
+    String dataSetDocId = null;
+    // DBConnection will be checkout
+    DBConnection dbConn = null;
+    int serialNumber = -1;
+    // String to store the sql command
+    String sqlCommand = null;
+    try
+    {
+      // Checkout DBConnection from pool
+      dbConn=DBConnectionPool.
+                  getDBConnection("DBUtil.findDataSetDocIdForGivenDocument");
+      serialNumber=dbConn.getCheckOutSerialNumber();
+      // Sql command to chose a docid from xm_relation table
+      sqlCommand = "select docid from xml_relation where object like ? or " 
+                                                    + "subject like ?";
+      // Prepared statement
+      pStmt = dbConn.prepareStatement(sqlCommand);
+      // Bind variable
+      pStmt.setString(1, givenDocId);
+      pStmt.setString(2, givenDocId);
+      // Excute prepared statement
+      pStmt.execute();
+      // Get result set
+      resultSet = pStmt.getResultSet();
+      
+      // There has record
+      if (resultSet.next())
+      {
+        // Put the docid into dataSetDocid
+        dataSetDocId = resultSet.getString(1);
+        return dataSetDocId;
+      }//if
+      else
+      {
+        // No record in xml_relation table for given doicd, null returned
+        return dataSetDocId;
+      }//else
+    
+    }//try
+    catch ( SQLException e)
+    {
+      // Print out excepition
+      MetaCatUtil.debugMessage("Error in DBUil.findDataSEtDocIdForGivenDocument"
+                                +e.getMessage(), 30);
+      // return null
+      return dataSetDocId;
+     
+    }//catch
+    finally
+    {
+      try
+      {
+        // Close result set
+        resultSet.close();
+        // Close preparedStatement
+        pStmt.close();
+      }//try
+      catch ( SQLException e)
+      {
+        // Print out excepition
+        MetaCatUtil.debugMessage("Error in DBUil.findDataSetDocIdForGivenDoc"
+                                + e.getMessage(), 30);
+     
+      }//catch
+      finally
+      {
+        // Return DBConnection to the pool
+        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
+      }//finally
+    }//finally
+        
+  }//findDataSetDocIdForGivenDocument
+  
+  /**
+   * Method to get current revision and doctype for a given docid
+   * The output will look like "rev;doctype"
+   * @param givenDocId, the docid which we want 
+   */
+  public String getCurrentRevisionAndDocTypeForGivenDocument(String givenDocId)
+                                                 throws SQLException
+  {
+    // DBConection for JDBC
+    DBConnection dbConn = null;
+    int serialNumber = -1;
+    // Prepared Statement
+    PreparedStatement pstmt = null;
+    // String to store a docid without rev
+    String docIdWithoutRevision = null;
+    // SQL comand
+    String sqlCommand = null;
+    // Resulst set
+    ResultSet rs = null;
+    // String to store the revision
+    String revision = null;
+    // String to store the doctype
+    String docType = null;
+    
+    // Get docid without rev
+    docIdWithoutRevision = MetaCatUtil.getDocIdFromString(givenDocId);
+    // SQL comand is:
+    sqlCommand = "select rev, doctype from xml_documents where docid like ?";
+    
+    try
+    {
+      // Check out the connection
+      dbConn=DBConnectionPool.
+         getDBConnection("DBUtil.getCurrentRevisionAndDocTypeForGivenDocument");
+      serialNumber=dbConn.getCheckOutSerialNumber();
+      
+      // Prepare the sql command
+      pstmt = dbConn.prepareStatement(sqlCommand);
+      // Bin vairable
+      pstmt.setString(1, docIdWithoutRevision);
+      // Excute the prepared statement
+      pstmt.execute();
+      // Get result set
+      rs = pstmt.getResultSet();
+      // If there is some record
+      if (rs.next())
+      {
+        revision = rs.getString(1);
+        docType = rs.getString(2);
+      }//if
+      else
+      {
+        // No record, throw a exception
+        throw new 
+              SQLException("There is not record for given docid:"+givenDocId);
+      }//else
+        
+    }
+    finally
+    {
+      try
+      {
+        // Close result set
+        rs.close();
+        // Close preparedStatement
+        pstmt.close();
+      }//try
+      catch ( SQLException e)
+      {
+        // Print out excepition
+        MetaCatUtil.debugMessage("Error in DBUil.getCurrentRevisionAndDocType"
+                                + e.getMessage(), 30);
+     
+      }//catch
+      finally
+      {
+        // Return DBConnection to the pool
+        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
+      }//finally
+    }
+    return revision+";"+docType;
+  }//getCurrentRevisionAndDocTypeForGivenDocument
+   
 }
Index: src/edu/ucsb/nceas/metacat/ForceReplicationHandler.java
===================================================================
--- src/edu/ucsb/nceas/metacat/ForceReplicationHandler.java	(revision 1291)
+++ src/edu/ucsb/nceas/metacat/ForceReplicationHandler.java	(revision 1292)
@@ -48,27 +48,52 @@
 public class ForceReplicationHandler implements Runnable
 {
   private Thread btThread;
-  //private Connection conn;
   private MetaCatUtil util = new MetaCatUtil();
   private String docid;
   private String action;
   private boolean xmlDocument;
   private boolean dbactionFlag = true;
-  private Hashtable serverList;
+  private ReplicationServerList serverLists = null;//Serverlist 
+  private int homeServerCode = 0; // home server code for the docid
+  // When a metacat A got forcereplication 
+  // notification from B, then A will update its record. And A will notification
+  // other metacat in its serverlist to update this docid if A is a hub. But we
+  // don't want A to notify B again. B is nofitification of A
+  private String notificationServer = null;
   
   
+  
   /**
+   * Constructor of ForceReplicationHandler
    * @param docid the docid to force replicate
    * @param the action that is being performed on the document (either 
    *        INSERT or UPDATE)
+   * @param xml the docid is a xml document or not (data file)
+   * @param notificationServer, when a metacat A got forcereplication 
+   * notification from B, then A will update its record. And A will notification
+   * other metacat in its serverlist to update this docid if A is a hub. But we
+   * don't want A to notify B again. B is nofitification of A.
    */
   public ForceReplicationHandler(String docid, String action, boolean xml, 
-                                                          Hashtable server )
+                                                   String myNotificationServer)
   {
     this.docid = docid;
     this.action = action;
     this.xmlDocument =xml;
-    this.serverList = server;
+    // Build a severLists from xml_replication table
+    this.serverLists = new ReplicationServerList();
+    // Get sever code for this docid
+    try
+    {
+      this.homeServerCode = MetacatReplication.getHomeServerCodeForDocId(docid);
+    }//try
+    catch (Exception e)
+    {
+      MetaCatUtil.debugMessage("Error in ForceReplicationHandle(): "
+                                                          +e.getMessage(), 30);
+    }//catch
+    // Get the notification server
+    this.notificationServer = myNotificationServer;
     
     if(this.action.equals(""))
     {
@@ -83,101 +108,215 @@
   /**
    * Use this constructor when the action is implied.
    */
-  public ForceReplicationHandler(String docid, boolean xml, Hashtable server)
+  public ForceReplicationHandler(String docid, boolean xml, 
+                                                String myNotificationServer )
   {
     this.docid = docid;
     this.xmlDocument = xml;
     dbactionFlag = false;
-    this.serverList = server;
+    // Build a severLists from xml_replication table
+    this.serverLists = new ReplicationServerList();
+    // Get home server code for this doicd
+    try
+    {
+      this.homeServerCode = MetacatReplication.getHomeServerCodeForDocId(docid);
+    }
+     catch (Exception e)
+    {
+      MetaCatUtil.debugMessage("Error in ForceReplicationHandle(): "
+                                                          +e.getMessage(), 30);
+    }//catch
+    // Get notification server
+    this.notificationServer = myNotificationServer;
     btThread = new Thread(this);
     btThread.setPriority(Thread.MIN_PRIORITY);
     btThread.start();
   }
   
+  /**
+   * Method to send force replication command to other server to get 
+   * a new or updated docid
+   */
   public void run()
   {
-    //System.out.println("in ForceReplicationHandler Thread");
+    
     try
     {
-      //check if the metacat was configured to hanldle replication
-      if (!(util.getOption("replication")).equals("on"))
-      {
-         return;
-      }
+      // URL for notifcation
       URL comeAndGetIt = null;
-      //conn = util.getConnection();
       // If no server in xml_replication table, metacat don't need do anything
-      if (ReplicationHandler.buildServerList()==null)
+      if (serverLists.isEmpty())
       {
         return;
       }
-      //Enumeration keys = (ReplicationHandler.buildServerList(conn)).keys();
-      //Make sure that server list is not empty
-      if (serverList==null || serverList.isEmpty())
-      {
-        return;
-      }
       
-      Enumeration keys = serverList.keys();
-      //get the list of servers
-      while(keys.hasMoreElements())
+      // Thread seelping for some seconds to make sure the document was insert 
+      // into the database before we send force replication request
+      int sleepTime = Integer.parseInt
+                         (MetaCatUtil.getOption("forcereplicationwaitingtime"));
+      Thread.sleep(sleepTime);
+      MetaCatUtil.debugMessage("notification server:"+notificationServer, 34);
+      // Check every server in the serverlists
+      for (int i=0; i<serverLists.size(); i++)
       {
-        String server = (String)(keys.nextElement());
-        if(dbactionFlag)
+        //Set comeAndGetIt null
+        comeAndGetIt = null;
+        // Get ReplicationServer object in index i
+        ReplicationServer replicationServer = serverLists.serverAt(i);
+       // Get this ReplicationServer 's name
+        String server = replicationServer.getServerName();
+        
+        // If the server is the notification server, we don't notify it back 
+        // again, if server is null we don't replication it
+        if (server!=null && !server.equals(notificationServer))
         {
-            if (xmlDocument)// xml documents
+          
+          if(dbactionFlag)
+          {
+            // xml documents and server can replicate xml doucment
+            if (xmlDocument && replicationServer.getReplication())
             {
-              MetacatReplication.replLog("force xml replicating to " + server);
-              comeAndGetIt = new URL("https://" + server + 
+              // If this docid's homeserver is localhost, replicate it
+              if (homeServerCode==1)
+              {
+                MetacatReplication.replLog("force xml replicating to " 
+                                                                    + server);
+                comeAndGetIt = new URL("https://" + server + 
                                  "?action=forcereplicate&server=" + 
                                  util.getOption("server") + 
                                  util.getOption("replicationpath") +
                                  "&docid=" + docid + "&dbaction=" +
                                   action);
-            }
+              }//if servercode==1
+              else if (replicationServer.getHub()||
+                   server.equals(MetacatReplication.
+                                  getServerNameForServerCode(homeServerCode)))
+              {
+                // If the docid's home server is not local host, but local host
+                // is a hub of this server, replicate the docid too.
+                // If the server is homeserver of the docid, replication it too
+                MetacatReplication.replLog("force xml replicating to " 
+                                                                    + server);
+                comeAndGetIt = new URL("https://" + server + 
+                                 "?action=forcereplicate&server=" + 
+                                 util.getOption("server") + 
+                                 util.getOption("replicationpath") +
+                                 "&docid=" + docid + "&dbaction=" +
+                                  action);
+               
+              }//else
+             
+            }//if xmlDocument
             //It is data file and configured to handle data replication
-            else if ((util.getOption("replicationsenddata")).equals("on"))
+            else if (replicationServer.getDataReplication())
             {
-              MetacatReplication.replLog("force data replicating to " + server);
-              comeAndGetIt = new URL("https://" + server + 
+              // If the docid's home server is local host, replicate the docid
+              if (homeServerCode==1)
+              {
+                MetacatReplication.replLog("force data replicating to " 
+                                                                      + server);
+                comeAndGetIt = new URL("https://" + server + 
                                  "?action=forcereplicatedatafile&server=" + 
                                  util.getOption("server") + 
                                  util.getOption("replicationpath") +
                                  "&docid=" + docid + "&dbaction=" +
                                   action);
-                                
-            }//else if
+              }//if serverCode==1
+              else if (replicationServer.getHub()||
+                server.equals(MetacatReplication.
+                                    getServerNameForServerCode(homeServerCode)))
+              {
+                // If the docid's home server is not local host, but local host 
+                // is a hub of this server, replicate the docid too.
+                // If the server is homeserver of the docid replication it too
+                 MetacatReplication.replLog("force data replicating to " 
+                                                                      + server);
+                comeAndGetIt = new URL("https://" + server + 
+                                 "?action=forcereplicatedatafile&server=" + 
+                                 util.getOption("server") + 
+                                 util.getOption("replicationpath") +
+                                 "&docid=" + docid + "&dbaction=" +
+                                  action);
+                
+              }//else if servercode==1
+            }//else if data file
     
-        }//if
-        else
-        {
-          MetacatReplication.replLog("force replicating (default action) to )" + 
-                                      server);
-          if (xmlDocument)
-          {
-            comeAndGetIt = new URL("https://" + server + 
+          }//if has explicite action
+          else
+          { // has implicite action
+            MetacatReplication.replLog("force replicating (default action) to )"
+                                                + server);
+            // this docid is xml documents and can replicate xml doucment
+            if (xmlDocument && replicationServer.getReplication())
+            {
+              // If homeserver of this doicd is local, replicate it
+              if (homeServerCode ==1)
+              { 
+                comeAndGetIt = new URL("https://" + server + 
                                  "?action=forcereplicate&server=" + 
                                  util.getOption("server") + 
                                  util.getOption("replicationpath") +
                                  "&docid=" + docid);
-          }
-          //It is datafile and metacat is configured to handle data file
-          else if ((util.getOption("replicationsenddata")).equals("on"))
-          {
-            comeAndGetIt = new URL("https://" + server + 
+                
+              }//if homeserver ==1
+              else if (replicationServer.getHub()||
+                   server.equals(MetacatReplication.
+                   getServerNameForServerCode(homeServerCode)))
+              {
+                // If home server of this docid is not local host, but local 
+                // host is a hub for this server, replicate this doicd
+                // If the server is homeserver of the docid, replication it too
+                comeAndGetIt = new URL("https://" + server + 
+                                 "?action=forcereplicate&server=" + 
+                                 util.getOption("server") + 
+                                 util.getOption("replicationpath") +
+                                 "&docid=" + docid);
+                
+              }//else if
+              
+            }//if xmlDoucment
+            else if (replicationServer.getDataReplication())          
+            { //It is datafile and server is configured to replicate data file
+              
+              //if home server is local host, replicate the data file
+              if (homeServerCode ==1)
+              {
+                comeAndGetIt = new URL("https://" + server + 
                                  "?action=forcereplicatedatafile&server=" + 
                                  util.getOption("server") + 
                                  util.getOption("replicationpath") +
                                  "&docid=" + docid);
-          }//else if
-        }//else
-        MetaCatUtil.debugMessage("sending message: " + comeAndGetIt.toString());
-        String message = MetacatReplication.getURLContent(comeAndGetIt);
-        //send out the url.  message is a dummy variable as the target of
-        //the URL never directly replies to the request.  this simply
-        //invoces a read request from the server to this local machine.
-      }//while
-      //util.returnConnection(conn);
+              }//if
+              else if (replicationServer.getHub()||
+                          server.equals(MetacatReplication.
+                          getServerNameForServerCode(homeServerCode)))
+              {
+                // If home server is not local host, but the local host is a hub
+                // For this server, replicate the data file
+                // If the server is homeserver of the docid, replication it too
+                comeAndGetIt = new URL("https://" + server + 
+                                 "?action=forcereplicatedatafile&server=" + 
+                                 util.getOption("server") + 
+                                 util.getOption("replicationpath") +
+                                 "&docid=" + docid);
+                
+              }//else
+            }//else if
+          }//else has implicit action
+          
+          //Make sure comeAndGetIt is not empty
+          if ( comeAndGetIt != null && !comeAndGetIt.equals(""))
+          {
+            MetaCatUtil.debugMessage("sending message: " 
+                                                + comeAndGetIt.toString(), 25);
+            String message = MetacatReplication.getURLContent(comeAndGetIt);
+          }
+          //send out the url.  message is a dummy variable as the target of
+          //the URL never directly replies to the request.  this simply
+          //invoces a read request from the server to this local machine.
+        }//if notification server
+      }//for
+     
     }//try
     catch(Exception e)
     {
@@ -185,6 +324,6 @@
                           e.getMessage());
       e.printStackTrace(System.out);
     }
-    MetaCatUtil.debugMessage("exiting ForceReplicationHandler Thread");
-  }
-}
+    MetaCatUtil.debugMessage("exiting ForceReplicationHandler Thread", 25);
+  }//run
+}//ForceReplication class
Index: src/edu/ucsb/nceas/metacat/McdbDocNotFoundException.java
===================================================================
--- src/edu/ucsb/nceas/metacat/McdbDocNotFoundException.java	(revision 1291)
+++ src/edu/ucsb/nceas/metacat/McdbDocNotFoundException.java	(revision 1292)
@@ -35,11 +35,16 @@
  */
 public class McdbDocNotFoundException extends McdbException {
 
+  // String sto stroe which docid couldn't find
+  private String unfoundDocId = null;
+  private String unfoundRevision = null;
   /**
    * Create a new McdbDocNotFoundException.
    */
   public McdbDocNotFoundException() {
     super();
+    unfoundDocId = null;
+    unfoundRevision = null;
   }
 
   /**
@@ -47,8 +52,11 @@
    *
    * @param message The error or warning message.
    */
-  public McdbDocNotFoundException(String message) {
+  public McdbDocNotFoundException(String message, String givenDocId, 
+                                                    String givenRevision) {
     super(message);
+    unfoundDocId = givenDocId;
+    unfoundRevision = givenRevision;
   }
 
   /**
@@ -69,4 +77,20 @@
   public McdbDocNotFoundException(String message, Exception e) {
     super(message, e);
   }
+  
+  /**
+   * Method to get the docid which couldn't be found
+   */
+  public String getUnfoundDocId ()
+  {
+    return unfoundDocId;
+  }// getUnfoundDocid
+  
+  /**
+   * Method to get the docid's revsion which couldn't be found
+   */
+  public String getUnfoundRevision ()
+  {
+    return unfoundRevision;
+  }// getUnfoundDocid
 }
Index: src/edu/ucsb/nceas/metacat/RemoteDocument.java
===================================================================
--- src/edu/ucsb/nceas/metacat/RemoteDocument.java	(nonexistent)
+++ src/edu/ucsb/nceas/metacat/RemoteDocument.java	(revision 1292)
@@ -0,0 +1,514 @@
+/**
+ *  '$RCSfile$'
+ *    Purpose: A Class that represents an document in remote metacat server
+ *  Copyright: 2000 Regents of the University of California and the
+ *             National Center for Ecological Analysis and Synthesis
+ *    Authors: Jing Tao
+ *    Release: @release@
+ *
+ *   '$Author$'
+ *     '$Date$'
+ * '$Revision$'
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+package edu.ucsb.nceas.metacat;
+
+import javax.servlet.ServletOutputStream;
+import java.io.*;
+import java.net.*;
+import java.util.*;
+import java.util.zip.*;
+
+/**
+ * A class represents a document in remote metacat server. During the 
+ * replication between two metacats, metadata (xml documents) might be 
+ * replicated from Metacat A to Metacat B. But data file didn't. 
+ * Sometime, user in Metacat B might query the data file which doesn't riside in
+ * Metacat B. We need to download it from remote metacat server A and output it
+ * to user. But it still doesn't reside in Metacat B.
+ */
+public class RemoteDocument
+{
+  private String docIdWithoutRevision = null; //Docid for this document
+  private String revision = null; // Reviseion number for this document
+  private String dataSetId = null; // Data set document Id which contains
+                                   // this document
+  private String documentHomeServerURL = null; // Home metacat server url
+                                               // for this document
+  private String docType = null; //String to store docType
+  private String userName = null; // User name to require this document
+  private String passWord = null; // The user's passwd
+  private String zipEntry = null; // For zip entry
+  private String revisionAndDocType; // String to store this info
+
+  
+  /**
+   * Constructor of RemoteDcoument
+   * @param myDocIdWithoutRevision, Docid for this document
+   * @param myRevision, revision number for this document
+   * @param myUserName, the user who require this document
+   * @param myGroup, the gourps the user belong to
+   * @param myPassWord, the password of the user
+   * @param myOutPut, the output stream the document will be put
+   * @param myZipEntryPath, the base line for zip entry
+   */
+  public RemoteDocument ( String myDocIdWithoutRevision, String myRevision,
+                    String myUserName, String myPassWord, String myZipEntryPath)
+                          throws Exception
+  {
+    docIdWithoutRevision = myDocIdWithoutRevision;
+    // Get data set id for the given docid
+    dataSetId = DBUtil.findDataSetDocIdForGivenDocument(docIdWithoutRevision);
+    documentHomeServerURL = getMetacatURLForGivenDocId(dataSetId);
+    // Get revisionAndDocType
+    getRevisionAndDocTypeString();
+    revision = myRevision;
+    // If rev is null or empty (user didn't specify it,
+    // then set it current one in remote metacat
+    if (revision == null ||revision.equals(""))
+    {
+      revision = setRevision();
+    }
+    docType = setDocType();
+    userName = myUserName;
+    passWord = myPassWord;
+    zipEntry = myZipEntryPath+ docIdWithoutRevision + 
+                MetaCatUtil.getOption("accNumSeparator") + revision;
+   
+
+  }// Constructor
+
+  /**
+   * Method to get docidWithout revision
+   */
+  public String getDocIdWithoutRevsion()
+  {
+    return docIdWithoutRevision;
+  }//getDocIdWithoutRevsion
+  
+  /**
+   * Method to get revsion
+   */
+  public String getRevision()
+  {
+    return revision;
+  }//getRevision
+  
+  /**
+   * Method to get docType
+   */
+  public String getDocType()
+  {
+    return docType;
+  }//getDocType
+  
+  /**
+   * Set revision if client didn't specify the revision number.
+   * It come from revsionAndDocType String. This String look like "rev;doctype"
+   * Rule: 
+   *      1) Get current revision number from remote metacat
+   *      2) If couldn't get, set revision number 1
+   */
+  private String setRevision()
+  {
+    // String to store the result
+    String revision = null;
+    // Int to store the index of ";" in revision
+    int index = -1;
+    // If String revisionAndDocType is null, revision set to 1
+    if (revisionAndDocType == null || revisionAndDocType.equals(""))
+    {
+      revision = "1";
+    }//if
+    else
+    {
+      // Get the index of ";" in String revisionAndDocType
+      index = revisionAndDocType.indexOf(";");
+      // Get the subString about rev in String revisionAndDocType
+      revision = revisionAndDocType.substring(0, index);
+      // If revision is null or empty set revision 1
+      if (revision == null || revision.equals(""))
+      {
+        revision = "1";
+      }//if
+    }//else
+    return revision;
+  }//setRevision
+  
+  /**
+   * Set docType for this document base on the information from retmote metacat
+   * It come from revsionAndDocType String. This String look like "rev;doctype"
+   * If we couldn't get it from remote metacat, null will be set
+   */
+  private String setDocType()
+  {
+    // String to store the result
+    String remoteDocType = null;
+    // Int to store the index of ";" in revision
+    int index = -1;
+    
+    // If String revisionAndDocType is null, revision set to 1
+    if (revisionAndDocType == null || revisionAndDocType.equals(""))
+    {
+      remoteDocType = null;
+    }//if
+    else
+    {
+      // Get the index of ";" in String revisionAndDocType
+      index = revisionAndDocType.indexOf(";");
+      // Get the subString about doctype in String revisionAndDocType
+      remoteDocType = revisionAndDocType.substring(index+1);
+      
+    }//else
+    return remoteDocType;
+  }//setDocType
+  
+  /**
+   * Method to get a metacat url for dataset document id.
+   * First, get replication document home server for dataset document.
+   * Second, transfer a doc home server from replication servlet to metacat 
+   * servlet. The reseaon is when we use read action to get the document, the
+   * url is metacat servlet. Note: the protocol should be https. Because
+   * replication is using https. If we use http and maybe access wrong port 
+   * number.
+   * @param dataSetId, the document id for which we need to find metacat url
+   */
+  private String getMetacatURLForGivenDocId( String givenDocId) throws Exception
+  {
+    // DocumentImpl object of this given docid
+    DocumentImpl document = null;
+    // Replication home server
+    String replicationDocHomeServer = null;
+    // String metacat url
+    String metacatURL = null;
+    
+    // Check the given Docid is not null or empty
+    if (givenDocId == null || givenDocId.equals(""))
+    {
+      throw new Exception ("Couldn't find a dataset docid for the required id");
+    }
+    // Create a documentImpl object
+    document = new DocumentImpl(givenDocId, false);
+    // get the replication home server (it come from xml_replication table)
+    replicationDocHomeServer = document.getDocHomeServer();
+    
+    // If replication doc home server is local host. throws a exception
+    if (replicationDocHomeServer.
+                           equals(MetaCatUtil.getLocalReplicationServerName()))
+    {
+      throw new Exception ("Couldn't find the docid: "
+                                          +docIdWithoutRevision+"."+revision);
+    }//if
+    
+    // replicationDocHomeServer looks like 
+    // "pine.nceas.ucsb.edu:8443/tao/servlet/replication" and we should transfer
+    // it to"https://pine.nceas.ucsb.edu:8443/tao/servlet/metacat"
+    // get index of "replication" ocurrence
+    int index = replicationDocHomeServer.indexOf("replication");
+    // Get the subString from 0 to the index
+    String subString = replicationDocHomeServer.substring(0, index);
+    // Add https at head and append metacat 
+    metacatURL = "https://" + subString +"metacat";
+    MetaCatUtil.debugMessage("metacatURL: "+metacatURL, 30);
+    
+    return metacatURL;
+    
+  }//getMetacatURLForGivenDocId
+  
+  /**
+   * Method to get revisionAndDocType String from remote metacat
+   */
+  private void getRevisionAndDocTypeString()
+  {
+    // Set property for login action
+    Properties prop = new Properties();
+    // Set action = getrevisionanddoctype
+    prop.put("action", "getrevisionanddoctype");
+    prop.put("docid", docIdWithoutRevision);
+    // Now contact metacat and login.
+    String response = getMetacatString(prop);
+   
+    // response contains error information
+    if (response.indexOf("<error>")!=-1)
+    {
+      // Set response null
+      response = null;
+    }
+    
+    // Set revisionAndDocType equals reponse which get rid of white space
+    if ( response != null)
+    {
+      revisionAndDocType = response.trim();
+    }//if
+    else
+    {
+      revisionAndDocType = response;
+    }//else
+   
+    
+  }//getRevisionAndDocTypeString
+   
+  
+  /**
+   * Method to read both xml and data file from remote server
+   * and put the output into the given output stream
+   * @param outPut, the serverlstoutputStream which the remote document or
+   *                data file need to put.
+   */
+  public void readDocumentFromRemoteServer(ServletOutputStream outPut)
+                                              throws Exception
+  {
+    // Set properties
+    Properties prop = new Properties();
+    // qformat set to be xml. Data file will be handle in MetaCatServlet class
+    String qformat = "xml";
+    // Action set to read
+    String action = "read";
+    // Input stream from remote metacat
+    InputStream remoteResponse = null;
+    
+    // Check docIdWithoutRevision is not null or empty
+    if (docIdWithoutRevision ==null || docIdWithoutRevision.equals(""))
+    {
+      throw new Exception("User didn't specify the required docid");
+    }
+    // User specified docid (including revision number
+    String specifiedDocId = docIdWithoutRevision + 
+                MetaCatUtil.getOption("accNumSeparator") +revision;
+    MetaCatUtil.debugMessage("The requried docid is: "+ specifiedDocId, 30);
+    
+    // At first login to remote metacat server. 
+    logIn(userName, passWord);
+   
+    // Set action  
+    prop.put("action", action);
+    // Set qformat xml
+    prop.put("qformat", qformat);
+    // Set the docid
+    prop.put("docid", specifiedDocId);
+    
+    // Get remote metacat response
+    try
+    {
+      remoteResponse = getMetacatInputStream(prop);
+    }//try
+    catch (Exception e)
+    {
+      // If has a exception throws it again
+      throw e;
+    }//catch
+    
+    // Read content from the remote input and write the content into
+    // the given output
+     byte[] buf = new byte[4 * 1024]; // 4K buffer
+     // Read remote input into buffer
+     int index = remoteResponse.read(buf);
+     // If index is -1, this meams remote input ended
+     while (index != -1) 
+     {
+        // Write the content of butter to given output
+        outPut.write(buf, 0, index);
+        // Read next bytes to the buffer from remote input stream
+        index = remoteResponse.read(buf);
+     }//while
+     // Close remote reponse
+     if (remoteResponse != null)
+     {
+       remoteResponse.close();
+     }//if
+    
+  }//readDocumentFormRemoteServer
+  
+  
+    /**
+   * Method to read both xml and data file from remote server by zip output
+   * and put the output into the given output stream
+   * @param outPut, the serverlstoutputStream which the remote document or
+   *                data file need to put.
+   */
+  public void readDocumentFromRemoteServerByZip(ZipOutputStream outPut)
+                                              throws Exception
+  {
+    // Set properties
+    Properties prop = new Properties();
+    // qformat set to be xml. Data file will be handle in MetaCatServlet class
+    String qformat = "xml";
+    // Action set to read
+    String action = "read";
+    // Input stream from remote metacat
+    InputStream remoteResponse = null;
+    
+    // Check docIdWithoutRevision is not null or empty
+    if (docIdWithoutRevision ==null || docIdWithoutRevision.equals(""))
+    {
+      throw new Exception("User didn't specify the required docid");
+    }
+    // User specified docid (including revision number
+    String specifiedDocId = docIdWithoutRevision + 
+                MetaCatUtil.getOption("accNumSeparator") +revision;
+    MetaCatUtil.debugMessage("The requried docid is: "+ specifiedDocId, 30);
+    
+    // At first login to remote metacat server.
+    logIn(userName, passWord);
+       
+    // Set action  
+    prop.put("action", action);
+    // Set qformat xml
+    prop.put("qformat", qformat);
+    // Set the docid
+    prop.put("docid", specifiedDocId);
+    
+    // Get remote metacat response
+    try
+    {
+      remoteResponse = getMetacatInputStream(prop);
+    }//try
+    catch (Exception e)
+    {
+      // If has a exception throws it again
+      throw e;
+    }//catch
+    
+    // Create a zip entry
+    ZipEntry zentry = new ZipEntry(zipEntry);
+    outPut.putNextEntry(zentry);
+    // Read content from the remote input and write the content into
+    // the given output
+     byte[] buf = new byte[4 * 1024]; // 4K buffer
+     // Read remote input into buffer
+     int index = remoteResponse.read(buf);
+     // If index is -1, this meams remote input ended
+     while (index != -1) 
+     {
+        // Write the content of butter to given output
+        outPut.write(buf, 0, index);
+        // Read next bytes to the buffer from remote input stream
+        index = remoteResponse.read(buf);
+     }//while
+     // Close remote reponse
+     if (remoteResponse != null)
+     {
+       remoteResponse.close();
+     }//if
+     // Close zip entry
+     outPut.closeEntry();
+    
+  }//readDocumentFormRemoteServerByZip
+  
+  
+  /**
+   * Method to do login action. set cookie for it
+   * @param usrerName, the DN name of the test method
+   * @param passWord, the passwd of the user
+   */
+  private void logIn(String userName, String passWord)
+  {
+     // Make sure userName and password are not null 
+    if ( userName == null || passWord == null || 
+                                  userName.equals("") || passWord.equals(""))
+    {
+      return;
+    }
+    // Set property for login action
+    Properties prop = new Properties();
+    prop.put("action", "login");
+    prop.put("qformat", "xml");
+    prop.put("username", userName);
+    prop.put("password", passWord);
+
+    // Now contact metacat and login.
+    String response = getMetacatString(prop);
+    MetaCatUtil.debugMessage("Login Message: "+response, 30);
+  }//login
+  
+  /**
+   * Method to do logout action
+   */
+  private void logOut()
+  {
+    // Set property
+    Properties prop = new Properties();
+    prop.put("action", "logout");
+    prop.put("qformat", "xml");
+    // Send it to remote metacat
+    String response = getMetacatString(prop);
+    MetaCatUtil.debugMessage("Logout Message: "+response, 55);
+    // Set cookie to null
+    HttpMessage.setCookie(null);
+     
+  }//logout
+  
+  /**
+   * Send a request to Metacat and the return is a string from remote
+   * Metacat.
+   * @param prop the properties to be sent to Metacat
+   */
+  private String getMetacatString(Properties prop)
+  {
+    // Variable to store the response
+    String response = null;
+
+    // Now contact metacat and send the request
+    try
+    {
+      InputStreamReader returnStream = 
+                        new InputStreamReader(getMetacatInputStream(prop));
+      StringWriter sw = new StringWriter();
+      int len;
+      char[] characters = new char[512];
+      // Write inputstream into String
+      while ((len = returnStream.read(characters, 0, 512)) != -1)
+      {
+        sw.write(characters, 0, len);
+      }
+      // Close the input stream reader
+      returnStream.close();
+      // Transfer string writer to String
+      response = sw.toString();
+      // close string wirter
+      sw.close();
+    }
+    catch(Exception e)
+    {
+      MetaCatUtil.debugMessage("Error in RemoteDocument.getMetacatString: "+
+                               e.getMessage(), 30);
+      // If there is some exception return null
+      return null;
+    }
+  
+    return response;
+  }// getMetaCatString
+  
+  /**
+   * Send a request to Metacat and the return is a input stream from remote
+   * Metacat.
+   * @param prop the properties to be sent to Metacat
+   */
+  private InputStream getMetacatInputStream(Properties prop) throws Exception
+  {
+    // Variable to store the returned input stream
+    InputStream returnStream = null;
+    // Create a URL for remtate
+    URL url = new URL(documentHomeServerURL);
+    HttpMessage msg = new HttpMessage(url);
+    // Now contact metacat and send the request
+    returnStream = msg.sendPostMessage(prop);
+    return returnStream;
+ 
+  }//getMetacatInputStream
+
+}//Class RemoteDocument

Property changes on: src/edu/ucsb/nceas/metacat/RemoteDocument.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Author Date Id Revision
\ No newline at end of property
Index: src/edu/ucsb/nceas/metacat/ReplicationServerList.java
===================================================================
--- src/edu/ucsb/nceas/metacat/ReplicationServerList.java	(nonexistent)
+++ src/edu/ucsb/nceas/metacat/ReplicationServerList.java	(revision 1292)
@@ -0,0 +1,477 @@
+/**
+ *  '$RCSfile$'
+ *    Purpose: A class represent a replication server list in 
+               xml_replcation table
+ *  Copyright: 2000 Regents of the University of California and the
+ *             National Center for Ecological Analysis and Synthesis
+ *    Authors: Jing Tao
+ *    Release: @release@
+ *
+ *   '$Author$'
+ *     '$Date$'
+ * '$Revision$'
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+package edu.ucsb.nceas.metacat;
+
+import java.util.Vector;
+import java.sql.*;
+
+/**
+ * A class represent a replication server list in xml_replcation table
+ */
+ 
+public class ReplicationServerList
+{
+  private static Vector serverList = null; //Vector to store server list
+  
+  /**
+   * constructor of ReplicationServerList
+   * It will build server list. If only local host exists, ther server list
+   * will be null
+   */
+  public ReplicationServerList()
+  {
+    
+    serverList = new Vector();
+    //Build serverList
+    buildServerList();
+  }//ReplicationServerList
+  
+  /**
+   * Method to create server list from xml_replication table
+   * If in xml_replication table, only local host exists, server list will be
+   * empty
+   */
+  private void buildServerList()
+  {
+    ReplicationServer server = null; //element in server list
+    DBConnection dbConn = null;//DBConnection
+    int serialNumber = -1;//DBConnection serial number
+    PreparedStatement pstmt = null;
+    ResultSet rs = null;
+    boolean hasReplication = false;//Replication xml or not
+    boolean hasDataReplication = false;//Replication data file or not
+    boolean isHub = false;//local host is the hub for this server or not
+    
+    try
+    {
+      //Get DBConnection
+      dbConn=DBConnectionPool.
+                  getDBConnection("ReplicationHandler.buildServerList");
+      serialNumber=dbConn.getCheckOutSerialNumber();
+      //Select fields from xml_replication table
+      pstmt = dbConn.prepareStatement("select server, last_checked, replicate,"+
+                    " datareplicate, hub from xml_replication");
+      //Execute prepare statement
+      pstmt.execute();
+      //Get result set
+      rs = pstmt.getResultSet();
+      //Iterate over the result set
+      boolean tableHasRows = rs.next();
+      while(tableHasRows)
+      {
+        //Server name
+        String serverName = rs.getString(1);
+        MetaCatUtil.debugMessage("ServerName: "+serverName, 40);
+        //Last check date
+        String lastChecked = rs.getString(2);
+        MetaCatUtil.debugMessage("Last checked time: "+lastChecked, 40);
+        //Replication value
+        int replication = rs.getInt(3);
+        MetaCatUtil.debugMessage("Replication value: "+replication, 40);
+        //Data replication value
+        int dataReplication = rs.getInt(4);
+        MetaCatUtil.debugMessage("DataReplication value: "+dataReplication, 40);
+        //Hub value
+        int hubValue = rs.getInt(5);
+        MetaCatUtil.debugMessage("Hub value: "+hubValue, 40);
+        //Get rid of local host
+        if(!serverName.equals("localhost"))
+        {
+          
+          //create a new object of Replication
+          server = new ReplicationServer();
+         
+          //Set server name
+          server.setServerName(serverName);
+     
+          //Set last check date
+          server.setLastCheckedDate(lastChecked);
+          //From replication value to determine hasReplication valuse
+          if (replication ==1)
+          {
+            //If replication equals 1, it can replicate xml documents
+            hasReplication = true;
+          }//if
+          else
+          {
+            //if replication is NOT 1, it can't replicate xml documents
+            hasReplication = false;
+          }//else
+          //Set replication value
+          server.setReplication(hasReplication);
+           
+          //From both replication and data replication value to determine
+          //hasDataReplication value
+          if (hasReplication && dataReplication ==1)
+          { 
+            //Only server can replicate xml (hasRplication == true) and
+            // dataReplication is 1, local host can replicate data file
+            hasDataReplication = true;
+          }//if
+          else
+          {
+            hasDataReplication = false;
+          }//else
+          //Set data replciation value
+          server.setDataReplication(hasDataReplication);
+          
+          //Detemine isHub by hubValue
+          if (hubValue ==1)
+          {
+            isHub = true;
+          }//if
+          else
+          {
+            isHub = false;
+          }//else
+          //Set hub value
+          server.setHub(isHub);
+          
+          //Add this server into server list
+          serverList.add(server);
+        }//if
+        //Go to new row      
+        tableHasRows = rs.next();   
+      }//while
+     
+    }//try
+    catch(Exception e)
+    {
+      MetaCatUtil.debugMessage("Error in ReplicationServerList."
+                                    +"buildServerList(): "+e.getMessage(), 30);
+    }//catch
+    finally
+    {
+      try
+      {
+        //close result set
+        rs.close();
+        //close prepareed statement
+        pstmt.close();
+      }//try
+      catch (SQLException sqlE)
+      {
+        MetaCatUtil.debugMessage("Error in ReplicationHandler.buildServerList: "
+                                +sqlE.getMessage());
+      }//catch
+      finally
+      {
+        //Return dbconnection too pool
+        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
+      }//finally
+    }//finally
+  
+  }//buildServerList
+  
+  /**
+   * Method to determine the server list is empty or not
+   */
+  public boolean isEmpty()
+  {
+    return serverList.isEmpty();
+  }//isEmpty
+  
+  /**
+   * Method to get the size of serverList
+   */
+  public int size()
+  {
+    return serverList.size();
+  }//size()
+  
+  /**
+   * Method to add a new replciation server object to serverList
+   * @Param newReplciationServer, the object need to be add
+   */
+  private synchronized void addNewReplicationServer
+                                      (ReplicationServer newReplicationServer)
+  {
+    serverList.add(newReplicationServer);
+  }//addNewReplicationServer
+  
+  /**
+   * Method to get a server object given a index number
+   * @param index, the given index number
+   */
+  public ReplicationServer serverAt(int index)
+  {
+    return (ReplicationServer)serverList.elementAt(index);
+  }//serverAt
+   
+
+  /**
+   * Method to determine if a given server in the replication server list
+   * @param givenServerName, a server name will be check.
+   */
+  public boolean isGivenServerInList(String givenServerName)
+  {
+    boolean result = false;//Variable store the return value
+    ReplicationServer server = null; //Element in vetor
+    int size = 0;//Variable to store the size of vector serverList
+    //Get the size of vector
+    size = serverList.size();
+    
+    //If server list is empty
+    if (size == 0||givenServerName == null||givenServerName.equals(""))
+    {
+      result = false;
+      return result;
+    }
+    
+    //Check every element in the vector
+    for (int i = 0; i < size; i++)
+    {
+      //Get the ReplicationServer object indexed i in vector
+      server = (ReplicationServer) serverList.elementAt(i);
+      //If given name match a server's name, return true
+      if ( givenServerName.equalsIgnoreCase(server.getServerName()))
+      {
+        result = true;
+        return result;
+      }//if
+      
+    }//for
+    
+    //If reach here, there is no server's name match the given name
+    //flase will return
+    return result;
+  }//isGinvenServerInList
+  
+  /**
+   * Method to determine its index in server list for a given server.
+   * If couldn't find it, -1 will be returned
+   * @param givenServerName, a server name will be check.
+   */
+  private synchronized int findIndexInServerList(String givenServerName)
+  {
+    int index = -1;//Variable store the return value
+    ReplicationServer server = null; //Element in vetor
+    int size = 0;//Variable to store the size of vector serverList
+    //Get the size of vector
+    size = serverList.size();
+    
+    //If server list is empty, -1 will be returned
+    if (size == 0 || givenServerName ==null ||givenServerName.equals(""))
+    {
+      return index;
+    }
+    
+    //Check every element in the vector
+    for (int i = 0; i < size; i++)
+    {
+      //Get the ReplicationServer object indexed i in vector
+      server = (ReplicationServer) serverList.elementAt(i);
+      //If given name match a server's name, return true
+      if ( givenServerName.equalsIgnoreCase(server.getServerName()))
+      {
+        index = i;
+        return index;
+      }//if
+      
+    }//for
+    
+    //If reach here, there is no server's name match the given name
+    //-1 will return
+    return index;
+  }//isGinvenServerInList
+  
+  /**
+   * To a given server name, try to get its lastcheck date.
+   * If couldn't find the server in the server list, null will return
+   * @param givenServerName, the server's name which we want to get last checked
+   * out date
+   */
+  public synchronized String getLastCheckedDate(String givenServerName)
+  {
+    int index = -1;//Variable to store the index
+    ReplicationServer server = null;//Variable for replication server
+    
+    //Get the server's index in server list
+    index = findIndexInServerList(givenServerName);
+    //If index = -1, couldn't find this server, null will return
+    if (index == -1)
+    {
+      return null;
+    }//if
+    //Get Replication server object
+    server = (ReplicationServer) serverList.elementAt(index);
+    //return its lastcheckeddate attributes in this object
+    return server.getLastCheckedDate();
+  }//getLastCehckedDate
+   
+  /**
+   * To a given server name, try to get its xml replciation option
+   * If couldn't find the server in the server list, false will return
+   * @param givenServerName, the server's name which we want to get replication
+   * value
+   */
+  public synchronized boolean getReplicationValue(String givenServerName)
+  {
+    int index = -1;//Variable to store the index
+    ReplicationServer server = null;//Variable for replication server
+    
+    //Get the server's index in server list
+    index = findIndexInServerList(givenServerName);
+    //If index = -1, couldn't find this server, null will return
+    if (index == -1)
+    {
+      return false;
+    }//if
+    //Get Replication server object
+    server = (ReplicationServer) serverList.elementAt(index);
+    //return this object's replication value
+    return server.getReplication();
+  }//getReplicationValue
+  
+  /**
+   * To a given server name, try to get its data file replciation option
+   * If couldn't find the server in the server list, false will return
+   * @param givenServerName, the server's name which we want to get data file 
+   * replication value
+   */
+  public synchronized boolean getDataReplicationValue(String givenServerName)
+  {
+    int index = -1;//Variable to store the index
+    ReplicationServer server = null;//Variable for replication server
+    
+    //Get the server's index in server list
+    index = findIndexInServerList(givenServerName);
+    //If index = -1, couldn't find this server, null will return
+    if (index == -1)
+    {
+      return false;
+    }//if
+    //Get Replication server object
+    server = (ReplicationServer) serverList.elementAt(index);
+    //Return this object's data replication value
+    return server.getDataReplication();
+  }//getDataReplicationValue
+
+  /**
+   * To a given server name, try to get its hub option
+   * If couldn't find the server in the server list, false will return
+   * @param givenServerName, the server's name which we want to get hub
+   */
+  public synchronized boolean getHubValue(String givenServerName)
+  {
+    int index = -1;//Variable to store the index
+    ReplicationServer server = null;//Variable for replication server
+    
+    //Get the server's index in server list
+    index = findIndexInServerList(givenServerName);
+    //If index = -1, couldn't find this server, null will return
+    if (index == -1)
+    {
+      return false;
+    }//if
+    //Get Replication server object
+    server = (ReplicationServer) serverList.elementAt(index);
+    //Return this object's hub value
+    return server.getHub();
+  }//getHubValue  
+  
+  /**
+   * To a given server name, to check if it is in the server list.
+   * If it is not, add it to server list and the xml_replication table
+   * This method is for a document was replicated by a hub and the document's
+   * home server is not in the replication table. The value for replicate,
+   * datareplicate and hub are all false
+   * @param givenServerName, the server's name which want to check
+   */
+  public synchronized void addToServerListIfItIsNot(String givenServerName)
+  {
+    // Variable to store the index for the givenServerName
+    int index = -1;
+    // Variable to store the new replciation server object
+    ReplicationServer newServer = null;
+    // For sql command
+    PreparedStatement pStmt=null;
+    // For check out DBConnection
+    DBConnection dbConn = null;
+    int serialNumber = -1;
+    // Field value for xml_replication table
+    int replicate = 0;
+    int dataReplicate = 0;
+    int hub = 0;
+    
+    // Get the the index
+    index = findIndexInServerList(givenServerName);
+    // if index ==-1, it not in the server list
+    // Add the server to server list
+    // Add the server to xml_replication table
+    if (index ==-1)
+    {
+      // Create a new replication server object it's replicate, datareplicate
+      // and hub values are default - false
+      newServer = new ReplicationServer();
+      // Set newServer's name as givenServerName
+      newServer.setServerName(givenServerName);
+      // Add newServer to serverList
+      this.addNewReplicationServer(newServer);
+      // Add this server to xml_table too
+     try
+      {
+        // Checkout DBConnection     
+        dbConn=DBConnectionPool.
+             getDBConnection("ReplicationSErverList.addToServerListIfItIsNot");
+        serialNumber=dbConn.getCheckOutSerialNumber();
+        // Inser it into xml_replication table
+        pStmt = dbConn.prepareStatement("INSERT INTO xml_replication " +
+                      "(server, last_checked, replicate, datareplicate, hub) "+
+                       "VALUES ('" + givenServerName + "', to_date(" +
+                       "'01/01/00', 'MM/DD/YY'), '" +
+                       replicate +"', '"+dataReplicate+"','"+ hub + "')");
+        pStmt.execute();
+        pStmt.close();
+      }//try
+      catch (Exception e)
+      {
+        MetaCatUtil.debugMessage("Error in ReplicationServerList."+
+                            "addToServerListIfItIsNot: " + e.getMessage(), 30);
+      }//catch
+      finally
+      { 
+        try
+        {
+          pStmt.close();
+        }//try
+        catch (Exception ee)
+        { 
+          MetaCatUtil.debugMessage("Error in ReplicationServerList."+
+                            "addToServerListIfItIsNot: " + ee.getMessage(), 50);
+        }//catch
+        finally
+        {
+          DBConnectionPool.returnDBConnection(dbConn, serialNumber);
+        }//finally
+      }//finally
+    }//if
+  }//addToServerListIfItIsNot
+  
+}//ReplicationServerList

Property changes on: src/edu/ucsb/nceas/metacat/ReplicationServerList.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Author Date Id Revision
\ No newline at end of property
Index: build.xml
===================================================================
--- build.xml	(revision 1291)
+++ build.xml	(revision 1292)
@@ -7,8 +7,8 @@
   * For Details: http://www.nceas.ucsb.edu/
   *
   *    '$Author$'
-  *      '$Date$'
-  *  '$Revision$'
+  *    '$Date$'
+  *    '$Revision$'
   *
   * Build file for the Ant cross-platform build system for metacat
   * See http://jakarta.apache.org for details on Ant
@@ -60,14 +60,12 @@
       <property name="webapps" value="/opt/tomcat/webapps" />
       <property name="context" value="tao" />
       <property name="user" value="tao"/>
-      <property name="password" value="tdataint"/>
-      <property name="server" value="dev.nceas.ucsb.edu"/>
-      <property name="systemidserver" value="http://dev.nceas.ucsb.edu" />
-      <property name="datafilepath" value="/opt/tomcat/data/tao/data" />
-      <property name="replication" value="off" />
-      <property name="replicationsenddata" value="off" />
-      <property name="replicationacceptdata" value="off" />
+      <property name="password" value="your-pw-goes-here"/>
+      <property name="server" value="pine.nceas.ucsb.edu:8443"/>
+      <property name="systemidserver" value="http://pine.nceas.ucsb.edu:8080" />
+      <property name="datafilepath" value="/usr/local/devtools/jakarta-tomcat/data/tao/data" />
       <property name="debuglevel" value="35" />
+      <property name="forcereplicationwaitingtime" value="30000"/>
       <property name="web-base-url" 
                 value="http://knb.ecoinformatics.org"/>
       <property name="default-style" value="knb" />
@@ -141,9 +139,7 @@
       <filter token="default-style" value="${default-style}"/>
       <filter token="eml-version" value="${eml-version}"/>
       <filter token="context" value="${context}"/>
-      <filter token="replication" value="${replication}" />
-      <filter token="replicationsenddata" value="${replicationsenddata}" />
-      <filter token="replicationacceptdata" value="${replicationacceptdata}" />
+      <filter token="forcereplicationwaitingtime" value="${forcereplicationwaitingtime}" />
       <filter token="debuglevel" value="${debuglevel}" />
       <filter token="datafilepath" value="${datafilepath}" />
       <property name="srcdir" value="./src" />
