Project

General

Profile

1 522 berkley
/**
2
 *  '$RCSfile$'
3
 *    Purpose: A class to asyncronously do delta-T replication checking
4
 *  Copyright: 2000 Regents of the University of California and the
5
 *             National Center for Ecological Analysis and Synthesis
6
 *    Authors: Chad Berkley
7
 *
8
 *   '$Author$'
9
 *     '$Date$'
10
 * '$Revision$'
11 669 jones
 *
12
 * This program is free software; you can redistribute it and/or modify
13
 * it under the terms of the GNU General Public License as published by
14
 * the Free Software Foundation; either version 2 of the License, or
15
 * (at your option) any later version.
16
 *
17
 * This program is distributed in the hope that it will be useful,
18
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20
 * GNU General Public License for more details.
21
 *
22
 * You should have received a copy of the GNU General Public License
23
 * along with this program; if not, write to the Free Software
24
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
25 522 berkley
 */
26 2286 tao
27 5014 daigle
package edu.ucsb.nceas.metacat.replication;
28 522 berkley
29 5014 daigle
import edu.ucsb.nceas.metacat.CatalogMessageHandler;
30
import edu.ucsb.nceas.metacat.DBUtil;
31
import edu.ucsb.nceas.metacat.DocInfoHandler;
32
import edu.ucsb.nceas.metacat.DocumentImpl;
33
import edu.ucsb.nceas.metacat.DocumentImplWrapper;
34
import edu.ucsb.nceas.metacat.EventLog;
35 5089 daigle
import edu.ucsb.nceas.metacat.accesscontrol.AccessControlForSingleFile;
36 5098 daigle
import edu.ucsb.nceas.metacat.accesscontrol.XMLAccessDAO;
37 5014 daigle
import edu.ucsb.nceas.metacat.database.DBConnection;
38
import edu.ucsb.nceas.metacat.database.DBConnectionPool;
39
import edu.ucsb.nceas.metacat.database.DatabaseService;
40 5030 daigle
import edu.ucsb.nceas.metacat.properties.PropertyService;
41 5014 daigle
import edu.ucsb.nceas.metacat.shared.HandlerException;
42 4698 daigle
import edu.ucsb.nceas.metacat.util.MetacatUtil;
43 4080 daigle
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
44
45 522 berkley
import java.sql.*;
46
import java.util.*;
47 2555 tao
import java.util.Date;
48 522 berkley
import java.io.*;
49
import java.net.*;
50 543 berkley
import java.text.*;
51 2663 sgarg
52
import org.apache.log4j.Logger;
53 522 berkley
import org.xml.sax.ContentHandler;
54
import org.xml.sax.ErrorHandler;
55
import org.xml.sax.InputSource;
56 5014 daigle
import org.xml.sax.SAXException;
57 522 berkley
import org.xml.sax.XMLReader;
58
import org.xml.sax.helpers.XMLReaderFactory;
59 561 berkley
import org.xml.sax.helpers.DefaultHandler;
60 522 berkley
61 561 berkley
62
63 522 berkley
/**
64
 * This class handles deltaT replication checking.  Whenever this TimerTask
65
 * is fired it checks each server in xml_replication for updates and updates
66
 * the local db as needed.
67
 */
