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