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-10-30 15:39:35 -0700 (Fri, 30 Oct 2009) $'
10
 * '$Revision: 5098 $'
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.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
import edu.ucsb.nceas.metacat.accesscontrol.AccessControlForSingleFile;
36
import edu.ucsb.nceas.metacat.accesscontrol.XMLAccessDAO;
37
import edu.ucsb.nceas.metacat.database.DBConnection;
38
import edu.ucsb.nceas.metacat.database.DBConnectionPool;
39
import edu.ucsb.nceas.metacat.database.DatabaseService;
40
import edu.ucsb.nceas.metacat.properties.PropertyService;
41
import edu.ucsb.nceas.metacat.shared.HandlerException;
42
import edu.ucsb.nceas.metacat.util.MetacatUtil;
43
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
44

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

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

    
61

    
62

    
63
/**
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
  int serverCheckCode = 1;
71
  ReplicationServerList serverList = null;
72
  //PrintWriter out;
73
//  private static final AbstractDatabase dbAdapter = MetacatUtil.dbAdapter;
74
  private static Logger logReplication = Logger.getLogger("ReplicationLogging");
75
  private static Logger logMetacat = Logger.getLogger(ReplicationHandler.class);
76
  private static int DOCINSERTNUMBER = 1;
77
  private static int DOCERRORNUMBER  = 1;
78
  private static int REVINSERTNUMBER = 1;
79
  private static int REVERRORNUMBER  = 1;
80
  public ReplicationHandler()
81
  {
82
    //this.out = o;
83
    serverList = new ReplicationServerList();
84
  }
85

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

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

    
113
  /**
114
   * Method that uses revision taging for replication instead of update_date.
115
   */
116
  private void update()
117
  {
118
    /*
119
     Pseudo-algorithm
120
     - request a doc list from each server in xml_replication
121
     - check the rev number of each of those documents agains the
122
       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
       (this info is theoretically not needed using this system but probably
129
       should be kept anyway)
130
    */
131

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

    
140

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

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

    
181
    //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
    	logMetacat.error("ReplicationHandler.update - " + ReplicationService.METACAT_REPL_ERROR_MSG);
186
        logReplication.info( "ReplicationHandler.update - No updated doc list for "+
187
                           "every server and failed to replicate");
188
        return;
189
    }
190

    
191

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

    
262
    //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

    
277
  }//update
278

    
279
  /* Handle replicate single xml document*/
280
  private void handleSingleXMLDocument(String remoteserver, String actions,
281
                                       String accNumber, String tableName)
282
               throws HandlerException
283
  {
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
      String readDocURLString = "https://" + remoteserver + "?server="+
294
              MetacatUtil.getLocalReplicationServerName()+"&action=read&docid="+accNumber;
295
      readDocURLString = MetacatUtil.replaceWhiteSpaceForURL(readDocURLString);
296
      URL u = new URL(readDocURLString);
297

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

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

    
333
      String parserBase = null;
334
      // this for eml2 and we need user eml2 parser
335
      if (docType != null && (docType.trim()).equals(DocumentImpl.EML2_0_0NAMESPACE))
336
      {
337
         parserBase = DocumentImpl.EML200;
338
      }
339
      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
      // Write the document into local host
348
      DocumentImplWrapper wrapper = new DocumentImplWrapper(parserBase, false);
349
      String newDocid = wrapper.writeReplication(dbConn,
350
                              new StringReader(newxmldoc),
351
                              docinfoHash.get("public_access"),
352
                              null,  /* the dtd text */
353
                              actions,
354
                              accNumber,
355
                              docinfoHash.get("user_owner"),
356
                              null, /* null for groups[] */
357
                              docHomeServer,
358
                              remoteserver, tableName, true,// true is for time replication 
359
                              createdDate,
360
                              updatedDate);
361
      
362
      //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
          }
371
      }
372
      
373
      logReplication.info("ReplicationHandler.handleSingleXMLDocument - Successfully replicated doc " + accNumber);
374
      if (tableName.equals(DocumentImpl.DOCUMENTTABLE))
375
      {
376
        logReplication.info("ReplicationHandler.handleSingleXMLDocument - " + DOCINSERTNUMBER + " Wrote xml doc " + accNumber +
377
                                     " into "+tableName + " from " +
378
                                         remoteserver);
379
        DOCINSERTNUMBER++;
380
      }
381
      else
382
      {
383
          logReplication.info("ReplicationHandler.handleSingleXMLDocument - " +REVINSERTNUMBER + " Wrote xml doc " + accNumber +
384
                  " into "+tableName + " from " +
385
                      remoteserver);
386
          REVINSERTNUMBER++;
387
      }