68
public class ReplicationHandler extends TimerTask
69
{
70 573 berkley
  int serverCheckCode = 1;
71 2286 tao
  ReplicationServerList serverList = null;
72 2573 tao
  //PrintWriter out;
73 4698 daigle
//  private static final AbstractDatabase dbAdapter = MetacatUtil.dbAdapter;
74 5014 daigle
  private static Logger logReplication = Logger.getLogger("ReplicationLogging");
75 2663 sgarg
  private static Logger logMetacat = Logger.getLogger(ReplicationHandler.class);
76 2725 tao
  private static int DOCINSERTNUMBER = 1;
77
  private static int DOCERRORNUMBER  = 1;
78
  private static int REVINSERTNUMBER = 1;
79
  private static int REVERRORNUMBER  = 1;
80 2573 tao
  public ReplicationHandler()
81 522 berkley
  {
82 2573 tao
    //this.out = o;
83 1292 tao
    serverList = new ReplicationServerList();
84 522 berkley
  }
85 2286 tao
86 2573 tao
  public ReplicationHandler(int serverCheckCode)
87 573 berkley
  {
88 2573 tao
    //this.out = o;
89 573 berkley
    this.serverCheckCode = serverCheckCode;
90 1292 tao
    serverList = new ReplicationServerList();
91 573 berkley
  }
92 2286 tao
93 522 berkley
  /**
94 2286 tao
   * Method that implements TimerTask.run().  It runs whenever the timer is
95 522 berkley
   * fired.
96
   */
97
  public void run()
98
  {
99
    //find out the last_checked time of each server in the server list and
100 2286 tao
    //send a query to each server to see if there are any documents in
101 522 berkley
    //xml_documents with an update_date > last_checked
102 5014 daigle
103 1032 tao
      //if serverList is null, metacat don't need to replication
104
      if (serverList==null||serverList.isEmpty())
105
      {
106
        return;
107
      }
108 1292 tao
      updateCatalog();
109
      update();
110 1217 tao
      //conn.close();
111 522 berkley
  }
112 2286 tao
113 522 berkley
  /**
114 577 berkley
   * Method that uses revision taging for replication instead of update_date.
115
   */
116 1292 tao
  private void update()
117 577 berkley
  {
118
    /*
119
     Pseudo-algorithm
120
     - request a doc list from each server in xml_replication
121 2286 tao
     - check the rev number of each of those documents agains the
122 577 berkley
       documents in the local database
123
     - pull any documents that have a lesser rev number on the local server
124
       from the remote server
125
     - delete any documents that still exist in the local xml_documents but
126
       are in the deletedDocuments tag of the remote host response.
127
     - update last_checked to keep track of the last time it was checked.
128 2286 tao
       (this info is theoretically not needed using this system but probably
129 577 berkley
       should be kept anyway)
130
    */
131 2286 tao
132
    ReplicationServer replServer = null; // Variable to store the
133
                                        // ReplicationServer got from
134 1292 tao
                                        // Server list
135 2298 tao
    String server = null; // Variable to store server name
136 5014 daigle
//    String update;
137
    Vector<String> responses = new Vector<String>();
138 577 berkley
    URL u;
139 2286 tao
140
141 3898 tao
142 1585 tao
    //Check for every server in server list to get updated list and put
143
    // them in to response
144
    for (int i=0; i<serverList.size(); i++)
145
    {
146 1292 tao
        // Get ReplicationServer object from server list
147
        replServer = serverList.serverAt(i);
148
        // Get server name from ReplicationServer object
149 2578 tao
        server = replServer.getServerName().trim();
150 1585 tao
        String result = null;
151 5014 daigle
        logReplication.info("ReplicationHandler.update - full update started to: " + server);
152 1292 tao
        // Send command to that server to get updated docid information
153
        try
154
        {
155 1585 tao
          u = new URL("https://" + server + "?server="
156 4698 daigle
          +MetacatUtil.getLocalReplicationServerName()+"&action=update");
157 5014 daigle
          logReplication.info("ReplicationHandler.update - Sending infomation " +u.toString());
158
          result = ReplicationService.getURLContent(u);
159 1585 tao
        }
160 1292 tao
        catch (Exception e)
161
        {
162 5014 daigle
          logMetacat.error("ReplicationHandler.update - " + ReplicationService.METACAT_REPL_ERROR_MSG);
163
          logReplication.error( "ReplicationHandler.update - Failed to get updated doc list "+
164 2663 sgarg
                       "for server " + server + " because "+e.getMessage());
165 1292 tao
          continue;
166 1585 tao
        }
167 2286 tao
168 5014 daigle
        logReplication.info("docid: "+server+" "+result);
169 1292 tao
        //check if result have error or not, if has skip it.
170 1609 tao
        if (result.indexOf("<error>")!=-1 && result.indexOf("</error>")!=-1)
171 1102 tao
        {
172 5014 daigle
          logMetacat.error("ReplicationHandler.update - " + ReplicationService.METACAT_REPL_ERROR_MSG);
173
          logReplication.error( "ReplicationHandler.update - Failed to get updated doc list "+
174 2663 sgarg
                       "for server " + server + " because "+result);
175 1102 tao
          continue;
176
        }
177 1585 tao
        //Add result to vector
178 577 berkley
        responses.add(result);
179 1585 tao
    }
180 2286 tao
181 1585 tao
    //make sure that there is updated file list
182
    //If response is null, metacat don't need do anything
183
    if (responses==null || responses.isEmpty())
184
    {
185 5014 daigle
    	logMetacat.error("ReplicationHandler.update - " + ReplicationService.METACAT_REPL_ERROR_MSG);
186
        logReplication.info( "ReplicationHandler.update - No updated doc list for "+
187 1585 tao
                           "every server and failed to replicate");
188 1032 tao
        return;
189 1585 tao
    }
190 2286 tao
191
192 5014 daigle
    logReplication.info("ReplicationHandler.update - Responses from remote metacat about updated "+
193 2663 sgarg
                   "document information: "+ responses.toString());
194 1585 tao
    // go through response vector(it contains updated vector and delete vector
195
    for(int i=0; i<responses.size(); i++)
196 2286 tao
    {
197 3898 tao
    	XMLReader parser;
198
    	ReplMessageHandler message = new ReplMessageHandler();
199
    	try
200
        {
201
          parser = initParser(message);
202
        }
203
        catch (Exception e)
204
        {
205 5014 daigle
          logMetacat.error("ReplicationHandler.update - " + ReplicationService.METACAT_REPL_ERROR_MSG);
206
          logReplication.error("ReplicationHandler.update - Failed to replicate becaue couldn't " +
207 3898 tao
                                " initParser for message and " +e.getMessage());
208
           // stop replication
209
           return;
210
        }
211
212 1585 tao
        try
213
        {
214
          parser.parse(new InputSource(
215 577 berkley
                     new StringReader(
216
                     (String)(responses.elementAt(i)))));
217 1585 tao
        }
218
        catch(Exception e)
219
        {
220 5014 daigle
          logMetacat.error("ReplicationHandler.update - " + ReplicationService.METACAT_REPL_ERROR_MSG);
221
          logReplication.error("ReplicationHandler.update - Couldn't parse one responses "+
222 2663 sgarg
                                   "because "+ e.getMessage());
223 1585 tao
          continue;
224
        }
225 1037 tao
        //v is the list of updated documents
226 5014 daigle
        Vector<Vector<String>> updateList = new Vector<Vector<String>>(message.getUpdatesVect());
227
        logReplication.info("ReplicationHandler.update - The document list size is "+updateList.size()+ " from "+message.getServerName());
228 577 berkley
        //System.out.println("v: " + v.toString());
229 1037 tao
        //d is the list of deleted documents
230 5014 daigle
        Vector<Vector<String>> deleteList = new Vector<Vector<String>>(message.getDeletesVect());
231 1037 tao
        //System.out.println("d: " + d.toString());
232 5014 daigle
        logReplication.info("ReplicationHandler.update - Update vector size: "+ updateList.size()+" from "+message.getServerName());
233
        logReplication.info("ReplicationHandler.update - Delete vector size: "+ deleteList.size()+" from "+message.getServerName());
234
        logReplication.info("ReplicationHandler.update - The delete document list size is "+deleteList.size()+" from "+message.getServerName());
235 1585 tao
        // go though every element in updated document vector
236 2608 tao
        handleDocList(updateList, DocumentImpl.DOCUMENTTABLE);
237 1037 tao
        //handle deleted docs
238 1585 tao
        for(int k=0; k<deleteList.size(); k++)
239 577 berkley
        { //delete the deleted documents;
240 5014 daigle
          Vector<String> w = new Vector<String>(deleteList.elementAt(k));
241 1585 tao
          String docId = (String)w.elementAt(0);
242
          try
243 579 berkley
          {
244 2298 tao
            handleDeleteSingleDocument(docId, server);
245 579 berkley
          }
246 1585 tao
          catch (Exception ee)
247
          {
248
            continue;
249
          }
250 1037 tao
        }//for delete docs
251 2608 tao
252
        // handle replicate doc in xml_revision
253 5014 daigle
        Vector<Vector<String>> revisionList = new Vector<Vector<String>>(message.getRevisionsVect());
254
        logReplication.info("ReplicationHandler.update - The revision document list size is "+revisionList.size()+ " from "+message.getServerName());
255 2608 tao
        handleDocList(revisionList, DocumentImpl.REVISIONTABLE);
256 2725 tao
        DOCINSERTNUMBER = 1;
257
        DOCERRORNUMBER  = 1;
258
        REVINSERTNUMBER = 1;
259
        REVERRORNUMBER  = 1;
260 1585 tao
    }//for response
261 2286 tao
262 1585 tao
    //updated last_checked
263
    for (int i=0;i<serverList.size(); i++)
264
    {
265
       // Get ReplicationServer object from server list
266
       replServer = serverList.serverAt(i);
267
       try
268
       {
269
         updateLastCheckTimeForSingleServer(replServer);
270
       }
271
       catch(Exception e)
272
       {
273
         continue;
274
       }
275
    }//for
276 2286 tao
277 1585 tao
  }//update
278 2286 tao
279 1585 tao
  /* Handle replicate single xml document*/
280 2286 tao
  private void handleSingleXMLDocument(String remoteserver, String actions,
281 2641 tao
                                       String accNumber, String tableName)
282 5014 daigle
               throws HandlerException
283 1585 tao
  {
284
    DBConnection dbConn = null;
285
    int serialNumber = -1;
286
    try
287
    {
288
      // Get DBConnection from pool
289
      dbConn=DBConnectionPool.
290
                  getDBConnection("ReplicationHandler.handleSingleXMLDocument");
291
      serialNumber=dbConn.getCheckOutSerialNumber();
292
      //if the document needs to be updated or inserted, this is executed
293 1600 tao
      String readDocURLString = "https://" + remoteserver + "?server="+
294 4698 daigle
              MetacatUtil.getLocalReplicationServerName()+"&action=read&docid="+accNumber;
295
      readDocURLString = MetacatUtil.replaceWhiteSpaceForURL(readDocURLString);
296 1600 tao
      URL u = new URL(readDocURLString);
297 2286 tao
298 1585 tao
      // Get docid content
299 5014 daigle
      String newxmldoc = ReplicationService.getURLContent(u);
300 1585 tao
      // If couldn't get skip it
301 1609 tao
      if ( newxmldoc.indexOf("<error>")!= -1 && newxmldoc.indexOf("</error>")!=-1)
302 1292 tao
      {
303 5014 daigle
         throw new HandlerException("ReplicationHandler.handleSingleXMLDocument - " + newxmldoc);
304 1585 tao
      }
305 5014 daigle
      //logReplication.info("xml documnet:");
306
      //logReplication.info(newxmldoc);
307 2286 tao
308 1585 tao
      // Try get the docid info from remote server
309
      DocInfoHandler dih = new DocInfoHandler();
310
      XMLReader docinfoParser = initParser(dih);
311 2286 tao
      String docInfoURLStr = "https://" + remoteserver +
312 4698 daigle
                       "?server="+MetacatUtil.getLocalReplicationServerName()+
313 2641 tao
                       "&action=getdocumentinfo&docid="+accNumber;
314 4698 daigle
      docInfoURLStr = MetacatUtil.replaceWhiteSpaceForURL(docInfoURLStr);
315 1600 tao
      URL docinfoUrl = new URL(docInfoURLStr);
316 5014 daigle
      logReplication.info("ReplicationHandler.handleSingleXMLDocument - Sending message: " +
317 2663 sgarg
                                                  docinfoUrl.toString());
318 5014 daigle
      String docInfoStr = ReplicationService.getURLContent(docinfoUrl);
319 1585 tao
      docinfoParser.parse(new InputSource(new StringReader(docInfoStr)));
320 5014 daigle
      Hashtable<String, String> docinfoHash = dih.getDocInfo();
321 1585 tao
      // Get home server of the docid
322 5014 daigle
      String docHomeServer = docinfoHash.get("home_server");
323
      logReplication.info("ReplicationHandler.handleSingleXMLDocument - doc home server in repl: "+docHomeServer);
324
      String createdDate = docinfoHash.get("date_created");
325
      String updatedDate = docinfoHash.get("date_updated");
326 1585 tao
      //docid should include rev number too
327 4212 daigle
      /*String accnum=docId+util.getProperty("document.accNumSeparator")+
328 2641 tao
                                              (String)docinfoHash.get("rev");*/
329 5014 daigle
      logReplication.info("ReplicationHandler.handleSingleXMLDocument - docid in repl: "+accNumber);
330
      String docType = docinfoHash.get("doctype");
331
      logReplication.info("ReplicationHandler.handleSingleXMLDocument - doctype in repl: "+docType);
332 2286 tao
333 1585 tao
      String parserBase = null;
334
      // this for eml2 and we need user eml2 parser
335 2169 sgarg
      if (docType != null && (docType.trim()).equals(DocumentImpl.EML2_0_0NAMESPACE))
336 1585 tao
      {
337 2163 tao
         parserBase = DocumentImpl.EML200;
338 1585 tao
      }
339 2286 tao
      else if (docType != null && (docType.trim()).equals(DocumentImpl.EML2_0_1NAMESPACE))
340
      {
341
        parserBase = DocumentImpl.EML200;
342
      }
343
      else if (docType != null && (docType.trim()).equals(DocumentImpl.EML2_1_0NAMESPACE))
344
      {
345
        parserBase = DocumentImpl.EML210;
346
      }
347 1585 tao
      // Write the document into local host
348
      DocumentImplWrapper wrapper = new DocumentImplWrapper(parserBase, false);
349 2286 tao
      String newDocid = wrapper.writeReplication(dbConn,
350 1585 tao
                              new StringReader(newxmldoc),
351 5014 daigle
                              docinfoHash.get("public_access"),
352 1585 tao
                              null,  /* the dtd text */
353 2286 tao
                              actions,
354 2641 tao
                              accNumber,
355 5014 daigle
                              docinfoHash.get("user_owner"),
356 1585 tao
                              null, /* null for groups[] */
357 2286 tao
                              docHomeServer,
358 2624 tao
                              remoteserver, tableName, true,// true is for time replication
359
                              createdDate,
360 3230 tao
                              updatedDate);
361 4419 leinfelder
362 5098 daigle
      //process extra access rules
363
      Vector<XMLAccessDAO> xmlAccessDAOList = dih.getAccessControlList();
364
      if (xmlAccessDAOList != null) {
365
      	AccessControlForSingleFile acfsf = new AccessControlForSingleFile(accNumber);
366
      	for (XMLAccessDAO xmlAccessDAO : xmlAccessDAOList) {
367
      		if (!acfsf.accessControlExists(xmlAccessDAO)) {
368
      			acfsf.insertPermissions(xmlAccessDAO);
369
      		}
370 4419 leinfelder
          }
371
      }
372
373 5014 daigle
      logReplication.info("ReplicationHandler.handleSingleXMLDocument - Successfully replicated doc " + accNumber);
374 2725 tao
      if (tableName.equals(DocumentImpl.DOCUMENTTABLE))
375
      {
376 5014 daigle
        logReplication.info("ReplicationHandler.handleSingleXMLDocument - " + DOCINSERTNUMBER + " Wrote xml doc " + accNumber +
377 2725 tao
                                     " into "+tableName + " from " +
378 1585 tao
                                         remoteserver);
379 2725 tao
        DOCINSERTNUMBER++;
380
      }
381
      else
382
      {
383 5014 daigle
          logReplication.info("ReplicationHandler.handleSingleXMLDocument - " +REVINSERTNUMBER + " Wrote xml doc " + accNumber +
384 2725 tao
                  " into "+tableName + " from " +
385
                      remoteserver);
386
          REVINSERTNUMBER++;
387
      }
388 3234 tao
      String ip = getIpFromURL(u);
389 5014 daigle
      EventLog.getInstance().log(ip, ReplicationService.REPLICATIONUSER, accNumber, actions);
390 2725 tao
391 2286 tao
392
    }//try
393 577 berkley
    catch(Exception e)
394
    {
395 2725 tao
396
        if (tableName.equals(DocumentImpl.DOCUMENTTABLE))
397
        {
398 5014 daigle
        	logMetacat.error("ReplicationHandler.handleSingleXMLDocument - " + ReplicationService.METACAT_REPL_ERROR_MSG);
399
        	logReplication.error("ReplicationHandler.handleSingleXMLDocument - " +DOCERRORNUMBER + " Failed to write xml doc " + accNumber +
400 2725 tao
                                       " into "+tableName + " from " +
401
                                           remoteserver + " because "+e.getMessage());
402
          DOCERRORNUMBER++;
403
        }
404
        else
405
        {
406 5014 daigle
        	logMetacat.error("ReplicationHandler.handleSingleXMLDocument - " + ReplicationService.METACAT_REPL_ERROR_MSG);
407
        	logReplication.error("ReplicationHandler.handleSingleXMLDocument - " +REVERRORNUMBER + " Failed to write xml doc " + accNumber +
408 2725 tao
                    " into "+tableName + " from " +
409
                        remoteserver +" because "+e.getMessage());
410
            REVERRORNUMBER++;
411
        }
412 5014 daigle
        logMetacat.error("ReplicationHandler.handleSingleXMLDocument - " + ReplicationService.METACAT_REPL_ERROR_MSG);
413
        logReplication.error("ReplicationHandler.handleSingleXMLDocument - Failed to write doc " + accNumber +
414 2663 sgarg
                                      " into db because " +e.getMessage());
415 5014 daigle
      throw new HandlerException("ReplicationHandler.handleSingleXMLDocument - generic exception "
416
    		  + "writing Replication: " +e.getMessage());
417 577 berkley
    }
418 667 berkley
    finally
419
    {
420 1585 tao
       //return DBConnection
421
       DBConnectionPool.returnDBConnection(dbConn, serialNumber);
422
    }//finally
423
  }
424 2286 tao
425
426
427 1585 tao
  /* Handle replicate single xml document*/
428 2286 tao
  private void handleSingleDataFile(String remoteserver, String actions,
429 2641 tao
                                    String accNumber, String tableName)
430 5014 daigle
               throws HandlerException
431 1585 tao
  {
432 5014 daigle
    logReplication.info("ReplicationHandler.handleSingleDataFile - Try to replicate data file: " + accNumber);
433 1585 tao
    DBConnection dbConn = null;
434
    int serialNumber = -1;
435
    try
436
    {
437
      // Get DBConnection from pool
438
      dbConn=DBConnectionPool.
439
                  getDBConnection("ReplicationHandler.handleSinlgeDataFile");
440
      serialNumber=dbConn.getCheckOutSerialNumber();
441
      // Try get docid info from remote server
442
      DocInfoHandler dih = new DocInfoHandler();
443
      XMLReader docinfoParser = initParser(dih);
444 2286 tao
      String docInfoURLString = "https://" + remoteserver +
445 4698 daigle
                  "?server="+MetacatUtil.getLocalReplicationServerName()+
446 2641 tao
                  "&action=getdocumentinfo&docid="+accNumber;
447 4698 daigle
      docInfoURLString = MetacatUtil.replaceWhiteSpaceForURL(docInfoURLString);
448 1600 tao
      URL docinfoUrl = new URL(docInfoURLString);
449 2286 tao
450 5014 daigle
      String docInfoStr = ReplicationService.getURLContent(docinfoUrl);
451 1585 tao
      docinfoParser.parse(new InputSource(new StringReader(docInfoStr)));
452 5014 daigle
      Hashtable<String, String> docinfoHash = dih.getDocInfo();
453 1585 tao
      // Get doicd owner
454 5014 daigle
      String user = docinfoHash.get("user_owner");
455 1585 tao
      // Get docid name (such as acl or dataset)
456 5014 daigle
      String docName = docinfoHash.get("docname");
457 2286 tao
      // Get doc type (eml public id)
458 5014 daigle
      String docType = docinfoHash.get("doctype");
459 1585 tao
      // Get docid home sever. it might be different to remoteserver
460
      // becuause of hub feature
461 5014 daigle
      String docHomeServer = docinfoHash.get("home_server");
462
      String createdDate = docinfoHash.get("date_created");
463
      String updatedDate = docinfoHash.get("date_updated");
464 1585 tao
      //docid should include rev number too
465 4212 daigle
      /*String accnum=docId+util.getProperty("document.accNumSeparator")+
466 2641 tao
                                              (String)docinfoHash.get("rev");*/
467 2286 tao
468
469 4080 daigle
      String datafilePath = PropertyService.getProperty("application.datafilepath");
470 1585 tao
      // Get data file content
471 1600 tao
      String readDataURLString = "https://" + remoteserver + "?server="+
472 4698 daigle
                                        MetacatUtil.getLocalReplicationServerName()+
473 2641 tao
                                            "&action=readdata&docid="+accNumber;
474 4698 daigle
      readDataURLString = MetacatUtil.replaceWhiteSpaceForURL(readDataURLString);
475 1600 tao
      URL u = new URL(readDataURLString);
476 2286 tao
      InputStream input = u.openStream();
477 1585 tao
      //register data file into xml_documents table and wite data file
478
      //into file system
479 1600 tao
      if ( input != null)
480 667 berkley
      {
481 2286 tao
        DocumentImpl.writeDataFileInReplication(input,
482 2608 tao
                                                datafilePath,
483
                                                docName,docType,
484 2641 tao
                                                accNumber, user,
485 2608 tao
                                                docHomeServer,
486
                                                remoteserver,
487
                                                tableName,
488 2624 tao
                                                true, //true means timed replication
489
                                                createdDate,
490 3230 tao
                                                updatedDate);
491 2624 tao
492 4419 leinfelder
        //process extra access rules
493 5098 daigle
        Vector<XMLAccessDAO> xmlAccessDAOList = dih.getAccessControlList();
494
        if (xmlAccessDAOList != null) {
495
        	AccessControlForSingleFile acfsf = new AccessControlForSingleFile(accNumber);
496
        	for (XMLAccessDAO xmlAccessDAO : xmlAccessDAOList) {
497
        		if (!acfsf.accessControlExists(xmlAccessDAO)) {
498
        			acfsf.insertPermissions(xmlAccessDAO);
499
        		}
500 4419 leinfelder
            }
501
        }
502
503 5014 daigle
        logReplication.info("ReplicationHandler.handleSingleDataFile - Successfully to write datafile " + accNumber);
504 2725 tao
        /*MetacatReplication.replLog("wrote datafile " + accNumber + " from " +
505
                                    remoteserver);*/
506
        if (tableName.equals(DocumentImpl.DOCUMENTTABLE))
507
        {
508 5014 daigle
          logReplication.info("ReplicationHandler.handleSingleDataFile - " + DOCINSERTNUMBER + " Wrote data file" + accNumber +
509 2725 tao
                                       " into "+tableName + " from " +
510
                                           remoteserver);
511
          DOCINSERTNUMBER++;
512
        }
513
        else
514
        {
515 5014 daigle
            logReplication.info("ReplicationHandler.handleSingleDataFile - " + REVINSERTNUMBER + " Wrote data file" + accNumber +
516 2725 tao
                    " into "+tableName + " from " +
517
                        remoteserver);
518
            REVINSERTNUMBER++;
519
        }
520 3234 tao
        String ip = getIpFromURL(u);
521 5014 daigle
        EventLog.getInstance().log(ip, ReplicationService.REPLICATIONUSER, accNumber, actions);
522 2725 tao
523 1585 tao
      }//if
524
      else
525 1217 tao
      {
526 5014 daigle
         logReplication.info("ReplicationHandler.handleSingleDataFile - Couldn't open the data file: " + accNumber);
527
         throw new HandlerException("ReplicationHandler.handleSingleDataFile - Couldn't open the data file: " + accNumber);
528 1585 tao
      }//else
529 2286 tao
530
    }//try
531 1585 tao
    catch(Exception e)
532
    {
533 2725 tao
      /*MetacatReplication.replErrorLog("Failed to try wrote datafile " + accNumber +
534
                                      " because " +e.getMessage());*/
535
      if (tableName.equals(DocumentImpl.DOCUMENTTABLE))
536
      {
537 5014 daigle
    	logMetacat.error("ReplicationHandler.handleSingleDataFile - " + ReplicationService.METACAT_REPL_ERROR_MSG);
538
    	logReplication.error("ReplicationHandler.handleSingleDataFile - " + DOCERRORNUMBER + " Failed to write data file " + accNumber +
539
                                     " into " + tableName + " from " +
540
                                         remoteserver + " because " + e.getMessage());
541 2725 tao
        DOCERRORNUMBER++;
542
      }
543
      else
544
      {
545 5014 daigle
    	  logMetacat.error("ReplicationHandler.handleSingleDataFile - " + ReplicationService.METACAT_REPL_ERROR_MSG);
546
    	  logReplication.error("ReplicationHandler.handleSingleDataFile - " + REVERRORNUMBER + " Failed to write data file" + accNumber +
547
                  " into " + tableName + " from " +
548
                      remoteserver +" because "+ e.getMessage());
549 2725 tao
          REVERRORNUMBER++;
550
      }
551 5014 daigle
      logMetacat.error("ReplicationHandler.handleSingleDataFile - " + ReplicationService.METACAT_REPL_ERROR_MSG);
552
      logReplication.error("ReplicationHandler.handleSingleDataFile - Failed to try wrote datafile " + accNumber +
553
                                      " because " + e.getMessage());
554
      throw new HandlerException("ReplicationHandler.handleSingleDataFile - generic exception "
555
    		  + "writing Replication: " + e.getMessage());
556 1585 tao
    }
557
    finally
558
    {
559
       //return DBConnection
560
       DBConnectionPool.returnDBConnection(dbConn, serialNumber);
561
    }//finally
562
  }
563 2286 tao
564
565
566 1585 tao
  /* Handle delete single document*/
567 2298 tao
  private void handleDeleteSingleDocument(String docId, String notifyServer)
568 5014 daigle
               throws HandlerException
569 1585 tao
  {
570 5014 daigle
    logReplication.info("ReplicationHandler.handleDeleteSingleDocument - Try delete doc: "+docId);
571 1585 tao
    DBConnection dbConn = null;
572
    int serialNumber = -1;
573
    try
574
    {
575
      // Get DBConnection from pool
576
      dbConn=DBConnectionPool.
577
                  getDBConnection("ReplicationHandler.handleDeleteSingleDoc");
578
      serialNumber=dbConn.getCheckOutSerialNumber();
579
      if(!alreadyDeleted(docId))
580 1217 tao
      {
581 2286 tao
582 1585 tao
         //because delete method docid should have rev number
583
         //so we just add one for it. This rev number is no sence.
584 4212 daigle
         String accnum=docId+PropertyService.getProperty("document.accNumSeparator")+"1";
585 1585 tao
         //System.out.println("accnum: "+accnum);
586 3230 tao
         DocumentImpl.delete(accnum, null, null, notifyServer);
587 5014 daigle
         logReplication.info("ReplicationHandler.handleDeleteSingleDocument - Successfully deleted doc " + docId);
588
         logReplication.info("ReplicationHandler.handleDeleteSingleDocument - Doc " + docId + " deleted");
589 3234 tao
         URL u = new URL("https://"+notifyServer);
590
         String ip = getIpFromURL(u);
591 5014 daigle
         EventLog.getInstance().log(ip, ReplicationService.REPLICATIONUSER, docId, "delete");
592 1585 tao
      }
593 2286 tao
594
    }//try
595 1585 tao
    catch(Exception e)
596
    {
597 5014 daigle
      logMetacat.error("ReplicationHandler.handleDeleteSingleDocument - " + ReplicationService.METACAT_REPL_ERROR_MSG);
598
      logReplication.error("ReplicationHandler.handleDeleteSingleDocument - Failed to delete doc " + docId +
599 2663 sgarg
                                 " in db because because " + e.getMessage());
600 5014 daigle
      throw new HandlerException("ReplicationHandler.handleDeleteSingleDocument - generic exception "
601
    		  + "when handling document: " + e.getMessage());
602 1585 tao
    }
603
    finally
604
    {
605
       //return DBConnection
606
       DBConnectionPool.returnDBConnection(dbConn, serialNumber);
607 1037 tao
    }//finally
608 1585 tao
  }
609 2286 tao
610 1585 tao
  /* Handle updateLastCheckTimForSingleServer*/
611 2286 tao
  private void updateLastCheckTimeForSingleServer(ReplicationServer repServer)
612 5014 daigle
                                                  throws HandlerException
613 590 berkley
  {
614 1585 tao
    String server = repServer.getServerName();
615 1217 tao
    DBConnection dbConn = null;
616
    int serialNumber = -1;
617
    PreparedStatement pstmt = null;
618 590 berkley
    try
619
    {
620 1585 tao
      // Get DBConnection from pool
621 1217 tao
      dbConn=DBConnectionPool.
622 1585 tao
             getDBConnection("ReplicationHandler.updateLastCheckTimeForServer");
623 1217 tao
      serialNumber=dbConn.getCheckOutSerialNumber();
624 2286 tao
625 5014 daigle
      logReplication.info("ReplicationHandler.updateLastCheckTimeForSingleServer - Try to update last_check for server: "+server);
626 1585 tao
      // Get time from remote server
627
      URL dateurl = new URL("https://" + server + "?server="+
628 4698 daigle
      MetacatUtil.getLocalReplicationServerName()+"&action=gettime");
629 5014 daigle
      String datexml = ReplicationService.getURLContent(dateurl);
630
      logReplication.info("ReplicationHandler.updateLastCheckTimeForSingleServer - datexml: "+datexml);
631 1585 tao
      if (datexml!=null && !datexml.equals(""))
632
      {
633
         String datestr = datexml.substring(11, datexml.indexOf('<', 11));
634
         StringBuffer sql = new StringBuffer();
635 1751 tao
         /*sql.append("update xml_replication set last_checked = to_date('");
636 1585 tao
         sql.append(datestr).append("', 'YY-MM-DD HH24:MI:SS') where ");
637 1751 tao
         sql.append("server like '").append(server).append("'");*/
638
         sql.append("update xml_replication set last_checked = ");
639 4335 daigle
         sql.append(DatabaseService.getDBAdapter().toDate(datestr, "MM/DD/YY HH24:MI:SS"));
640 1751 tao
         sql.append(" where server like '").append(server).append("'");
641 1585 tao
         pstmt = dbConn.prepareStatement(sql.toString());
642 2286 tao
643 1585 tao
         pstmt.executeUpdate();
644
         dbConn.commit();
645
         pstmt.close();
646 5014 daigle
         logReplication.info("ReplicationHandler.updateLastCheckTimeForSingleServer - last_checked updated to "+datestr+" on "
647 2663 sgarg
                                      + server);
648 1585 tao
      }//if
649
      else
650
      {
651 2286 tao
652 5014 daigle
         logReplication.info("ReplicationHandler.updateLastCheckTimeForSingleServer - Failed to update last_checked for server "  +
653 2286 tao
                                  server + " in db because couldn't get time "
654 2663 sgarg
                                  );
655 1585 tao
         throw new Exception("Couldn't get time for server "+ server);
656
      }
657 2286 tao
658
    }//try
659 1585 tao
    catch(Exception e)
660
    {
661 5014 daigle
      logMetacat.error("ReplicationHandler.updateLastCheckTimeForSingleServer - " + ReplicationService.METACAT_REPL_ERROR_MSG);
662
      logReplication.error("ReplicationHandler.updateLastCheckTimeForSingleServer - Failed to update last_checked for server " +
663
                                server + " in db because because " + e.getMessage());
664
      throw new HandlerException("ReplicationHandler.updateLastCheckTimeForSingleServer - "
665
    		  + "Error updating last checked time: " + e.getMessage());
666 1585 tao
    }
667
    finally
668
    {
669
       //return DBConnection
670
       DBConnectionPool.returnDBConnection(dbConn, serialNumber);
671
    }//finally
672
  }
673 2286 tao
674
675
676 1585 tao
  /**
677
   * updates xml_catalog with entries from other servers.
678
   */
679
  private void updateCatalog()
680
  {
681 5014 daigle
    logReplication.info("ReplicationHandler.updateCatalog - Start of updateCatalog");
682 1585 tao
    // ReplicationServer object in server list
683
    ReplicationServer replServer = null;
684
    PreparedStatement pstmt = null;
685
    String server = null;
686 2286 tao
687
688 1585 tao
    // Go through each ReplicationServer object in sererlist
689
    for (int j=0; j<serverList.size(); j++)
690 2286 tao
    {
691 5014 daigle
      Vector<Vector<String>> remoteCatalog = new Vector<Vector<String>>();
692
      Vector<String> publicId = new Vector<String>();
693 1585 tao
      try
694
      {
695 1292 tao
        // Get ReplicationServer object from server list
696
        replServer = serverList.serverAt(j);
697
        // Get server name from the ReplicationServer object
698
        server = replServer.getServerName();
699
        // Try to get catalog
700 1011 tao
        URL u = new URL("https://" + server + "?server="+
701 4698 daigle
        MetacatUtil.getLocalReplicationServerName()+"&action=getcatalog");
702 5014 daigle
        logReplication.info("ReplicationHandler.updateCatalog - sending message " + u.toString());
703
        String catxml = ReplicationService.getURLContent(u);
704 2286 tao
705 1292 tao
        // Make sure there are not error, no empty string
706
        if (catxml.indexOf("error")!=-1 || catxml==null||catxml.equals(""))
707
        {
708 1585 tao
          throw new Exception("Couldn't get catalog list form server " +server);
709 1292 tao
        }
710 5014 daigle
        logReplication.info("ReplicationHandler.updateCatalog - catxml: " + catxml);
711 590 berkley
        CatalogMessageHandler cmh = new CatalogMessageHandler();
712
        XMLReader catparser = initParser(cmh);
713
        catparser.parse(new InputSource(new StringReader(catxml)));
714
        //parse the returned catalog xml and put it into a vector
715 1585 tao
        remoteCatalog = cmh.getCatalogVect();
716 2286 tao
717 1292 tao
        // Makse sure remoteCatalog is not empty
718
        if (remoteCatalog.isEmpty())
719
        {
720 1585 tao
          throw new Exception("Couldn't get catalog list form server " +server);
721 1292 tao
        }
722 2286 tao
723 5014 daigle
        String localcatxml = ReplicationService.getCatalogXML();
724 2286 tao
725 1292 tao
        // Make sure local catalog is no empty
726
        if (localcatxml==null||localcatxml.equals(""))
727
        {
728 1585 tao
          throw new Exception("Couldn't get catalog list form server " +server);
729 1292 tao
        }
730 2286 tao
731 590 berkley
        cmh = new CatalogMessageHandler();
732
        catparser = initParser(cmh);
733
        catparser.parse(new InputSource(new StringReader(localcatxml)));
734 5014 daigle
        Vector<Vector<String>> localCatalog = cmh.getCatalogVect();
735 2286 tao
736 590 berkley
        //now we have the catalog from the remote server and this local server
737
        //we now need to compare the two and merge the differences.
738
        //the comparison is base on the public_id fields which is the 4th
739
        //entry in each row vector.
740 5014 daigle
        publicId = new Vector<String>();
741 590 berkley
        for(int i=0; i<localCatalog.size(); i++)
742
        {
743 5014 daigle
          Vector<String> v = new Vector<String>(localCatalog.elementAt(i));
744
          logReplication.info("ReplicationHandler.updateCatalog - v1: " + v.toString());
745 590 berkley
          publicId.add(new String((String)v.elementAt(3)));
746 595 berkley
          //System.out.println("adding " + (String)v.elementAt(3));
747 590 berkley
        }
748 1585 tao
      }//try
749
      catch (Exception e)
750
      {
751 5014 daigle
        logMetacat.error("ReplicationHandler.updateCatalog - " + ReplicationService.METACAT_REPL_ERROR_MSG);
752
        logReplication.error("ReplicationHandler.updateCatalog - Failed to update catalog for server "+
753 1585 tao
                                    server + " because " +e.getMessage());
754
      }//catch
755 2286 tao
756 1585 tao
      for(int i=0; i<remoteCatalog.size(); i++)
757
      {
758
         // DConnection
759
        DBConnection dbConn = null;
760
        // DBConnection checkout serial number
761
        int serialNumber = -1;
762
        try
763 590 berkley
        {
764 1585 tao
            dbConn=DBConnectionPool.
765
                  getDBConnection("ReplicationHandler.updateCatalog");
766
            serialNumber=dbConn.getCheckOutSerialNumber();
767 5014 daigle
            Vector<String> v = remoteCatalog.elementAt(i);
768 1585 tao
            //System.out.println("v2: " + v.toString());
769
            //System.out.println("i: " + i);
770
            //System.out.println("remoteCatalog.size(): " + remoteCatalog.size());
771
            //System.out.println("publicID: " + publicId.toString());
772 5014 daigle
            logReplication.info
773
                              ("ReplicationHandler.updateCatalog - v.elementAt(3): " + (String)v.elementAt(3));
774 1585 tao
           if(!publicId.contains(v.elementAt(3)))
775
           { //so we don't have this public id in our local table so we need to
776
             //add it.
777
             //System.out.println("in if");
778
             StringBuffer sql = new StringBuffer();
779
             sql.append("insert into xml_catalog (entry_type, source_doctype, ");
780
             sql.append("target_doctype, public_id, system_id) values (?,?,?,");
781
             sql.append("?,?)");
782
             //System.out.println("sql: " + sql.toString());
783
             pstmt = dbConn.prepareStatement(sql.toString());
784
             pstmt.setString(1, (String)v.elementAt(0));
785
             pstmt.setString(2, (String)v.elementAt(1));
786
             pstmt.setString(3, (String)v.elementAt(2));
787
             pstmt.setString(4, (String)v.elementAt(3));
788
             pstmt.setString(5, (String)v.elementAt(4));
789
             pstmt.execute();
790
             pstmt.close();
791 5014 daigle
             logReplication.info("ReplicationHandler.updateCatalog - Success fully to insert new publicid "+
792 1585 tao
                               (String)v.elementAt(3) + " from server"+server);
793
           }
794 590 berkley
        }
795 1585 tao
        catch(Exception e)
796
        {
797 5014 daigle
           logMetacat.error("ReplicationHandler.updateCatalog - " + ReplicationService.METACAT_REPL_ERROR_MSG);
798
           logReplication.error("ReplicationHandler.updateCatalog - Failed to update catalog for server "+
799 1585 tao
                                    server + " because " +e.getMessage());
800
        }//catch
801
        finally
802
        {
803
           DBConnectionPool.returnDBConnection(dbConn, serialNumber);
804
        }//finall
805
      }//for remote catalog
806
    }//for server list
807 5014 daigle
    logReplication.info("End of updateCatalog");
808 590 berkley
  }
809 2286 tao
810 590 berkley
  /**
811 579 berkley
   * Method that returns true if docid has already been "deleted" from metacat.
812 582 berkley
   * This method really implements a truth table for deleted documents
813 590 berkley
   * The table is (a docid in one of the tables is represented by the X):
814 582 berkley
   * xml_docs      xml_revs      deleted?
815
   * ------------------------------------
816
   *   X             X             FALSE
817
   *   X             _             FALSE
818
   *   _             X             TRUE
819
   *   _             _             TRUE
820 579 berkley
   */
821 5014 daigle
  private static boolean alreadyDeleted(String docid) throws HandlerException
822 579 berkley
  {
823 1217 tao
    DBConnection dbConn = null;
824
    int serialNumber = -1;
825
    PreparedStatement pstmt = null;
826 579 berkley
    try
827
    {
828 1217 tao
      dbConn=DBConnectionPool.
829
                  getDBConnection("ReplicationHandler.alreadyDeleted");
830
      serialNumber=dbConn.getCheckOutSerialNumber();
831 582 berkley
      boolean xml_docs = false;
832
      boolean xml_revs = false;
833 2286 tao
834 579 berkley
      StringBuffer sb = new StringBuffer();
835 582 berkley
      sb.append("select docid from xml_revisions where docid like '");
836 579 berkley
      sb.append(docid).append("'");
837 1217 tao
      pstmt = dbConn.prepareStatement(sb.toString());
838 579 berkley
      pstmt.execute();
839
      ResultSet rs = pstmt.getResultSet();
840
      boolean tablehasrows = rs.next();
841
      if(tablehasrows)
842
      {
843 582 berkley
        xml_revs = true;
844
      }
845 2286 tao
846 582 berkley
      sb = new StringBuffer();
847
      sb.append("select docid from xml_documents where docid like '");
848
      sb.append(docid).append("'");
849 667 berkley
      pstmt.close();
850 1217 tao
      pstmt = dbConn.prepareStatement(sb.toString());
851
      //increase usage count
852
      dbConn.increaseUsageCount(1);
853 582 berkley
      pstmt.execute();
854
      rs = pstmt.getResultSet();
855
      tablehasrows = rs.next();
856 667 berkley
      pstmt.close();
857 582 berkley
      if(tablehasrows)
858
      {
859
        xml_docs = true;
860
      }
861 2286 tao
862 582 berkley
      if(xml_docs && xml_revs)
863
      {
864
        return false;
865
      }
866
      else if(xml_docs && !xml_revs)
867
      {
868
        return false;
869
      }
870
      else if(!xml_docs && xml_revs)
871
      {
872 579 berkley
        return true;
873
      }
874 582 berkley
      else if(!xml_docs && !xml_revs)
875
      {
876
        return true;
877
      }
878 579 berkley
    }
879
    catch(Exception e)
880
    {
881 5014 daigle
      logMetacat.error("ReplicationHandler.alreadyDeleted - " + ReplicationService.METACAT_REPL_ERROR_MSG);
882
      logReplication.error("ReplicationHandler.alreadyDeleted - general error in alreadyDeleted: " +
883 2663 sgarg
                          e.getMessage());
884 5014 daigle
      throw new HandlerException("ReplicationHandler.alreadyDeleted - general error: "
885
    		  + e.getMessage());
886 579 berkley
    }
887 667 berkley
    finally
888
    {
889 1217 tao
      try
890
      {
891
        pstmt.close();
892
      }//try
893
      catch (SQLException ee)
894
      {
895 5014 daigle
    	logMetacat.error("ReplicationHandler.alreadyDeleted - " + ReplicationService.METACAT_REPL_ERROR_MSG);
896
        logReplication.error("ReplicationHandler.alreadyDeleted - Error in replicationHandler.alreadyDeleted "+
897 2663 sgarg
                          "to close pstmt: "+ee.getMessage());
898 5014 daigle
        throw new HandlerException("ReplicationHandler.alreadyDeleted - SQL error when closing prepared statement: "
899
      		  + ee.getMessage());
900 1217 tao
      }//catch
901
      finally
902
      {
903
        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
904
      }//finally
905
    }//finally
906 579 berkley
    return false;
907
  }
908 533 berkley
909 2286 tao
910 533 berkley
  /**
911 574 berkley
   * Method to initialize the message parser
912
   */
913
  public static XMLReader initParser(DefaultHandler dh)
914 5014 daigle
          throws HandlerException
915 574 berkley
  {
916
    XMLReader parser = null;
917
918
    try {
919
      ContentHandler chandler = dh;
920
921
      // Get an instance of the parser
922 4213 daigle
      String parserName = PropertyService.getProperty("xml.saxparser");
923 574 berkley
      parser = XMLReaderFactory.createXMLReader(parserName);
924
925
      // Turn off validation
926
      parser.setFeature("http://xml.org/sax/features/validation", false);
927 2286 tao
928 574 berkley
      parser.setContentHandler((ContentHandler)chandler);
929
      parser.setErrorHandler((ErrorHandler)chandler);
930
931 5014 daigle
    } catch (SAXException se) {
932
      throw new HandlerException("ReplicationHandler.initParser - Sax error when "
933
    		  + " initializing parser: " + se.getMessage());
934
    } catch (PropertyNotFoundException pnfe) {
935
        throw new HandlerException("ReplicationHandler.initParser - Property error when "
936
      		  + " getting parser name: " + pnfe.getMessage());
937
    }
938 574 berkley
939
    return parser;
940
  }
941 2286 tao
942 2555 tao
  /**
943 5014 daigle
	 * This method will combinate given time string(in short format) to current
944
	 * date. If the given time (e.g 10:00 AM) passed the current time (e.g 2:00
945
	 * PM Aug 21, 2005), then the time will set to second day, 10:00 AM Aug 22,
946
	 * 2005. If the given time (e.g 10:00 AM) haven't passed the current time
947
	 * (e.g 8:00 AM Aug 21, 2005) The time will set to be 10:00 AM Aug 21, 2005.
948
	 *
949
	 * @param givenTime
950
	 *            the format should be "10:00 AM " or "2:00 PM"
951
	 * @return
952
	 * @throws Exception
953
	 */
954
	public static Date combinateCurrentDateAndGivenTime(String givenTime) throws HandlerException
955 2555 tao
  {
956 5014 daigle
	  try {
957 2555 tao
     Date givenDate = parseTime(givenTime);
958
     Date newDate = null;
959
     Date now = new Date();
960
     String currentTimeString = getTimeString(now);
961
     Date currentTime = parseTime(currentTimeString);
962
     if ( currentTime.getTime() >= givenDate.getTime())
963
     {
964 5014 daigle
        logReplication.info("ReplicationHandler.combinateCurrentDateAndGivenTime - Today already pass the given time, we should set it as tomorrow");
965 2555 tao
        String dateAndTime = getDateString(now) + " " + givenTime;
966
        Date combinationDate = parseDateTime(dateAndTime);
967
        // new date should plus 24 hours to make is the second day
968
        newDate = new Date(combinationDate.getTime()+24*3600*1000);
969
     }
970
     else
971
     {
972 5014 daigle
         logReplication.info("ReplicationHandler.combinateCurrentDateAndGivenTime - Today haven't pass the given time, we should it as today");
973 2555 tao
         String dateAndTime = getDateString(now) + " " + givenTime;
974
         newDate = parseDateTime(dateAndTime);
975
     }
976 5014 daigle
     logReplication.warn("ReplicationHandler.combinateCurrentDateAndGivenTime - final setting time is "+ newDate.toString());
977 2555 tao
     return newDate;
978 5014 daigle
	  } catch (ParseException pe) {
979
		  throw new HandlerException("ReplicationHandler.combinateCurrentDateAndGivenTime - "
980
				  + "parsing error: "  + pe.getMessage());
981
	  }
982 2555 tao
  }
983 2286 tao
984 2555 tao
  /*
985 5014 daigle
	 * parse a given string to Time in short format. For example, given time is
986
	 * 10:00 AM, the date will be return as Jan 1 1970, 10:00 AM
987
	 */
988
  private static Date parseTime(String timeString) throws ParseException
989 2555 tao
  {
990
    DateFormat format = DateFormat.getTimeInstance(DateFormat.SHORT);
991
    Date time = format.parse(timeString);
992 5014 daigle
    logReplication.info("ReplicationHandler.parseTime - Date string is after parse a time string "
993 2663 sgarg
                              +time.toString());
994 2555 tao
    return time;
995
996
  }
997
998
  /*
999
   * Pasre a given string to date and time. Date format is long and time
1000
   * format is short.
1001
   */
1002 5014 daigle
  private static Date parseDateTime(String timeString) throws ParseException
1003 2555 tao
  {
1004
    DateFormat format = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.SHORT);
1005
    Date time = format.parse(timeString);
1006 5014 daigle
    logReplication.info("ReplicationHandler.parseDateTime - Date string is after parse a time string "+
1007 2663 sgarg
                             time.toString());
1008 2555 tao
    return time;
1009
  }
