Project

General

Profile

1
/**
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: berkley $'
10
 *     '$Date: 2001-01-18 15:15:21 -0800 (Thu, 18 Jan 2001) $'
11
 * '$Revision: 675 $'
12
 *
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
 */
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

    
39
import org.xml.sax.*;
40

    
41
public class MetacatReplication extends HttpServlet implements Runnable
42
{  
43
  private String deltaT;
44
  Timer replicationDaemon;
45
  private static MetaCatUtil util = new MetaCatUtil();
46
  private Vector fileLocks = new Vector();
47
  private Thread lockThread = null;
48
  
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
    //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
    replicationDaemon = new Timer(true);
60
  }
61
  
62
  public void destroy() 
63
  {
64
    replicationDaemon.cancel();
65
    System.out.println("Replication daemon cancelled.");
66
  }
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
    PrintWriter out = response.getWriter();
87
    Hashtable params = new Hashtable();
88
    Enumeration paramlist = request.getParameterNames();
89
    
90
    while (paramlist.hasMoreElements()) 
91
    {
92
      String name = (String)paramlist.nextElement();
93
      String[] value = request.getParameterValues(name);
94
      params.put(name, value);  
95
    }
96
    
97
    if(params.containsKey("action"))
98
    {
99
      if(((String[])params.get("action"))[0].equals("stop"))
100
      { //stop the replication server
101
        replicationDaemon.cancel();
102
        replicationDaemon = new Timer(true);
103
        out.println("Replication Handler Stopped");
104
        System.out.println("Replication Handler Stopped");
105
        MetacatReplication.replLog("deltaT handler stopped");
106
      }
107
      else if(((String[])params.get("action"))[0].equals("start"))
108
      { //start the replication server
109
        int rate;
110
        if(params.containsKey("rate"))
111
        {
112
          rate = new Integer(
113
                 new String(((String[])params.get("rate"))[0])).intValue();
114
          if(rate < 30)
115
          {
116
            out.println("Replication deltaT rate cannot be less than 30!");
117
            //deltaT<30 is a timing mess!
118
            rate = 1000;
119
          }
120
        }
121
        else
122
        {
123
          rate = 1000;
124
        }
125
        
126
        out.println("New rate is: " + rate + " seconds.");
127
        replicationDaemon.cancel();
128
        replicationDaemon = new Timer(true);
129
        replicationDaemon.scheduleAtFixedRate(new ReplicationHandler(out), 0, 
130
                                              rate * 1000);
131
        MetacatReplication.replLog("deltaT handler started with rate=" + 
132
                                    rate + " seconds");
133
        out.println("Replication Handler Started");
134
        System.out.println("Replication Handler Started");
135
      }
136
      else if(((String[])params.get("action"))[0].equals("getall"))
137
      { //updates this server exactly once
138
        replicationDaemon.schedule(new ReplicationHandler(out), 0);
139
        response.setContentType("text/html");
140
        out.println("<html><body>\"Get All\" Done</body></html>");
141
      }
142
      else if(((String[])params.get("action"))[0].equals("forcereplicate"))
143
      {
144
        handleForceReplicateRequest(out, params, response);
145
      }
146
      else if(((String[])params.get("action"))[0].equals("update"))
147
      { //request an update list from the server
148
        handleUpdateRequest(out, params, response);
149
      }
150
      else if(((String[])params.get("action"))[0].equals("read"))
151
      { //request a specific document from the server
152
        //note that this could be replaced by a call to metacatServlet
153
        //handleGetDocumentAction().
154
        handleGetDocumentRequest(out, params, response);
155
      }
156
      else if(((String[])params.get("action"))[0].equals("getlock"))
157
      {
158
        handleGetLockRequest(out, params, response);
159
      }
160
      else if(((String[])params.get("action"))[0].equals("getdocumentinfo"))
161
      {
162
        handleGetDocumentInfoRequest(out, params, response);
163
      }
164
      else if(((String[])params.get("action"))[0].equals("gettime"))
165
      {
166
        handleGetTimeRequest(out, params, response);
167
      }
168
      else if(((String[])params.get("action"))[0].equals("getcatalog"))
169
      {
170
        handleGetCatalogRequest(out, params, response, true);
171
      }
172
      else if(((String[])params.get("action"))[0].equals("servercontrol"))
173
      {
174
        handleServerControlRequest(out, params, response);
175
      }
176
      
177
    }
