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