Project

General

Profile

1 522 berkley
/**
2
 *  '$RCSfile$'
3
 *    Purpose: A class to asyncronously do delta-T replication checking
4
 *  Copyright: 2000 Regents of the University of California and the
5
 *             National Center for Ecological Analysis and Synthesis
6
 *    Authors: Chad Berkley
7
 *    Release: @release@
8
 *
9
 *   '$Author$'
10
 *     '$Date$'
11
 * '$Revision$'
12 669 jones
 *
13
 * This program is free software; you can redistribute it and/or modify
14
 * it under the terms of the GNU General Public License as published by
15
 * the Free Software Foundation; either version 2 of the License, or
16
 * (at your option) any later version.
17
 *
18
 * This program is distributed in the hope that it will be useful,
19
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21
 * GNU General Public License for more details.
22
 *
23
 * You should have received a copy of the GNU General Public License
24
 * along with this program; if not, write to the Free Software
25
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26 522 berkley
 */
27
28
package edu.ucsb.nceas.metacat;
29
30
import java.sql.*;
31
import java.util.*;
32
import java.lang.Thread;
33
import java.io.*;
34
import java.net.*;
35 543 berkley
import java.text.*;
36 522 berkley
import org.xml.sax.AttributeList;
37
import org.xml.sax.ContentHandler;
38
import org.xml.sax.DTDHandler;
39
import org.xml.sax.EntityResolver;
40
import org.xml.sax.ErrorHandler;
41
import org.xml.sax.InputSource;
42
import org.xml.sax.XMLReader;
43
import org.xml.sax.SAXException;
44
import org.xml.sax.SAXParseException;
45
import org.xml.sax.helpers.XMLReaderFactory;
46 561 berkley
import org.xml.sax.helpers.DefaultHandler;
47 522 berkley
48 561 berkley
49
50 522 berkley
/**
51
 * This class handles deltaT replication checking.  Whenever this TimerTask
52
 * is fired it checks each server in xml_replication for updates and updates
53
 * the local db as needed.
54
 */