1010
1011
  /*
1012
   * Get a date string from a Date object. The date format will be long
1013
   */
1014
  private static String getDateString(Date now)
1015
  {
1016
     DateFormat df = DateFormat.getDateInstance(DateFormat.LONG);
1017
     String s = df.format(now);
1018 5014 daigle
     logReplication.info("ReplicationHandler.getDateString - Today is " + s);
1019 2555 tao
     return s;
1020
  }
1021
1022
  /*
1023
   * Get a time string from a Date object, the time format will be short
1024
   */
1025
  private static String getTimeString(Date now)
1026
  {
1027
     DateFormat df = DateFormat.getTimeInstance(DateFormat.SHORT);
1028
     String s = df.format(now);
1029 5014 daigle
     logReplication.info("ReplicationHandler.getTimeString - Time is " + s);
1030 2555 tao
     return s;
1031
  }
1032 2608 tao
1033
1034
  /*
1035 4080 daigle
	 * This method will go through the docid list both in xml_Documents table
1036
	 * and in xml_revisions table @author tao
1037
	 */
1038 5014 daigle
	private void handleDocList(Vector<Vector<String>> docList, String tableName) {
1039 4080 daigle
		boolean dataFile = false;
1040
		for (int j = 0; j < docList.size(); j++) {
1041
			// initial dataFile is false
1042
			dataFile = false;
1043
			// w is information for one document, information contain
1044
			// docid, rev, server or datafile.
1045 5014 daigle
			Vector<String> w = new Vector<String>(docList.elementAt(j));
1046 4080 daigle
			// Check if the vector w contain "datafile"
1047
			// If it has, this document is data file
1048
			try {
1049 4173 daigle
				if (w.contains((String) PropertyService.getProperty("replication.datafileflag"))) {
1050 4080 daigle
					dataFile = true;
1051
				}
1052
			} catch (PropertyNotFoundException pnfe) {
1053 5014 daigle
				logMetacat.error("ReplicationHandler.handleDocList - " + ReplicationService.METACAT_REPL_ERROR_MSG);
1054
				logReplication.error("ReplicationHandler.handleDocList - Could not retrieve data file flag property.  "
1055 4080 daigle
						+ "Leaving as false: " + pnfe.getMessage());
1056
			}
1057
			// System.out.println("w: " + w.toString());
1058
			// Get docid
1059
			String docid = (String) w.elementAt(0);
1060 5014 daigle
			logReplication.info("docid: " + docid);
1061 4080 daigle
			// Get revision number
1062
			int rev = Integer.parseInt((String) w.elementAt(1));
1063 5014 daigle
			logReplication.info("rev: " + rev);
1064 4080 daigle
			// Get remote server name (it is may not be doc homeserver because
1065
			// the new hub feature
1066
			String remoteServer = (String) w.elementAt(2);
1067
			remoteServer = remoteServer.trim();
1068 2608 tao
1069 4080 daigle
			try {
1070
				if (tableName.equals(DocumentImpl.DOCUMENTTABLE)) {
1071
					handleDocInXMLDocuments(docid, rev, remoteServer, dataFile);
1072
				} else if (tableName.equals(DocumentImpl.REVISIONTABLE)) {
1073
					handleDocInXMLRevisions(docid, rev, remoteServer, dataFile);
1074
				} else {
1075
					continue;
1076
				}
1077 2608 tao
1078 4861 daigle
			} catch (Exception e) {
1079 5014 daigle
				logMetacat.error("ReplicationHandler.handleDocList - " + ReplicationService.METACAT_REPL_ERROR_MSG);
1080
				logReplication.error("ReplicationHandler.handleDocList - error to handle update doc in " + tableName
1081 4861 daigle
						+ " in time replication" + e.getMessage());
1082 4080 daigle
				continue;
1083
			}
1084
1085
		}// for update docs
1086
1087
	}