178
  }
179
  
180
  /** 
181
   * This method can add, delete and list the servers currently included in
182
   * xml_replication.
183
   * action           subaction            other needed params
184
   * ---------------------------------------------------------
185
   * servercontrol    add                  server
186
   * servercontrol    delete               server
187
   * servercontrol    list                 
188
   */
189
  private void handleServerControlRequest(PrintWriter out, Hashtable params,
190
                                          HttpServletResponse response)
191
  {
192
    String subaction = ((String[])params.get("subaction"))[0];
193
    try
194
    {
195
      Connection conn = util.openDBConnection();
196
      PreparedStatement pstmt = null;
197
      if(subaction.equals("add"))
198
      {
199
        String replicate = ((String[])params.get("replicate"))[0];
200
        String server = ((String[])params.get("server"))[0];
201
        pstmt = conn.prepareStatement("insert into xml_replication (server, " +
202
                "last_checked, replicate) values ('" + server + "', to_date(" +
203
                "'01/01/00', 'MM/DD/YY'), '" + replicate + "')");
204
        pstmt.execute();
205
        out.println("Server says: server " + server + " added"); 
206
        response.setContentType("text/html");
207
        out.println("<html><body><table border=\"1\">");
208
        out.println("<tr><td><b>server</b></td><td><b>last_checked</b></td><td>");
209
        out.println("<b>replicate</b></td></tr>");
210
        pstmt = conn.prepareStatement("select * from xml_replication");
211
        pstmt.execute();
212
        ResultSet rs = pstmt.getResultSet();
213
        boolean tablehasrows = rs.next();
214
        while(tablehasrows)
215
        {
216
          out.println("<tr><td>" + rs.getString(2) + "</td><td>");
217
          out.println(rs.getString(3) + "</td><td>");
218
          out.println(rs.getString(4) + "</td></tr>");
219
          tablehasrows = rs.next();
220
        }
221
        out.println("</table></body></html>");
222
      }
223
      else if(subaction.equals("delete"))
224
      {
225
        String server = ((String[])params.get("server"))[0];
226
        pstmt = conn.prepareStatement("delete from xml_replication where " +
227
                "server like '" + server + "'");
228
        pstmt.execute();
229
        out.println("Server says: server " + server + " deleted");
230
        response.setContentType("text/html");
231
        out.println("<html><body><table border=\"1\">");
232
        out.println("<tr><td><b>server</b></td><td><b>last_checked</b></td><td>");
233
        out.println("<b>replicate</b></td></tr>");
234
        pstmt = conn.prepareStatement("select * from xml_replication");
235
        pstmt.execute();
236
        ResultSet rs = pstmt.getResultSet();
237
        boolean tablehasrows = rs.next();
238
        while(tablehasrows)
239
        {
240
          out.println("<tr><td>" + rs.getString(2) + "</td><td>");
241
          out.println(rs.getString(3) + "</td><td>");
242
          out.println(rs.getString(4) + "</td></tr>");
243
          tablehasrows = rs.next();
244
        }
245
        out.println("</table></body></html>");
246
      }
247
      else if(subaction.equals("list"))
248
      {
249
        response.setContentType("text/html");
250
        out.println("<html><body><table border=\"1\">");
251
        out.println("<tr><td><b>server</b></td><td><b>last_checked</b></td><td>");
252
        out.println("<b>replicate</b></td></tr>");
253
        pstmt = conn.prepareStatement("select * from xml_replication");
254
        pstmt.execute();
255
        ResultSet rs = pstmt.getResultSet();
256
        boolean tablehasrows = rs.next();
257
        while(tablehasrows)
258
        {
259
          out.println("<tr><td>" + rs.getString(2) + "</td><td>");
260
          out.println(rs.getString(3) + "</td><td>");
261
          out.println(rs.getString(4) + "</td></tr>");
262
          tablehasrows = rs.next();
263
        }
264
        out.println("</table></body></html>");
265
      }
266
      pstmt.close();
267
      conn.close();
268
    }
269
    catch(Exception e)
270
    {
271
      System.out.println("error in " + 
272
                         "MetacatReplication.handleServerControlRequest " + 
273
                         e.getMessage());
274
      e.printStackTrace(System.out);
275
    }
276
  }
