Project

General

Profile

1
/**
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: daigle $'
9
 *     '$Date: 2009-08-24 14:34:17 -0700 (Mon, 24 Aug 2009) $'
10
 * '$Revision: 5030 $'
11
 *
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
 */
26

    
27
package edu.ucsb.nceas.metacat.replication;
28

    
29
import edu.ucsb.nceas.metacat.AccessControlForSingleFile;
30
import edu.ucsb.nceas.metacat.CatalogMessageHandler;
31
import edu.ucsb.nceas.metacat.DBUtil;
32
import edu.ucsb.nceas.metacat.DocInfoHandler;
33
import edu.ucsb.nceas.metacat.DocumentImpl;
34
import edu.ucsb.nceas.metacat.DocumentImplWrapper;
35
import edu.ucsb.nceas.metacat.EventLog;
36
import edu.ucsb.nceas.metacat.database.DBConnection;
37
import edu.ucsb.nceas.metacat.database.DBConnectionPool;
38
import edu.ucsb.nceas.metacat.database.DatabaseService;
39
import edu.ucsb.nceas.metacat.properties.PropertyService;
40
import edu.ucsb.nceas.metacat.shared.HandlerException;
41
import edu.ucsb.nceas.metacat.util.MetacatUtil;
42
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
43

    
44
import java.sql.*;
45
import java.util.*;
46
import java.util.Date;
47
import java.io.*;
48
import java.net.*;
49
import java.text.*;
50

    
51
import org.apache.log4j.Logger;
52
import org.xml.sax.ContentHandler;
53
import org.xml.sax.ErrorHandler;
54
import org.xml.sax.InputSource;
55
import org.xml.sax.SAXException;
56
import org.xml.sax.XMLReader;
57
import org.xml.sax.helpers.XMLReaderFactory;
58
import org.xml.sax.helpers.DefaultHandler;
59

    
60

    
61

    
62
/**
63
 * This class handles deltaT replication checking.  Whenever this TimerTask
64
 * is fired it checks each server in xml_replication for updates and updates
65
 * the local db as needed.
66
 */
