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