277
  
278
  /**
279
   * when a forcereplication request comes in, this method sends a read request
280
   * to the requesting server for the specified docid.
281
   */
282
  private void handleForceReplicateRequest(PrintWriter out, Hashtable params,
283
                                           HttpServletResponse response)
284
  {
285
    //System.out.println("in handleforcereplicaterequest");
286
    String server = ((String[])params.get("server"))[0];
287
    if(!(replToServer(server)))
288
    { //do not get the server's new document if we are not replicating from there
289
      return;
290
    }
291
    
292
    //the server that the request came from
293
    String docid = ((String[])params.get("docid"))[0];
294
    //the docid of the document to get
295
    String dbaction = "UPDATE";
296
    //default action is update
297
    boolean override = false;
298
    int serverCode = 1;
299
    
300
    try
301
    {
302
      if(params.containsKey("dbaction"))
303
      { //if the url contains a dbaction then the default action is overridden
304
        dbaction = ((String[])params.get("dbaction"))[0];
305
        serverCode = MetacatReplication.getServerCode(server);
306
        override = true; //we are now overriding the default action
307
      }
308
      MetaCatUtil.debugMessage("action in forcereplicate is: " + dbaction);
309
      MetaCatUtil.debugMessage("serverCode in forcereplicate is: " + serverCode);
310
      MetacatReplication.replLog("force replication request from " + server); 
311
      
312
      int serverCheckCode = MetacatReplication.getServerCode(server);
313
      URL u = new URL("http://" + server + "?action=read&docid=" + docid);
314
      MetaCatUtil.debugMessage("sending message: " + u.toString());
315
      String xmldoc = MetacatReplication.getURLContent(u);
316
      MetaCatUtil.debugMessage("document: " + xmldoc);
317
      //get the document to write
318
      URL docinfourl = new URL("http://" + server + 
319
                               "?action=getdocumentinfo&docid=" +
320
                               docid);
321
      //we need to get the document's info so we can set the correct user
322
      //and group once we get the document and write it to our DB
323
      MetaCatUtil.debugMessage("sending message: " + docinfourl.toString());
324
      String docInfoStr = MetacatReplication.getURLContent(docinfourl);
325
      MetaCatUtil.debugMessage("docInfo: " + docInfoStr);
326
      DocInfoHandler dih = new DocInfoHandler();
327
      //dih is the parser for the docinfo xml format
328
      XMLReader docinfoParser = ReplicationHandler.initParser(dih);
329
      docinfoParser.parse(new InputSource(new StringReader(docInfoStr)));
330
      Hashtable docinfoHash = dih.getDocInfo();
331
      String user = (String)docinfoHash.get("user_owner");
332
      String group = new String(user);
333
      //right now the user and group are the same.
334
      Connection conn = util.openDBConnection();
335
      DocumentImpl.write(conn, new StringReader(xmldoc), null, dbaction, docid, 
336
                         user, group, serverCode, override);
337
      MetacatReplication.replLog("document " + docid + " added to DB with " +
338
                                 "action " + dbaction);
339
      conn.close();
340
    }
341
    catch(Exception e)
342
    {
343
      System.out.println("error in metacatReplication.handleForceReplicate" +
344
                         "Request: " + e.getMessage());
345
    }
346
  }