1088 2608 tao
1089
   /*
1090 4080 daigle
	 * This method will handle doc in xml_documents table.
1091
	 */
1092 2608 tao
   private void handleDocInXMLDocuments(String docid, int rev, String remoteServer, boolean dataFile)
1093 5014 daigle
                                        throws HandlerException
1094 2608 tao
   {
1095
       // compare the update rev and local rev to see what need happen
1096
       int localrev = -1;
1097
       String action = null;
1098
       boolean flag = false;
1099
       try
1100
       {
1101 2641 tao
         localrev = DBUtil.getLatestRevisionInDocumentTable(docid);
1102 2608 tao
       }
1103
       catch (SQLException e)
1104
       {
1105 5014 daigle
    	 logMetacat.error("ReplicationHandler.handleDocInXMLDocuments - " + ReplicationService.METACAT_REPL_ERROR_MSG);
1106
         logReplication.error("ReplicationHandler.handleDocInXMLDocuments - Local rev for docid "+ docid + " could not "+
1107 2663 sgarg
                                " be found because " + e.getMessage());
1108 5014 daigle
         logReplication.error("ReplicationHandler.handleDocInXMLDocuments - " + DOCERRORNUMBER+"Docid "+ docid + " could not be "+
1109 2608 tao
                 "written because error happend to find it's local revision");
1110 2739 tao
         DOCERRORNUMBER++;
1111 5014 daigle
         throw new HandlerException ("ReplicationHandler.handleDocInXMLDocuments - Local rev for docid "+ docid + " could not "+
1112
                 " be found: " + e.getMessage());
1113 2608 tao
       }
1114 5014 daigle
       logReplication.info("ReplicationHandler.handleDocInXMLDocuments - Local rev for docid "+ docid + " is "+
1115 2663 sgarg
                               localrev);
1116 2608 tao
1117
       //check the revs for an update because this document is in the
1118
       //local DB, it might be out of date.
1119
       if (localrev == -1)
1120
       {
1121 2713 tao
          // check if the revision is in the revision table
1122 5014 daigle
    	   Vector<Integer> localRevVector = null;
1123
    	 try {
1124
    		 localRevVector = DBUtil.getRevListFromRevisionTable(docid);
1125
    	 } catch (SQLException sqle) {
1126
    		 throw new HandlerException("ReplicationHandler.handleDocInXMLDocuments - SQL error "
1127
    				 + " when getting rev list for docid: " + docid + " : " + sqle.getMessage());
1128
    	 }
1129 2713 tao
         if (localRevVector != null && localRevVector.contains(new Integer(rev)))
1130
         {
1131
             // this version was deleted, so don't need replicate
1132
             flag = false;
1133
         }
1134
         else
1135
         {
1136
           //insert this document as new because it is not in the local DB
1137
           action = "INSERT";
1138
           flag = true;
1139
         }
1140 2608 tao
       }
1141
       else
1142
       {
1143
         if(localrev == rev)
1144
         {
1145
           // Local meatacat has the same rev to remote host, don't need
1146
           // update and flag set false
1147
           flag = false;
1148
         }
1149
         else if(localrev < rev)
1150
         {
1151
           //this document needs to be updated so send an read request
1152
           action = "UPDATE";
1153
           flag = true;
1154
         }
1155
       }
1156 2641 tao
1157 5014 daigle
       String accNumber = null;
1158
       try {
1159
    	   accNumber = docid + PropertyService.getProperty("document.accNumSeparator") + rev;
1160
       } catch (PropertyNotFoundException pnfe) {
1161
    	   throw new HandlerException("ReplicationHandler.handleDocInXMLDocuments - error getting "
1162
    			   + "account number separator : " + pnfe.getMessage());
1163
       }
1164 2608 tao
       // this is non-data file
1165
       if(flag && !dataFile)
1166
       {
1167
         try
1168
         {
1169 2641 tao
           handleSingleXMLDocument(remoteServer, action, accNumber, DocumentImpl.DOCUMENTTABLE);
1170 2608 tao
         }
1171 5014 daigle
         catch(HandlerException he)
1172 2608 tao
         {
1173
           // skip this document
1174 5014 daigle
           throw he;
1175 2608 tao
         }
1176
       }//if for non-data file
1177
1178
        // this is for data file
1179
       if(flag && dataFile)
1180
       {
1181
         try
1182
         {
1183 2641 tao
           handleSingleDataFile(remoteServer, action, accNumber, DocumentImpl.DOCUMENTTABLE);
1184 2608 tao
         }
1185 5014 daigle
         catch(HandlerException he)
1186 2608 tao
         {
1187
           // skip this datafile
1188 5014 daigle
           throw he;
1189 2608 tao
         }
1190
1191
       }//for datafile
1192
   }
