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