Project

General

Profile

1 522 berkley
/**
2
 *  '$RCSfile$'
3
 *    Purpose: A Class that implements replication for metacat
4
 *  Copyright: 2000 Regents of the University of California and the
5
 *             National Center for Ecological Analysis and Synthesis
6
 *    Authors: Chad Berkley
7
 *    Release: @release@
8
 *
9
 *   '$Author$'
10
 *     '$Date$'
11
 * '$Revision$'
12 669 jones
 *
13
 * This program is free software; you can redistribute it and/or modify
14
 * it under the terms of the GNU General Public License as published by
15
 * the Free Software Foundation; either version 2 of the License, or
16
 * (at your option) any later version.
17
 *
18
 * This program is distributed in the hope that it will be useful,
19
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21
 * GNU General Public License for more details.
22
 *
23
 * You should have received a copy of the GNU General Public License
24
 * along with this program; if not, write to the Free Software
25
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26 522 berkley
 */
27
28
package edu.ucsb.nceas.metacat;
29
30 1751 tao
import edu.ucsb.nceas.dbadapter.AbstractDatabase;
31 522 berkley
import java.util.*;
32
import java.io.*;
33
import java.sql.*;
34
import java.net.*;
35
import java.lang.*;
36
import java.text.*;
37
import javax.servlet.*;
38
import javax.servlet.http.*;
39 574 berkley
40 522 berkley
import org.xml.sax.*;
41
42 561 berkley
public class MetacatReplication extends HttpServlet implements Runnable
43 522 berkley
{
44
  private String deltaT;
45
  Timer replicationDaemon;
46 561 berkley
  private static MetaCatUtil util = new MetaCatUtil();
47
  private Vector fileLocks = new Vector();
48
  private Thread lockThread = null;
49 1751 tao
  private static final AbstractDatabase dbAdapter = MetaCatUtil.dbAdapter;
50 522 berkley
51
  /**
52
   * Initialize the servlet by creating appropriate database connections
53
   */
54
  public void init(ServletConfig config) throws ServletException
55
  {
56 1599 tao
     //initialize db connections to handle any update requests
57 522 berkley
    MetaCatUtil util = new MetaCatUtil();
58
    deltaT = util.getOption("deltaT");
59 583 berkley
    //the default deltaT can be set from metacat.properties
60
    //create a thread to do the delta-T check but don't execute it yet
61 522 berkley
    replicationDaemon = new Timer(true);
62 1606 tao
    /*java.net.URL.setURLStreamHandlerFactory(
63 1599 tao
       new java.net.URLStreamHandlerFactory()
64
       {
65
          public java.net.URLStreamHandler createURLStreamHandler(
66
                        final String protocol)
67
          {
68
              if ("http".equals(protocol))
69
              {
70
                 try
71
                 {
72
                    URLStreamHandler urlsh = new HTTPClient.http.Handler();
73
                    MetaCatUtil.debugMessage("Using HttpClient Protocol Handler for http", 45);
74
                    return urlsh;
75
                  }
76
                  catch (Exception e)
77
                  {
78
                     MetaCatUtil.debugMessage(
79
                          "Error setting URL StreamHandler!", 30);
80
                     return null;
81
                  }
82
               }//if
83
               else if ("https".equals(protocol))
84
               {
85
                 try
86
                 {
87
                   URLStreamHandler urlsh = new HTTPClient.https.Handler();
88
                   MetaCatUtil.debugMessage("Using HttpClient Protocol Handler for https", 45);
89
                   return urlsh;
90
                 }
91
                 catch (Exception e)
92
                 {
93
                   MetaCatUtil.debugMessage(
94
                              "Error setting URL StreamHandler!", 30);
95
                   return null;
96
                 }
97
              }
98
              return null;
99
         }//createURLStreamHandler
100 1606 tao
     });*/
101 1599 tao
102 522 berkley
  }
103
104
  public void destroy()
105
  {
106
    replicationDaemon.cancel();
107 840 bojilova
   // System.out.println("Replication daemon cancelled.");
108 522 berkley
  }
109
110
  public void doGet (HttpServletRequest request, HttpServletResponse response)
111
                     throws ServletException, IOException
112
  {
113
    // Process the data and send back the response
114
    handleGetOrPost(request, response);
115
  }
116
117
  public void doPost(HttpServletRequest request, HttpServletResponse response)
118
                     throws ServletException, IOException
119
  {
120
    // Process the data and send back the response
121
    handleGetOrPost(request, response);
122
  }
123
124
  private void handleGetOrPost(HttpServletRequest request,
125
                               HttpServletResponse response)
126
                               throws ServletException, IOException
127
  {
128 1020 tao
    //PrintWriter out = response.getWriter();
129
    //ServletOutputStream outPut = response.getOutputStream();
130 522 berkley
    Hashtable params = new Hashtable();
131 1020 tao
    Enumeration paramlist = request.getParameterNames();
132 522 berkley
133 1292 tao
134 1020 tao
135 837 bojilova
// NOT NEEDED - doesn't provide enough security because of possible IP spoofing
136
// REPLACED with running replication comminications over HTTPS
137
//    String requestingServerIP = request.getRemoteAddr();
138
//    InetAddress iaddr = InetAddress.getByName(requestingServerIP);
139
//    String requestingServer = iaddr.getHostName();
140 727 berkley
141 837 bojilova
    while (paramlist.hasMoreElements()) {
142 522 berkley
      String name = (String)paramlist.nextElement();
143
      String[] value = request.getParameterValues(name);
144
      params.put(name, value);
145
    }
146
147 840 bojilova
    String action = ((String[])params.get("action"))[0];
148
    String server = null;
149 727 berkley
150 837 bojilova
    try {
151
      // check if the server is included in the list of replicated servers
152 840 bojilova
      if ( !action.equals("servercontrol") &&
153
           !action.equals("stop") &&
154
           !action.equals("start") &&
155
           !action.equals("getall") ) {
156
157
        server = ((String[])params.get("server"))[0];
158 1292 tao
        if ( getServerCodeForServerName(server) == 0 ) {
159 840 bojilova
          System.out.println("Action \"" + action +
160
                             "\" rejected for server: " + server);
161
          return;
162
        } else {
163
          System.out.println("Action \"" + action +
164
                             "\" accepted for server: " + server);
165
        }
166 727 berkley
      }
167 837 bojilova
    } catch (Exception e) {
168
      System.out.println("Error in MetacatReplication.handleGetOrPost: " +
169
                         e.getMessage() );
170 727 berkley
      return;
171
    }
172 1020 tao
    if ( action.equals("readdata") )
173
    {
174 1023 tao
      OutputStream out=response.getOutputStream();
175 1020 tao
      //to get the data file.
176
      handleGetDataFileRequest(out, params, response);
177
      out.close();
178
    }
179 1023 tao
    else if ( action.equals("forcereplicatedatafile") )
180
    {
181
      //read a specific docid from remote host, and store it into local host
182
      handleForceReplicateDataFileRequest(params);
183 1292 tao
184 1023 tao
    }
185 1020 tao
    else
186
    {
187
    PrintWriter out = response.getWriter();
188 840 bojilova
    if ( action.equals("stop") ) {
189 837 bojilova
      //stop the replication server
190
      replicationDaemon.cancel();
191
      replicationDaemon = new Timer(true);
192
      out.println("Replication Handler Stopped");
193
      MetacatReplication.replLog("deltaT handler stopped");
194 1020 tao
195 837 bojilova
196 840 bojilova
    } else if ( action.equals("start") ) {
197 1020 tao
198 837 bojilova
      //start the replication server
199
      int rate;
200
      if ( params.containsKey("rate") ) {
201
        rate = new Integer(
202
               new String(((String[])params.get("rate"))[0])).intValue();
203
        if(rate < 30) {
204 549 berkley
            out.println("Replication deltaT rate cannot be less than 30!");
205 583 berkley
            //deltaT<30 is a timing mess!
206 549 berkley
            rate = 1000;
207
        }
208 837 bojilova
      } else {
209
        rate = 1000;
210
      }
211
      out.println("New rate is: " + rate + " seconds.");
212
      replicationDaemon.cancel();
213
      replicationDaemon = new Timer(true);
214
      replicationDaemon.scheduleAtFixedRate(new ReplicationHandler(out), 0,
215
                                            rate * 1000);
216
      out.println("Replication Handler Started");
217
      MetacatReplication.replLog("deltaT handler started with rate=" +
218 584 berkley
                                    rate + " seconds");
219 1020 tao
220 837 bojilova
221 840 bojilova
    } else if ( action.equals("getall") ) {
222 837 bojilova
      //updates this server exactly once
223
      replicationDaemon.schedule(new ReplicationHandler(out), 0);
224
      response.setContentType("text/html");
225
      out.println("<html><body>\"Get All\" Done</body></html>");
226
227 840 bojilova
    } else if ( action.equals("forcereplicate") ) {
228 1020 tao
      //read a specific docid from remote host, and store it into local host
229 837 bojilova
      handleForceReplicateRequest(out, params, response);
230 1023 tao
231 840 bojilova
    } else if ( action.equals("update") ) {
232 837 bojilova
      //request an update list from the server
233
      handleUpdateRequest(out, params, response);
234
235 840 bojilova
    } else if ( action.equals("read") ) {
236 837 bojilova
      //request a specific document from the server
237
      //note that this could be replaced by a call to metacatServlet
238
      //handleGetDocumentAction().
239
      handleGetDocumentRequest(out, params, response);
240 840 bojilova
    } else if ( action.equals("getlock") ) {
241 837 bojilova
      handleGetLockRequest(out, params, response);
242
243 840 bojilova
    } else if ( action.equals("getdocumentinfo") ) {
244 837 bojilova
      handleGetDocumentInfoRequest(out, params, response);
245
246 840 bojilova
    } else if ( action.equals("gettime") ) {
247 837 bojilova
      handleGetTimeRequest(out, params, response);
248
249 840 bojilova
    } else if ( action.equals("getcatalog") ) {
250 837 bojilova
      handleGetCatalogRequest(out, params, response, true);
251
252 840 bojilova
    } else if ( action.equals("servercontrol") ) {
253 837 bojilova
      handleServerControlRequest(out, params, response);
254 1097 tao
    } else if ( action.equals("test") ) {
255
      response.setContentType("text/html");
256
      out.println("<html><body>Test successfully</body></html>");
257 837 bojilova
    }
258 840 bojilova
259
    out.close();
260 1020 tao
    }//else
261 522 berkley
  }
262
263 595 berkley
  /**
264
   * This method can add, delete and list the servers currently included in
265
   * xml_replication.
266
   * action           subaction            other needed params
267
   * ---------------------------------------------------------
268
   * servercontrol    add                  server
269
   * servercontrol    delete               server
270
   * servercontrol    list
271
   */
272
  private void handleServerControlRequest(PrintWriter out, Hashtable params,
273
                                          HttpServletResponse response)
274
  {
275
    String subaction = ((String[])params.get("subaction"))[0];
276 1217 tao
    DBConnection dbConn = null;
277
    int serialNumber = -1;
278
    PreparedStatement pstmt = null;
279 1292 tao
    String replicate =null;
280
    String server = null;
281
    String dataReplicate = null;
282
    String hub = null;
283 837 bojilova
    try {
284 1217 tao
      //conn = util.openDBConnection();
285
      dbConn=DBConnectionPool.
286
               getDBConnection("MetacatReplication.handleServerControlRequest");
287
      serialNumber=dbConn.getCheckOutSerialNumber();
288
289 837 bojilova
      // add server to server list
290
      if ( subaction.equals("add") ) {
291 1292 tao
        replicate = ((String[])params.get("replicate"))[0];
292
        server = ((String[])params.get("server"))[0];
293 1756 tao
294 1292 tao
        //Get data replication value
295
        dataReplicate = ((String[])params.get("datareplicate"))[0];
296
        //Get hub value
297
        hub = ((String[])params.get("hub"))[0];
298
299 1751 tao
        /*pstmt = dbConn.prepareStatement("INSERT INTO xml_replication " +
300 1292 tao
                  "(server, last_checked, replicate, datareplicate, hub) " +
301 837 bojilova
                                      "VALUES ('" + server + "', to_date(" +
302
                                      "'01/01/00', 'MM/DD/YY'), '" +
303 1292 tao
                                      replicate +"', '" +dataReplicate+"', '"
304 1751 tao
                                      + hub +"')");*/
305
        pstmt = dbConn.prepareStatement("INSERT INTO xml_replication " +
306
                  "(server, last_checked, replicate, datareplicate, hub) " +
307
                                      "VALUES ('" + server + "', "+
308 1756 tao
                                      dbAdapter.toDate("01/01/80", "MM/DD/YY")
309 1751 tao
                                      + ", '" +
310
                                      replicate +"', '" +dataReplicate+"', '"
311 1292 tao
                                      + hub +"')");
312 1756 tao
313 595 berkley
        pstmt.execute();
314 837 bojilova
        pstmt.close();
315 1217 tao
        dbConn.commit();
316 837 bojilova
        out.println("Server " + server + " added");
317 631 berkley
        response.setContentType("text/html");
318
        out.println("<html><body><table border=\"1\">");
319
        out.println("<tr><td><b>server</b></td><td><b>last_checked</b></td><td>");
320 1292 tao
        out.println("<b>replicate</b></td>");
321
        out.println("<td><b>datareplicate</b></td>");
322
        out.println("<td><b>hub</b></td></tr>");
323 1217 tao
        pstmt = dbConn.prepareStatement("SELECT * FROM xml_replication");
324
        //increase dbconnection usage
325
        dbConn.increaseUsageCount(1);
326
327 631 berkley
        pstmt.execute();
328
        ResultSet rs = pstmt.getResultSet();
329
        boolean tablehasrows = rs.next();
330 837 bojilova
        while(tablehasrows) {
331 631 berkley
          out.println("<tr><td>" + rs.getString(2) + "</td><td>");
332
          out.println(rs.getString(3) + "</td><td>");
333 1292 tao
          out.println(rs.getString(4) + "</td><td>");
334
          out.println(rs.getString(5) + "</td><td>");
335
          out.println(rs.getString(6) + "</td></tr>");
336
337 631 berkley
          tablehasrows = rs.next();
338
        }
339
        out.println("</table></body></html>");
340 840 bojilova
341
        // download certificate with the public key on this server
342
        // and import it as a trusted certificate
343
        String certURL = ((String[])params.get("certificate"))[0];
344
        downloadCertificate(certURL);
345
346 837 bojilova
      // delete server from server list
347
      } else if ( subaction.equals("delete") ) {
348 1292 tao
        server = ((String[])params.get("server"))[0];
349 1217 tao
        pstmt = dbConn.prepareStatement("DELETE FROM xml_replication " +
350 837 bojilova
                                      "WHERE server LIKE '" + server + "'");
351 595 berkley
        pstmt.execute();
352 837 bojilova
        pstmt.close();
353 1217 tao
        dbConn.commit();
354 837 bojilova
        out.println("Server " + server + " deleted");
355 631 berkley
        response.setContentType("text/html");
356
        out.println("<html><body><table border=\"1\">");
357
        out.println("<tr><td><b>server</b></td><td><b>last_checked</b></td><td>");
358 1292 tao
        out.println("<b>replicate</b></td>");
359
        out.println("<td><b>datareplicate</b></td>");
360
        out.println("<td><b>hub</b></td></tr>");
361
362 1217 tao
        pstmt = dbConn.prepareStatement("SELECT * FROM xml_replication");
363
        //increase dbconnection usage
364
        dbConn.increaseUsageCount(1);
365 631 berkley
        pstmt.execute();
366
        ResultSet rs = pstmt.getResultSet();
367
        boolean tablehasrows = rs.next();
368
        while(tablehasrows)
369
        {
370
          out.println("<tr><td>" + rs.getString(2) + "</td><td>");
371
          out.println(rs.getString(3) + "</td><td>");
372 1292 tao
          out.println(rs.getString(4) + "</td><td>");
373
          out.println(rs.getString(5) + "</td><td>");
374
          out.println(rs.getString(6) + "</td></tr>");
375 631 berkley
          tablehasrows = rs.next();
376
        }
377
        out.println("</table></body></html>");
378 837 bojilova
379
      // list servers in server list
380
      } else if ( subaction.equals("list") ) {
381 595 berkley
        response.setContentType("text/html");
382
        out.println("<html><body><table border=\"1\">");
383 629 berkley
        out.println("<tr><td><b>server</b></td><td><b>last_checked</b></td><td>");
384 1292 tao
        out.println("<b>replicate</b></td>");
385
        out.println("<td><b>datareplicate</b></td>");
386
        out.println("<td><b>hub</b></td></tr>");
387 1217 tao
        pstmt = dbConn.prepareStatement("SELECT * FROM xml_replication");
388 595 berkley
        pstmt.execute();
389
        ResultSet rs = pstmt.getResultSet();
390
        boolean tablehasrows = rs.next();
391 837 bojilova
        while(tablehasrows) {
392 595 berkley
          out.println("<tr><td>" + rs.getString(2) + "</td><td>");
393 629 berkley
          out.println(rs.getString(3) + "</td><td>");
394 1292 tao
          out.println(rs.getString(4) + "</td><td>");
395
          out.println(rs.getString(5) + "</td><td>");
396
          out.println(rs.getString(6) + "</td></tr>");
397 595 berkley
          tablehasrows = rs.next();
398
        }
399
        out.println("</table></body></html>");
400 1292 tao
      }
401
      else
402
      {
403
404
        out.println("<error>Unkonwn subaction</error>");
405
406 595 berkley
      }
407 667 berkley
      pstmt.close();
408 1217 tao
      //conn.close();
409 837 bojilova
410
    } catch(Exception e) {
411
      System.out.println("Error in " +
412 675 berkley
                         "MetacatReplication.handleServerControlRequest " +
413 595 berkley
                         e.getMessage());
414
      e.printStackTrace(System.out);
415
    }
416 1217 tao
    finally
417
    {
418
      try
419
      {
420
        pstmt.close();
421
      }//try
422
      catch (SQLException ee)
423
      {
424
        MetaCatUtil.debugMessage("Error in " +
425
                "MetacatReplication.handleServerControlRequest to close pstmt "
426 1498 tao
                 + ee.getMessage(), 30);
427 1217 tao
      }//catch
428
      finally
429
      {
430
        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
431
      }//finally
432
    }//finally
433
434 595 berkley
  }
435
436 840 bojilova
  // download certificate with the public key from certURL and
437
  // upload it onto this server; it then must be imported as a
438
  // trusted certificate
439
  private void downloadCertificate (String certURL)
440
                throws FileNotFoundException, IOException, MalformedURLException
441
  {
442
    MetaCatUtil util = new MetaCatUtil();
443
    String certPath = util.getOption("certPath"); //the path to be uploaded to
444
445
    // get filename from the URL of the certificate
446
    String filename = certURL;
447
    int slash = Math.max(filename.lastIndexOf('/'), filename.lastIndexOf('\\'));
448
    if ( slash > -1 ) {
449
      filename = filename.substring(slash + 1);
450
    }
451
452
    // open file output strem to write the input into it
453
    File f = new File(certPath, filename);
454
    synchronized (f) {
455
      try {
456
        if ( f.exists() ) {
457
          throw new IOException("File already exist: " + f.getCanonicalFile());
458
          //if ( f.exists() && !f.canWrite() ) {
459
          //  throw new IOException("Not writable: " + f.getCanonicalFile());
460
        }
461
      } catch (SecurityException se) {
462
        // if a security manager exists,
463
        // its checkRead method is called for f.exist()
464
        // or checkWrite method is called for f.canWrite()
465
        throw se;
466
      }
467
468
      // create a buffered byte output stream
469
      // that uses a default-sized output buffer
470
      FileOutputStream fos = new FileOutputStream(f);
471
      BufferedOutputStream out = new BufferedOutputStream(fos);
472
473
      // this should be http url
474
      URL url = new URL(certURL);
475
      BufferedInputStream bis = null;
476
      try {
477
        bis = new BufferedInputStream(url.openStream());
478
        byte[] buf = new byte[4 * 1024]; // 4K buffer
479
        int b = bis.read(buf);
480
        while (b != -1) {
481
          out.write(buf, 0, b);
482
          b = bis.read(buf);
483
        }
484
      } finally {
485
        if (bis != null) bis.close();
486
      }
487
      // the input and the output streams must be closed
488
      bis.close();
489
	    out.flush();
490
	    out.close();
491
	    fos.close();
492
    } // end of synchronized(f)
493
  }
494
495 583 berkley
  /**
496 1020 tao
   * when a forcereplication request comes in, local host sends a read request
497
   * to the requesting server (remote server) for the specified docid.
498
   * Then store it in local database.
499 583 berkley
   */
500 574 berkley
  private void handleForceReplicateRequest(PrintWriter out, Hashtable params,
501
                                           HttpServletResponse response)
502
  {
503 837 bojilova
    String server = ((String[])params.get("server"))[0]; // the server that
504
    String docid = ((String[])params.get("docid"))[0]; // sent the document
505
    String dbaction = "UPDATE"; // the default action is UPDATE
506 577 berkley
    boolean override = false;
507
    int serverCode = 1;
508 1217 tao
    DBConnection dbConn = null;
509
    int serialNumber = -1;
510 1061 tao
511 837 bojilova
    try {
512
      //if the url contains a dbaction then the default action is overridden
513
      if(params.containsKey("dbaction")) {
514 577 berkley
        dbaction = ((String[])params.get("dbaction"))[0];
515 1057 tao
        //serverCode = MetacatReplication.getServerCode(server);
516
        //override = true; //we are now overriding the default action
517 577 berkley
      }
518 1292 tao
      MetacatReplication.replLog("force replication request from " + server);
519
      MetaCatUtil.debugMessage("Force replication request from: "+ server, 34);
520
      MetaCatUtil.debugMessage("Force replication docid: "+docid, 34);
521
      MetaCatUtil.debugMessage("Force replication action: "+dbaction, 34);
522
      // sending back read request to remote server
523 1014 tao
      URL u = new URL("https://" + server + "?server="
524
                +util.getLocalReplicationServerName()
525
                +"&action=read&docid=" + docid);
526 574 berkley
      String xmldoc = MetacatReplication.getURLContent(u);
527 1057 tao
528 837 bojilova
      // get the document info from server
529
      URL docinfourl = new URL("https://" + server +
530 1014 tao
                               "?server="+util.getLocalReplicationServerName()
531
                               +"&action=getdocumentinfo&docid=" + docid);
532 1057 tao
533 574 berkley
      String docInfoStr = MetacatReplication.getURLContent(docinfourl);
534 1057 tao
535 837 bojilova
      //dih is the parser for the docinfo xml format
536 574 berkley
      DocInfoHandler dih = new DocInfoHandler();
537
      XMLReader docinfoParser = ReplicationHandler.initParser(dih);
538
      docinfoParser.parse(new InputSource(new StringReader(docInfoStr)));
539
      Hashtable docinfoHash = dih.getDocInfo();
540 1292 tao
541
      // Get user owner of this docid
542 574 berkley
      String user = (String)docinfoHash.get("user_owner");
543 1292 tao
      // Get home server of this docid
544 1057 tao
      String homeServer=(String)docinfoHash.get("home_server");
545 1292 tao
      MetaCatUtil.debugMessage("homeServer: "+homeServer, 34);
546 1561 tao
      // Get Document type
547
      String docType = (String)docinfoHash.get("doctype");
548
      MetaCatUtil.debugMessage("docType: "+docType, 34);
549
      String parserBase = null;
550
      // this for eml2 and we need user eml2 parser
551
      if (docType != null &&
552
          (docType.trim()).equals(DocumentImpl.EMLNAMESPACE))
553
      {
554
         MetaCatUtil.debugMessage("This is an eml2 document!", 30);
555
         parserBase = DocumentImpl.EML2;
556
      }
557
      MetaCatUtil.debugMessage("The parserBase is: "+parserBase, 30);
558
559 1292 tao
      // Get DBConnection from pool
560 1217 tao
      dbConn=DBConnectionPool.
561
              getDBConnection("MetacatReplication.handleForceReplicateRequest");
562
      serialNumber=dbConn.getCheckOutSerialNumber();
563 1292 tao
      // write the document to local database
564 1561 tao
      DocumentImplWrapper wrapper = new DocumentImplWrapper(parserBase, false);
565
      wrapper.writeReplication(dbConn, new StringReader(xmldoc), null, null,
566
                               dbaction, docid, user, null, homeServer, server);
567 1057 tao
568 584 berkley
      MetacatReplication.replLog("document " + docid + " added to DB with " +
569
                                 "action " + dbaction);
570 1292 tao
    }//try
571
    catch(Exception e)
572
    {
573 1583 tao
      MetacatReplication.replErrorLog("document " + docid +
574
                                      " failed to added to DB with " +
575
                                      "action " + dbaction + " because "+
576
                                       e.getMessage());
577
      MetaCatUtil.debugMessage("ERROR in MetacatReplication.handleForceReplicate" +
578
                         "Request(): " + e.getMessage(), 30);
579 1061 tao
580 1292 tao
    }//catch
581 1217 tao
    finally
582
    {
583 1292 tao
      // Return the checked out DBConnection
584 1217 tao
      DBConnectionPool.returnDBConnection(dbConn, serialNumber);
585
    }//finally
586 574 berkley
  }
587
588 561 berkley
  /**
589 1023 tao
   * when a forcereplication data file request comes in, local host sends a
590
   * readdata request to the requesting server (remote server) for the specified
591
   * docid. Then store it in local database and file system
592
   */
593
  private void handleForceReplicateDataFileRequest(Hashtable params)
594
  {
595 1292 tao
596 1023 tao
    //make sure there is some parameters
597
    if(params.isEmpty())
598
    {
599
      return;
600
    }
601 1292 tao
    // Get remote server
602
    String server = ((String[])params.get("server"))[0];
603
    // the docid should include rev number
604
    String docid = ((String[])params.get("docid"))[0];
605
    // Make sure there is a docid and server
606
    if (docid==null || server==null || server.equals(""))
607 1023 tao
    {
608 1292 tao
      MetaCatUtil.debugMessage("Didn't specify docid or server for replication"
609
                              , 20);
610 1023 tao
      return;
611
    }
612 1292 tao
613
    // Overide or not
614 1023 tao
    boolean override = false;
615 1292 tao
    // dbaction - update or insert
616 1023 tao
    String dbaction=null;
617 1292 tao
618 1023 tao
    try
619
    {
620 1292 tao
      //docid was switch to two parts uinque code and rev
621 1023 tao
      String uniqueCode=MetaCatUtil.getDocIdFromString(docid);
622
      int rev=MetaCatUtil.getVersionFromString(docid);
623
      if(params.containsKey("dbaction"))
624
      {
625
        dbaction = ((String[])params.get("dbaction"))[0];
626
      }
627
      else//default value is update
628
      {
629
        dbaction = "update";
630
      }
631 1292 tao
632 1023 tao
      MetacatReplication.replLog("force replication request from " + server);
633 1292 tao
      MetaCatUtil.debugMessage("Force replication request from: "+ server, 34);
634
      MetaCatUtil.debugMessage("Force replication docid: "+docid, 34);
635
      MetaCatUtil.debugMessage("Force replication action: "+dbaction, 34);
636 1023 tao
      // get the document info from server
637
      URL docinfourl = new URL("https://" + server +
638
                               "?server="+util.getLocalReplicationServerName()
639
                               +"&action=getdocumentinfo&docid=" + uniqueCode);
640
641
      String docInfoStr = MetacatReplication.getURLContent(docinfourl);
642
643
      //dih is the parser for the docinfo xml format
644
      DocInfoHandler dih = new DocInfoHandler();
645
      XMLReader docinfoParser = ReplicationHandler.initParser(dih);
646
      docinfoParser.parse(new InputSource(new StringReader(docInfoStr)));
647
      Hashtable docinfoHash = dih.getDocInfo();
648
      String user = (String)docinfoHash.get("user_owner");
649
650
      String docName = (String)docinfoHash.get("docname");
651
652
      String docType = (String)docinfoHash.get("doctype");
653
654 1065 tao
      String docHomeServer= (String)docinfoHash.get("home_server");
655 1292 tao
      MetaCatUtil.debugMessage("docHomeServer of datafile: "+docHomeServer, 34);
656 1023 tao
657 1065 tao
658
659 1023 tao
      //if action is delete, we don't delete the data file. Just archieve
660
      //the xml_documents
661
      if (dbaction.equals("delete"))
662
      {
663 1217 tao
        //conn = util.getConnection();
664
        DocumentImpl.delete(docid,user,null);
665
        //util.returnConnection(conn);
666 1023 tao
      }
667 1031 tao
      //To data file insert or update is same
668
      else if (dbaction.equals("insert")||dbaction.equals("update"))
669 1023 tao
      {
670
        //Get data file and store it into local file system.
671
        // sending back readdata request to server
672
        URL url = new URL("https://" + server + "?server="
673
                +util.getLocalReplicationServerName()
674
                +"&action=readdata&docid=" + docid);
675 1031 tao
        String datafilePath = util.getOption("datafilepath");
676
        //register data file into xml_documents table and wite data file
677
        //into file system
678 1292 tao
        DocumentImpl.writeDataFileInReplication(url.openStream(), datafilePath,
679
                            docName, docType, docid, user,docHomeServer,server);
680 1023 tao
     }
681
682 1065 tao
683 1031 tao
684 1583 tao
    MetacatReplication.replLog("datafile " + docid + " added to DB with " +
685 1023 tao
                                 "action " + dbaction);
686 1583 tao
    }
687
    catch(Exception e)
688 1023 tao
    {
689 1065 tao
690 1583 tao
      MetacatReplication.replErrorLog("Datafile " + docid +
691
                                      " failed to added to DB with " +
692
                                      "action " + dbaction + " because "+
693
                                       e.getMessage());
694
      MetaCatUtil.debugMessage
695 1292 tao
              ("ERROR in MetacatReplication.handleForceDataFileReplicate" +
696 1065 tao
                         "Request(): " + e.getMessage(), 30);
697 1023 tao
    }
698
  }
699
  /**
700 561 berkley
   * Grants or denies a lock to a requesting host.
701
   * The servlet parameters of interrest are:
702
   * docid: the docid of the file the lock is being requested for
703
   * currentdate: the timestamp of the document on the remote server
704
   *
705
   */
706
  private void handleGetLockRequest(PrintWriter out, Hashtable params,
707
                                    HttpServletResponse response)
708
  {
709 1292 tao
710 561 berkley
    try
711
    {
712 1292 tao
713 561 berkley
      String docid = ((String[])params.get("docid"))[0];
714 580 berkley
      String remoteRev = ((String[])params.get("updaterev"))[0];
715 1217 tao
      DocumentImpl requestDoc = new DocumentImpl(docid);
716 584 berkley
      MetacatReplication.replLog("lock request for " + docid);
717 580 berkley
      int localRevInt = requestDoc.getRev();
718
      int remoteRevInt = Integer.parseInt(remoteRev);
719
720
      if(remoteRevInt >= localRevInt)
721 561 berkley
      {
722
        if(!fileLocks.contains(docid))
723 580 berkley
        { //grant the lock if it is not already locked
724 561 berkley
          fileLocks.add(0, docid); //insert at the beginning of the queue Vector
725
          //send a message back to the the remote host authorizing the insert
726
          out.println("<lockgranted><docid>" +docid+ "</docid></lockgranted>");
727
          lockThread = new Thread(this);
728
          lockThread.setPriority(Thread.MIN_PRIORITY);
729
          lockThread.start();
730 584 berkley
          MetacatReplication.replLog("lock granted for " + docid);
731 561 berkley
        }
732
        else
733
        { //deny the lock
734
          out.println("<filelocked><docid>" + docid + "</docid></filelocked>");
735 584 berkley
          MetacatReplication.replLog("lock denied for " + docid +
736
                                     "reason: file already locked");
737 561 berkley
        }
738
      }
739
      else
740
      {//deny the lock.
741
        out.println("<outdatedfile><docid>" + docid + "</docid></filelocked>");
742 584 berkley
        MetacatReplication.replLog("lock denied for " + docid +
743
                                   "reason: client has outdated file");
744 561 berkley
      }
745 1217 tao
      //conn.close();
746 561 berkley
    }
747
    catch(Exception e)
748
    {
749 675 berkley
      System.out.println("error requesting file lock from MetacatReplication." +
750
                         "handleGetLockRequest: " + e.getMessage());
751 568 berkley
      e.printStackTrace(System.out);
752 561 berkley
    }
753
  }
754
755
  /**
756
   * Sends all of the xml_documents information encoded in xml to a requestor
757 583 berkley
   * the format is:
758
   * <!ELEMENT documentinfo (docid, docname, doctype, doctitle, user_owner,
759 1057 tao
   *                  user_updated, home_server, public_access, rev)/>
760 583 berkley
   * all of the subelements of document info are #PCDATA
761 561 berkley
   */
762
  private void handleGetDocumentInfoRequest(PrintWriter out, Hashtable params,
763
                                        HttpServletResponse response)
764
  {
765
    String docid = ((String[])(params.get("docid")))[0];
766
    StringBuffer sb = new StringBuffer();
767 1292 tao
768 561 berkley
    try
769
    {
770 1292 tao
771 1217 tao
      DocumentImpl doc = new DocumentImpl(docid);
772 561 berkley
      sb.append("<documentinfo><docid>").append(docid);
773
      sb.append("</docid><docname>").append(doc.getDocname());
774
      sb.append("</docname><doctype>").append(doc.getDoctype());
775 692 bojilova
      sb.append("</doctype>");
776
      sb.append("<user_owner>").append(doc.getUserowner());
777 561 berkley
      sb.append("</user_owner><user_updated>").append(doc.getUserupdated());
778 1057 tao
      sb.append("</user_updated>");
779
      sb.append("<home_server>");
780 1061 tao
      sb.append(doc.getDocHomeServer());
781 1057 tao
      sb.append("</home_server>");
782
      sb.append("<public_access>").append(doc.getPublicaccess());
783 583 berkley
      sb.append("</public_access><rev>").append(doc.getRev());
784
      sb.append("</rev></documentinfo>");
785 561 berkley
      response.setContentType("text/xml");
786
      out.println(sb.toString());
787 1292 tao
788 561 berkley
    }
789
    catch (Exception e)
790
    {
791 675 berkley
      System.out.println("error in " +
792
                         "metacatReplication.handlegetdocumentinforequest: " +
793
                          e.getMessage());
794 561 berkley
    }
795
796
  }
797 1020 tao
798
  /**
799
   * Sends a datafile to a remote host
800
   */
801 1023 tao
  private void handleGetDataFileRequest(OutputStream outPut,
802 1020 tao
                            Hashtable params, HttpServletResponse response)
803
804
  {
805 1292 tao
    // File path for data file
806 1020 tao
    String filepath = util.getOption("datafilepath");
807 1292 tao
    // Request docid
808 1020 tao
    String docId = ((String[])(params.get("docid")))[0];
809 1023 tao
    //check if the doicd is null
810
    if (docId==null)
811
    {
812 1097 tao
      util.debugMessage("Didn't specify docid for replication", 20);
813 1023 tao
      return;
814
    }
815 1097 tao
816
    //try to open a https stream to test if the request server's public key
817
    //in the key store, this is security issue
818
    try
819
    {
820
      String server = ((String[])params.get("server"))[0];
821
      URL u = new URL("https://" + server + "?server="
822
                +util.getLocalReplicationServerName()
823
                +"&action=test");
824
      String test = MetacatReplication.getURLContent(u);
825
      //couldn't pass the test
826
      if (test.indexOf("successfully")==-1)
827
      {
828
        //response.setContentType("text/xml");
829
        //outPut.println("<error>Couldn't pass the trust test</error>");
830 1101 tao
        MetaCatUtil.debugMessage("Couldn't pass the trust test", 20);
831 1097 tao
        return;
832
      }
833
    }//try
834
    catch (Exception ee)
835
    {
836
      return;
837
    }//catch
838 561 berkley
839 1020 tao
    if(!filepath.endsWith("/"))
840
    {
841
          filepath += "/";
842
    }
843 1292 tao
    // Get file aboslute file name
844
    String filename = filepath + docId;
845 1023 tao
846 1292 tao
    //MIME type
847
    String contentType = null;
848
    if (filename.endsWith(".xml"))
849
    {
850
        contentType="text/xml";
851
    }
852
    else if (filename.endsWith(".css"))
853
    {
854
        contentType="text/css";
855
    }
856
    else if (filename.endsWith(".dtd"))
857
    {
858
        contentType="text/plain";
859
    }
860
    else if (filename.endsWith(".xsd"))
861
    {
862
        contentType="text/xml";
863
    }
864
    else if (filename.endsWith("/"))
865
    {
866
        contentType="text/html";
867
    }
868
    else
869
    {
870
        File f = new File(filename);
871
        if ( f.isDirectory() )
872
        {
873
           contentType="text/html";
874
        }
875
        else
876
        {
877
           contentType="application/octet-stream";
878
        }
879
     }
880 1023 tao
881 1292 tao
   // Set the mime type
882 1020 tao
   response.setContentType(contentType);
883 1292 tao
884
   // Get the content of the file
885 1020 tao
   FileInputStream fin = null;
886
   try
887
   {
888 1292 tao
      // FileInputStream to metacat
889 1020 tao
      fin = new FileInputStream(filename);
890 1292 tao
      // 4K buffer
891
      byte[] buf = new byte[4 * 1024];
892
      // Read data from file input stream to byte array
893 1020 tao
      int b = fin.read(buf);
894 1292 tao
      // Write to outStream from byte array
895 1020 tao
      while (b != -1)
896
      {
897
        outPut.write(buf, 0, b);
898
        b = fin.read(buf);
899
      }
900 1292 tao
      // close file input stream
901 1020 tao
      fin.close();
902 1023 tao
903 1292 tao
   }//try
904 1020 tao
   catch(Exception e)
905
   {
906
      System.out.println("error getting data file from MetacatReplication." +
907
                         "handlGetDataFileRequest " + e.getMessage());
908
      e.printStackTrace(System.out);
909 1292 tao
   }//catch
910 1020 tao
911
}
912
913
914 561 berkley
  /**
915
   * Sends a document to a remote host
916
   */
917 534 berkley
  private void handleGetDocumentRequest(PrintWriter out, Hashtable params,
918 561 berkley
                                        HttpServletResponse response)
919 534 berkley
  {
920 1292 tao
921 534 berkley
    try
922
    {
923 1097 tao
      //try to open a https stream to test if the request server's public key
924
      //in the key store, this is security issue
925
      String server = ((String[])params.get("server"))[0];
926
      URL u = new URL("https://" + server + "?server="
927
                +util.getLocalReplicationServerName()
928
                +"&action=test");
929
      String test = MetacatReplication.getURLContent(u);
930
      //couldn't pass the test
931
      if (test.indexOf("successfully")==-1)
932
      {
933
        response.setContentType("text/xml");
934
        out.println("<error>Couldn't pass the trust test</error>");
935 1292 tao
        out.close();
936 1097 tao
        return;
937
      }
938
939 536 berkley
      String docid = ((String[])(params.get("docid")))[0];
940 1292 tao
941 1217 tao
      DocumentImpl di = new DocumentImpl(docid);
942 534 berkley
      response.setContentType("text/xml");
943 537 berkley
      out.print(di.toString());
944 1292 tao
945 584 berkley
      MetacatReplication.replLog("document " + docid + " sent");
946 1014 tao
947 534 berkley
    }
948
    catch(Exception e)
949
    {
950 1099 tao
      MetaCatUtil.debugMessage("error getting document from MetacatReplication."
951
                          +"handlGetDocumentRequest " + e.getMessage(), 30);
952
      //e.printStackTrace(System.out);
953
      response.setContentType("text/xml");
954 1292 tao
      out.println("<error>"+e.getMessage()+"</error>");
955 534 berkley
    }
956
957
  }
958 573 berkley
959
  /**
960 583 berkley
   * Sends a list of all of the documents on this sever along with their
961
   * revision numbers.
962
   * The format is:
963
   * <!ELEMENT replication (server, updates)>
964
   * <!ELEMENT server (#PCDATA)>
965
   * <!ELEMENT updates ((updatedDocument | deleteDocument)*)>
966 1020 tao
   * <!ELEMENT updatedDocument (docid, rev, datafile*)>
967 1035 tao
   * <!ELEMENT deletedDocument (docid, rev)>
968 583 berkley
   * <!ELEMENT docid (#PCDATA)>
969
   * <!ELEMENT rev (#PCDATA)>
970 1020 tao
   * <!ELEMENT datafile (#PCDATA)>
971 583 berkley
   * note that the rev in deletedDocument is always empty.  I just left
972
   * it in there to make the parser implementation easier.
973 573 berkley
   */
974
  private void handleUpdateRequest(PrintWriter out, Hashtable params,
975 577 berkley
                                    HttpServletResponse response)
976
  {
977 1292 tao
    // Checked out DBConnection
978 1217 tao
    DBConnection dbConn = null;
979 1292 tao
    // DBConenction serial number when checked it out
980 1217 tao
    int serialNumber = -1;
981
    PreparedStatement pstmt = null;
982 1292 tao
    // Server list to store server info of xml_replication table
983
    ReplicationServerList serverList = null;
984
985 577 berkley
    try
986
    {
987 1292 tao
      // Check out a DBConnection from pool
988
      dbConn=DBConnectionPool.
989
                  getDBConnection("MetacatReplication.handleUpdateRequest");
990
      serialNumber=dbConn.getCheckOutSerialNumber();
991
      // Create a server list from xml_replication table
992
      serverList = new ReplicationServerList();
993
994
      // Get remote server name from param
995
      String server = ((String[])params.get("server"))[0];
996
      // If no servr name in param, return a error
997
      if ( server == null || server.equals(""))
998
      {
999
        response.setContentType("text/xml");
1000
        out.println("<error>Request didn't specify server name</error>");
1001
        out.close();
1002
        return;
1003
      }//if
1004
1005 1101 tao
      //try to open a https stream to test if the request server's public key
1006
      //in the key store, this is security issue
1007
      URL u = new URL("https://" + server + "?server="
1008
                +util.getLocalReplicationServerName()
1009
                +"&action=test");
1010
      String test = MetacatReplication.getURLContent(u);
1011
      //couldn't pass the test
1012
      if (test.indexOf("successfully")==-1)
1013
      {
1014
        response.setContentType("text/xml");
1015
        out.println("<error>Couldn't pass the trust test</error>");
1016 1292 tao
        out.close();
1017 1101 tao
        return;
1018
      }
1019 1014 tao
1020 1292 tao
1021
      // Check if local host configure to replicate xml documents to remote
1022
      // server. If not send back a error message
1023
      if (!serverList.getReplicationValue(server))
1024
      {
1025
        response.setContentType("text/xml");
1026
        out.println
1027
        ("<error>Configuration not allow to replicate document to you</error>");
1028
        out.close();
1029
        return;
1030
      }//if
1031
1032
      // Store the sql command
1033 577 berkley
      StringBuffer docsql = new StringBuffer();
1034 1292 tao
      // Stroe the docid list
1035 577 berkley
      StringBuffer doclist = new StringBuffer();
1036 1292 tao
      // Store the deleted docid list
1037
      StringBuffer delsql = new StringBuffer();
1038
      // Store the data set file
1039 625 berkley
      Vector packageFiles = new Vector();
1040 577 berkley
1041 1292 tao
      // Append local server's name and replication servlet to doclist
1042 577 berkley
      doclist.append("<?xml version=\"1.0\"?><replication>");
1043
      doclist.append("<server>").append(util.getOption("server"));
1044
      doclist.append(util.getOption("replicationpath"));
1045
      doclist.append("</server><updates>");
1046
1047 1292 tao
      // Get correct docid that reside on this server according the requesting
1048
      // server's replicate and data replicate value in xml_replication table
1049 1042 tao
      docsql.append("select docid, rev, doctype from xml_documents ");
1050 1292 tao
      // If the localhost is not a hub to the remote server, only replicate
1051
      // the docid' which home server is local host (server_location =1)
1052
      if (!serverList.getHubValue(server))
1053 1042 tao
      {
1054
        docsql.append("where server_location = 1");
1055
      }
1056 1292 tao
      MetaCatUtil.debugMessage("Doc sql: "+docsql.toString(), 30);
1057 577 berkley
1058 1292 tao
      // Get any deleted documents
1059 577 berkley
      delsql.append("select distinct docid from ");
1060
      delsql.append("xml_revisions where docid not in (select docid from ");
1061 1042 tao
      delsql.append("xml_documents) ");
1062 1292 tao
      // If the localhost is not a hub to the remote server, only replicate
1063
      // the docid' which home server is local host (server_location =1)
1064
      if (!serverList.getHubValue(server))
1065 1042 tao
      {
1066
        delsql.append("and server_location = 1");
1067
      }
1068 1292 tao
      MetaCatUtil.debugMessage("Deleted sql: "+delsql.toString(), 30);
1069
1070
1071
1072
      // Get docid list of local host
1073 1217 tao
      pstmt = dbConn.prepareStatement(docsql.toString());
1074 577 berkley
      pstmt.execute();
1075
      ResultSet rs = pstmt.getResultSet();
1076
      boolean tablehasrows = rs.next();
1077 1035 tao
      //If metacat configed to replicate data file
1078 1292 tao
      //if ((util.getOption("replicationsenddata")).equals("on"))
1079
      if (serverList.getDataReplicationValue(server))
1080 577 berkley
      {
1081 1020 tao
        while(tablehasrows)
1082
        {
1083
          String recordDoctype = rs.getString(3);
1084 1035 tao
          Vector packagedoctypes = MetaCatUtil.getOptionList(
1085
                                     MetaCatUtil.getOption("packagedoctype"));
1086 1292 tao
          //if this is a package file, put it at the end
1087
          //because if a package file is read before all of the files it
1088
          //refers to are loaded then there is an error
1089 1035 tao
          if(!packagedoctypes.contains(recordDoctype))
1090 1292 tao
          {
1091
              //If this is not data file
1092 1035 tao
              if (!recordDoctype.equals("BIN"))
1093
              {
1094
                //for non-data file document
1095
                doclist.append("<updatedDocument>");
1096
                doclist.append("<docid>").append(rs.getString(1));
1097
                doclist.append("</docid><rev>").append(rs.getInt(2));
1098
                doclist.append("</rev>");
1099
                doclist.append("</updatedDocument>");
1100 1292 tao
              }//if
1101 1035 tao
              else
1102
              {
1103
                //for data file document, in datafile attributes
1104
                //we put "datafile" value there
1105
                doclist.append("<updatedDocument>");
1106
                doclist.append("<docid>").append(rs.getString(1));
1107
                doclist.append("</docid><rev>").append(rs.getInt(2));
1108
                doclist.append("</rev>");
1109
                doclist.append("<datafile>");
1110
                doclist.append(MetaCatUtil.getOption("datafileflag"));
1111
                doclist.append("</datafile>");
1112
                doclist.append("</updatedDocument>");
1113 1292 tao
              }//else
1114
          }//if packagedoctpes
1115 1035 tao
          else
1116
          { //the package files are saved to be put into the xml later.
1117
              Vector v = new Vector();
1118
              v.add(new String(rs.getString(1)));
1119
              v.add(new Integer(rs.getInt(2)));
1120
              packageFiles.add(new Vector(v));
1121 1292 tao
          }//esle
1122 1035 tao
          tablehasrows = rs.next();
1123
        }//while
1124
      }//if
1125
      else //metacat was configured not to send data file
1126
      {
1127
        while(tablehasrows)
1128
        {
1129
          String recordDoctype = rs.getString(3);
1130 1020 tao
          if(!recordDoctype.equals("BIN"))
1131
          { //don't replicate data files
1132
            Vector packagedoctypes = MetaCatUtil.getOptionList(
1133 887 berkley
                                     MetaCatUtil.getOption("packagedoctype"));
1134 1020 tao
            if(!packagedoctypes.contains(recordDoctype))
1135
            {   //if this is a package file, put it at the end
1136
              //because if a package file is read before all of the files it
1137
              //refers to are loaded then there is an error
1138
              doclist.append("<updatedDocument>");
1139
              doclist.append("<docid>").append(rs.getString(1));
1140
              doclist.append("</docid><rev>").append(rs.getInt(2));
1141
              doclist.append("</rev>");
1142
              doclist.append("</updatedDocument>");
1143
            }
1144
            else
1145
            { //the package files are saved to be put into the xml later.
1146
              Vector v = new Vector();
1147
              v.add(new String(rs.getString(1)));
1148
              v.add(new Integer(rs.getInt(2)));
1149
              packageFiles.add(new Vector(v));
1150
            }
1151
         }//if
1152
         tablehasrows = rs.next();
1153
        }//while
1154 1035 tao
      }//else
1155 577 berkley
1156 1217 tao
      pstmt = dbConn.prepareStatement(delsql.toString());
1157
      //usage count should increas 1
1158
      dbConn.increaseUsageCount(1);
1159
1160 577 berkley
      pstmt.execute();
1161
      rs = pstmt.getResultSet();
1162
      tablehasrows = rs.next();
1163
      while(tablehasrows)
1164
      { //handle the deleted documents
1165
        doclist.append("<deletedDocument><docid>").append(rs.getString(1));
1166
        doclist.append("</docid><rev></rev></deletedDocument>");
1167 583 berkley
        //note that rev is always empty for deleted docs
1168 577 berkley
        tablehasrows = rs.next();
1169
      }
1170
1171 625 berkley
      //now we can put the package files into the xml results
1172
      for(int i=0; i<packageFiles.size(); i++)
1173
      {
1174
        Vector v = (Vector)packageFiles.elementAt(i);
1175
        doclist.append("<updatedDocument>");
1176
        doclist.append("<docid>").append((String)v.elementAt(0));
1177
        doclist.append("</docid><rev>");
1178
        doclist.append(((Integer)v.elementAt(1)).intValue());
1179
        doclist.append("</rev>");
1180
        doclist.append("</updatedDocument>");
1181
      }
1182
1183 577 berkley
      doclist.append("</updates></replication>");
1184 1498 tao
      MetaCatUtil.debugMessage("doclist: " + doclist.toString(), 40);
1185 667 berkley
      pstmt.close();
1186 1217 tao
      //conn.close();
1187 577 berkley
      response.setContentType("text/xml");
1188
      out.println(doclist.toString());
1189 1014 tao
1190 577 berkley
    }
1191
    catch(Exception e)
1192
    {
1193 1101 tao
      MetaCatUtil.debugMessage("error in MetacatReplication." +
1194
                         "handleupdaterequest: " + e.getMessage(), 30);
1195
      //e.printStackTrace(System.out);
1196
      response.setContentType("text/xml");
1197 1292 tao
      out.println("<error>"+e.getMessage()+"</error>");
1198 577 berkley
    }
1199 1217 tao
    finally
1200
    {
1201
      try
1202
      {
1203
        pstmt.close();
1204
      }//try
1205
      catch (SQLException ee)
1206
      {
1207
        MetaCatUtil.debugMessage("Error in MetacatReplication." +
1208
                "handleUpdaterequest to close pstmt: "+ee.getMessage(), 30);
1209
      }//catch
1210
      finally
1211
      {
1212
        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1213
      }//finally
1214
    }//finally
1215 1292 tao
1216
  }//handlUpdateRequest
1217 577 berkley
1218
  /**
1219 590 berkley
   * Returns the xml_catalog table encoded in xml
1220
   */
1221
  public static String getCatalogXML()
1222
  {
1223
    return handleGetCatalogRequest(null, null, null, false);
1224
  }
1225
1226
  /**
1227
   * Sends the contents of the xml_catalog table encoded in xml
1228
   * The xml format is:
1229
   * <!ELEMENT xml_catalog (row*)>
1230
   * <!ELEMENT row (entry_type, source_doctype, target_doctype, public_id,
1231
   *                system_id)>
1232
   * All of the sub elements of row are #PCDATA
1233
1234
   * If printFlag == false then do not print to out.
1235
   */
1236
  private static String handleGetCatalogRequest(PrintWriter out,
1237
                                                Hashtable params,
1238
                                                HttpServletResponse response,
1239
                                                boolean printFlag)
1240
  {
1241 1217 tao
    DBConnection dbConn = null;
1242
    int serialNumber = -1;
1243 667 berkley
    PreparedStatement pstmt = null;
1244 590 berkley
    try
1245 683 berkley
    {
1246 1217 tao
      /*conn = MetacatReplication.getDBConnection("MetacatReplication." +
1247
                                                "handleGetCatalogRequest");*/
1248
      dbConn=DBConnectionPool.
1249
                 getDBConnection("MetacatReplication.handleGetCatalogRequest");
1250
      serialNumber=dbConn.getCheckOutSerialNumber();
1251
      pstmt = dbConn.prepareStatement("select entry_type, " +
1252 590 berkley
                              "source_doctype, target_doctype, public_id, " +
1253
                              "system_id from xml_catalog");
1254
      pstmt.execute();
1255
      ResultSet rs = pstmt.getResultSet();
1256
      boolean tablehasrows = rs.next();
1257
      StringBuffer sb = new StringBuffer();
1258
      sb.append("<?xml version=\"1.0\"?><xml_catalog>");
1259
      while(tablehasrows)
1260
      {
1261
        sb.append("<row><entry_type>").append(rs.getString(1));
1262
        sb.append("</entry_type><source_doctype>").append(rs.getString(2));
1263
        sb.append("</source_doctype><target_doctype>").append(rs.getString(3));
1264
        sb.append("</target_doctype><public_id>").append(rs.getString(4));
1265
        sb.append("</public_id><system_id>").append(rs.getString(5));
1266
        sb.append("</system_id></row>");
1267
1268
        tablehasrows = rs.next();
1269
      }
1270
      sb.append("</xml_catalog>");
1271 1217 tao
      //conn.close();
1272 590 berkley
      if(printFlag)
1273
      {
1274
        response.setContentType("text/xml");
1275
        out.println(sb.toString());
1276
      }
1277 667 berkley
      pstmt.close();
1278 590 berkley
      return sb.toString();
1279
    }
1280
    catch(Exception e)
1281
    {
1282 1217 tao
1283 675 berkley
      System.out.println("error in MetacatReplication.handleGetCatalogRequest:"+
1284
                          e.getMessage());
1285 590 berkley
      e.printStackTrace(System.out);
1286 1292 tao
      if(printFlag)
1287
      {
1288
        out.println("<error>"+e.getMessage()+"</error>");
1289
      }
1290 590 berkley
    }
1291 1217 tao
    finally
1292
    {
1293
      try
1294
      {
1295
        pstmt.close();
1296
      }//try
1297
      catch (SQLException ee)
1298
      {
1299
        MetaCatUtil.
1300
           debugMessage("Error in MetacatReplication.handleGetCatalogRequest: "
1301
           +ee.getMessage(), 30);
1302
      }//catch
1303
      finally
1304
      {
1305
        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1306
      }//finally
1307
    }//finally
1308
1309 590 berkley
    return null;
1310
  }
1311
1312
  /**
1313 568 berkley
   * Sends the current system date to the remote server.  Using this action
1314
   * for replication gets rid of any problems with syncronizing clocks
1315
   * because a time specific to a document is always kept on its home server.
1316
   */
1317
  private void handleGetTimeRequest(PrintWriter out, Hashtable params,
1318
                                    HttpServletResponse response)
1319
  {
1320 1752 tao
    SimpleDateFormat formatter = new SimpleDateFormat ("MM/dd/yy HH:mm:ss");
1321 568 berkley
    java.util.Date localtime = new java.util.Date();
1322
    String dateString = formatter.format(localtime);
1323
    response.setContentType("text/xml");
1324
1325
    out.println("<timestamp>" + dateString + "</timestamp>");
1326
  }
1327
1328
  /**
1329 583 berkley
   * this method handles the timeout for a file lock.  when a lock is
1330
   * granted it is granted for 30 seconds.  When this thread runs out
1331
   * it deletes the docid from the queue, thus eliminating the lock.
1332 561 berkley
   */
1333
  public void run()
1334
  {
1335
    try
1336
    {
1337 590 berkley
      MetaCatUtil.debugMessage("thread started for docid: " +
1338 1097 tao
                               (String)fileLocks.elementAt(0), 45);
1339
1340 561 berkley
      Thread.sleep(30000); //the lock will expire in 30 seconds
1341 590 berkley
      MetaCatUtil.debugMessage("thread for docid: " +
1342 595 berkley
                             (String)fileLocks.elementAt(fileLocks.size() - 1) +
1343 1498 tao
                              " exiting.", 45);
1344 1097 tao
1345 561 berkley
      fileLocks.remove(fileLocks.size() - 1);
1346 568 berkley
      //fileLocks is treated as a FIFO queue.  If there are more than one lock
1347 561 berkley
      //in the vector, the first one inserted will be removed.
1348
    }
1349
    catch(Exception e)
1350
    {
1351 1097 tao
      MetaCatUtil.debugMessage("error in file lock thread from " +
1352 1498 tao
                                "MetacatReplication.run: " + e.getMessage(), 30);
1353 561 berkley
    }
1354
  }
1355
1356
  /**
1357
   * Returns the name of a server given a serverCode
1358
   * @param serverCode the serverid of the server
1359
   * @return the servername or null if the specified serverCode does not
1360
   *         exist.
1361
   */
1362 1292 tao
  public static String getServerNameForServerCode(int serverCode)
1363 561 berkley
  {
1364 569 berkley
    //System.out.println("serverid: " + serverCode);
1365 1217 tao
    DBConnection dbConn = null;
1366
    int serialNumber = -1;
1367
    PreparedStatement pstmt = null;
1368 561 berkley
    try
1369
    {
1370 1217 tao
      dbConn=DBConnectionPool.
1371
                  getDBConnection("MetacatReplication.getServer");
1372
      serialNumber=dbConn.getCheckOutSerialNumber();
1373 569 berkley
      String sql = new String("select server from " +
1374 561 berkley
                              "xml_replication where serverid = " +
1375
                              serverCode);
1376 1217 tao
      pstmt = dbConn.prepareStatement(sql);
1377 569 berkley
      //System.out.println("getserver sql: " + sql);
1378 561 berkley
      pstmt.execute();
1379
      ResultSet rs = pstmt.getResultSet();
1380
      boolean tablehasrows = rs.next();
1381
      if(tablehasrows)
1382
      {
1383 569 berkley
        //System.out.println("server: " + rs.getString(1));
1384 561 berkley
        return rs.getString(1);
1385
      }
1386 1217 tao
1387
      //conn.close();
1388 561 berkley
    }
1389
    catch(Exception e)
1390
    {
1391
      System.out.println("Error in MetacatReplication.getServer: " +
1392
                          e.getMessage());
1393
    }
1394 1217 tao
    finally
1395
    {
1396
      try
1397
      {
1398
        pstmt.close();
1399
      }//try
1400
      catch (SQLException ee)
1401
      {
1402
        MetaCatUtil.debugMessage("Error in MetacactReplication.getserver: "+
1403
                                    ee.getMessage(), 30);
1404
      }//catch
1405
      finally
1406
      {
1407
        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1408
      }//fianlly
1409
    }//finally
1410
1411
1412
1413 561 berkley
    return null;
1414
      //return null if the server does not exist
1415
  }
1416 569 berkley
1417
  /**
1418
   * Returns a server code given a server name
1419
   * @param server the name of the server
1420
   * @return integer > 0 representing the code of the server, 0 if the server
1421
   *  does not exist.
1422
   */
1423 1292 tao
  public static int getServerCodeForServerName(String server) throws Exception
1424 569 berkley
  {
1425 1217 tao
    DBConnection dbConn = null;
1426
    int serialNumber = -1;
1427 667 berkley
    PreparedStatement pstmt = null;
1428 837 bojilova
    int serverCode = 0;
1429
1430
    try {
1431
1432 1217 tao
      //conn = util.openDBConnection();
1433
      dbConn=DBConnectionPool.
1434
                  getDBConnection("MetacatReplication.getServerCode");
1435
      serialNumber=dbConn.getCheckOutSerialNumber();
1436
      pstmt = dbConn.prepareStatement("SELECT serverid FROM xml_replication " +
1437 837 bojilova
                                    "WHERE server LIKE '" + server + "'");
1438 569 berkley
      pstmt.execute();
1439
      ResultSet rs = pstmt.getResultSet();
1440
      boolean tablehasrows = rs.next();
1441 837 bojilova
      if ( tablehasrows ) {
1442
        serverCode = rs.getInt(1);
1443 667 berkley
        pstmt.close();
1444 1217 tao
        //conn.close();
1445 837 bojilova
        return serverCode;
1446 569 berkley
      }
1447 837 bojilova
1448
    } catch(Exception e) {
1449
      throw e;
1450
1451
    } finally {
1452 1217 tao
      try
1453
      {
1454 667 berkley
        pstmt.close();
1455 1217 tao
        //conn.close();
1456
       }//try
1457
       catch(Exception ee)
1458
       {
1459
         MetaCatUtil.debugMessage("Error in MetacatReplicatio.getServerCode: "
1460
                                  +ee.getMessage(), 30);
1461
1462
       }//catch
1463
       finally
1464
       {
1465
         DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1466
       }//finally
1467
    }//finally
1468 837 bojilova
1469
    return serverCode;
1470 569 berkley
  }
1471
1472
  /**
1473 1292 tao
   * Method to get a host server information for given docid
1474
   * @param conn a connection to the database
1475
   */
1476
  public static Hashtable getHomeServerInfoForDocId(String docId)
1477
  {
1478
    Hashtable sl = new Hashtable();
1479
    DBConnection dbConn = null;
1480
    int serialNumber = -1;
1481
    //MetaCatUtil ut=new MetaCatUtil();
1482
    docId=MetaCatUtil.getDocIdFromString(docId);
1483
    PreparedStatement pstmt=null;
1484
    int serverLocation;
1485
    try
1486
    {
1487
      //get conection
1488
      dbConn=DBConnectionPool.
1489
                  getDBConnection("ReplicationHandler.getHomeServer");
1490
      serialNumber=dbConn.getCheckOutSerialNumber();
1491
      //get a server location from xml_document table
1492
      pstmt=dbConn.prepareStatement("select server_location from xml_documents "
1493
                                            +"where docid = ?");
1494
      pstmt.setString(1, docId);
1495
      pstmt.execute();
1496
      ResultSet serverName = pstmt.getResultSet();
1497
      //get a server location
1498
      if(serverName.next())
1499
      {
1500
        serverLocation=serverName.getInt(1);
1501
        pstmt.close();
1502
      }
1503
      else
1504
      {
1505
        pstmt.close();
1506
        //ut.returnConnection(conn);
1507
        return null;
1508
      }
1509
      pstmt=dbConn.prepareStatement("select server, last_checked, replicate " +
1510
                        "from xml_replication where serverid = ?");
1511
      //increase usage count
1512
      dbConn.increaseUsageCount(1);
1513
      pstmt.setInt(1, serverLocation);
1514
      pstmt.execute();
1515
      ResultSet rs = pstmt.getResultSet();
1516
      boolean tableHasRows = rs.next();
1517
      if (tableHasRows)
1518
      {
1519
1520
          String server = rs.getString(1);
1521
          String last_checked = rs.getString(2);
1522
          if(!server.equals("localhost"))
1523
          {
1524
            sl.put(server, last_checked);
1525
          }
1526
1527
      }
1528
      else
1529
      {
1530
        pstmt.close();
1531
        //ut.returnConnection(conn);
1532
        return null;
1533
      }
1534
      pstmt.close();
1535
    }
1536
    catch(Exception e)
1537
    {
1538
      System.out.println("error in replicationHandler.getHomeServer(): " +
1539
                         e.getMessage());
1540
    }
1541
    finally
1542
    {
1543
      try
1544
      {
1545
        pstmt.close();
1546
        //ut.returnConnection(conn);
1547
      }
1548
      catch (Exception ee)
1549
      {
1550
        MetaCatUtil.debugMessage("Eror irn rplicationHandler.getHomeServer() "+
1551
                          "to close pstmt: "+ee.getMessage(), 30);
1552
      }
1553
      finally
1554
      {
1555
        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1556
      }
1557
1558
    }//finally
1559
    return sl;
1560
  }
1561
1562
  /**
1563
   * Returns a home server location  given a accnum
1564
   * @param accNum , given accNum for a document
1565
   *
1566
   */
1567
  public static int getHomeServerCodeForDocId(String accNum) throws Exception
1568
  {
1569
    DBConnection dbConn = null;
1570
    int serialNumber = -1;
1571
    PreparedStatement pstmt = null;
1572
    int serverCode = 1;
1573
    //MetaCatUtil ut = new MetaCatUtil();
1574
    String docId=MetaCatUtil.getDocIdFromString(accNum);
1575
1576
    try
1577
    {
1578
1579
      // Get DBConnection
1580
      dbConn=DBConnectionPool.
1581
                  getDBConnection("ReplicationHandler.getServerLocation");
1582
      serialNumber=dbConn.getCheckOutSerialNumber();
1583
      pstmt=dbConn.prepareStatement("SELECT server_location FROM xml_documents "
1584
                              + "WHERE docid LIKE '" + docId + "'");
1585
      pstmt.execute();
1586
      ResultSet rs = pstmt.getResultSet();
1587
      boolean tablehasrows = rs.next();
1588
      //If a document is find, return the server location for it
1589
      if ( tablehasrows )
1590
      {
1591
        serverCode = rs.getInt(1);
1592
        pstmt.close();
1593
        //conn.close();
1594
        return serverCode;
1595
      }
1596
      //if couldn't find in xml_documents table, we think server code is 1
1597
      //(this is new document)
1598
      else
1599
      {
1600
        pstmt.close();
1601
        //conn.close();
1602
        return serverCode;
1603
      }
1604
1605
    }
1606
    catch(Exception e)
1607
    {
1608
1609
      throw e;
1610
1611
    }
1612
    finally
1613
    {
1614
      try
1615
      {
1616
        pstmt.close();
1617
        //conn.close();
1618
1619
      }
1620
      catch(Exception ee)
1621
      {
1622
        MetaCatUtil.debugMessage("Erorr in Replication.getServerLocation "+
1623
                     "to close pstmt"+ee.getMessage(), 30);
1624
      }
1625
      finally
1626
      {
1627
        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1628
      }//finally
1629
    }//finally
1630
   //return serverCode;
1631
  }
1632
1633
1634
1635
  /**
1636 569 berkley
   * This method returns the content of a url
1637
   * @param u the url to return the content from
1638
   * @return a string representing the content of the url
1639
   * @throws java.io.IOException
1640
   */
1641
  public static String getURLContent(URL u) throws java.io.IOException
1642
  {
1643
    char istreamChar;
1644
    int istreamInt;
1645 1606 tao
    MetaCatUtil.debugMessage("Before open the stream"+u.toString(), 50);
1646
    InputStream input = u.openStream();
1647
    MetaCatUtil.debugMessage("Afetr open the stream"+u.toString(), 50);
1648
    InputStreamReader istream = new InputStreamReader(input);
1649 569 berkley
    StringBuffer serverResponse = new StringBuffer();
1650
    while((istreamInt = istream.read()) != -1)
1651
    {
1652
      istreamChar = (char)istreamInt;
1653
      serverResponse.append(istreamChar);
1654
    }
1655 1606 tao
    istream.close();
1656
    input.close();
1657
1658 569 berkley
    return serverResponse.toString();
1659
  }
1660 584 berkley
1661
  /**
1662
   * Method for writing replication messages to a log file specified in
1663
   * metacat.properties
1664
   */
1665
  public static void replLog(String message)
1666
  {
1667
    try
1668
    {
1669
      FileOutputStream fos = new FileOutputStream(
1670
                                 util.getOption("replicationlog"), true);
1671
      PrintWriter pw = new PrintWriter(fos);
1672
      SimpleDateFormat formatter = new SimpleDateFormat ("yy-MM-dd HH:mm:ss");
1673
      java.util.Date localtime = new java.util.Date();
1674
      String dateString = formatter.format(localtime);
1675
      dateString += " :: " + message;
1676
      //time stamp each entry
1677
      pw.println(dateString);
1678
      pw.flush();
1679
    }
1680
    catch(Exception e)
1681
    {
1682 675 berkley
      System.out.println("error writing to replication log from " +
1683
                         "MetacatReplication.replLog: " + e.getMessage());
1684 595 berkley
      //e.printStackTrace(System.out);
1685 584 berkley
    }
1686
  }
1687 629 berkley
1688
  /**
1689 1583 tao
   * Method for writing replication messages to a log file specified in
1690
   * metacat.properties
1691
   */
1692
  public static void replErrorLog(String message)
1693
  {
1694
    try
1695
    {
1696
      FileOutputStream fos = new FileOutputStream(
1697
                                 util.getOption("replicationerrorlog"), true);
1698
      PrintWriter pw = new PrintWriter(fos);
1699
      SimpleDateFormat formatter = new SimpleDateFormat ("yy-MM-dd HH:mm:ss");
1700
      java.util.Date localtime = new java.util.Date();
1701
      String dateString = formatter.format(localtime);
1702
      dateString += " :: " + message;
1703
      //time stamp each entry
1704
      pw.println(dateString);
1705
      pw.flush();
1706
    }
1707
    catch(Exception e)
1708
    {
1709
      System.out.println("error writing to replication log from " +
1710
                         "MetacatReplication.replLog: " + e.getMessage());
1711
      //e.printStackTrace(System.out);
1712
    }
1713
  }
1714
1715
  /**
1716 629 berkley
   * Returns true if the replicate field for server in xml_replication is 1.
1717
   * Returns false otherwise
1718
   */
1719
  public static boolean replToServer(String server)
1720
  {
1721 1217 tao
    DBConnection dbConn = null;
1722
    int serialNumber = -1;
1723 667 berkley
    PreparedStatement pstmt = null;
1724 629 berkley
    try
1725
    {
1726 1217 tao
      dbConn=DBConnectionPool.
1727
                  getDBConnection("MetacatReplication.repltoServer");
1728
      serialNumber=dbConn.getCheckOutSerialNumber();
1729
      pstmt = dbConn.prepareStatement("select replicate from " +
1730 667 berkley
                                    "xml_replication where server like '" +
1731
                                     server + "'");
1732 629 berkley
      pstmt.execute();
1733
      ResultSet rs = pstmt.getResultSet();
1734
      boolean tablehasrows = rs.next();
1735
      if(tablehasrows)
1736
      {
1737
        int i = rs.getInt(1);
1738
        if(i == 1)
1739
        {
1740 667 berkley
          pstmt.close();
1741 1217 tao
          //conn.close();
1742 629 berkley
          return true;
1743
        }
1744
        else
1745
        {
1746 667 berkley
          pstmt.close();
1747 1217 tao
          //conn.close();
1748 629 berkley
          return false;
1749
        }
1750
      }
1751
    }
1752
    catch(Exception e)
1753
    {
1754 675 berkley
      System.out.println("error in MetacatReplication.replToServer: " +
1755
                         e.getMessage());
1756 629 berkley
    }
1757 667 berkley
    finally
1758
    {
1759
      try
1760
      {
1761
        pstmt.close();
1762 1217 tao
        //conn.close();
1763
      }//try
1764 667 berkley
      catch(Exception ee)
1765 1217 tao
      {
1766
        MetaCatUtil.debugMessage("Error in MetacatReplication.replToServer: "
1767
                                  +ee.getMessage(), 30);
1768
      }//catch
1769
      finally
1770
      {
1771
        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1772
      }//finally
1773
    }//finally
1774 629 berkley
    return false;
1775
    //the default if this server does not exist is to not replicate to it.
1776
  }
1777 683 berkley
1778 1217 tao
1779 522 berkley
}