347
  
348
  /**
349
   * Grants or denies a lock to a requesting host.
350
   * The servlet parameters of interrest are:
351
   * docid: the docid of the file the lock is being requested for
352
   * currentdate: the timestamp of the document on the remote server
353
   * 
354
   */
355
  private void handleGetLockRequest(PrintWriter out, Hashtable params,
356
                                    HttpServletResponse response)
357
  {
358
    try
359
    {
360
      Connection conn = util.openDBConnection();
361
      String docid = ((String[])params.get("docid"))[0];
362
      String remoteRev = ((String[])params.get("updaterev"))[0];
363
      DocumentImpl requestDoc = new DocumentImpl(conn, docid);
364
      MetacatReplication.replLog("lock request for " + docid);
365
      int localRevInt = requestDoc.getRev();
366
      int remoteRevInt = Integer.parseInt(remoteRev);
367
      
368
      if(remoteRevInt >= localRevInt)
369
      {
370
        if(!fileLocks.contains(docid))
371
        { //grant the lock if it is not already locked
372
          fileLocks.add(0, docid); //insert at the beginning of the queue Vector
373
          //send a message back to the the remote host authorizing the insert
374
          out.println("<lockgranted><docid>" +docid+ "</docid></lockgranted>");
375
          lockThread = new Thread(this);
376
          lockThread.setPriority(Thread.MIN_PRIORITY);
377
          lockThread.start();
378
          System.out.println("lock granted for " + docid);
379
          MetacatReplication.replLog("lock granted for " + docid);
380
        }
381
        else
382
        { //deny the lock
383
          out.println("<filelocked><docid>" + docid + "</docid></filelocked>");
384
          MetacatReplication.replLog("lock denied for " + docid + 
385
                                     "reason: file already locked");
386
        }
387
      }
388
      else
389
      {//deny the lock.
390
        out.println("<outdatedfile><docid>" + docid + "</docid></filelocked>");
391
        MetacatReplication.replLog("lock denied for " + docid + 
392
                                   "reason: client has outdated file");
393
      }
394
      conn.close();
395
    }
396
    catch(Exception e)
397
    {
398
      System.out.println("error requesting file lock from MetacatReplication." +
399
                         "handleGetLockRequest: " + e.getMessage());
400
      e.printStackTrace(System.out);
401
    }
402
  }
403
  
404
  /**
405
   * Sends all of the xml_documents information encoded in xml to a requestor
406
   * the format is:
407
   * <!ELEMENT documentinfo (docid, docname, doctype, doctitle, user_owner,
408
   *                         user_updated, public_access, rev)
409
   * all of the subelements of document info are #PCDATA
410
   */
411
  private void handleGetDocumentInfoRequest(PrintWriter out, Hashtable params, 
412
                                        HttpServletResponse response)
413
  {
414
    String docid = ((String[])(params.get("docid")))[0];
415
    StringBuffer sb = new StringBuffer();
416
    try
417
    {
418
      Connection conn = util.openDBConnection();
419
      DocumentImpl doc = new DocumentImpl(conn, docid);
420
      sb.append("<documentinfo><docid>").append(docid);
421
      sb.append("</docid><docname>").append(doc.getDocname());
422
      sb.append("</docname><doctype>").append(doc.getDoctype());
423
      sb.append("</doctype><doctitle>").append(doc.getDocTitle());
424
      sb.append("</doctitle><user_owner>").append(doc.getUserowner());
425
      sb.append("</user_owner><user_updated>").append(doc.getUserupdated());
426
      sb.append("</user_updated><public_access>").append(doc.getPublicaccess());
427
      sb.append("</public_access><rev>").append(doc.getRev());
428
      sb.append("</rev></documentinfo>");
429
      response.setContentType("text/xml");
430
      out.println(sb.toString());
431
      conn.close();
432
    }
433
    catch (Exception e)
434
    {
435
      System.out.println("error in " +
436
                         "metacatReplication.handlegetdocumentinforequest: " + 
437
                          e.getMessage());
438
    }
439
    
440
  }