388
      String ip = getIpFromURL(u);
389
      EventLog.getInstance().log(ip, ReplicationService.REPLICATIONUSER, accNumber, actions);
390
      
391

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

    
425

    
426

    
427
  /* Handle replicate single xml document*/
428
  private void handleSingleDataFile(String remoteserver, String actions,
429
                                    String accNumber, String tableName)
430
               throws HandlerException
431
  {
432
    logReplication.info("ReplicationHandler.handleSingleDataFile - Try to replicate data file: " + accNumber);
433
    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
      String docInfoURLString = "https://" + remoteserver +
445
                  "?server="+MetacatUtil.getLocalReplicationServerName()+
446
                  "&action=getdocumentinfo&docid="+accNumber;
447
      docInfoURLString = MetacatUtil.replaceWhiteSpaceForURL(docInfoURLString);
448
      URL docinfoUrl = new URL(docInfoURLString);
449

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

    
468

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

    
530
    }//try
531
    catch(Exception e)
532
    {
533
      /*MetacatReplication.replErrorLog("Failed to try wrote datafile " + accNumber +
534
                                      " because " +e.getMessage());*/
535
      if (tableName.equals(DocumentImpl.DOCUMENTTABLE))
536
      {
537
    	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
        DOCERRORNUMBER++;
542
      }
543
      else
544
      {
545
    	  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
          REVERRORNUMBER++;
550
      }
551
      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
    }
557
    finally
558
    {
559
       //return DBConnection
560
       DBConnectionPool.returnDBConnection(dbConn, serialNumber);
561
    }//finally
562
  }
563

    
564

    
565

    
566
  /* Handle delete single document*/
567
  private void handleDeleteSingleDocument(String docId, String notifyServer)
568
               throws HandlerException
569
  {
570
    logReplication.info("ReplicationHandler.handleDeleteSingleDocument - Try delete doc: "+docId);
571
    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
      {
581

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

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

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

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

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

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

    
658
    }//try
659
    catch(Exception e)
660
    {
661
      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
    }
667
    finally
668
    {
669
       //return DBConnection
670
       DBConnectionPool.returnDBConnection(dbConn, serialNumber);
671
    }//finally
672
  }
673

    
674

    
675

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

    
687

    
688
    // Go through each ReplicationServer object in sererlist
689
    for (int j=0; j<serverList.size(); j++)
