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