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