Project

General

Profile

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