441
  
442
  /**
443
   * Sends a document to a remote host
444
   */
445
  private void handleGetDocumentRequest(PrintWriter out, Hashtable params, 
446
                                        HttpServletResponse response)
447
  {
448
    try
449
    {
450
      String docid = ((String[])(params.get("docid")))[0];
451
      MetaCatUtil.debugMessage("incoming get request for document: " + docid);
452
      Connection conn = util.openDBConnection();
453
      DocumentImpl di = new DocumentImpl(conn, docid);
454
      response.setContentType("text/xml");
455
      out.print(di.toString());
456
      conn.close();
457
      MetacatReplication.replLog("document " + docid + " sent");
458
      System.out.println("document " + docid + " sent");
459
    }
460
    catch(Exception e)
461
    {
462
      System.out.println("error getting document from MetacatReplication." +
463
                         "handlGetDocumentRequest " + e.getMessage());
464
    }
465
    
466
  }
467
  
468
  /**
469
   * Sends a list of all of the documents on this sever along with their
470
   * revision numbers.  
471
   * The format is:
472
   * <!ELEMENT replication (server, updates)>
473
   * <!ELEMENT server (#PCDATA)>
474
   * <!ELEMENT updates ((updatedDocument | deleteDocument)*)>
475
   * <!ELEMENT updatedDocument (docid, rev)>
476
   * <!ELEMENT deletedDocument (docid, rev)>
477
   * <!ELEMENT docid (#PCDATA)>
478
   * <!ELEMENT rev (#PCDATA)>
479
   * note that the rev in deletedDocument is always empty.  I just left
480
   * it in there to make the parser implementation easier.
481
   */
482
  private void handleUpdateRequest(PrintWriter out, Hashtable params, 
483
                                    HttpServletResponse response)
484
  {
485
    try
486
    {
487
      System.out.println("received update request");
488
      StringBuffer docsql = new StringBuffer();
489
      StringBuffer doclist = new StringBuffer();
490
      Vector packageFiles = new Vector();
491
      
492
      //get all docs that reside on this server
493
      doclist.append("<?xml version=\"1.0\"?><replication>");
494
      doclist.append("<server>").append(util.getOption("server"));
495
      doclist.append(util.getOption("replicationpath"));
496
      doclist.append("</server><updates>");
497
      
498
      docsql.append("select docid, rev, doctype from xml_documents where "); 
499
      docsql.append("server_location = 1");
500
      
501
      //get any deleted documents
502
      StringBuffer delsql = new StringBuffer();
503
      delsql.append("select distinct docid from ");
504
      delsql.append("xml_revisions where docid not in (select docid from ");
505
      delsql.append("xml_documents) and server_location = 1");
506
      
507
      Connection conn = util.openDBConnection();
508
      PreparedStatement pstmt = conn.prepareStatement(docsql.toString());
509
      pstmt.execute();
510
      ResultSet rs = pstmt.getResultSet();
511
      boolean tablehasrows = rs.next();
512
      while(tablehasrows)
513
      {
514
        if(!rs.getString(3).equals(util.getOption("packagedoctype")))
515
        { //if this is a package file, put it at the end
516
          //because if a package file is read before all of the files it
517
          //refers to are loaded then there is an error
518
          doclist.append("<updatedDocument>");
519
          doclist.append("<docid>").append(rs.getString(1));
520
          doclist.append("</docid><rev>").append(rs.getInt(2));
521
          doclist.append("</rev>");
522
          doclist.append("</updatedDocument>");
523
        }
524
        else
525
        { //the package files are saved to be put into the xml later.
526
          Vector v = new Vector();
527
          v.add(new String(rs.getString(1)));
528
          v.add(new Integer(rs.getInt(2)));
529
          packageFiles.add(new Vector(v));
530
        }
531
        tablehasrows = rs.next();
532
      }
533
      
534
      pstmt = conn.prepareStatement(delsql.toString());
535
      pstmt.execute();
536
      rs = pstmt.getResultSet();
537
      tablehasrows = rs.next();
538
      while(tablehasrows)
539
      { //handle the deleted documents
540
        doclist.append("<deletedDocument><docid>").append(rs.getString(1));
541
        doclist.append("</docid><rev></rev></deletedDocument>");
542
        //note that rev is always empty for deleted docs
543
        tablehasrows = rs.next();
544
      }
545
      
546
      //now we can put the package files into the xml results
547
      for(int i=0; i<packageFiles.size(); i++)
548
      {
549
        Vector v = (Vector)packageFiles.elementAt(i);
550
        doclist.append("<updatedDocument>");
551
        doclist.append("<docid>").append((String)v.elementAt(0));
552
        doclist.append("</docid><rev>");
553
        doclist.append(((Integer)v.elementAt(1)).intValue());
554
        doclist.append("</rev>");
555
        doclist.append("</updatedDocument>");
556
      }
557
      
558
      doclist.append("</updates></replication>");
559
      MetaCatUtil.debugMessage("doclist: " + doclist.toString());
560
      pstmt.close();
561
      conn.close();
562
      response.setContentType("text/xml");
563
      out.println(doclist.toString());
564
      System.out.println("doclist: " + doclist.toString());
565
      System.out.println("update request handled");
566
    }
567
    catch(Exception e)
568
    {
569
      System.out.println("error in MetacatReplication.handleupdaterequest: " + 
570
                          e.getMessage());
571
      e.printStackTrace(System.out);
572
    }
573
    
574
  }