1193
1194
   /*
1195
    * This method will handle doc in xml_documents table.
1196
    */
1197
   private void handleDocInXMLRevisions(String docid, int rev, String remoteServer, boolean dataFile)
1198 5014 daigle
                                        throws HandlerException
1199 2608 tao
   {
1200
       // compare the update rev and local rev to see what need happen
1201 5014 daigle
       logReplication.info("ReplicationHandler.handleDocInXMLRevisions - In handle repliation revsion table");
1202
       logReplication.info("ReplicationHandler.handleDocInXMLRevisions - the docid is "+ docid);
1203
       logReplication.info("ReplicationHandler.handleDocInXMLRevisions - The rev is "+rev);
1204
       Vector<Integer> localrev = null;
1205 2608 tao
       String action = "INSERT";
1206
       boolean flag = false;
1207
       try
1208
       {
1209
         localrev = DBUtil.getRevListFromRevisionTable(docid);
1210
       }
1211 5014 daigle
       catch (SQLException sqle)
1212 2608 tao
       {
1213 5014 daigle
    	 logMetacat.error("ReplicationHandler.handleDocInXMLDocuments - " + ReplicationService.METACAT_REPL_ERROR_MSG);
1214
         logReplication.error("ReplicationHandler.handleDocInXMLRevisions - Local rev for docid "+ docid + " could not "+
1215
                                " be found because " + sqle.getMessage());
1216 2739 tao
         REVERRORNUMBER++;
1217 5014 daigle
         throw new HandlerException ("ReplicationHandler.handleDocInXMLRevisions - SQL exception getting rev list: "
1218
        		 + sqle.getMessage());
1219 2608 tao
       }
1220 5014 daigle
       logReplication.info("ReplicationHandler.handleDocInXMLRevisions - rev list in xml_revision table for docid "+ docid + " is "+
1221 2663 sgarg
                               localrev.toString());
1222 2608 tao
1223
       // if the rev is not in the xml_revision, we need insert it
1224
       if (!localrev.contains(new Integer(rev)))
1225
       {
1226
           flag = true;
1227
       }
1228 2641 tao
1229 5014 daigle
       String accNumber = null;
1230
       try {
1231
    	   accNumber = docid + PropertyService.getProperty("document.accNumSeparator") + rev;
1232
       } catch (PropertyNotFoundException pnfe) {
1233
    	   throw new HandlerException("ReplicationHandler.handleDocInXMLRevisions - error getting "
1234
    			   + "account number separator : " + pnfe.getMessage());
1235
       }
1236 2608 tao
       // this is non-data file
1237
       if(flag && !dataFile)
1238
       {
1239
         try
1240
         {
1241 2641 tao
1242
           handleSingleXMLDocument(remoteServer, action, accNumber, DocumentImpl.REVISIONTABLE);
1243 2608 tao
         }
1244 5014 daigle
         catch(HandlerException he)
1245 2608 tao
         {
1246
           // skip this document
1247 5014 daigle
           throw he;
1248 2608 tao
         }
1249
       }//if for non-data file
1250
1251
        // this is for data file
1252
       if(flag && dataFile)
1253
       {
1254
         try
1255
         {
1256 2641 tao
           handleSingleDataFile(remoteServer, action, accNumber, DocumentImpl.REVISIONTABLE);
1257 2608 tao
         }
1258 5014 daigle
         catch(HandlerException he)
1259 2608 tao
         {
1260
           // skip this datafile
1261 5014 daigle
           throw he;
1262 2608 tao
         }
1263
1264
       }//for datafile
1265
   }
1266 3234 tao
1267
   /*
1268
    * Return a ip address for given url
1269
    */
1270
   private String getIpFromURL(URL url)
1271
   {
1272
	   String ip = null;
1273
	   try
1274
	   {
1275
	      InetAddress address = InetAddress.getByName(url.getHost());
1276
	      ip = address.getHostAddress();
1277
	   }
1278
	   catch(UnknownHostException e)
1279
	   {
1280 5014 daigle
		   logMetacat.error("ReplicationHandler.getIpFromURL - " + ReplicationService.METACAT_REPL_ERROR_MSG);
1281
		   logReplication.error("ReplicationHandler.getIpFromURL - Error in get ip address for host: "
1282 3234 tao
                   +e.getMessage());
1283
	   }
1284
1285
	   return ip;
1286
   }
1287 2608 tao
1288 522 berkley
}