67
public class ReplicationHandler extends TimerTask
68
{
69
  int serverCheckCode = 1;
70
  ReplicationServerList serverList = null;
71
  //PrintWriter out;
72
//  private static final AbstractDatabase dbAdapter = MetacatUtil.dbAdapter;
73
  private static Logger logReplication = Logger.getLogger("ReplicationLogging");
74
  private static Logger logMetacat = Logger.getLogger(ReplicationHandler.class);
75
  private static int DOCINSERTNUMBER = 1;
76
  private static int DOCERRORNUMBER  = 1;
77
  private static int REVINSERTNUMBER = 1;
78
  private static int REVERRORNUMBER  = 1;
79
  public ReplicationHandler()
80
  {
81
    //this.out = o;
82
    serverList = new ReplicationServerList();
83
  }
84

    
85
  public ReplicationHandler(int serverCheckCode)
86
  {
87
    //this.out = o;
88
    this.serverCheckCode = serverCheckCode;
89
    serverList = new ReplicationServerList();
90
  }
91

    
92
  /**
93
   * Method that implements TimerTask.run().  It runs whenever the timer is
94
   * fired.
95
   */
96
  public void run()
97
  {
98
    //find out the last_checked time of each server in the server list and
99
    //send a query to each server to see if there are any documents in
100
    //xml_documents with an update_date > last_checked
101
	  
102
      //if serverList is null, metacat don't need to replication
103
      if (serverList==null||serverList.isEmpty())
104
      {
105
        return;
106
      }
107
      updateCatalog();
108
      update();
109
      //conn.close();
110
  }
111

    
112
  /**
113
   * Method that uses revision taging for replication instead of update_date.
114
   */
115
  private void update()
116
  {
117
    /*
118
     Pseudo-algorithm
119
     - request a doc list from each server in xml_replication
120
     - check the rev number of each of those documents agains the
121
       documents in the local database
122
     - pull any documents that have a lesser rev number on the local server
123
       from the remote server
124
     - delete any documents that still exist in the local xml_documents but
125
       are in the deletedDocuments tag of the remote host response.
126
     - update last_checked to keep track of the last time it was checked.
127
       (this info is theoretically not needed using this system but probably
128
       should be kept anyway)
129
    */
130

    
131
    ReplicationServer replServer = null; // Variable to store the
132
                                        // ReplicationServer got from
133
                                        // Server list
134
    String server = null; // Variable to store server name
135
//    String update;
136
    Vector<String> responses = new Vector<String>();
137
    URL u;
138

    
139

    
140
    
141
    //Check for every server in server list to get updated list and put
142
    // them in to response
143
    for (int i=0; i<serverList.size(); i++)
144
    {
145
        // Get ReplicationServer object from server list
146
        replServer = serverList.serverAt(i);
147
        // Get server name from ReplicationServer object
148
        server = replServer.getServerName().trim();
149
        String result = null;
150
        logReplication.info("ReplicationHandler.update - full update started to: " + server);
151
        // Send command to that server to get updated docid information
152
        try
153
        {
154
          u = new URL("https://" + server + "?server="
155
          +MetacatUtil.getLocalReplicationServerName()+"&action=update");
156
          logReplication.info("ReplicationHandler.update - Sending infomation " +u.toString());
157
          result = ReplicationService.getURLContent(u);
158
        }
159
        catch (Exception e)
160
        {
161
          logMetacat.error("ReplicationHandler.update - " + ReplicationService.METACAT_REPL_ERROR_MSG);
162
          logReplication.error( "ReplicationHandler.update - Failed to get updated doc list "+
163
                       "for server " + server + " because "+e.getMessage());
164
          continue;
165
        }
166

    
167
        logReplication.info("docid: "+server+" "+result);
168
        //check if result have error or not, if has skip it.
169
        if (result.indexOf("<error>")!=-1 && result.indexOf("</error>")!=-1)
170
        {
171
          logMetacat.error("ReplicationHandler.update - " + ReplicationService.METACAT_REPL_ERROR_MSG);
172
          logReplication.error( "ReplicationHandler.update - Failed to get updated doc list "+
173
                       "for server " + server + " because "+result);
174
          continue;
175
        }
176
        //Add result to vector
177
        responses.add(result);
178
    }
179

    
180
    //make sure that there is updated file list
181
    //If response is null, metacat don't need do anything
182
    if (responses==null || responses.isEmpty())
183
    {
184
    	logMetacat.error("ReplicationHandler.update - " + ReplicationService.METACAT_REPL_ERROR_MSG);
185
        logReplication.info( "ReplicationHandler.update - No updated doc list for "+
186
                           "every server and failed to replicate");
187
        return;
188
    }
189

    
190

    
191
    logReplication.info("ReplicationHandler.update - Responses from remote metacat about updated "+
192
                   "document information: "+ responses.toString());
193
    // go through response vector(it contains updated vector and delete vector
194
    for(int i=0; i<responses.size(); i++)
195
    {
196
    	XMLReader parser;
197
    	ReplMessageHandler message = new ReplMessageHandler();
198
    	try
199
        {
200
          parser = initParser(message);
201
        }
202
        catch (Exception e)
203
        {
204
          logMetacat.error("ReplicationHandler.update - " + ReplicationService.METACAT_REPL_ERROR_MSG);
205
          logReplication.error("ReplicationHandler.update - Failed to replicate becaue couldn't " +
206
                                " initParser for message and " +e.getMessage());
207
           // stop replication
208
           return;
209
        }
210
    	
211
        try
212
        {
213
          parser.parse(new InputSource(
214
                     new StringReader(
215
                     (String)(responses.elementAt(i)))));
216
        }
217
        catch(Exception e)
218
        {
219
          logMetacat.error("ReplicationHandler.update - " + ReplicationService.METACAT_REPL_ERROR_MSG);
220
          logReplication.error("ReplicationHandler.update - Couldn't parse one responses "+
221
                                   "because "+ e.getMessage());
222
          continue;
223
        }
224
        //v is the list of updated documents
225
        Vector<Vector<String>> updateList = new Vector<Vector<String>>(message.getUpdatesVect());
226
        logReplication.info("ReplicationHandler.update - The document list size is "+updateList.size()+ " from "+message.getServerName());
227
        //System.out.println("v: " + v.toString());
228
        //d is the list of deleted documents
229
        Vector<Vector<String>> deleteList = new Vector<Vector<String>>(message.getDeletesVect());
230
        //System.out.println("d: " + d.toString());
231
        logReplication.info("ReplicationHandler.update - Update vector size: "+ updateList.size()+" from "+message.getServerName());
232
        logReplication.info("ReplicationHandler.update - Delete vector size: "+ deleteList.size()+" from "+message.getServerName());
233
        logReplication.info("ReplicationHandler.update - The delete document list size is "+deleteList.size()+" from "+message.getServerName());
234
        // go though every element in updated document vector
235
        handleDocList(updateList, DocumentImpl.DOCUMENTTABLE);
236
        //handle deleted docs
237
        for(int k=0; k<deleteList.size(); k++)
238
        { //delete the deleted documents;
239
          Vector<String> w = new Vector<String>(deleteList.elementAt(k));
240
          String docId = (String)w.elementAt(0);
241
          try
242
          {
243
            handleDeleteSingleDocument(docId, server);
244
          }
245
          catch (Exception ee)
246
          {
247
            continue;
248
          }
249
        }//for delete docs
250
        
251
        // handle replicate doc in xml_revision
252
        Vector<Vector<String>> revisionList = new Vector<Vector<String>>(message.getRevisionsVect());
253
        logReplication.info("ReplicationHandler.update - The revision document list size is "+revisionList.size()+ " from "+message.getServerName());
254
        handleDocList(revisionList, DocumentImpl.REVISIONTABLE);
255
        DOCINSERTNUMBER = 1;
256
        DOCERRORNUMBER  = 1;
257
        REVINSERTNUMBER = 1;
258
        REVERRORNUMBER  = 1;
259
    }//for response
260

    
261
    //updated last_checked
262
    for (int i=0;i<serverList.size(); i++)
263
    {
264
       // Get ReplicationServer object from server list
265
       replServer = serverList.serverAt(i);
266
       try
267
       {
268
         updateLastCheckTimeForSingleServer(replServer);
269
       }
270
       catch(Exception e)
271
       {
272
         continue;
273
       }
274
    }//for
275

    
276
  }//update
277

    
278
  /* Handle replicate single xml document*/
279
  private void handleSingleXMLDocument(String remoteserver, String actions,
280
                                       String accNumber, String tableName)
281
               throws HandlerException
282
  {
283
    DBConnection dbConn = null;
284
    int serialNumber = -1;
285
    try
286
    {
287
      // Get DBConnection from pool
288
      dbConn=DBConnectionPool.
289
                  getDBConnection("ReplicationHandler.handleSingleXMLDocument");
290
      serialNumber=dbConn.getCheckOutSerialNumber();
291
      //if the document needs to be updated or inserted, this is executed
292
      String readDocURLString = "https://" + remoteserver + "?server="+
293
              MetacatUtil.getLocalReplicationServerName()+"&action=read&docid="+accNumber;
294
      readDocURLString = MetacatUtil.replaceWhiteSpaceForURL(readDocURLString);
295
      URL u = new URL(readDocURLString);
296

    
297
      // Get docid content
298
      String newxmldoc = ReplicationService.getURLContent(u);
299
      // If couldn't get skip it
300
      if ( newxmldoc.indexOf("<error>")!= -1 && newxmldoc.indexOf("</error>")!=-1)
301
      {
302
         throw new HandlerException("ReplicationHandler.handleSingleXMLDocument - " + newxmldoc);
303
      }
304
      //logReplication.info("xml documnet:");
305
      //logReplication.info(newxmldoc);
306

    
307
      // Try get the docid info from remote server
308
      DocInfoHandler dih = new DocInfoHandler();
309
      XMLReader docinfoParser = initParser(dih);
310
      String docInfoURLStr = "https://" + remoteserver +
311
                       "?server="+MetacatUtil.getLocalReplicationServerName()+
312
                       "&action=getdocumentinfo&docid="+accNumber;
313
      docInfoURLStr = MetacatUtil.replaceWhiteSpaceForURL(docInfoURLStr);
314
      URL docinfoUrl = new URL(docInfoURLStr);
315
      logReplication.info("ReplicationHandler.handleSingleXMLDocument - Sending message: " +
316
                                                  docinfoUrl.toString());
317
      String docInfoStr = ReplicationService.getURLContent(docinfoUrl);
318
      docinfoParser.parse(new InputSource(new StringReader(docInfoStr)));
319
      Hashtable<String, String> docinfoHash = dih.getDocInfo();
320
      // Get home server of the docid
321
      String docHomeServer = docinfoHash.get("home_server");
322
      logReplication.info("ReplicationHandler.handleSingleXMLDocument - doc home server in repl: "+docHomeServer);
323
      String createdDate = docinfoHash.get("date_created");
324
      String updatedDate = docinfoHash.get("date_updated");
325
      //docid should include rev number too
326
      /*String accnum=docId+util.getProperty("document.accNumSeparator")+
327
                                              (String)docinfoHash.get("rev");*/
328
      logReplication.info("ReplicationHandler.handleSingleXMLDocument - docid in repl: "+accNumber);
329
      String docType = docinfoHash.get("doctype");
330
      logReplication.info("ReplicationHandler.handleSingleXMLDocument - doctype in repl: "+docType);
331

    
332
      String parserBase = null;
333
      // this for eml2 and we need user eml2 parser
334
      if (docType != null && (docType.trim()).equals(DocumentImpl.EML2_0_0NAMESPACE))
335
      {
336
         parserBase = DocumentImpl.EML200;
337
      }
338
      else if (docType != null && (docType.trim()).equals(DocumentImpl.EML2_0_1NAMESPACE))
339
      {
340
        parserBase = DocumentImpl.EML200;
341
      }
342
      else if (docType != null && (docType.trim()).equals(DocumentImpl.EML2_1_0NAMESPACE))
343
      {
344
        parserBase = DocumentImpl.EML210;
345
      }
346
      // Write the document into local host
347
      DocumentImplWrapper wrapper = new DocumentImplWrapper(parserBase, false);
348
      String newDocid = wrapper.writeReplication(dbConn,
349
                              new StringReader(newxmldoc),
350
                              docinfoHash.get("public_access"),
351
                              null,  /* the dtd text */
352
                              actions,
353
                              accNumber,
354
                              docinfoHash.get("user_owner"),
355
                              null, /* null for groups[] */
356
                              docHomeServer,
357
                              remoteserver, tableName, true,// true is for time replication 
358
                              createdDate,
359
                              updatedDate);
360
      
361
      //process extra access rules
362
      Vector<AccessControlForSingleFile> accessControlList = dih.getAccessControlList();
363
      if (accessControlList != null) {
364
    	  for (AccessControlForSingleFile acfsf : accessControlList) {
365
        	  if (!acfsf.accessControlExists()) {
366
        		  acfsf.insertPermissions();
367
        	  }
368
          }
369
      }
370
      
371
      logReplication.info("ReplicationHandler.handleSingleXMLDocument - Successfully replicated doc " + accNumber);
372
      if (tableName.equals(DocumentImpl.DOCUMENTTABLE))
373
      {
374
        logReplication.info("ReplicationHandler.handleSingleXMLDocument - " + DOCINSERTNUMBER + " Wrote xml doc " + accNumber +
375
                                     " into "+tableName + " from " +
376
                                         remoteserver);
377
        DOCINSERTNUMBER++;
378
      }
379
      else
380
      {
381
          logReplication.info("ReplicationHandler.handleSingleXMLDocument - " +REVINSERTNUMBER + " Wrote xml doc " + accNumber +
382
                  " into "+tableName + " from " +
383
                      remoteserver);
384
          REVINSERTNUMBER++;
385
      }
386
      String ip = getIpFromURL(u);
387
      EventLog.getInstance().log(ip, ReplicationService.REPLICATIONUSER, accNumber, actions);
388
      
389

    
390
    }//try
391
    catch(Exception e)
392
    {
393
        
394
        if (tableName.equals(DocumentImpl.DOCUMENTTABLE))
395
        {
396
        	logMetacat.error("ReplicationHandler.handleSingleXMLDocument - " + ReplicationService.METACAT_REPL_ERROR_MSG); 
397
        	logReplication.error("ReplicationHandler.handleSingleXMLDocument - " +DOCERRORNUMBER + " Failed to write xml doc " + accNumber +
398
                                       " into "+tableName + " from " +
399
                                           remoteserver + " because "+e.getMessage());
400
          DOCERRORNUMBER++;
401
        }
402
        else
403
        {
404
        	logMetacat.error("ReplicationHandler.handleSingleXMLDocument - " + ReplicationService.METACAT_REPL_ERROR_MSG); 
405
        	logReplication.error("ReplicationHandler.handleSingleXMLDocument - " +REVERRORNUMBER + " Failed to write xml doc " + accNumber +
406
                    " into "+tableName + " from " +
407
                        remoteserver +" because "+e.getMessage());
408
            REVERRORNUMBER++;
409
        }
410
        logMetacat.error("ReplicationHandler.handleSingleXMLDocument - " + ReplicationService.METACAT_REPL_ERROR_MSG); 
411
        logReplication.error("ReplicationHandler.handleSingleXMLDocument - Failed to write doc " + accNumber +
412
                                      " into db because " +e.getMessage());
413
      throw new HandlerException("ReplicationHandler.handleSingleXMLDocument - generic exception " 
414
    		  + "writing Replication: " +e.getMessage());
415
    }
416
    finally
417
    {
418
       //return DBConnection
419
       DBConnectionPool.returnDBConnection(dbConn, serialNumber);
420
    }//finally
421
  }
422

    
423

    
424

    
425
  /* Handle replicate single xml document*/
426
  private void handleSingleDataFile(String remoteserver, String actions,
427
                                    String accNumber, String tableName)
428
               throws HandlerException
429
  {
430
    logReplication.info("ReplicationHandler.handleSingleDataFile - Try to replicate data file: " + accNumber);
431
    DBConnection dbConn = null;
432
    int serialNumber = -1;
433
    try
434
    {
435
      // Get DBConnection from pool
436
      dbConn=DBConnectionPool.
437
                  getDBConnection("ReplicationHandler.handleSinlgeDataFile");
438
      serialNumber=dbConn.getCheckOutSerialNumber();
439
      // Try get docid info from remote server
440
      DocInfoHandler dih = new DocInfoHandler();
441
      XMLReader docinfoParser = initParser(dih);
442
      String docInfoURLString = "https://" + remoteserver +
443
                  "?server="+MetacatUtil.getLocalReplicationServerName()+
444
                  "&action=getdocumentinfo&docid="+accNumber;
445
      docInfoURLString = MetacatUtil.replaceWhiteSpaceForURL(docInfoURLString);
446
      URL docinfoUrl = new URL(docInfoURLString);
447

    
448
      String docInfoStr = ReplicationService.getURLContent(docinfoUrl);
449
      docinfoParser.parse(new InputSource(new StringReader(docInfoStr)));
450
      Hashtable<String, String> docinfoHash = dih.getDocInfo();
451
      // Get doicd owner
452
      String user = docinfoHash.get("user_owner");
453
      // Get docid name (such as acl or dataset)
454
      String docName = docinfoHash.get("docname");
455
      // Get doc type (eml public id)
456
      String docType = docinfoHash.get("doctype");
457
      // Get docid home sever. it might be different to remoteserver
458
      // becuause of hub feature
459
      String docHomeServer = docinfoHash.get("home_server");
460
      String createdDate = docinfoHash.get("date_created");
461
      String updatedDate = docinfoHash.get("date_updated");
462
      //docid should include rev number too
463
      /*String accnum=docId+util.getProperty("document.accNumSeparator")+
464
                                              (String)docinfoHash.get("rev");*/
465

    
466

    
467
      String datafilePath = PropertyService.getProperty("application.datafilepath");
468
      // Get data file content
469
      String readDataURLString = "https://" + remoteserver + "?server="+
470
                                        MetacatUtil.getLocalReplicationServerName()+
471
                                            "&action=readdata&docid="+accNumber;
472
      readDataURLString = MetacatUtil.replaceWhiteSpaceForURL(readDataURLString);
473
      URL u = new URL(readDataURLString);
474
      InputStream input = u.openStream();
475
      //register data file into xml_documents table and wite data file
476
      //into file system
477
      if ( input != null)
478
      {
479
        DocumentImpl.writeDataFileInReplication(input,
480
                                                datafilePath,
481
                                                docName,docType,
482
                                                accNumber, user,
483
                                                docHomeServer,
484
                                                remoteserver,
485
                                                tableName,
486
                                                true, //true means timed replication
487
                                                createdDate,
488
                                                updatedDate);
489
                                         
490
        //process extra access rules
491
        Vector<AccessControlForSingleFile> accessControlList = dih.getAccessControlList();
492
        if (accessControlList != null) {
493
      	  for (AccessControlForSingleFile acfsf : accessControlList) {
494
          	  if (!acfsf.accessControlExists()) {
495
          		acfsf.insertPermissions();
496
          	  }
497
            }
498
        }
499
        
500
        logReplication.info("ReplicationHandler.handleSingleDataFile - Successfully to write datafile " + accNumber);
501
        /*MetacatReplication.replLog("wrote datafile " + accNumber + " from " +
502
                                    remoteserver);*/
503
        if (tableName.equals(DocumentImpl.DOCUMENTTABLE))
504
        {
505
          logReplication.info("ReplicationHandler.handleSingleDataFile - " + DOCINSERTNUMBER + " Wrote data file" + accNumber +
506
                                       " into "+tableName + " from " +
507
                                           remoteserver);
508
          DOCINSERTNUMBER++;
509
        }
510
        else
511
        {
512
            logReplication.info("ReplicationHandler.handleSingleDataFile - " + REVINSERTNUMBER + " Wrote data file" + accNumber +
513
                    " into "+tableName + " from " +
514
                        remoteserver);
515
            REVINSERTNUMBER++;
516
        }
517
        String ip = getIpFromURL(u);
518
        EventLog.getInstance().log(ip, ReplicationService.REPLICATIONUSER, accNumber, actions);
519
        
520
      }//if
521
      else
522
      {
523
         logReplication.info("ReplicationHandler.handleSingleDataFile - Couldn't open the data file: " + accNumber);
524
         throw new HandlerException("ReplicationHandler.handleSingleDataFile - Couldn't open the data file: " + accNumber);
525
      }//else
526

    
527
    }//try
528
    catch(Exception e)
529
    {
530
      /*MetacatReplication.replErrorLog("Failed to try wrote datafile " + accNumber +
531
                                      " because " +e.getMessage());*/
532
      if (tableName.equals(DocumentImpl.DOCUMENTTABLE))
533
      {
534
    	logMetacat.error("ReplicationHandler.handleSingleDataFile - " + ReplicationService.METACAT_REPL_ERROR_MSG); 
535
    	logReplication.error("ReplicationHandler.handleSingleDataFile - " + DOCERRORNUMBER + " Failed to write data file " + accNumber +
536
                                     " into " + tableName + " from " +
537
                                         remoteserver + " because " + e.getMessage());
538
        DOCERRORNUMBER++;
539
      }
540
      else
541
      {
542
    	  logMetacat.error("ReplicationHandler.handleSingleDataFile - " + ReplicationService.METACAT_REPL_ERROR_MSG); 
543
    	  logReplication.error("ReplicationHandler.handleSingleDataFile - " + REVERRORNUMBER + " Failed to write data file" + accNumber +
544
                  " into " + tableName + " from " +
545
                      remoteserver +" because "+ e.getMessage());
546
          REVERRORNUMBER++;
547
      }
548
      logMetacat.error("ReplicationHandler.handleSingleDataFile - " + ReplicationService.METACAT_REPL_ERROR_MSG); 
549
      logReplication.error("ReplicationHandler.handleSingleDataFile - Failed to try wrote datafile " + accNumber +
550
                                      " because " + e.getMessage());
551
      throw new HandlerException("ReplicationHandler.handleSingleDataFile - generic exception " 
552
    		  + "writing Replication: " + e.getMessage());
553
    }
554
    finally
555
    {
556
       //return DBConnection
557
       DBConnectionPool.returnDBConnection(dbConn, serialNumber);
558
    }//finally
559
  }
560

    
561

    
562

    
563
  /* Handle delete single document*/
564
  private void handleDeleteSingleDocument(String docId, String notifyServer)
565
               throws HandlerException
566
  {
567
    logReplication.info("ReplicationHandler.handleDeleteSingleDocument - Try delete doc: "+docId);
568
    DBConnection dbConn = null;
569
    int serialNumber = -1;
570
    try
571
    {
572
      // Get DBConnection from pool
573
      dbConn=DBConnectionPool.
574
                  getDBConnection("ReplicationHandler.handleDeleteSingleDoc");
575
      serialNumber=dbConn.getCheckOutSerialNumber();
576
      if(!alreadyDeleted(docId))
577
      {
578

    
579
         //because delete method docid should have rev number
580
         //so we just add one for it. This rev number is no sence.
581
         String accnum=docId+PropertyService.getProperty("document.accNumSeparator")+"1";
582
         //System.out.println("accnum: "+accnum);
583
         DocumentImpl.delete(accnum, null, null, notifyServer);
584
         logReplication.info("ReplicationHandler.handleDeleteSingleDocument - Successfully deleted doc " + docId);
585
         logReplication.info("ReplicationHandler.handleDeleteSingleDocument - Doc " + docId + " deleted");
586
         URL u = new URL("https://"+notifyServer);
587
         String ip = getIpFromURL(u);
588
         EventLog.getInstance().log(ip, ReplicationService.REPLICATIONUSER, docId, "delete");
589
      }
590

    
591
    }//try
592
    catch(Exception e)
593
    {
594
      logMetacat.error("ReplicationHandler.handleDeleteSingleDocument - " + ReplicationService.METACAT_REPL_ERROR_MSG); 
595
      logReplication.error("ReplicationHandler.handleDeleteSingleDocument - Failed to delete doc " + docId +
596
                                 " in db because because " + e.getMessage());
597
      throw new HandlerException("ReplicationHandler.handleDeleteSingleDocument - generic exception " 
598
    		  + "when handling document: " + e.getMessage());
599
    }
600
    finally
601
    {
602
       //return DBConnection
603
       DBConnectionPool.returnDBConnection(dbConn, serialNumber);
604
    }//finally
605
  }
606

    
607
  /* Handle updateLastCheckTimForSingleServer*/
608
  private void updateLastCheckTimeForSingleServer(ReplicationServer repServer)
609
                                                  throws HandlerException
610
  {
611
    String server = repServer.getServerName();
612
    DBConnection dbConn = null;
613
    int serialNumber = -1;
614
    PreparedStatement pstmt = null;
615
    try
616
    {
617
      // Get DBConnection from pool
618
      dbConn=DBConnectionPool.
619
             getDBConnection("ReplicationHandler.updateLastCheckTimeForServer");
620
      serialNumber=dbConn.getCheckOutSerialNumber();
621

    
622
      logReplication.info("ReplicationHandler.updateLastCheckTimeForSingleServer - Try to update last_check for server: "+server);
623
      // Get time from remote server
624
      URL dateurl = new URL("https://" + server + "?server="+
625
      MetacatUtil.getLocalReplicationServerName()+"&action=gettime");
626
      String datexml = ReplicationService.getURLContent(dateurl);
627
      logReplication.info("ReplicationHandler.updateLastCheckTimeForSingleServer - datexml: "+datexml);
628
      if (datexml!=null && !datexml.equals(""))
629
      {
630
         String datestr = datexml.substring(11, datexml.indexOf('<', 11));
631
         StringBuffer sql = new StringBuffer();
632
         /*sql.append("update xml_replication set last_checked = to_date('");
633
         sql.append(datestr).append("', 'YY-MM-DD HH24:MI:SS') where ");
634
         sql.append("server like '").append(server).append("'");*/
635
         sql.append("update xml_replication set last_checked = ");
636
         sql.append(DatabaseService.getDBAdapter().toDate(datestr, "MM/DD/YY HH24:MI:SS"));
637
         sql.append(" where server like '").append(server).append("'");
638
         pstmt = dbConn.prepareStatement(sql.toString());
639

    
640
         pstmt.executeUpdate();
641
         dbConn.commit();
642
         pstmt.close();
643
         logReplication.info("ReplicationHandler.updateLastCheckTimeForSingleServer - last_checked updated to "+datestr+" on "
644
                                      + server);
645
      }//if
646
      else
647
      {
648

    
649
         logReplication.info("ReplicationHandler.updateLastCheckTimeForSingleServer - Failed to update last_checked for server "  +
650
                                  server + " in db because couldn't get time "
651
                                  );
652
         throw new Exception("Couldn't get time for server "+ server);
653
      }
654

    
655
    }//try
656
    catch(Exception e)
657
    {
658
      logMetacat.error("ReplicationHandler.updateLastCheckTimeForSingleServer - " + ReplicationService.METACAT_REPL_ERROR_MSG); 
659
      logReplication.error("ReplicationHandler.updateLastCheckTimeForSingleServer - Failed to update last_checked for server " +
660
                                server + " in db because because " + e.getMessage());
661
      throw new HandlerException("ReplicationHandler.updateLastCheckTimeForSingleServer - " 
662
    		  + "Error updating last checked time: " + e.getMessage());
663
    }
664
    finally
665
    {
666
       //return DBConnection
667
       DBConnectionPool.returnDBConnection(dbConn, serialNumber);
668
    }//finally
669
  }
670

    
671

    
672

    
673
  /**
674
   * updates xml_catalog with entries from other servers.
675
   */
676
  private void updateCatalog()
677
  {
678
    logReplication.info("ReplicationHandler.updateCatalog - Start of updateCatalog");
679
    // ReplicationServer object in server list
680
    ReplicationServer replServer = null;
681
    PreparedStatement pstmt = null;
682
    String server = null;
683

    
684

    
685
    // Go through each ReplicationServer object in sererlist
686
    for (int j=0; j<serverList.size(); j++)
687
    {
688
      Vector<Vector<String>> remoteCatalog = new Vector<Vector<String>>();
689
      Vector<String> publicId = new Vector<String>();
690
      try
691
      {
692
        // Get ReplicationServer object from server list
693
        replServer = serverList.serverAt(j);
694
        // Get server name from the ReplicationServer object
695
        server = replServer.getServerName();
696
        // Try to get catalog
697
        URL u = new URL("https://" + server + "?server="+
698
        MetacatUtil.getLocalReplicationServerName()+"&action=getcatalog");
699
        logReplication.info("ReplicationHandler.updateCatalog - sending message " + u.toString());
700
        String catxml = ReplicationService.getURLContent(u);
701

    
702
        // Make sure there are not error, no empty string
703
        if (catxml.indexOf("error")!=-1 || catxml==null||catxml.equals(""))
704
        {
705
          throw new Exception("Couldn't get catalog list form server " +server);
706
        }
707
        logReplication.info("ReplicationHandler.updateCatalog - catxml: " + catxml);
708
        CatalogMessageHandler cmh = new CatalogMessageHandler();
709
        XMLReader catparser = initParser(cmh);
710
        catparser.parse(new InputSource(new StringReader(catxml)));
711
        //parse the returned catalog xml and put it into a vector
712
        remoteCatalog = cmh.getCatalogVect();
713

    
714
        // Makse sure remoteCatalog is not empty
715
        if (remoteCatalog.isEmpty())
716
        {
717
          throw new Exception("Couldn't get catalog list form server " +server);
718
        }
719

    
720
        String localcatxml = ReplicationService.getCatalogXML();
721

    
722
        // Make sure local catalog is no empty
723
        if (localcatxml==null||localcatxml.equals(""))
724
        {
725
          throw new Exception("Couldn't get catalog list form server " +server);
726
        }
727

    
728
        cmh = new CatalogMessageHandler();
729
        catparser = initParser(cmh);
730
        catparser.parse(new InputSource(new StringReader(localcatxml)));
731
        Vector<Vector<String>> localCatalog = cmh.getCatalogVect();
732

    
733
        //now we have the catalog from the remote server and this local server
734
        //we now need to compare the two and merge the differences.
735
        //the comparison is base on the public_id fields which is the 4th
736
        //entry in each row vector.
737
        publicId = new Vector<String>();
738
        for(int i=0; i<localCatalog.size(); i++)
739
        {
740
          Vector<String> v = new Vector<String>(localCatalog.elementAt(i));
741
          logReplication.info("ReplicationHandler.updateCatalog - v1: " + v.toString());
742
          publicId.add(new String((String)v.elementAt(3)));
743
          //System.out.println("adding " + (String)v.elementAt(3));
744
        }
745
      }//try
746
      catch (Exception e)
747
      {
748
        logMetacat.error("ReplicationHandler.updateCatalog - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
749
        logReplication.error("ReplicationHandler.updateCatalog - Failed to update catalog for server "+
750
                                    server + " because " +e.getMessage());
751
      }//catch
752

    
753
      for(int i=0; i<remoteCatalog.size(); i++)
754
      {
755
         // DConnection
756
        DBConnection dbConn = null;
757
        // DBConnection checkout serial number
758
        int serialNumber = -1;
759
        try
760
        {
761
            dbConn=DBConnectionPool.
762
                  getDBConnection("ReplicationHandler.updateCatalog");
763
            serialNumber=dbConn.getCheckOutSerialNumber();
764
            Vector<String> v = remoteCatalog.elementAt(i);
765
            //System.out.println("v2: " + v.toString());
766
            //System.out.println("i: " + i);
767
            //System.out.println("remoteCatalog.size(): " + remoteCatalog.size());
768
            //System.out.println("publicID: " + publicId.toString());
769
            logReplication.info
770
                              ("ReplicationHandler.updateCatalog - v.elementAt(3): " + (String)v.elementAt(3));
771
           if(!publicId.contains(v.elementAt(3)))
772
           { //so we don't have this public id in our local table so we need to
773
             //add it.
774
             //System.out.println("in if");
775
             StringBuffer sql = new StringBuffer();
776
             sql.append("insert into xml_catalog (entry_type, source_doctype, ");
777
             sql.append("target_doctype, public_id, system_id) values (?,?,?,");
778
             sql.append("?,?)");
779
             //System.out.println("sql: " + sql.toString());
780
             pstmt = dbConn.prepareStatement(sql.toString());
781
             pstmt.setString(1, (String)v.elementAt(0));
782
             pstmt.setString(2, (String)v.elementAt(1));
783
             pstmt.setString(3, (String)v.elementAt(2));
784
             pstmt.setString(4, (String)v.elementAt(3));
785
             pstmt.setString(5, (String)v.elementAt(4));
786
             pstmt.execute();
787
             pstmt.close();
788
             logReplication.info("ReplicationHandler.updateCatalog - Success fully to insert new publicid "+
789
                               (String)v.elementAt(3) + " from server"+server);
790
           }
791
        }
792
        catch(Exception e)
793
        {
794
           logMetacat.error("ReplicationHandler.updateCatalog - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
795
           logReplication.error("ReplicationHandler.updateCatalog - Failed to update catalog for server "+
796
                                    server + " because " +e.getMessage());
797
        }//catch
798
        finally
799
        {
800
           DBConnectionPool.returnDBConnection(dbConn, serialNumber);
801
        }//finall
802
      }//for remote catalog
803
    }//for server list
804
    logReplication.info("End of updateCatalog");
805
  }
806

    
807
  /**
808
   * Method that returns true if docid has already been "deleted" from metacat.
809
   * This method really implements a truth table for deleted documents
810
   * The table is (a docid in one of the tables is represented by the X):
811
   * xml_docs      xml_revs      deleted?
812
   * ------------------------------------
813
   *   X             X             FALSE
814
   *   X             _             FALSE
815
   *   _             X             TRUE
816
   *   _             _             TRUE
817
   */
818
  private static boolean alreadyDeleted(String docid) throws HandlerException
819
  {
820
    DBConnection dbConn = null;
821
    int serialNumber = -1;
822
    PreparedStatement pstmt = null;
823
    try
824
    {
825
      dbConn=DBConnectionPool.
826
                  getDBConnection("ReplicationHandler.alreadyDeleted");
827
      serialNumber=dbConn.getCheckOutSerialNumber();
828
      boolean xml_docs = false;
829
      boolean xml_revs = false;
830

    
831
      StringBuffer sb = new StringBuffer();
832
      sb.append("select docid from xml_revisions where docid like '");
833
      sb.append(docid).append("'");
834
      pstmt = dbConn.prepareStatement(sb.toString());
835
      pstmt.execute();
836
      ResultSet rs = pstmt.getResultSet();
837
      boolean tablehasrows = rs.next();
838
      if(tablehasrows)
839
      {
840
        xml_revs = true;
841
      }
842

    
843
      sb = new StringBuffer();
844
      sb.append("select docid from xml_documents where docid like '");
845
      sb.append(docid).append("'");
846
      pstmt.close();
847
      pstmt = dbConn.prepareStatement(sb.toString());
848
      //increase usage count
849
      dbConn.increaseUsageCount(1);
850
      pstmt.execute();
851
      rs = pstmt.getResultSet();
852
      tablehasrows = rs.next();
853
      pstmt.close();
854
      if(tablehasrows)
855
      {
856
        xml_docs = true;
857
      }
858

    
859
      if(xml_docs && xml_revs)
860
      {
861
        return false;
862
      }
863
      else if(xml_docs && !xml_revs)
864
      {
865
        return false;
866
      }
867
      else if(!xml_docs && xml_revs)
868
      {
869
        return true;
870
      }
871
      else if(!xml_docs && !xml_revs)
872
      {
873
        return true;
874
      }
875
    }
876
    catch(Exception e)
877
    {
878
      logMetacat.error("ReplicationHandler.alreadyDeleted - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
879
      logReplication.error("ReplicationHandler.alreadyDeleted - general error in alreadyDeleted: " +
880
                          e.getMessage());
881
      throw new HandlerException("ReplicationHandler.alreadyDeleted - general error: " 
882
    		  + e.getMessage());
883
    }
884
    finally
885
    {
886
      try
887
      {
888
        pstmt.close();
889
      }//try
890
      catch (SQLException ee)
891
      {
892
    	logMetacat.error("ReplicationHandler.alreadyDeleted - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
893
        logReplication.error("ReplicationHandler.alreadyDeleted - Error in replicationHandler.alreadyDeleted "+
894
                          "to close pstmt: "+ee.getMessage());
895
        throw new HandlerException("ReplicationHandler.alreadyDeleted - SQL error when closing prepared statement: " 
896
      		  + ee.getMessage());
897
      }//catch
898
      finally
899
      {
900
        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
901
      }//finally
902
    }//finally
903
    return false;
904
  }
905

    
906

    
907
  /**
908
   * Method to initialize the message parser
909
   */
910
  public static XMLReader initParser(DefaultHandler dh)
911
          throws HandlerException
912
  {
913
    XMLReader parser = null;
914

    
915
    try {
916
      ContentHandler chandler = dh;
917

    
918
      // Get an instance of the parser
919
      String parserName = PropertyService.getProperty("xml.saxparser");
920
      parser = XMLReaderFactory.createXMLReader(parserName);
921

    
922
      // Turn off validation
923
      parser.setFeature("http://xml.org/sax/features/validation", false);
924

    
925
      parser.setContentHandler((ContentHandler)chandler);
926
      parser.setErrorHandler((ErrorHandler)chandler);
927

    
928
    } catch (SAXException se) {
929
      throw new HandlerException("ReplicationHandler.initParser - Sax error when " 
930
    		  + " initializing parser: " + se.getMessage());
931
    } catch (PropertyNotFoundException pnfe) {
932
        throw new HandlerException("ReplicationHandler.initParser - Property error when " 
933
      		  + " getting parser name: " + pnfe.getMessage());
934
    } 
935

    
936
    return parser;
937
  }
938

    
939
  /**
940
	 * This method will combinate given time string(in short format) to current
941
	 * date. If the given time (e.g 10:00 AM) passed the current time (e.g 2:00
942
	 * PM Aug 21, 2005), then the time will set to second day, 10:00 AM Aug 22,
943
	 * 2005. If the given time (e.g 10:00 AM) haven't passed the current time
944
	 * (e.g 8:00 AM Aug 21, 2005) The time will set to be 10:00 AM Aug 21, 2005.
945
	 * 
946
	 * @param givenTime
947
	 *            the format should be "10:00 AM " or "2:00 PM"
948
	 * @return
949
	 * @throws Exception
950
	 */
951
	public static Date combinateCurrentDateAndGivenTime(String givenTime) throws HandlerException
952
  {
953
	  try {
954
     Date givenDate = parseTime(givenTime);
955
     Date newDate = null;
956
     Date now = new Date();
957
     String currentTimeString = getTimeString(now);
958
     Date currentTime = parseTime(currentTimeString); 
959
     if ( currentTime.getTime() >= givenDate.getTime())
960
     {
961
        logReplication.info("ReplicationHandler.combinateCurrentDateAndGivenTime - Today already pass the given time, we should set it as tomorrow");
962
        String dateAndTime = getDateString(now) + " " + givenTime;
963
        Date combinationDate = parseDateTime(dateAndTime);
964
        // new date should plus 24 hours to make is the second day
965
        newDate = new Date(combinationDate.getTime()+24*3600*1000);
966
     }
967
     else
968
     {
969
         logReplication.info("ReplicationHandler.combinateCurrentDateAndGivenTime - Today haven't pass the given time, we should it as today");
970
         String dateAndTime = getDateString(now) + " " + givenTime;
971
         newDate = parseDateTime(dateAndTime);
972
     }
973
     logReplication.warn("ReplicationHandler.combinateCurrentDateAndGivenTime - final setting time is "+ newDate.toString());
974
     return newDate;
975
	  } catch (ParseException pe) {
976
		  throw new HandlerException("ReplicationHandler.combinateCurrentDateAndGivenTime - "
977
				  + "parsing error: "  + pe.getMessage());
978
	  }
979
  }
980

    
981
  /*
982
	 * parse a given string to Time in short format. For example, given time is
983
	 * 10:00 AM, the date will be return as Jan 1 1970, 10:00 AM
984
	 */
985
  private static Date parseTime(String timeString) throws ParseException
986
  {
987
    DateFormat format = DateFormat.getTimeInstance(DateFormat.SHORT);
988
    Date time = format.parse(timeString); 
989
    logReplication.info("ReplicationHandler.parseTime - Date string is after parse a time string "
990
                              +time.toString());
991
    return time;
992

    
993
  }
994
  
995
  /*
996
   * Pasre a given string to date and time. Date format is long and time
997
   * format is short.
998
   */
999
  private static Date parseDateTime(String timeString) throws ParseException
1000
  {
1001
    DateFormat format = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.SHORT);
1002
    Date time = format.parse(timeString);
1003
    logReplication.info("ReplicationHandler.parseDateTime - Date string is after parse a time string "+
1004
                             time.toString());
1005
    return time;
1006
  }
1007
  
1008
  /*
1009
   * Get a date string from a Date object. The date format will be long
1010
   */
1011
  private static String getDateString(Date now)
1012
  {
1013
     DateFormat df = DateFormat.getDateInstance(DateFormat.LONG);
1014
     String s = df.format(now);
1015
     logReplication.info("ReplicationHandler.getDateString - Today is " + s);
1016
     return s;
1017
  }
1018
  
1019
  /*
1020
   * Get a time string from a Date object, the time format will be short
1021
   */
1022
  private static String getTimeString(Date now)
1023
  {
1024
     DateFormat df = DateFormat.getTimeInstance(DateFormat.SHORT);
1025
     String s = df.format(now);
1026
     logReplication.info("ReplicationHandler.getTimeString - Time is " + s);
1027
     return s;
1028
  }
1029
  
1030
  
1031
  /*
1032
	 * This method will go through the docid list both in xml_Documents table
1033
	 * and in xml_revisions table @author tao
1034
	 */
1035
	private void handleDocList(Vector<Vector<String>> docList, String tableName) {
1036
		boolean dataFile = false;
1037
		for (int j = 0; j < docList.size(); j++) {
1038
			// initial dataFile is false
1039
			dataFile = false;
1040
			// w is information for one document, information contain
1041
			// docid, rev, server or datafile.
1042
			Vector<String> w = new Vector<String>(docList.elementAt(j));
1043
			// Check if the vector w contain "datafile"
1044
			// If it has, this document is data file
1045
			try {
1046
				if (w.contains((String) PropertyService.getProperty("replication.datafileflag"))) {
1047
					dataFile = true;
1048
				}
1049
			} catch (PropertyNotFoundException pnfe) {
1050
				logMetacat.error("ReplicationHandler.handleDocList - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1051
				logReplication.error("ReplicationHandler.handleDocList - Could not retrieve data file flag property.  "
1052
						+ "Leaving as false: " + pnfe.getMessage());
1053
			}
1054
			// System.out.println("w: " + w.toString());
1055
			// Get docid
1056
			String docid = (String) w.elementAt(0);
1057
			logReplication.info("docid: " + docid);
1058
			// Get revision number
1059
			int rev = Integer.parseInt((String) w.elementAt(1));
1060
			logReplication.info("rev: " + rev);
1061
			// Get remote server name (it is may not be doc homeserver because
1062
			// the new hub feature
1063
			String remoteServer = (String) w.elementAt(2);
1064
			remoteServer = remoteServer.trim();
1065

    
1066
			try {
1067
				if (tableName.equals(DocumentImpl.DOCUMENTTABLE)) {
1068
					handleDocInXMLDocuments(docid, rev, remoteServer, dataFile);
1069
				} else if (tableName.equals(DocumentImpl.REVISIONTABLE)) {
1070
					handleDocInXMLRevisions(docid, rev, remoteServer, dataFile);
1071
				} else {
1072
					continue;
1073
				}
1074

    
1075
			} catch (Exception e) {
1076
				logMetacat.error("ReplicationHandler.handleDocList - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1077
				logReplication.error("ReplicationHandler.handleDocList - error to handle update doc in " + tableName
1078
						+ " in time replication" + e.getMessage());
1079
				continue;
1080
			}
1081

    
1082
		}// for update docs
1083

    
1084
	}
1085
   
1086
   /*
1087
	 * This method will handle doc in xml_documents table.
1088
	 */
1089
   private void handleDocInXMLDocuments(String docid, int rev, String remoteServer, boolean dataFile) 
1090
                                        throws HandlerException
1091
   {
1092
       // compare the update rev and local rev to see what need happen
1093
       int localrev = -1;
1094
       String action = null;
1095
       boolean flag = false;
1096
       try
1097
       {
1098
         localrev = DBUtil.getLatestRevisionInDocumentTable(docid);
1099
       }
1100
       catch (SQLException e)
1101
       {
1102
    	 logMetacat.error("ReplicationHandler.handleDocInXMLDocuments - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1103
         logReplication.error("ReplicationHandler.handleDocInXMLDocuments - Local rev for docid "+ docid + " could not "+
1104
                                " be found because " + e.getMessage());
1105
         logReplication.error("ReplicationHandler.handleDocInXMLDocuments - " + DOCERRORNUMBER+"Docid "+ docid + " could not be "+
1106
                 "written because error happend to find it's local revision");
1107
         DOCERRORNUMBER++;
1108
         throw new HandlerException ("ReplicationHandler.handleDocInXMLDocuments - Local rev for docid "+ docid + " could not "+
1109
                 " be found: " + e.getMessage());
1110
       }
1111
       logReplication.info("ReplicationHandler.handleDocInXMLDocuments - Local rev for docid "+ docid + " is "+
1112
                               localrev);
1113

    
1114
       //check the revs for an update because this document is in the
1115
       //local DB, it might be out of date.
1116
       if (localrev == -1)
1117
       {
1118
          // check if the revision is in the revision table
1119
    	   Vector<Integer> localRevVector = null;
1120
    	 try {
1121
    		 localRevVector = DBUtil.getRevListFromRevisionTable(docid);
1122
    	 } catch (SQLException sqle) {
1123
    		 throw new HandlerException("ReplicationHandler.handleDocInXMLDocuments - SQL error " 
1124
    				 + " when getting rev list for docid: " + docid + " : " + sqle.getMessage());
1125
    	 }
1126
         if (localRevVector != null && localRevVector.contains(new Integer(rev)))
1127
         {
1128
             // this version was deleted, so don't need replicate
1129
             flag = false;
1130
         }
1131
         else
1132
         {
1133
           //insert this document as new because it is not in the local DB
1134
           action = "INSERT";
1135
           flag = true;
1136
         }
1137
       }
1138
       else
1139
       {
1140
         if(localrev == rev)
1141
         {
1142
           // Local meatacat has the same rev to remote host, don't need
1143
           // update and flag set false
1144
           flag = false;
1145
         }
1146
         else if(localrev < rev)
1147
         {
1148
           //this document needs to be updated so send an read request
1149
           action = "UPDATE";
1150
           flag = true;
1151
         }
1152
       }
1153
       
1154
       String accNumber = null;
1155
       try {
1156
    	   accNumber = docid + PropertyService.getProperty("document.accNumSeparator") + rev;
1157
       } catch (PropertyNotFoundException pnfe) {
1158
    	   throw new HandlerException("ReplicationHandler.handleDocInXMLDocuments - error getting " 
1159
    			   + "account number separator : " + pnfe.getMessage());
1160
       }
1161
       // this is non-data file
1162
       if(flag && !dataFile)
1163
       {
1164
         try
1165
         {
1166
           handleSingleXMLDocument(remoteServer, action, accNumber, DocumentImpl.DOCUMENTTABLE);
1167
         }
1168
         catch(HandlerException he)
1169
         {
1170
           // skip this document
1171
           throw he;
1172
         }
1173
       }//if for non-data file
1174

    
1175
        // this is for data file
1176
       if(flag && dataFile)
1177
       {
1178
         try
1179
         {
1180
           handleSingleDataFile(remoteServer, action, accNumber, DocumentImpl.DOCUMENTTABLE);
1181
         }
1182
         catch(HandlerException he)
1183
         {
1184
           // skip this datafile
1185
           throw he;
1186
         }
1187

    
1188
       }//for datafile
1189
   }
1190
   
1191
   /*
1192
    * This method will handle doc in xml_documents table.
1193
    */
1194
   private void handleDocInXMLRevisions(String docid, int rev, String remoteServer, boolean dataFile) 
1195
                                        throws HandlerException
1196
   {
1197
       // compare the update rev and local rev to see what need happen
1198
       logReplication.info("ReplicationHandler.handleDocInXMLRevisions - In handle repliation revsion table");
1199
       logReplication.info("ReplicationHandler.handleDocInXMLRevisions - the docid is "+ docid);
1200
       logReplication.info("ReplicationHandler.handleDocInXMLRevisions - The rev is "+rev);
1201
       Vector<Integer> localrev = null;
1202
       String action = "INSERT";
1203
       boolean flag = false;
1204
       try
1205
       {
1206
         localrev = DBUtil.getRevListFromRevisionTable(docid);
1207
       }
1208
       catch (SQLException sqle)
1209
       {
1210
    	 logMetacat.error("ReplicationHandler.handleDocInXMLDocuments - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1211
         logReplication.error("ReplicationHandler.handleDocInXMLRevisions - Local rev for docid "+ docid + " could not "+
1212
                                " be found because " + sqle.getMessage());
1213
         REVERRORNUMBER++;
1214
         throw new HandlerException ("ReplicationHandler.handleDocInXMLRevisions - SQL exception getting rev list: " 
1215
        		 + sqle.getMessage());
1216
       }
1217
       logReplication.info("ReplicationHandler.handleDocInXMLRevisions - rev list in xml_revision table for docid "+ docid + " is "+
1218
                               localrev.toString());
1219
       
1220
       // if the rev is not in the xml_revision, we need insert it
1221
       if (!localrev.contains(new Integer(rev)))
1222
       {
1223
           flag = true;    
1224
       }
1225
     
1226
       String accNumber = null;
1227
       try {
1228
    	   accNumber = docid + PropertyService.getProperty("document.accNumSeparator") + rev;
1229
       } catch (PropertyNotFoundException pnfe) {
1230
    	   throw new HandlerException("ReplicationHandler.handleDocInXMLRevisions - error getting " 
1231
    			   + "account number separator : " + pnfe.getMessage());
1232
       }
1233
       // this is non-data file
1234
       if(flag && !dataFile)
1235
       {
1236
         try
1237
         {
1238
           
1239
           handleSingleXMLDocument(remoteServer, action, accNumber, DocumentImpl.REVISIONTABLE);
1240
         }
1241
         catch(HandlerException he)
1242
         {
1243
           // skip this document
1244
           throw he;
1245
         }
1246
       }//if for non-data file
1247

    
1248
        // this is for data file
1249
       if(flag && dataFile)
1250
       {
1251
         try
1252
         {
1253
           handleSingleDataFile(remoteServer, action, accNumber, DocumentImpl.REVISIONTABLE);
1254
         }
1255
         catch(HandlerException he)
1256
         {
1257
           // skip this datafile
1258
           throw he;
1259
         }
1260

    
1261
       }//for datafile
1262
   }
1263
   
1264
   /*
1265
    * Return a ip address for given url
1266
    */
1267
   private String getIpFromURL(URL url)
1268
   {
1269
	   String ip = null;
1270
	   try
1271
	   {
1272
	      InetAddress address = InetAddress.getByName(url.getHost());
1273
	      ip = address.getHostAddress();
1274
	   }
1275
	   catch(UnknownHostException e)
1276
	   {
1277
		   logMetacat.error("ReplicationHandler.getIpFromURL - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1278
		   logReplication.error("ReplicationHandler.getIpFromURL - Error in get ip address for host: "
1279
                   +e.getMessage());
1280
	   }
1281

    
1282
	   return ip;
1283
   }
1284
  
1285
}
1286

    
(3-3/7)