575
  
576
  /**
577
   * Returns the xml_catalog table encoded in xml
578
   */
579
  public static String getCatalogXML()
580
  {
581
    return handleGetCatalogRequest(null, null, null, false);
582
  }
583
  
584
  /**
585
   * Sends the contents of the xml_catalog table encoded in xml
586
   * The xml format is:
587
   * <!ELEMENT xml_catalog (row*)>
588
   * <!ELEMENT row (entry_type, source_doctype, target_doctype, public_id,
589
   *                system_id)>
590
   * All of the sub elements of row are #PCDATA
591
   
592
   * If printFlag == false then do not print to out.
593
   */
594
  private static String handleGetCatalogRequest(PrintWriter out, 
595
                                                Hashtable params,
596
                                                HttpServletResponse response,
597
                                                boolean printFlag)
598
  {
599
    Connection conn = null;
600
    PreparedStatement pstmt = null;
601
    try
602
    {
603
      conn = util.openDBConnection();
604
      pstmt = conn.prepareStatement("select entry_type, " +
605
                              "source_doctype, target_doctype, public_id, " +
606
                              "system_id from xml_catalog");
607
      pstmt.execute();
608
      ResultSet rs = pstmt.getResultSet();
609
      boolean tablehasrows = rs.next();
610
      StringBuffer sb = new StringBuffer();
611
      sb.append("<?xml version=\"1.0\"?><xml_catalog>");
612
      while(tablehasrows)
613
      {
614
        sb.append("<row><entry_type>").append(rs.getString(1));
615
        sb.append("</entry_type><source_doctype>").append(rs.getString(2));
616
        sb.append("</source_doctype><target_doctype>").append(rs.getString(3));
617
        sb.append("</target_doctype><public_id>").append(rs.getString(4));
618
        sb.append("</public_id><system_id>").append(rs.getString(5));
619
        sb.append("</system_id></row>");
620
      
621
        tablehasrows = rs.next();
622
      }
623
      sb.append("</xml_catalog>");
624
      conn.close();
625
      if(printFlag)
626
      {
627
        response.setContentType("text/xml");
628
        out.println(sb.toString());
629
      }
630
      pstmt.close();
631
      return sb.toString();
632
    }
633
    catch(Exception e)
634
    {
635
      try
636
      {
637
        pstmt.close();
638
        conn.close();
639
      }
640
      catch(Exception ee)
641
      {}
642
      System.out.println("error in MetacatReplication.handleGetCatalogRequest:"+ 
643
                          e.getMessage());
644
      e.printStackTrace(System.out);
645
    }
646
    return null;
647
  }