55
public class ReplicationHandler extends TimerTask
56
{
57 573 berkley
  int serverCheckCode = 1;
58 522 berkley
  MetaCatUtil util = new MetaCatUtil();
59 1292 tao
  ReplicationServerList serverList = null;
60 522 berkley
  PrintWriter out;
61
62
  public ReplicationHandler(PrintWriter o)
63
  {
64
    this.out = o;
65 1292 tao
    serverList = new ReplicationServerList();
66 522 berkley
  }
67
68 573 berkley
  public ReplicationHandler(PrintWriter o, int serverCheckCode)
69
  {
70
    this.out = o;
71
    this.serverCheckCode = serverCheckCode;
72 1292 tao
    serverList = new ReplicationServerList();
73 573 berkley
  }
74
75 522 berkley
  /**
76
   * Method that implements TimerTask.run().  It runs whenever the timer is
77
   * fired.
78
   */
79
  public void run()
80
  {
81
    //find out the last_checked time of each server in the server list and
82
    //send a query to each server to see if there are any documents in
83
    //xml_documents with an update_date > last_checked
84
    try
85
    {
86 1032 tao
      //if serverList is null, metacat don't need to replication
87
      if (serverList==null||serverList.isEmpty())
88
      {
89
        return;
90
      }
91 1292 tao
      updateCatalog();
92
      update();
93 1217 tao
      //conn.close();
94
    }//try
95 522 berkley
    catch (Exception e)
96
    {
97 1217 tao
      MetaCatUtil.debugMessage("Error in replicationHandler.run():"
98
                                                    +e.getMessage(), 30);
99 1292 tao
      e.printStackTrace();
100 1217 tao
    }//catch
101 522 berkley
  }
102
103
  /**
104 577 berkley
   * Method that uses revision taging for replication instead of update_date.
105
   */
106 1292 tao
  private void update()
107 577 berkley
  {
108
    /*
109
     Pseudo-algorithm
110
     - request a doc list from each server in xml_replication
111
     - check the rev number of each of those documents agains the
112
       documents in the local database
113
     - pull any documents that have a lesser rev number on the local server
114
       from the remote server
115
     - delete any documents that still exist in the local xml_documents but
116
       are in the deletedDocuments tag of the remote host response.
117
     - update last_checked to keep track of the last time it was checked.
118
       (this info is theoretically not needed using this system but probably
119
       should be kept anyway)
120
    */
121 683 berkley
122 1292 tao
    ReplicationServer replServer = null; // Variable to store the
123
                                        // ReplicationServer got from
124
                                        // Server list
125
    String server; // Variable to store server name
126 577 berkley
    String update;
127
    ReplMessageHandler message = new ReplMessageHandler();
128
    Vector responses = new Vector();
129 1292 tao
    boolean flag=false; // If a document need to update
130 1037 tao
    boolean dataFile=false;
131 577 berkley
    String action = new String();
132
    XMLReader parser;
133
    URL u;
134
135 1585 tao
136 577 berkley
    try
137
    {
138
      parser = initParser(message);
139 1585 tao
    }
140
    catch (Exception e)
141
    {
142
      MetacatReplication.replErrorLog("Failed to replicate becaue couldn't "+
143
                                 " initParser for message and" +e.getMessage());
144
      MetaCatUtil.debugMessage("Failed to replicate becaue couldn't " +
145
                            " initParser for message and " +e.getMessage(), 30);
146
       // stop replication
147
       return;
148
    }
149
    //Check for every server in server list to get updated list and put
150
    // them in to response
151
    for (int i=0; i<serverList.size(); i++)
152
    {
153 1292 tao
        // Get ReplicationServer object from server list
154
        replServer = serverList.serverAt(i);
155
        // Get server name from ReplicationServer object
156
        server = replServer.getServerName();
157 1585 tao
        String result = null;
158 584 berkley
        MetacatReplication.replLog("full update started to: " + server);
159 1292 tao
        // Send command to that server to get updated docid information
160
        try
161
        {
162 1585 tao
          u = new URL("https://" + server + "?server="
163
          +util.getLocalReplicationServerName()+"&action=update");
164
          MetaCatUtil.debugMessage("Sending infomation " +u.toString(), 50);
165 1292 tao
          result = MetacatReplication.getURLContent(u);
166 1585 tao
        }
167 1292 tao
        catch (Exception e)
168
        {
169 1585 tao
          MetacatReplication.replErrorLog("Failed to get updated doc list "+
170
                          "for server " + server + " because "+e.getMessage());
171
          MetaCatUtil.debugMessage( "Failed to get updated doc list "+
172
                       "for server " + server + " because "+e.getMessage(), 30);
173 1292 tao
          continue;
174 1585 tao
        }
175
176 1292 tao
        MetaCatUtil.debugMessage("docid: "+server+" "+result, 50);
177
        //check if result have error or not, if has skip it.
178 1609 tao
        if (result.indexOf("<error>")!=-1 && result.indexOf("</error>")!=-1)
179 1102 tao
        {
180 1585 tao
          MetacatReplication.replErrorLog("Failed to get updated doc list "+
181
                          "for server " + server + " because "+result);
182
          MetaCatUtil.debugMessage( "Failed to get updated doc list "+
183
                       "for server " + server + " because "+result, 30);
184 1102 tao
          continue;
185
        }
186 1585 tao
        //Add result to vector
187 577 berkley
        responses.add(result);
188 1585 tao
    }
189 577 berkley
190 1585 tao
    //make sure that there is updated file list
191
    //If response is null, metacat don't need do anything
192
    if (responses==null || responses.isEmpty())
193
    {
194
        MetacatReplication.replErrorLog("No updated doc list for "+
195
                           "every server and failed to replicate");
196
        MetaCatUtil.debugMessage( "No updated doc list for "+
197
                           "every server and failed to replicate", 30);
198 1032 tao
        return;
199 1585 tao
    }
200 1292 tao
201 1032 tao
202 1585 tao
    MetaCatUtil.debugMessage("Responses from remote metacat about updated "+
203
                   "document information: "+ responses.toString(), 35);
204
    // go through response vector(it contains updated vector and delete vector
205
    for(int i=0; i<responses.size(); i++)
206
    {
207
        try
208
        {
209
          parser.parse(new InputSource(
210 577 berkley
                     new StringReader(
211
                     (String)(responses.elementAt(i)))));
212 1585 tao
        }
213
        catch(Exception e)
214
        {
215
          MetacatReplication.replErrorLog("Couldn't parse one responses "+
216
                           "because "+ e.getMessage());
217
          MetaCatUtil.debugMessage("Couldn't parse one responses "+
218
                                   "because "+ e.getMessage(), 30);
219
          continue;
220
        }
221 1037 tao
        //v is the list of updated documents
222 1585 tao
        Vector updateList = new Vector(message.getUpdatesVect());
223 577 berkley
        //System.out.println("v: " + v.toString());
224 1037 tao
        //d is the list of deleted documents
225 1585 tao
        Vector deleteList = new Vector(message.getDeletesVect());
226 1037 tao
        //System.out.println("d: " + d.toString());
227 1585 tao
        MetaCatUtil.debugMessage("Update vector size: "+ updateList.size(), 40);
228
        MetaCatUtil.debugMessage("Delete vector size: "+ deleteList.size(),40);
229
        // go though every element in updated document vector
230
        for(int j=0; j<updateList.size(); j++)
231 577 berkley
        {
232 1037 tao
          //initial dataFile is false
233
          dataFile=false;
234
          //w is information for one document, information contain
235
          //docid, rev, server or datafile.
236 1585 tao
          Vector w = new Vector((Vector)(updateList.elementAt(j)));
237 1037 tao
          //Check if the vector w contain "datafile"
238
          //If it has, this document is data file
239
          if (w.contains((String)util.getOption("datafileflag")))
240
          {
241
            dataFile=true;
242
          }
243 577 berkley
          //System.out.println("w: " + w.toString());
244 1292 tao
          // Get docid
245 577 berkley
          String docid = (String)w.elementAt(0);
246 1071 tao
          MetaCatUtil.debugMessage("docid: " + docid, 40);
247 1292 tao
          // Get revision number
248 577 berkley
          int rev = Integer.parseInt((String)w.elementAt(1));
249 1071 tao
          MetaCatUtil.debugMessage("rev: " + rev, 40);
250 1292 tao
          // Get remote server name (it is may not be doc homeserver because
251
          // the new hub feature
252
          String remoteServer = (String)w.elementAt(2);
253 1071 tao
254 1585 tao
255
          // compare the update rev and local rev to see what need happen
256
          int localrev = -1;
257
          try
258
          {
259
            localrev = DocumentImpl.getLatestRevisionNumber(docid);
260
          }
261
          catch (SQLException e)
262
          {
263
            MetaCatUtil.debugMessage("Local rev for docid "+ docid + " could not "+
264
                                   " be found because " + e.getMessage(), 45);
265
            MetacatReplication.replErrorLog("Docid "+ docid + " could not be "+
266
                    "written because error happend to find it's local revision");
267
            continue;
268
          }
269
          MetaCatUtil.debugMessage("Local rev for docid "+ docid + " is "+
270
                                  localrev, 45);
271
272
          //check the revs for an update because this document is in the
273
          //local DB, it might be out of date.
274
          if (localrev == -1)
275
          {
276
            //insert this document as new because it is not in the local DB
277
            action = "INSERT";
278
            flag = true;
279
          }
280
          else
281
          {
282 577 berkley
            if(localrev == rev)
283
            {
284 1292 tao
              // Local meatacat has the same rev to remote host, don't need
285
              // update and flag set false
286 577 berkley
              flag = false;
287
            }
288
            else if(localrev < rev)
289 1585 tao
            {
290
              //this document needs to be updated so send an read request
291 577 berkley
              action = "UPDATE";
292
              flag = true;
293
            }
294
          }
295 1585 tao
296 1037 tao
          // this is non-data file
297
          if(flag && !dataFile)
298 1585 tao
          {
299 625 berkley
            try
300
            {
301 1585 tao
              handleSingleXMLDocument(remoteServer, action, docid);
302 625 berkley
            }
303
            catch(Exception e)
304
            {
305 1585 tao
              // skip this document
306
              continue;
307 625 berkley
            }
308 1037 tao
          }//if for non-data file
309
310 1292 tao
           // this is for data file
311
          if(flag && dataFile)
312 1037 tao
          {
313
            try
314
            {
315 1585 tao
              handleSingleDataFile(remoteServer, action, docid);
316
            }
317 1037 tao
            catch(Exception e)
318
            {
319 1585 tao
              // skip this datafile
320
              continue;
321
            }
322
323 1037 tao
          }//for datafile
324
        }//for update docs
325 577 berkley
326 1037 tao
        //handle deleted docs
327 1585 tao
        for(int k=0; k<deleteList.size(); k++)
328 577 berkley
        { //delete the deleted documents;
329 1585 tao
          Vector w = new Vector((Vector)deleteList.elementAt(k));
330
          String docId = (String)w.elementAt(0);
331
          try
332 579 berkley
          {
333 1585 tao
            handleDeleteSingleDocument(docId);
334 579 berkley
          }
335 1585 tao
          catch (Exception ee)
336
          {
337
            continue;
338
          }
339 1037 tao
        }//for delete docs
340 1585 tao
    }//for response
341 1292 tao
342 1585 tao
    //updated last_checked
343
    for (int i=0;i<serverList.size(); i++)
344
    {
345
       // Get ReplicationServer object from server list
346
       replServer = serverList.serverAt(i);
347
       try
348
       {
349
         updateLastCheckTimeForSingleServer(replServer);
350
       }
351
       catch(Exception e)
352
       {
353
         continue;
354
       }
355
    }//for
356
357
  }//update
358
359
  /* Handle replicate single xml document*/
360
  private void handleSingleXMLDocument(String remoteserver, String actions,
361
                                       String docId)
362
               throws Exception
363
  {
364
    DBConnection dbConn = null;
365
    int serialNumber = -1;
366
    try
367
    {
368
      // Get DBConnection from pool
369
      dbConn=DBConnectionPool.
370
                  getDBConnection("ReplicationHandler.handleSingleXMLDocument");
371
      serialNumber=dbConn.getCheckOutSerialNumber();
372
      //if the document needs to be updated or inserted, this is executed
373 1600 tao
      String readDocURLString = "https://" + remoteserver + "?server="+
374
              util.getLocalReplicationServerName()+"&action=read&docid="+docId;
375
      readDocURLString = MetaCatUtil.replaceWhiteSpaceForURL(readDocURLString);
376
      URL u = new URL(readDocURLString);
377 1585 tao
378
      // Get docid content
379
      String newxmldoc = MetacatReplication.getURLContent(u);
380
      // If couldn't get skip it
381 1609 tao
      if ( newxmldoc.indexOf("<error>")!= -1 && newxmldoc.indexOf("</error>")!=-1)
382 1292 tao
      {
383 1585 tao
         throw new Exception(newxmldoc);
384
      }
385
      MetaCatUtil.debugMessage("xml documnet:", 45);
386
      MetaCatUtil.debugMessage(newxmldoc, 45);
387
388
      // Try get the docid info from remote server
389
      DocInfoHandler dih = new DocInfoHandler();
390
      XMLReader docinfoParser = initParser(dih);
391 1600 tao
      String docInfoURLStr = "https://" + remoteserver +
392 1585 tao
                       "?server="+util.getLocalReplicationServerName()+
393 1600 tao
                       "&action=getdocumentinfo&docid="+docId;
394
      docInfoURLStr = MetaCatUtil.replaceWhiteSpaceForURL(docInfoURLStr);
395
      URL docinfoUrl = new URL(docInfoURLStr);
396 1585 tao
      MetaCatUtil.debugMessage("Sending message: " +
397
                                                  docinfoUrl.toString(), 45);
398
      String docInfoStr = MetacatReplication.getURLContent(docinfoUrl);
399
      docinfoParser.parse(new InputSource(new StringReader(docInfoStr)));
400
      Hashtable docinfoHash = dih.getDocInfo();
401
      // Get home server of the docid
402
      String docHomeServer = (String)docinfoHash.get("home_server");
403
      MetaCatUtil.debugMessage("doc home server in repl: "+docHomeServer, 45);
404
405
      //docid should include rev number too
406
      String accnum=docId+util.getOption("accNumSeparator")+
407
                                              (String)docinfoHash.get("rev");
408
      MetaCatUtil.debugMessage("docid in repl: "+accnum, 45);
409
      String docType = (String)docinfoHash.get("doctype");
410
      MetaCatUtil.debugMessage("doctype in repl: "+docType, 45);
411
412
      String parserBase = null;
413
      // this for eml2 and we need user eml2 parser
414
      if (docType != null && (docType.trim()).equals(DocumentImpl.EMLNAMESPACE))
415
      {
416
         parserBase = DocumentImpl.EML2;
417
      }
418
      // Write the document into local host
419
      DocumentImplWrapper wrapper = new DocumentImplWrapper(parserBase, false);
420
      String newDocid = wrapper.writeReplication(dbConn,
421
                              new StringReader(newxmldoc),
422
                              (String)docinfoHash.get("public_access"),
423
                              null,  /* the dtd text */
424
                              actions,
425
                              accnum,
426
                              (String)docinfoHash.get("user_owner"),
427
                              null, /* null for groups[] */
428
                              docHomeServer,
429
                              remoteserver);
430
      MetaCatUtil.debugMessage("Successfully replicated doc " + accnum, 35);
431
      MetacatReplication.replLog("wrote doc " + accnum + " from " +
432
                                         remoteserver);
433
434
    }//try
435 577 berkley
    catch(Exception e)
436
    {
437 1585 tao
      MetacatReplication.replErrorLog("Failed to write doc " + docId +
438
                                      " into db because " +e.getMessage());
439
      MetaCatUtil.debugMessage("Failed to write doc " + docId +
440
                                      " into db because " +e.getMessage(), 30);
441
      throw e;
442 577 berkley
    }
443 667 berkley
    finally
444
    {
445 1585 tao
       //return DBConnection
446
       DBConnectionPool.returnDBConnection(dbConn, serialNumber);
447
    }//finally
448
  }
449
450
451
452
  /* Handle replicate single xml document*/
453
  private void handleSingleDataFile(String remoteserver, String actions,
454
                                    String docId)
455
               throws Exception
456
  {
457
    MetaCatUtil.debugMessage("Try to replicate data file: "+docId, 40);
458
    DBConnection dbConn = null;
459
    int serialNumber = -1;
460
    try
461
    {
462
      // Get DBConnection from pool
463
      dbConn=DBConnectionPool.
464
                  getDBConnection("ReplicationHandler.handleSinlgeDataFile");
465
      serialNumber=dbConn.getCheckOutSerialNumber();
466
      // Try get docid info from remote server
467
      DocInfoHandler dih = new DocInfoHandler();
468
      XMLReader docinfoParser = initParser(dih);
469 1600 tao
      String docInfoURLString = "https://" + remoteserver +
470 1585 tao
                  "?server="+util.getLocalReplicationServerName()+
471 1600 tao
                  "&action=getdocumentinfo&docid="+docId;
472
      docInfoURLString = MetaCatUtil.replaceWhiteSpaceForURL(docInfoURLString);
473
      URL docinfoUrl = new URL(docInfoURLString);
474
475 1585 tao
      String docInfoStr = MetacatReplication.getURLContent(docinfoUrl);
476
      docinfoParser.parse(new InputSource(new StringReader(docInfoStr)));
477
      Hashtable docinfoHash = dih.getDocInfo();
478
      // Get doicd owner
479
      String user = (String)docinfoHash.get("user_owner");
480
      // Get docid name (such as acl or dataset)
481
      String docName = (String)docinfoHash.get("docname");
482
      // Get doc type (eml public id)
483
      String docType = (String)docinfoHash.get("doctype");
484
      // Get docid home sever. it might be different to remoteserver
485
      // becuause of hub feature
486
      String docHomeServer = (String)docinfoHash.get("home_server");
487
488
      //docid should include rev number too
489
      String accnum=docId+util.getOption("accNumSeparator")+
490
                                              (String)docinfoHash.get("rev");
491 1600 tao
492
493 1585 tao
      String datafilePath = util.getOption("datafilepath");
494
      // Get data file content
495 1600 tao
      String readDataURLString = "https://" + remoteserver + "?server="+
496 1585 tao
                                        util.getLocalReplicationServerName()+
497 1600 tao
                                            "&action=readdata&docid="+accnum;
498
      readDataURLString = MetaCatUtil.replaceWhiteSpaceForURL(readDataURLString);
499
      URL u = new URL(readDataURLString);
500
      InputStream input = u.openStream();
501 1585 tao
      //register data file into xml_documents table and wite data file
502
      //into file system
503 1600 tao
      if ( input != null)
504 667 berkley
      {
505 1600 tao
        DocumentImpl.writeDataFileInReplication(input,
506 1585 tao
                                                        datafilePath,
507
                                                        docName,docType,
508
                                                        accnum, user,
509
                                                        docHomeServer,
510
                                                        remoteserver);
511
        MetaCatUtil.debugMessage("Successfully to write datafile " + docId, 30);
512
        MetacatReplication.replLog("wrote datafile " + accnum + " from " +
513
                                    remoteserver);
514
      }//if
515
      else
516 1217 tao
      {
517 1600 tao
         MetaCatUtil.debugMessage("Couldn't open the data file: " + accnum, 30);
518 1585 tao
         throw new Exception("Couldn't open the data file: " + accnum);
519
      }//else
520
521
    }//try
522
    catch(Exception e)
523
    {
524
      MetacatReplication.replErrorLog("Failed to try wrote datafile " + docId +
525
                                      " because " +e.getMessage());
526
      MetaCatUtil.debugMessage("Failed to try wrote datafile " + docId +
527
                                      " because " +e.getMessage(), 30);
528
      throw e;
529
    }
530
    finally
531
    {
532
       //return DBConnection
533
       DBConnectionPool.returnDBConnection(dbConn, serialNumber);
534
    }//finally
535
  }
536
537
538
539
  /* Handle delete single document*/
540
  private void handleDeleteSingleDocument(String docId)
541
               throws Exception
542
  {
543
    MetaCatUtil.debugMessage("Try delete doc: "+docId, 40);
544
    DBConnection dbConn = null;
545
    int serialNumber = -1;
546
    try
547
    {
548
      // Get DBConnection from pool
549
      dbConn=DBConnectionPool.
550
                  getDBConnection("ReplicationHandler.handleDeleteSingleDoc");
551
      serialNumber=dbConn.getCheckOutSerialNumber();
552
      if(!alreadyDeleted(docId))
553 1217 tao
      {
554 1585 tao
555
         //because delete method docid should have rev number
556
         //so we just add one for it. This rev number is no sence.
557
         String accnum=docId+util.getOption("accNumSeparator")+"1";
558
         //System.out.println("accnum: "+accnum);
559
         DocumentImpl.delete(accnum, null, null);
560
         MetaCatUtil.debugMessage("Successfully deleted doc " + docId, 30);
561
         MetacatReplication.replLog("Doc " + docId + " deleted");
562
      }
563
564
    }//try
565
    catch(Exception e)
566
    {
567
      MetacatReplication.replErrorLog("Failed to delete doc " + docId +
568
                                      " in db because " +e.getMessage());
569
      MetaCatUtil.debugMessage("Failed to delete doc " + docId +
570
                                 " in db because because " +e.getMessage(), 30);
571
      throw e;
572
    }
573
    finally
574
    {
575
       //return DBConnection
576
       DBConnectionPool.returnDBConnection(dbConn, serialNumber);
577 1037 tao
    }//finally
578 1585 tao
  }
579 577 berkley
580 1585 tao
  /* Handle updateLastCheckTimForSingleServer*/
581
  private void updateLastCheckTimeForSingleServer(ReplicationServer repServer)
582
                                                  throws Exception
583 590 berkley
  {
584 1585 tao
    String server = repServer.getServerName();
585 1217 tao
    DBConnection dbConn = null;
586
    int serialNumber = -1;
587
    PreparedStatement pstmt = null;
588 590 berkley
    try
589
    {
590 1585 tao
      // Get DBConnection from pool
591 1217 tao
      dbConn=DBConnectionPool.
592 1585 tao
             getDBConnection("ReplicationHandler.updateLastCheckTimeForServer");
593 1217 tao
      serialNumber=dbConn.getCheckOutSerialNumber();
594 1292 tao
595 1585 tao
      MetaCatUtil.debugMessage("Try to update last_check for server: "+server, 40);
596
      // Get time from remote server
597
      URL dateurl = new URL("https://" + server + "?server="+
598
      util.getLocalReplicationServerName()+"&action=gettime");
599
      String datexml = MetacatReplication.getURLContent(dateurl);
600
      MetaCatUtil.debugMessage("datexml: "+datexml, 45);
601
      if (datexml!=null && !datexml.equals(""))
602
      {
603
         String datestr = datexml.substring(11, datexml.indexOf('<', 11));
604
         StringBuffer sql = new StringBuffer();
605
         sql.append("update xml_replication set last_checked = to_date('");
606
         sql.append(datestr).append("', 'YY-MM-DD HH24:MI:SS') where ");
607
         sql.append("server like '").append(server).append("'");
608
         //System.out.println("sql: " + sql.toString());
609
         pstmt = dbConn.prepareStatement(sql.toString());
610
         pstmt.executeUpdate();
611
         dbConn.commit();
612
         pstmt.close();
613
         MetaCatUtil.debugMessage("last_checked updated to "+datestr+" on "
614
                                      + server, 45);
615
      }//if
616
      else
617
      {
618
619
         MetaCatUtil.debugMessage("Failed to update last_checked for server "  +
620
                                  server + " in db because couldn't get time "
621
                                  , 30);
622
         throw new Exception("Couldn't get time for server "+ server);
623
      }
624
625
    }//try
626
    catch(Exception e)
627
    {
628
629
      MetaCatUtil.debugMessage("Failed to update last_checked for server " +
630
                                server + " in db because because " +
631
                                e.getMessage(), 30);
632
      throw e;
633
    }
634
    finally
635
    {
636
       //return DBConnection
637
       DBConnectionPool.returnDBConnection(dbConn, serialNumber);
638
    }//finally
639
  }
640
641
642
643
  /**
644
   * updates xml_catalog with entries from other servers.
645
   */
646
  private void updateCatalog()
647
  {
648
    MetaCatUtil.debugMessage("Start of updateCatalog", 35 );
649
    // ReplicationServer object in server list
650
    ReplicationServer replServer = null;
651
    PreparedStatement pstmt = null;
652
    String server = null;
653
654
655
    // Go through each ReplicationServer object in sererlist
656
    for (int j=0; j<serverList.size(); j++)
657
    {
658
      Vector remoteCatalog = new Vector();
659
      Vector publicId = new Vector();
660
      try
661
      {
662 1292 tao
        // Get ReplicationServer object from server list
663
        replServer = serverList.serverAt(j);
664
        // Get server name from the ReplicationServer object
665
        server = replServer.getServerName();
666
        // Try to get catalog
667 1011 tao
        URL u = new URL("https://" + server + "?server="+
668 1015 tao
        util.getLocalReplicationServerName()+"&action=getcatalog");
669 1292 tao
        MetaCatUtil.debugMessage("sending message " + u.toString(), 50);
670 590 berkley
        String catxml = MetacatReplication.getURLContent(u);
671 1292 tao
672
        // Make sure there are not error, no empty string
673
        if (catxml.indexOf("error")!=-1 || catxml==null||catxml.equals(""))
674
        {
675 1585 tao
          throw new Exception("Couldn't get catalog list form server " +server);
676 1292 tao
        }
677 1585 tao
        MetaCatUtil.debugMessage("catxml: " + catxml, 40);
678 590 berkley
        CatalogMessageHandler cmh = new CatalogMessageHandler();
679
        XMLReader catparser = initParser(cmh);
680
        catparser.parse(new InputSource(new StringReader(catxml)));
681
        //parse the returned catalog xml and put it into a vector
682 1585 tao
        remoteCatalog = cmh.getCatalogVect();
683 590 berkley
684 1292 tao
        // Makse sure remoteCatalog is not empty
685
        if (remoteCatalog.isEmpty())
686
        {
687 1585 tao
          throw new Exception("Couldn't get catalog list form server " +server);
688 1292 tao
        }
689
690 590 berkley
        String localcatxml = MetacatReplication.getCatalogXML();
691 1292 tao
692
        // Make sure local catalog is no empty
693
        if (localcatxml==null||localcatxml.equals(""))
694
        {
695 1585 tao
          throw new Exception("Couldn't get catalog list form server " +server);
696 1292 tao
        }
697
698 590 berkley
        cmh = new CatalogMessageHandler();
699
        catparser = initParser(cmh);
700
        catparser.parse(new InputSource(new StringReader(localcatxml)));
701
        Vector localCatalog = cmh.getCatalogVect();
702
703
        //now we have the catalog from the remote server and this local server
704
        //we now need to compare the two and merge the differences.
705
        //the comparison is base on the public_id fields which is the 4th
706
        //entry in each row vector.
707 1585 tao
        publicId = new Vector();
708 590 berkley
        for(int i=0; i<localCatalog.size(); i++)
709
        {
710
          Vector v = new Vector((Vector)localCatalog.elementAt(i));
711 1292 tao
          MetaCatUtil.debugMessage("v1: " + v.toString(), 50);
712 590 berkley
          publicId.add(new String((String)v.elementAt(3)));
713 595 berkley
          //System.out.println("adding " + (String)v.elementAt(3));
714 590 berkley
        }
715 1585 tao
      }//try
716
      catch (Exception e)
717
      {
718
        MetacatReplication.replErrorLog("Failed to update catalog for server "+
719
                                    server + " because " +e.getMessage());
720
        MetaCatUtil.debugMessage("Failed to update catalog for server "+
721
                                    server + " because " +e.getMessage(), 30);
722
      }//catch
723
724
      for(int i=0; i<remoteCatalog.size(); i++)
725
      {
726
         // DConnection
727
        DBConnection dbConn = null;
728
        // DBConnection checkout serial number
729
        int serialNumber = -1;
730
        try
731 590 berkley
        {
732 1585 tao
            dbConn=DBConnectionPool.
733
                  getDBConnection("ReplicationHandler.updateCatalog");
734
            serialNumber=dbConn.getCheckOutSerialNumber();
735
            Vector v = (Vector)remoteCatalog.elementAt(i);
736
            //System.out.println("v2: " + v.toString());
737
            //System.out.println("i: " + i);
738
            //System.out.println("remoteCatalog.size(): " + remoteCatalog.size());
739
            //System.out.println("publicID: " + publicId.toString());
740
            MetaCatUtil.debugMessage
741 1292 tao
                              ("v.elementAt(3): " + (String)v.elementAt(3), 50);
742 1585 tao
           if(!publicId.contains(v.elementAt(3)))
743
           { //so we don't have this public id in our local table so we need to
744
             //add it.
745
             //System.out.println("in if");
746
             StringBuffer sql = new StringBuffer();
747
             sql.append("insert into xml_catalog (entry_type, source_doctype, ");
748
             sql.append("target_doctype, public_id, system_id) values (?,?,?,");
749
             sql.append("?,?)");
750
             //System.out.println("sql: " + sql.toString());
751
             pstmt = dbConn.prepareStatement(sql.toString());
752
             pstmt.setString(1, (String)v.elementAt(0));
753
             pstmt.setString(2, (String)v.elementAt(1));
754
             pstmt.setString(3, (String)v.elementAt(2));
755
             pstmt.setString(4, (String)v.elementAt(3));
756
             pstmt.setString(5, (String)v.elementAt(4));
757
             pstmt.execute();
758
             pstmt.close();
759
             MetacatReplication.replLog("Success fully to insert new publicid "+
760
                               (String)v.elementAt(3) + " from server"+server);
761
             MetaCatUtil.debugMessage("Success fully to insert new publicid "+
762
                             (String)v.elementAt(3) + " from server" +server, 30);
763
           }
764 590 berkley
        }
765 1585 tao
        catch(Exception e)
766
        {
767
           MetacatReplication.replErrorLog("Failed to update catalog for server "+
768
                                    server + " because " +e.getMessage());
769
           MetaCatUtil.debugMessage("Failed to update catalog for server "+
770
                                    server + " because " +e.getMessage(), 30);
771
        }//catch
772
        finally
773
        {
774
           DBConnectionPool.returnDBConnection(dbConn, serialNumber);
775
        }//finall
776
      }//for remote catalog
777
    }//for server list
778
    MetaCatUtil.debugMessage("End of updateCatalog", 35);
779 590 berkley
  }
780
781
  /**
782 579 berkley
   * Method that returns true if docid has already been "deleted" from metacat.
783 582 berkley
   * This method really implements a truth table for deleted documents
784 590 berkley
   * The table is (a docid in one of the tables is represented by the X):
785 582 berkley
   * xml_docs      xml_revs      deleted?
786
   * ------------------------------------
787
   *   X             X             FALSE
788
   *   X             _             FALSE
789
   *   _             X             TRUE
790
   *   _             _             TRUE
791 579 berkley
   */
792 1585 tao
  private static boolean alreadyDeleted(String docid) throws Exception
793 579 berkley
  {
794 1217 tao
    DBConnection dbConn = null;
795
    int serialNumber = -1;
796
    PreparedStatement pstmt = null;
797 579 berkley
    try
798
    {
799 1217 tao
      dbConn=DBConnectionPool.
800
                  getDBConnection("ReplicationHandler.alreadyDeleted");
801
      serialNumber=dbConn.getCheckOutSerialNumber();
802 582 berkley
      boolean xml_docs = false;
803
      boolean xml_revs = false;
804
805 579 berkley
      StringBuffer sb = new StringBuffer();
806 582 berkley
      sb.append("select docid from xml_revisions where docid like '");
807 579 berkley
      sb.append(docid).append("'");
808 1217 tao
      pstmt = dbConn.prepareStatement(sb.toString());
809 579 berkley
      pstmt.execute();
810
      ResultSet rs = pstmt.getResultSet();
811
      boolean tablehasrows = rs.next();
812
      if(tablehasrows)
813
      {
814 582 berkley
        xml_revs = true;
815
      }
816
817
      sb = new StringBuffer();
818
      sb.append("select docid from xml_documents where docid like '");
819
      sb.append(docid).append("'");
820 667 berkley
      pstmt.close();
821 1217 tao
      pstmt = dbConn.prepareStatement(sb.toString());
822
      //increase usage count
823
      dbConn.increaseUsageCount(1);
824 582 berkley
      pstmt.execute();
825
      rs = pstmt.getResultSet();
826
      tablehasrows = rs.next();
827 667 berkley
      pstmt.close();
828 582 berkley
      if(tablehasrows)
829
      {
830
        xml_docs = true;
831
      }
832
833
      if(xml_docs && xml_revs)
834
      {
835
        return false;
836
      }
837
      else if(xml_docs && !xml_revs)
838
      {
839
        return false;
840
      }
841
      else if(!xml_docs && xml_revs)
842
      {
843 579 berkley
        return true;
844
      }
845 582 berkley
      else if(!xml_docs && !xml_revs)
846
      {
847
        return true;
848
      }
849 579 berkley
    }
850
    catch(Exception e)
851
    {
852 1585 tao
      MetaCatUtil.debugMessage("error in ReplicationHandler.alreadyDeleted: " +
853
                          e.getMessage(), 30);
854
      throw e;
855 579 berkley
    }
856 667 berkley
    finally
857
    {
858 1217 tao
      try
859
      {
860
        pstmt.close();
861
      }//try
862
      catch (SQLException ee)
863
      {
864
        MetaCatUtil.debugMessage("Error in replicationHandler.alreadyDeleted "+
865
                          "to close pstmt: "+ee.getMessage(), 30);
866 1585 tao
        throw ee;
867 1217 tao
      }//catch
868
      finally
869
      {
870
        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
871
      }//finally
872
    }//finally
873 579 berkley
    return false;
874
  }
875 533 berkley
876
877
  /**
878 574 berkley
   * Method to initialize the message parser
879
   */
880
  public static XMLReader initParser(DefaultHandler dh)
881
          throws Exception
882
  {
883
    XMLReader parser = null;
884
885
    try {
886
      ContentHandler chandler = dh;
887
888
      // Get an instance of the parser
889
      MetaCatUtil util = new MetaCatUtil();
890
      String parserName = util.getOption("saxparser");
891
      parser = XMLReaderFactory.createXMLReader(parserName);
892
893
      // Turn off validation
894
      parser.setFeature("http://xml.org/sax/features/validation", false);
895
896
      parser.setContentHandler((ContentHandler)chandler);
897
      parser.setErrorHandler((ErrorHandler)chandler);
898
899
    } catch (Exception e) {
900
      throw e;
901
    }
902
903
    return parser;
904
  }
905 1011 tao
906 1015 tao
907 522 berkley
}