690
    {
691
      Vector<Vector<String>> remoteCatalog = new Vector<Vector<String>>();
692
      Vector<String> publicId = new Vector<String>();
693
      try
694
      {
695
        // 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
        URL u = new URL("https://" + server + "?server="+
701
        MetacatUtil.getLocalReplicationServerName()+"&action=getcatalog");
702
        logReplication.info("ReplicationHandler.updateCatalog - sending message " + u.toString());
703
        String catxml = ReplicationService.getURLContent(u);
704

    
705
        // Make sure there are not error, no empty string
706
        if (catxml.indexOf("error")!=-1 || catxml==null||catxml.equals(""))
707
        {
708
          throw new Exception("Couldn't get catalog list form server " +server);
709
        }
710
        logReplication.info("ReplicationHandler.updateCatalog - catxml: " + catxml);
711
        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
        remoteCatalog = cmh.getCatalogVect();
716

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

    
723
        String localcatxml = ReplicationService.getCatalogXML();
724

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

    
731
        cmh = new CatalogMessageHandler();
732
        catparser = initParser(cmh);
733
        catparser.parse(new InputSource(new StringReader(localcatxml)));
734
        Vector<Vector<String>> localCatalog = cmh.getCatalogVect();
735

    
736
        //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
        publicId = new Vector<String>();
741
        for(int i=0; i<localCatalog.size(); i++)
742
        {
743
          Vector<String> v = new Vector<String>(localCatalog.elementAt(i));
744
          logReplication.info("ReplicationHandler.updateCatalog - v1: " + v.toString());
745
          publicId.add(new String((String)v.elementAt(3)));
746
          //System.out.println("adding " + (String)v.elementAt(3));
747
        }
748
      }//try
749
      catch (Exception e)
750
      {
751
        logMetacat.error("ReplicationHandler.updateCatalog - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
752
        logReplication.error("ReplicationHandler.updateCatalog - Failed to update catalog for server "+
753
                                    server + " because " +e.getMessage());
754
      }//catch
755

    
756
      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
        {
764
            dbConn=DBConnectionPool.
765
                  getDBConnection("ReplicationHandler.updateCatalog");
766
            serialNumber=dbConn.getCheckOutSerialNumber();
767
            Vector<String> v = remoteCatalog.elementAt(i);
768
            //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
            logReplication.info
773
                              ("ReplicationHandler.updateCatalog - v.elementAt(3): " + (String)v.elementAt(3));
774
           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
             logReplication.info("ReplicationHandler.updateCatalog - Success fully to insert new publicid "+
792
                               (String)v.elementAt(3) + " from server"+server);
793
           }
794
        }
795
        catch(Exception e)
796
        {
797
           logMetacat.error("ReplicationHandler.updateCatalog - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
798
           logReplication.error("ReplicationHandler.updateCatalog - Failed to update catalog for server "+
799
                                    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
    logReplication.info("End of updateCatalog");
808
  }
809

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

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

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

    
862
      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
        return true;
873
      }
874
      else if(!xml_docs && !xml_revs)
875
      {
876
        return true;
877
      }
878
    }
879
    catch(Exception e)
880
    {
881
      logMetacat.error("ReplicationHandler.alreadyDeleted - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
882
      logReplication.error("ReplicationHandler.alreadyDeleted - general error in alreadyDeleted: " +
883
                          e.getMessage());
884
      throw new HandlerException("ReplicationHandler.alreadyDeleted - general error: " 
885
    		  + e.getMessage());
886
    }
887
    finally
888
    {
889
      try
890
      {
891
        pstmt.close();
892
      }//try
893
      catch (SQLException ee)
894
      {
895
    	logMetacat.error("ReplicationHandler.alreadyDeleted - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
896
        logReplication.error("ReplicationHandler.alreadyDeleted - Error in replicationHandler.alreadyDeleted "+
897
                          "to close pstmt: "+ee.getMessage());
898
        throw new HandlerException("ReplicationHandler.alreadyDeleted - SQL error when closing prepared statement: " 
899
      		  + ee.getMessage());
900
      }//catch
901
      finally
902
      {
903
        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
904
      }//finally
905
    }//finally
906
    return false;
907
  }
908

    
909

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

    
918
    try {
919
      ContentHandler chandler = dh;
920

    
921
      // Get an instance of the parser
922
      String parserName = PropertyService.getProperty("xml.saxparser");
923
      parser = XMLReaderFactory.createXMLReader(parserName);
924

    
925
      // Turn off validation
926
      parser.setFeature("http://xml.org/sax/features/validation", false);
927

    
928
      parser.setContentHandler((ContentHandler)chandler);
929
      parser.setErrorHandler((ErrorHandler)chandler);
930

    
931
    } 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

    
939
    return parser;
940
  }
941

    
942
  /**
943
	 * 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
  {
956
	  try {
957
     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
        logReplication.info("ReplicationHandler.combinateCurrentDateAndGivenTime - Today already pass the given time, we should set it as tomorrow");
965
        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
         logReplication.info("ReplicationHandler.combinateCurrentDateAndGivenTime - Today haven't pass the given time, we should it as today");
973
         String dateAndTime = getDateString(now) + " " + givenTime;
974
         newDate = parseDateTime(dateAndTime);
975
     }
976
     logReplication.warn("ReplicationHandler.combinateCurrentDateAndGivenTime - final setting time is "+ newDate.toString());
977
     return newDate;
978
	  } catch (ParseException pe) {
979
		  throw new HandlerException("ReplicationHandler.combinateCurrentDateAndGivenTime - "
980
				  + "parsing error: "  + pe.getMessage());
981
	  }
982
  }
983

    
984
  /*
985
	 * 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
  {
990
    DateFormat format = DateFormat.getTimeInstance(DateFormat.SHORT);
991
    Date time = format.parse(timeString); 
992
    logReplication.info("ReplicationHandler.parseTime - Date string is after parse a time string "
993
                              +time.toString());
994
    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
  private static Date parseDateTime(String timeString) throws ParseException
1003
  {
1004
    DateFormat format = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.SHORT);
1005
    Date time = format.parse(timeString);
1006
    logReplication.info("ReplicationHandler.parseDateTime - Date string is after parse a time string "+
1007
                             time.toString());
1008
    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
     logReplication.info("ReplicationHandler.getDateString - Today is " + s);
1019
     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
     logReplication.info("ReplicationHandler.getTimeString - Time is " + s);
1030
     return s;
1031
  }
1032
  
1033
  
1034
  /*
1035
	 * This method will go through the docid list both in xml_Documents table
1036
	 * and in xml_revisions table @author tao
1037
	 */
1038
	private void handleDocList(Vector<Vector<String>> docList, String tableName) {
1039
		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
			Vector<String> w = new Vector<String>(docList.elementAt(j));
1046
			// Check if the vector w contain "datafile"
1047
			// If it has, this document is data file
1048
			try {
1049
				if (w.contains((String) PropertyService.getProperty("replication.datafileflag"))) {
1050
					dataFile = true;
1051
				}
1052
			} catch (PropertyNotFoundException pnfe) {
1053
				logMetacat.error("ReplicationHandler.handleDocList - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1054
				logReplication.error("ReplicationHandler.handleDocList - Could not retrieve data file flag property.  "
1055
						+ "Leaving as false: " + pnfe.getMessage());
1056
			}
1057
			// System.out.println("w: " + w.toString());
1058
			// Get docid
1059
			String docid = (String) w.elementAt(0);
1060
			logReplication.info("docid: " + docid);
1061
			// Get revision number
1062
			int rev = Integer.parseInt((String) w.elementAt(1));
1063
			logReplication.info("rev: " + rev);
1064
			// 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

    
1069
			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

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

    
1085
		}// for update docs
1086

    
1087
	}
1088
   
1089
   /*
1090
	 * This method will handle doc in xml_documents table.
1091
	 */
1092
   private void handleDocInXMLDocuments(String docid, int rev, String remoteServer, boolean dataFile) 
1093
                                        throws HandlerException
1094
   {
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
         localrev = DBUtil.getLatestRevisionInDocumentTable(docid);
1102
       }
1103
       catch (SQLException e)
1104
       {
1105
    	 logMetacat.error("ReplicationHandler.handleDocInXMLDocuments - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1106
         logReplication.error("ReplicationHandler.handleDocInXMLDocuments - Local rev for docid "+ docid + " could not "+
1107
                                " be found because " + e.getMessage());
1108
         logReplication.error("ReplicationHandler.handleDocInXMLDocuments - " + DOCERRORNUMBER+"Docid "+ docid + " could not be "+
1109
                 "written because error happend to find it's local revision");
1110
         DOCERRORNUMBER++;
1111
         throw new HandlerException ("ReplicationHandler.handleDocInXMLDocuments - Local rev for docid "+ docid + " could not "+
1112
                 " be found: " + e.getMessage());
1113
       }
1114
       logReplication.info("ReplicationHandler.handleDocInXMLDocuments - Local rev for docid "+ docid + " is "+
1115
                               localrev);
1116

    
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
          // check if the revision is in the revision table
1122
    	   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
         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
       }
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
       
1157
       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
       // this is non-data file
1165
       if(flag && !dataFile)
1166
       {
1167
         try
1168
         {
1169
           handleSingleXMLDocument(remoteServer, action, accNumber, DocumentImpl.DOCUMENTTABLE);
1170
         }
1171
         catch(HandlerException he)
1172
         {
1173
           // skip this document
1174
           throw he;
1175
         }
1176
       }//if for non-data file
1177

    
1178
        // this is for data file
1179
       if(flag && dataFile)
1180
       {
1181
         try
1182
         {
1183
           handleSingleDataFile(remoteServer, action, accNumber, DocumentImpl.DOCUMENTTABLE);
1184
         }
1185
         catch(HandlerException he)
1186
         {
1187
           // skip this datafile
1188
           throw he;
1189
         }
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
                                        throws HandlerException
1199
   {
1200
       // compare the update rev and local rev to see what need happen
1201
       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
       String action = "INSERT";
1206
       boolean flag = false;
1207
       try
1208
       {
1209
         localrev = DBUtil.getRevListFromRevisionTable(docid);
1210
       }
1211
       catch (SQLException sqle)
1212
       {
1213
    	 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
         REVERRORNUMBER++;
1217
         throw new HandlerException ("ReplicationHandler.handleDocInXMLRevisions - SQL exception getting rev list: " 
1218
        		 + sqle.getMessage());
1219
       }
1220
       logReplication.info("ReplicationHandler.handleDocInXMLRevisions - rev list in xml_revision table for docid "+ docid + " is "+
1221
                               localrev.toString());
1222
       
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
     
1229
       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
       // this is non-data file
1237
       if(flag && !dataFile)
1238
       {
1239
         try
1240
         {
1241
           
1242
           handleSingleXMLDocument(remoteServer, action, accNumber, DocumentImpl.REVISIONTABLE);
1243
         }
1244
         catch(HandlerException he)
1245
         {
1246
           // skip this document
1247
           throw he;
1248
         }
1249
       }//if for non-data file
1250

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

    
1264
       }//for datafile
1265
   }
1266
   
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
		   logMetacat.error("ReplicationHandler.getIpFromURL - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1281
		   logReplication.error("ReplicationHandler.getIpFromURL - Error in get ip address for host: "
1282
                   +e.getMessage());
1283
	   }
1284

    
1285
	   return ip;
1286
   }
1287
  
1288
}
1289

    
(3-3/7)