648
  
649
  /**
650
   * Sends the current system date to the remote server.  Using this action
651
   * for replication gets rid of any problems with syncronizing clocks 
652
   * because a time specific to a document is always kept on its home server.
653
   */
654
  private void handleGetTimeRequest(PrintWriter out, Hashtable params, 
655
                                    HttpServletResponse response)
656
  {
657
    SimpleDateFormat formatter = new SimpleDateFormat ("yy-MM-dd HH:mm:ss");
658
    java.util.Date localtime = new java.util.Date();
659
    String dateString = formatter.format(localtime);
660
    response.setContentType("text/xml");
661
    
662
    out.println("<timestamp>" + dateString + "</timestamp>");
663
  }
664
  
665
  /**
666
   * this method handles the timeout for a file lock.  when a lock is 
667
   * granted it is granted for 30 seconds.  When this thread runs out
668
   * it deletes the docid from the queue, thus eliminating the lock.
669
   */
670
  public void run()
671
  {
672
    try
673
    {
674
      MetaCatUtil.debugMessage("thread started for docid: " + 
675
                               (String)fileLocks.elementAt(0));
676
      System.out.println("thread started for docid: " + 
677
                               (String)fileLocks.elementAt(0));
678
      Thread.sleep(30000); //the lock will expire in 30 seconds
679
      MetaCatUtil.debugMessage("thread for docid: " + 
680
                             (String)fileLocks.elementAt(fileLocks.size() - 1) + 
681
                              " exiting.");
682
      System.out.println("thread for docid: " + 
683
                         (String)fileLocks.elementAt(fileLocks.size() - 1) + 
684
                         " exiting.");
685
      fileLocks.remove(fileLocks.size() - 1);
686
      //fileLocks is treated as a FIFO queue.  If there are more than one lock
687
      //in the vector, the first one inserted will be removed.
688
    }
689
    catch(Exception e)
690
    {
691
      System.out.println("error in file lock thread from MetacatReplication." + 
692
                         "run: " + e.getMessage());
693
    }
694
  }
695
  
696
  /**
697
   * Returns the name of a server given a serverCode
698
   * @param serverCode the serverid of the server
699
   * @return the servername or null if the specified serverCode does not
700
   *         exist.
701
   */
702
  public static String getServer(int serverCode)
703
  {
704
    //System.out.println("serverid: " + serverCode);
705
    try
706
    {
707
      Connection conn = util.openDBConnection();
708
      String sql = new String("select server from " +
709
                              "xml_replication where serverid = " + 
710
                              serverCode);
711
      PreparedStatement pstmt = conn.prepareStatement(sql);
712
      //System.out.println("getserver sql: " + sql);
713
      pstmt.execute();
714
      ResultSet rs = pstmt.getResultSet();
715
      boolean tablehasrows = rs.next();
716
      if(tablehasrows)
717
      {
718
        //System.out.println("server: " + rs.getString(1));
719
        return rs.getString(1);
720
      }
721
      pstmt.close();
722
      conn.close();
723
    }
724
    catch(Exception e)
725
    {
726
      System.out.println("Error in MetacatReplication.getServer: " + 
727
                          e.getMessage());
728
    }
729
    return null;
730
      //return null if the server does not exist
731
  }
732
  
733
  /**
734
   * Returns a server code given a server name
735
   * @param server the name of the server
736
   * @return integer > 0 representing the code of the server, 0 if the server
737
   *  does not exist.
738
   */
739
  public static int getServerCode(String server) throws Exception
