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: 2000-12-21 14:57:10 -0800 (Thu, 21 Dec 2000) $'
11
 * '$Revision: 631 $'
12
 */
13

    
14
package edu.ucsb.nceas.metacat;
15

    
16
import java.util.*;
17
import java.io.*;
18
import java.sql.*;
19
import java.net.*;
20
import java.lang.*;
21
import java.text.*;
22
import javax.servlet.*;
23
import javax.servlet.http.*;
24

    
25
import org.xml.sax.*;
26

    
27
public class MetacatReplication extends HttpServlet implements Runnable
28
{  
29
  private String deltaT;
30
  Timer replicationDaemon;
31
  private static MetaCatUtil util = new MetaCatUtil();
32
  private Vector fileLocks = new Vector();
33
  private Thread lockThread = null;
34
  
35
  /**
36
   * Initialize the servlet by creating appropriate database connections
37
   */
38
  public void init(ServletConfig config) throws ServletException 
39
  {
40
    //initialize db connections to handle any update requests
41
    MetaCatUtil util = new MetaCatUtil();
42
    deltaT = util.getOption("deltaT");
43
    //the default deltaT can be set from metacat.properties
44
    //create a thread to do the delta-T check but don't execute it yet
45
    replicationDaemon = new Timer(true);
46
  }
47
  
48
  public void destroy() 
49
  {
50
    replicationDaemon.cancel();
51
    System.out.println("Replication daemon cancelled.");
52
  }
53
  
54
  public void doGet (HttpServletRequest request, HttpServletResponse response)
55
                     throws ServletException, IOException 
56
  {
57
    // Process the data and send back the response
58
    handleGetOrPost(request, response);
59
  }
60

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