740
  {
741
    Connection conn = null;
742
    PreparedStatement pstmt = null;
743
    try
744
    {
745
      conn = util.openDBConnection();
746
      pstmt = conn.prepareStatement("select serverid from " +
747
                                         "xml_replication where server " +
748
                                         "like '" + server + "'");
749
      pstmt.execute();
750
      ResultSet rs = pstmt.getResultSet();
751
      boolean tablehasrows = rs.next();
752
      int serverCode = 0;
753
      if(tablehasrows)
754
      {  
755
        int ret = rs.getInt(1);
756
        pstmt.close();
757
        conn.close();
758
        return ret;
759
      }
760
      else
761
      {
762
        pstmt.close();
763
        conn.close();
764
        return 0;
765
      }
766
    }
767
    catch(Exception e)
768
    {
769
      throw e;
770
    }
771
    finally
772
    {
773
       try
774
       {
775
         pstmt.close();
776
         conn.close();
777
       }
778
       catch(Exception ee) {}
779
    }
780
  }
781
  
782
  /**
783
   * This method returns the content of a url
784
   * @param u the url to return the content from
785
   * @return a string representing the content of the url
786
   * @throws java.io.IOException
787
   */
788
  public static String getURLContent(URL u) throws java.io.IOException
789
  {
790
    //System.out.println("url: " + u.toString());
791
    char istreamChar;
792
    int istreamInt;
793
    InputStreamReader istream = new InputStreamReader(u.openStream());
794
    StringBuffer serverResponse = new StringBuffer();
795
    while((istreamInt = istream.read()) != -1)
796
    {
797
      istreamChar = (char)istreamInt;
798
      serverResponse.append(istreamChar);
799
    }
800
    
801
    return serverResponse.toString();
802
  }
803
  
804
  /**
805
   * Method for writing replication messages to a log file specified in 
806
   * metacat.properties
807
   */
808
  public static void replLog(String message)
809
  {
810
    try
811
    {
812
      FileOutputStream fos = new FileOutputStream(
813
                                 util.getOption("replicationlog"), true);
814
      PrintWriter pw = new PrintWriter(fos);
815
      SimpleDateFormat formatter = new SimpleDateFormat ("yy-MM-dd HH:mm:ss");
816
      java.util.Date localtime = new java.util.Date();
817
      String dateString = formatter.format(localtime);
818
      dateString += " :: " + message;
819
      //time stamp each entry
820
      pw.println(dateString);
821
      pw.flush();
822
    }
823
    catch(Exception e)
824
    {
825
      System.out.println("error writing to replication log from " +
826
                         "MetacatReplication.replLog: " + e.getMessage());
827
      //e.printStackTrace(System.out);
828
    }
829
  }
830
  
831
  /**
832
   * Returns true if the replicate field for server in xml_replication is 1.
833
   * Returns false otherwise
834
   */
835
  public static boolean replToServer(String server)
836
  {
837
    Connection conn = null;
838
    PreparedStatement pstmt = null;
839
    try
840
    {
841
      conn = util.openDBConnection();
842
      pstmt = conn.prepareStatement("select replicate from " + 
843
                                    "xml_replication where server like '" +
844
                                     server + "'");
845
      pstmt.execute();
846
      ResultSet rs = pstmt.getResultSet();
847
      boolean tablehasrows = rs.next();
848
      if(tablehasrows)
849
      {
850
        int i = rs.getInt(1);
851
        if(i == 1)
852
        {
853
          pstmt.close();
854
          conn.close();
855
          return true;
856
        }
857
        else
858
        {
859
          pstmt.close();
860
          conn.close();
861
          return false;
862
        }
863
      }
864
    }
865
    catch(Exception e)
866
    {
867
      System.out.println("error in MetacatReplication.replToServer: " + 
868
                         e.getMessage());
869
    }
870
    finally
871
    {
872
      try
873
      {
874
        pstmt.close();
875
        conn.close();
876
      }
877
      catch(Exception ee)
878
      {}
879
    }
880
    return false;
881
    //the default if this server does not exist is to not replicate to it.
882
  }
883
}
(34-34/43)