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: tao $'
10
 *     '$Date: 2003-04-18 20:31:39 -0700 (Fri, 18 Apr 2003) $'
11
 * '$Revision: 1583 $'
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
    //ServletOutputStream outPut = response.getOutputStream();
88
    Hashtable params = new Hashtable();
89
    Enumeration paramlist = request.getParameterNames();
90
    
91
   
92
    
93
// NOT NEEDED - doesn't provide enough security because of possible IP spoofing
94
// REPLACED with running replication comminications over HTTPS
95
//    String requestingServerIP = request.getRemoteAddr();
96
//    InetAddress iaddr = InetAddress.getByName(requestingServerIP);
97
//    String requestingServer = iaddr.getHostName();
98
    
99
    while (paramlist.hasMoreElements()) {
100
      String name = (String)paramlist.nextElement();
101
      String[] value = request.getParameterValues(name);
102
      params.put(name, value);  
103
    }
104
    
105
    String action = ((String[])params.get("action"))[0];
106
    String server = null;
107
    
108
    try {
109
      // check if the server is included in the list of replicated servers
110
      if ( !action.equals("servercontrol") && 
111
           !action.equals("stop") &&
112
           !action.equals("start") &&
113
           !action.equals("getall") ) {
114

    
115
        server = ((String[])params.get("server"))[0];
116
        if ( getServerCodeForServerName(server) == 0 ) {
117
          System.out.println("Action \"" + action + 
118
                             "\" rejected for server: " + server);
119
          return;
120
        } else {
121
          System.out.println("Action \"" + action + 
122
                             "\" accepted for server: " + server);
123
        }
124
      }
125
    } catch (Exception e) {
126
      System.out.println("Error in MetacatReplication.handleGetOrPost: " +
127
                         e.getMessage() );
128
      return;
129
    }
130
    if ( action.equals("readdata") ) 
131
    {
132
      OutputStream out=response.getOutputStream();
133
      //to get the data file.
134
      handleGetDataFileRequest(out, params, response);
135
      out.close();
136
    }
137
    else if ( action.equals("forcereplicatedatafile") ) 
138
    {
139
      //read a specific docid from remote host, and store it into local host
140
      handleForceReplicateDataFileRequest(params);
141
     
142
    }
143
    else
144
    {
145
    PrintWriter out = response.getWriter();
146
    if ( action.equals("stop") ) {
147
      //stop the replication server
148
      replicationDaemon.cancel();
149
      replicationDaemon = new Timer(true);
150
      out.println("Replication Handler Stopped");
151
      MetacatReplication.replLog("deltaT handler stopped");
152
    
153

    
154
    } else if ( action.equals("start") ) {
155
      
156
      //start the replication server
157
      int rate;
158
      if ( params.containsKey("rate") ) {
159
        rate = new Integer(
160
               new String(((String[])params.get("rate"))[0])).intValue();
161
        if(rate < 30) {
162
            out.println("Replication deltaT rate cannot be less than 30!");
163
            //deltaT<30 is a timing mess!
164
            rate = 1000;
165
        }
166
      } else {
167
        rate = 1000;
168
      }
169
      out.println("New rate is: " + rate + " seconds.");
170
      replicationDaemon.cancel();
171
      replicationDaemon = new Timer(true);
172
      replicationDaemon.scheduleAtFixedRate(new ReplicationHandler(out), 0, 
173
                                            rate * 1000);
174
      out.println("Replication Handler Started");
175
      MetacatReplication.replLog("deltaT handler started with rate=" + 
176
                                    rate + " seconds");
177
     
178

    
179
    } else if ( action.equals("getall") ) {
180
      //updates this server exactly once
181
      replicationDaemon.schedule(new ReplicationHandler(out), 0);
182
      response.setContentType("text/html");
183
      out.println("<html><body>\"Get All\" Done</body></html>");
184

    
185
    } else if ( action.equals("forcereplicate") ) {
186
      //read a specific docid from remote host, and store it into local host
187
      handleForceReplicateRequest(out, params, response);
188
   
189
    } else if ( action.equals("update") ) {
190
      //request an update list from the server
191
      handleUpdateRequest(out, params, response);
192

    
193
    } else if ( action.equals("read") ) {
194
      //request a specific document from the server
195
      //note that this could be replaced by a call to metacatServlet
196
      //handleGetDocumentAction().
197
      handleGetDocumentRequest(out, params, response);
198
    } else if ( action.equals("getlock") ) {
199
      handleGetLockRequest(out, params, response);
200

    
201
    } else if ( action.equals("getdocumentinfo") ) {
202
      handleGetDocumentInfoRequest(out, params, response);
203

    
204
    } else if ( action.equals("gettime") ) {
205
      handleGetTimeRequest(out, params, response);
206

    
207
    } else if ( action.equals("getcatalog") ) {
208
      handleGetCatalogRequest(out, params, response, true);
209

    
210
    } else if ( action.equals("servercontrol") ) {
211
      handleServerControlRequest(out, params, response);
212
    } else if ( action.equals("test") ) {
213
      response.setContentType("text/html");
214
      out.println("<html><body>Test successfully</body></html>");
215
    }
216
    
217
    out.close();
218
    }//else
219
  }
220
  
221
  /** 
222
   * This method can add, delete and list the servers currently included in
223
   * xml_replication.
224
   * action           subaction            other needed params
225
   * ---------------------------------------------------------
226
   * servercontrol    add                  server
227
   * servercontrol    delete               server
228
   * servercontrol    list                 
229
   */
230
  private void handleServerControlRequest(PrintWriter out, Hashtable params,
231
                                          HttpServletResponse response)
232
  {
233
    String subaction = ((String[])params.get("subaction"))[0];
234
    DBConnection dbConn = null;
235
    int serialNumber = -1;
236
    PreparedStatement pstmt = null;
237
    String replicate =null;
238
    String server = null;
239
    String dataReplicate = null;
240
    String hub = null;
241
    try {
242
      //conn = util.openDBConnection();
243
      dbConn=DBConnectionPool.
244
               getDBConnection("MetacatReplication.handleServerControlRequest");
245
      serialNumber=dbConn.getCheckOutSerialNumber();
246
      
247
      // add server to server list
248
      if ( subaction.equals("add") ) {
249
        replicate = ((String[])params.get("replicate"))[0];
250
        server = ((String[])params.get("server"))[0];
251
        //Get data replication value
252
        dataReplicate = ((String[])params.get("datareplicate"))[0];
253
        //Get hub value
254
        hub = ((String[])params.get("hub"))[0];
255
        
256
        pstmt = dbConn.prepareStatement("INSERT INTO xml_replication " +
257
                  "(server, last_checked, replicate, datareplicate, hub) " +
258
                                      "VALUES ('" + server + "', to_date(" +
259
                                      "'01/01/00', 'MM/DD/YY'), '" +
260
                                      replicate +"', '" +dataReplicate+"', '"
261
                                      + hub +"')");
262
        pstmt.execute();
263
        pstmt.close();
264
        dbConn.commit();
265
        out.println("Server " + server + " added"); 
266
        response.setContentType("text/html");
267
        out.println("<html><body><table border=\"1\">");
268
        out.println("<tr><td><b>server</b></td><td><b>last_checked</b></td><td>");
269
        out.println("<b>replicate</b></td>");
270
        out.println("<td><b>datareplicate</b></td>");
271
        out.println("<td><b>hub</b></td></tr>");
272
        pstmt = dbConn.prepareStatement("SELECT * FROM xml_replication");
273
        //increase dbconnection usage
274
        dbConn.increaseUsageCount(1);
275
        
276
        pstmt.execute();
277
        ResultSet rs = pstmt.getResultSet();
278
        boolean tablehasrows = rs.next();
279
        while(tablehasrows) {
280
          out.println("<tr><td>" + rs.getString(2) + "</td><td>");
281
          out.println(rs.getString(3) + "</td><td>");
282
          out.println(rs.getString(4) + "</td><td>");
283
          out.println(rs.getString(5) + "</td><td>");
284
          out.println(rs.getString(6) + "</td></tr>");
285
          
286
          tablehasrows = rs.next();
287
        }
288
        out.println("</table></body></html>");
289
        
290
        // download certificate with the public key on this server
291
        // and import it as a trusted certificate
292
        String certURL = ((String[])params.get("certificate"))[0];
293
        downloadCertificate(certURL);
294
        
295
      // delete server from server list
296
      } else if ( subaction.equals("delete") ) {
297
        server = ((String[])params.get("server"))[0];
298
        pstmt = dbConn.prepareStatement("DELETE FROM xml_replication " +
299
                                      "WHERE server LIKE '" + server + "'");
300
        pstmt.execute();
301
        pstmt.close();
302
        dbConn.commit();
303
        out.println("Server " + server + " deleted");
304
        response.setContentType("text/html");
305
        out.println("<html><body><table border=\"1\">");
306
        out.println("<tr><td><b>server</b></td><td><b>last_checked</b></td><td>");
307
        out.println("<b>replicate</b></td>");
308
        out.println("<td><b>datareplicate</b></td>");
309
        out.println("<td><b>hub</b></td></tr>");
310
  
311
        pstmt = dbConn.prepareStatement("SELECT * FROM xml_replication");
312
        //increase dbconnection usage
313
        dbConn.increaseUsageCount(1);
314
        pstmt.execute();
315
        ResultSet rs = pstmt.getResultSet();
316
        boolean tablehasrows = rs.next();
317
        while(tablehasrows)
318
        {
319
          out.println("<tr><td>" + rs.getString(2) + "</td><td>");
320
          out.println(rs.getString(3) + "</td><td>");
321
          out.println(rs.getString(4) + "</td><td>");
322
          out.println(rs.getString(5) + "</td><td>");
323
          out.println(rs.getString(6) + "</td></tr>");
324
          tablehasrows = rs.next();
325
        }
326
        out.println("</table></body></html>");
327

    
328
      // list servers in server list
329
      } else if ( subaction.equals("list") ) {
330
        response.setContentType("text/html");
331
        out.println("<html><body><table border=\"1\">");
332
        out.println("<tr><td><b>server</b></td><td><b>last_checked</b></td><td>");
333
        out.println("<b>replicate</b></td>");
334
        out.println("<td><b>datareplicate</b></td>");
335
        out.println("<td><b>hub</b></td></tr>");
336
        pstmt = dbConn.prepareStatement("SELECT * FROM xml_replication");
337
        pstmt.execute();
338
        ResultSet rs = pstmt.getResultSet();
339
        boolean tablehasrows = rs.next();
340
        while(tablehasrows) {
341
          out.println("<tr><td>" + rs.getString(2) + "</td><td>");
342
          out.println(rs.getString(3) + "</td><td>");
343
          out.println(rs.getString(4) + "</td><td>");
344
          out.println(rs.getString(5) + "</td><td>");
345
          out.println(rs.getString(6) + "</td></tr>");
346
          tablehasrows = rs.next();
347
        }
348
        out.println("</table></body></html>");
349
      } 
350
      else
351
      {
352
       
353
        out.println("<error>Unkonwn subaction</error>");
354
       
355
      }
356
      pstmt.close();
357
      //conn.close();
358

    
359
    } catch(Exception e) {
360
      System.out.println("Error in " + 
361
                         "MetacatReplication.handleServerControlRequest " + 
362
                         e.getMessage());
363
      e.printStackTrace(System.out);
364
    }
365
    finally
366
    {
367
      try
368
      {
369
        pstmt.close();
370
      }//try
371
      catch (SQLException ee)
372
      {
373
        MetaCatUtil.debugMessage("Error in " + 
374
                "MetacatReplication.handleServerControlRequest to close pstmt "
375
                 + ee.getMessage(), 30);
376
      }//catch
377
      finally
378
      {
379
        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
380
      }//finally
381
    }//finally
382
      
383
  }
384
  
385
  // download certificate with the public key from certURL and 
386
  // upload it onto this server; it then must be imported as a 
387
  // trusted certificate 
388
  private void downloadCertificate (String certURL)
389
                throws FileNotFoundException, IOException, MalformedURLException
390
  {
391
    MetaCatUtil util = new MetaCatUtil();
392
    String certPath = util.getOption("certPath"); //the path to be uploaded to
393
    
394
    // get filename from the URL of the certificate
395
    String filename = certURL;
396
    int slash = Math.max(filename.lastIndexOf('/'), filename.lastIndexOf('\\'));
397
    if ( slash > -1 ) {
398
      filename = filename.substring(slash + 1);
399
    }
400
    
401
    // open file output strem to write the input into it
402
    File f = new File(certPath, filename);
403
    synchronized (f) { 
404
      try {
405
        if ( f.exists() ) {
406
          throw new IOException("File already exist: " + f.getCanonicalFile());
407
          //if ( f.exists() && !f.canWrite() ) {
408
          //  throw new IOException("Not writable: " + f.getCanonicalFile());
409
        }
410
      } catch (SecurityException se) {
411
        // if a security manager exists,
412
        // its checkRead method is called for f.exist()
413
        // or checkWrite method is called for f.canWrite()
414
        throw se;
415
      }
416
      
417
      // create a buffered byte output stream
418
      // that uses a default-sized output buffer
419
      FileOutputStream fos = new FileOutputStream(f);
420
      BufferedOutputStream out = new BufferedOutputStream(fos);
421

    
422
      // this should be http url
423
      URL url = new URL(certURL);
424
      BufferedInputStream bis = null;
425
      try {
426
        bis = new BufferedInputStream(url.openStream());
427
        byte[] buf = new byte[4 * 1024]; // 4K buffer
428
        int b = bis.read(buf);
429
        while (b != -1) {
430
          out.write(buf, 0, b);
431
          b = bis.read(buf);
432
        }
433
      } finally {
434
        if (bis != null) bis.close();
435
      }
436
      // the input and the output streams must be closed
437
      bis.close();
438
	    out.flush();
439
	    out.close();
440
	    fos.close();
441
    } // end of synchronized(f)
442
  }
443
  
444
  /**
445
   * when a forcereplication request comes in, local host sends a read request
446
   * to the requesting server (remote server) for the specified docid.
447
   * Then store it in local database.
448
   */
449
  private void handleForceReplicateRequest(PrintWriter out, Hashtable params,
450
                                           HttpServletResponse response)
451
  {
452
    String server = ((String[])params.get("server"))[0]; // the server that
453
    String docid = ((String[])params.get("docid"))[0]; // sent the document
454
    String dbaction = "UPDATE"; // the default action is UPDATE
455
    boolean override = false;
456
    int serverCode = 1;
457
    DBConnection dbConn = null;
458
    int serialNumber = -1;
459
   
460
    try {
461
      //if the url contains a dbaction then the default action is overridden
462
      if(params.containsKey("dbaction")) {
463
        dbaction = ((String[])params.get("dbaction"))[0];
464
        //serverCode = MetacatReplication.getServerCode(server);
465
        //override = true; //we are now overriding the default action
466
      }
467
      MetacatReplication.replLog("force replication request from " + server);
468
      MetaCatUtil.debugMessage("Force replication request from: "+ server, 34);
469
      MetaCatUtil.debugMessage("Force replication docid: "+docid, 34);
470
      MetaCatUtil.debugMessage("Force replication action: "+dbaction, 34);
471
      // sending back read request to remote server
472
      URL u = new URL("https://" + server + "?server="
473
                +util.getLocalReplicationServerName()
474
                +"&action=read&docid=" + docid);
475
      String xmldoc = MetacatReplication.getURLContent(u);
476
    
477
      // get the document info from server
478
      URL docinfourl = new URL("https://" + server + 
479
                               "?server="+util.getLocalReplicationServerName()
480
                               +"&action=getdocumentinfo&docid=" + docid);
481
    
482
      String docInfoStr = MetacatReplication.getURLContent(docinfourl);
483
  
484
      //dih is the parser for the docinfo xml format
485
      DocInfoHandler dih = new DocInfoHandler();
486
      XMLReader docinfoParser = ReplicationHandler.initParser(dih);
487
      docinfoParser.parse(new InputSource(new StringReader(docInfoStr)));
488
      Hashtable docinfoHash = dih.getDocInfo();
489
      
490
      // Get user owner of this docid
491
      String user = (String)docinfoHash.get("user_owner");
492
      // Get home server of this docid
493
      String homeServer=(String)docinfoHash.get("home_server");
494
      MetaCatUtil.debugMessage("homeServer: "+homeServer, 34);
495
      // Get Document type
496
      String docType = (String)docinfoHash.get("doctype");
497
      MetaCatUtil.debugMessage("docType: "+docType, 34);
498
      String parserBase = null;
499
      // this for eml2 and we need user eml2 parser
500
      if (docType != null && 
501
          (docType.trim()).equals(DocumentImpl.EMLNAMESPACE))
502
      {
503
         MetaCatUtil.debugMessage("This is an eml2 document!", 30);
504
         parserBase = DocumentImpl.EML2;
505
      }
506
      MetaCatUtil.debugMessage("The parserBase is: "+parserBase, 30);
507
           
508
      // Get DBConnection from pool
509
      dbConn=DBConnectionPool.
510
              getDBConnection("MetacatReplication.handleForceReplicateRequest");
511
      serialNumber=dbConn.getCheckOutSerialNumber();
512
      // write the document to local database
513
      DocumentImplWrapper wrapper = new DocumentImplWrapper(parserBase, false);
514
      wrapper.writeReplication(dbConn, new StringReader(xmldoc), null, null, 
515
                               dbaction, docid, user, null, homeServer, server);
516
              
517
      MetacatReplication.replLog("document " + docid + " added to DB with " +
518
                                 "action " + dbaction);
519
    }//try
520
    catch(Exception e) 
521
    {
522
      MetacatReplication.replErrorLog("document " + docid + 
523
                                      " failed to added to DB with " +
524
                                      "action " + dbaction + " because "+
525
                                       e.getMessage());
526
      MetaCatUtil.debugMessage("ERROR in MetacatReplication.handleForceReplicate" +
527
                         "Request(): " + e.getMessage(), 30);
528
      
529
    }//catch
530
    finally
531
    {
532
      // Return the checked out DBConnection
533
      DBConnectionPool.returnDBConnection(dbConn, serialNumber);
534
    }//finally
535
  }
536
  
537
  /**
538
   * when a forcereplication data file request comes in, local host sends a 
539
   * readdata request to the requesting server (remote server) for the specified 
540
   * docid. Then store it in local database and file system
541
   */
542
  private void handleForceReplicateDataFileRequest(Hashtable params)
543
  {
544
    
545
    //make sure there is some parameters
546
    if(params.isEmpty())
547
    {
548
      return;
549
    }
550
    // Get remote server 
551
    String server = ((String[])params.get("server"))[0]; 
552
    // the docid should include rev number
553
    String docid = ((String[])params.get("docid"))[0]; 
554
    // Make sure there is a docid and server
555
    if (docid==null || server==null || server.equals(""))
556
    {
557
      MetaCatUtil.debugMessage("Didn't specify docid or server for replication"
558
                              , 20);
559
      return;
560
    }
561
    
562
    // Overide or not
563
    boolean override = false;
564
    // dbaction - update or insert
565
    String dbaction=null;
566
   
567
    try 
568
    {
569
      //docid was switch to two parts uinque code and rev
570
      String uniqueCode=MetaCatUtil.getDocIdFromString(docid);
571
      int rev=MetaCatUtil.getVersionFromString(docid);
572
      if(params.containsKey("dbaction")) 
573
      {
574
        dbaction = ((String[])params.get("dbaction"))[0];
575
      }
576
      else//default value is update
577
      {
578
        dbaction = "update";
579
      }
580
      
581
      MetacatReplication.replLog("force replication request from " + server); 
582
      MetaCatUtil.debugMessage("Force replication request from: "+ server, 34);
583
      MetaCatUtil.debugMessage("Force replication docid: "+docid, 34);
584
      MetaCatUtil.debugMessage("Force replication action: "+dbaction, 34);
585
      // get the document info from server
586
      URL docinfourl = new URL("https://" + server + 
587
                               "?server="+util.getLocalReplicationServerName()
588
                               +"&action=getdocumentinfo&docid=" + uniqueCode);
589
     
590
      String docInfoStr = MetacatReplication.getURLContent(docinfourl);
591

    
592
      //dih is the parser for the docinfo xml format
593
      DocInfoHandler dih = new DocInfoHandler();
594
      XMLReader docinfoParser = ReplicationHandler.initParser(dih);
595
      docinfoParser.parse(new InputSource(new StringReader(docInfoStr)));
596
      Hashtable docinfoHash = dih.getDocInfo();
597
      String user = (String)docinfoHash.get("user_owner");
598
     
599
      String docName = (String)docinfoHash.get("docname");
600
     
601
      String docType = (String)docinfoHash.get("doctype");
602
      
603
      String docHomeServer= (String)docinfoHash.get("home_server");
604
      MetaCatUtil.debugMessage("docHomeServer of datafile: "+docHomeServer, 34);
605
      
606
      
607
      
608
      //if action is delete, we don't delete the data file. Just archieve
609
      //the xml_documents
610
      if (dbaction.equals("delete"))
611
      {
612
        //conn = util.getConnection();
613
        DocumentImpl.delete(docid,user,null);
614
        //util.returnConnection(conn);
615
      }
616
      //To data file insert or update is same
617
      else if (dbaction.equals("insert")||dbaction.equals("update"))
618
      {
619
        //Get data file and store it into local file system.
620
        // sending back readdata request to server
621
        URL url = new URL("https://" + server + "?server="
622
                +util.getLocalReplicationServerName()
623
                +"&action=readdata&docid=" + docid);
624
        String datafilePath = util.getOption("datafilepath");
625
        //register data file into xml_documents table and wite data file
626
        //into file system
627
        DocumentImpl.writeDataFileInReplication(url.openStream(), datafilePath, 
628
                            docName, docType, docid, user,docHomeServer,server);
629
     }
630
    
631
  
632
    
633
    MetacatReplication.replLog("datafile " + docid + " added to DB with " +
634
                                 "action " + dbaction);
635
    } 
636
    catch(Exception e) 
637
    {
638
      
639
      MetacatReplication.replErrorLog("Datafile " + docid + 
640
                                      " failed to added to DB with " +
641
                                      "action " + dbaction + " because "+
642
                                       e.getMessage());
643
      MetaCatUtil.debugMessage
644
              ("ERROR in MetacatReplication.handleForceDataFileReplicate" +
645
                         "Request(): " + e.getMessage(), 30);
646
    }
647
  }
648
  /**
649
   * Grants or denies a lock to a requesting host.
650
   * The servlet parameters of interrest are:
651
   * docid: the docid of the file the lock is being requested for
652
   * currentdate: the timestamp of the document on the remote server
653
   * 
654
   */
655
  private void handleGetLockRequest(PrintWriter out, Hashtable params,
656
                                    HttpServletResponse response)
657
  {
658

    
659
    try
660
    {
661
    
662
      String docid = ((String[])params.get("docid"))[0];
663
      String remoteRev = ((String[])params.get("updaterev"))[0];
664
      DocumentImpl requestDoc = new DocumentImpl(docid);
665
      MetacatReplication.replLog("lock request for " + docid);
666
      int localRevInt = requestDoc.getRev();
667
      int remoteRevInt = Integer.parseInt(remoteRev);
668
      
669
      if(remoteRevInt >= localRevInt)
670
      {
671
        if(!fileLocks.contains(docid))
672
        { //grant the lock if it is not already locked
673
          fileLocks.add(0, docid); //insert at the beginning of the queue Vector
674
          //send a message back to the the remote host authorizing the insert
675
          out.println("<lockgranted><docid>" +docid+ "</docid></lockgranted>");
676
          lockThread = new Thread(this);
677
          lockThread.setPriority(Thread.MIN_PRIORITY);
678
          lockThread.start();
679
          MetacatReplication.replLog("lock granted for " + docid);
680
        }
681
        else
682
        { //deny the lock
683
          out.println("<filelocked><docid>" + docid + "</docid></filelocked>");
684
          MetacatReplication.replLog("lock denied for " + docid + 
685
                                     "reason: file already locked");
686
        }
687
      }
688
      else
689
      {//deny the lock.
690
        out.println("<outdatedfile><docid>" + docid + "</docid></filelocked>");
691
        MetacatReplication.replLog("lock denied for " + docid + 
692
                                   "reason: client has outdated file");
693
      }
694
      //conn.close();
695
    }
696
    catch(Exception e)
697
    {
698
      System.out.println("error requesting file lock from MetacatReplication." +
699
                         "handleGetLockRequest: " + e.getMessage());
700
      e.printStackTrace(System.out);
701
    }
702
  }
703
  
704
  /**
705
   * Sends all of the xml_documents information encoded in xml to a requestor
706
   * the format is:
707
   * <!ELEMENT documentinfo (docid, docname, doctype, doctitle, user_owner,
708
   *                  user_updated, home_server, public_access, rev)/>
709
   * all of the subelements of document info are #PCDATA
710
   */
711
  private void handleGetDocumentInfoRequest(PrintWriter out, Hashtable params, 
712
                                        HttpServletResponse response)
713
  {
714
    String docid = ((String[])(params.get("docid")))[0];
715
    StringBuffer sb = new StringBuffer();
716
  
717
    try
718
    {
719
      
720
      DocumentImpl doc = new DocumentImpl(docid);
721
      sb.append("<documentinfo><docid>").append(docid);
722
      sb.append("</docid><docname>").append(doc.getDocname());
723
      sb.append("</docname><doctype>").append(doc.getDoctype());
724
      sb.append("</doctype>");
725
      sb.append("<user_owner>").append(doc.getUserowner());
726
      sb.append("</user_owner><user_updated>").append(doc.getUserupdated());
727
      sb.append("</user_updated>");
728
      sb.append("<home_server>");
729
      sb.append(doc.getDocHomeServer());
730
      sb.append("</home_server>");
731
      sb.append("<public_access>").append(doc.getPublicaccess());
732
      sb.append("</public_access><rev>").append(doc.getRev());
733
      sb.append("</rev></documentinfo>");
734
      response.setContentType("text/xml");
735
      out.println(sb.toString());
736
      
737
    }
738
    catch (Exception e)
739
    {
740
      System.out.println("error in " +
741
                         "metacatReplication.handlegetdocumentinforequest: " + 
742
                          e.getMessage());
743
    }
744
    
745
  }
746
   
747
  /**
748
   * Sends a datafile to a remote host
749
   */
750
  private void handleGetDataFileRequest(OutputStream outPut, 
751
                            Hashtable params, HttpServletResponse response)
752
                                 
753
  {
754
    // File path for data file    
755
    String filepath = util.getOption("datafilepath");
756
    // Request docid
757
    String docId = ((String[])(params.get("docid")))[0];
758
    //check if the doicd is null
759
    if (docId==null)
760
    {
761
      util.debugMessage("Didn't specify docid for replication", 20);
762
      return;
763
    }
764
    
765
    //try to open a https stream to test if the request server's public key
766
    //in the key store, this is security issue
767
    try
768
    {
769
      String server = ((String[])params.get("server"))[0];
770
      URL u = new URL("https://" + server + "?server="
771
                +util.getLocalReplicationServerName()
772
                +"&action=test");
773
      String test = MetacatReplication.getURLContent(u);
774
      //couldn't pass the test
775
      if (test.indexOf("successfully")==-1)
776
      {
777
        //response.setContentType("text/xml");
778
        //outPut.println("<error>Couldn't pass the trust test</error>");
779
        MetaCatUtil.debugMessage("Couldn't pass the trust test", 20);
780
        return;
781
      }
782
    }//try
783
    catch (Exception ee)
784
    {
785
      return;
786
    }//catch
787
  
788
    if(!filepath.endsWith("/")) 
789
    {
790
          filepath += "/";
791
    }
792
    // Get file aboslute file name
793
    String filename = filepath + docId;      
794
    
795
    //MIME type
796
    String contentType = null;
797
    if (filename.endsWith(".xml")) 
798
    {
799
        contentType="text/xml";
800
    } 
801
    else if (filename.endsWith(".css")) 
802
    {
803
        contentType="text/css";
804
    } 
805
    else if (filename.endsWith(".dtd")) 
806
    {
807
        contentType="text/plain";
808
    } 
809
    else if (filename.endsWith(".xsd")) 
810
    {
811
        contentType="text/xml";
812
    } 
813
    else if (filename.endsWith("/")) 
814
    {
815
        contentType="text/html";
816
    } 
817
    else 
818
    {
819
        File f = new File(filename);
820
        if ( f.isDirectory() ) 
821
        {
822
           contentType="text/html";
823
        } 
824
        else
825
        {
826
           contentType="application/octet-stream";
827
        }
828
     }
829
   
830
   // Set the mime type
831
   response.setContentType(contentType);
832
   
833
   // Get the content of the file
834
   FileInputStream fin = null;
835
   try 
836
   {
837
      // FileInputStream to metacat
838
      fin = new FileInputStream(filename);
839
      // 4K buffer
840
      byte[] buf = new byte[4 * 1024];
841
      // Read data from file input stream to byte array
842
      int b = fin.read(buf);
843
      // Write to outStream from byte array
844
      while (b != -1) 
845
      {
846
        outPut.write(buf, 0, b);
847
        b = fin.read(buf);
848
      }
849
      // close file input stream
850
      fin.close();
851
   
852
   }//try
853
   catch(Exception e)
854
   {
855
      System.out.println("error getting data file from MetacatReplication." +
856
                         "handlGetDataFileRequest " + e.getMessage());
857
      e.printStackTrace(System.out);
858
   }//catch
859
  
860
}
861
  
862
  
863
  /**
864
   * Sends a document to a remote host
865
   */
866
  private void handleGetDocumentRequest(PrintWriter out, Hashtable params, 
867
                                        HttpServletResponse response)
868
  {
869
  
870
    try
871
    {
872
      //try to open a https stream to test if the request server's public key
873
      //in the key store, this is security issue
874
      String server = ((String[])params.get("server"))[0];
875
      URL u = new URL("https://" + server + "?server="
876
                +util.getLocalReplicationServerName()
877
                +"&action=test");
878
      String test = MetacatReplication.getURLContent(u);
879
      //couldn't pass the test
880
      if (test.indexOf("successfully")==-1)
881
      {
882
        response.setContentType("text/xml");
883
        out.println("<error>Couldn't pass the trust test</error>");
884
        out.close();
885
        return;
886
      }
887
      
888
      String docid = ((String[])(params.get("docid")))[0];
889
      
890
      DocumentImpl di = new DocumentImpl(docid);
891
      response.setContentType("text/xml");
892
      out.print(di.toString());
893
   
894
      MetacatReplication.replLog("document " + docid + " sent");
895
    
896
    }
897
    catch(Exception e)
898
    {
899
      MetaCatUtil.debugMessage("error getting document from MetacatReplication."
900
                          +"handlGetDocumentRequest " + e.getMessage(), 30);
901
      //e.printStackTrace(System.out);
902
      response.setContentType("text/xml");
903
      out.println("<error>"+e.getMessage()+"</error>");
904
    }
905
    
906
  }
907
  
908
  /**
909
   * Sends a list of all of the documents on this sever along with their
910
   * revision numbers.  
911
   * The format is:
912
   * <!ELEMENT replication (server, updates)>
913
   * <!ELEMENT server (#PCDATA)>
914
   * <!ELEMENT updates ((updatedDocument | deleteDocument)*)>
915
   * <!ELEMENT updatedDocument (docid, rev, datafile*)>
916
   * <!ELEMENT deletedDocument (docid, rev)>
917
   * <!ELEMENT docid (#PCDATA)>
918
   * <!ELEMENT rev (#PCDATA)>
919
   * <!ELEMENT datafile (#PCDATA)>
920
   * note that the rev in deletedDocument is always empty.  I just left
921
   * it in there to make the parser implementation easier.
922
   */
923
  private void handleUpdateRequest(PrintWriter out, Hashtable params, 
924
                                    HttpServletResponse response)
925
  {
926
    // Checked out DBConnection 
927
    DBConnection dbConn = null;
928
    // DBConenction serial number when checked it out
929
    int serialNumber = -1;
930
    PreparedStatement pstmt = null;
931
    // Server list to store server info of xml_replication table
932
    ReplicationServerList serverList = null;
933
  
934
    try
935
    {
936
      // Check out a DBConnection from pool
937
      dbConn=DBConnectionPool.
938
                  getDBConnection("MetacatReplication.handleUpdateRequest");
939
      serialNumber=dbConn.getCheckOutSerialNumber();
940
      // Create a server list from xml_replication table
941
      serverList = new ReplicationServerList();
942
      
943
      // Get remote server name from param
944
      String server = ((String[])params.get("server"))[0];
945
      // If no servr name in param, return a error
946
      if ( server == null || server.equals(""))
947
      {
948
        response.setContentType("text/xml");
949
        out.println("<error>Request didn't specify server name</error>");
950
        out.close();
951
        return;
952
      }//if
953
      
954
      //try to open a https stream to test if the request server's public key
955
      //in the key store, this is security issue
956
      URL u = new URL("https://" + server + "?server="
957
                +util.getLocalReplicationServerName()
958
                +"&action=test");
959
      String test = MetacatReplication.getURLContent(u);
960
      //couldn't pass the test
961
      if (test.indexOf("successfully")==-1)
962
      {
963
        response.setContentType("text/xml");
964
        out.println("<error>Couldn't pass the trust test</error>");
965
        out.close();
966
        return;
967
      }
968
      
969
      
970
      // Check if local host configure to replicate xml documents to remote
971
      // server. If not send back a error message
972
      if (!serverList.getReplicationValue(server))
973
      {
974
        response.setContentType("text/xml");
975
        out.println
976
        ("<error>Configuration not allow to replicate document to you</error>");
977
        out.close();
978
        return;
979
      }//if
980
      
981
      // Store the sql command
982
      StringBuffer docsql = new StringBuffer();
983
      // Stroe the docid list
984
      StringBuffer doclist = new StringBuffer();
985
      // Store the deleted docid list
986
      StringBuffer delsql = new StringBuffer();
987
      // Store the data set file
988
      Vector packageFiles = new Vector();
989
      
990
      // Append local server's name and replication servlet to doclist
991
      doclist.append("<?xml version=\"1.0\"?><replication>");
992
      doclist.append("<server>").append(util.getOption("server"));
993
      doclist.append(util.getOption("replicationpath"));
994
      doclist.append("</server><updates>");
995
      
996
      // Get correct docid that reside on this server according the requesting
997
      // server's replicate and data replicate value in xml_replication table
998
      docsql.append("select docid, rev, doctype from xml_documents ");
999
      // If the localhost is not a hub to the remote server, only replicate
1000
      // the docid' which home server is local host (server_location =1)
1001
      if (!serverList.getHubValue(server))
1002
      {
1003
        docsql.append("where server_location = 1");
1004
      }
1005
      MetaCatUtil.debugMessage("Doc sql: "+docsql.toString(), 30);
1006
      
1007
      // Get any deleted documents
1008
      delsql.append("select distinct docid from ");
1009
      delsql.append("xml_revisions where docid not in (select docid from ");
1010
      delsql.append("xml_documents) ");
1011
      // If the localhost is not a hub to the remote server, only replicate
1012
      // the docid' which home server is local host (server_location =1)
1013
      if (!serverList.getHubValue(server))
1014
      {
1015
        delsql.append("and server_location = 1");
1016
      }
1017
      MetaCatUtil.debugMessage("Deleted sql: "+delsql.toString(), 30);
1018
      
1019
      
1020
      
1021
      // Get docid list of local host
1022
      pstmt = dbConn.prepareStatement(docsql.toString());
1023
      pstmt.execute();
1024
      ResultSet rs = pstmt.getResultSet();
1025
      boolean tablehasrows = rs.next();
1026
      //If metacat configed to replicate data file
1027
      //if ((util.getOption("replicationsenddata")).equals("on"))
1028
      if (serverList.getDataReplicationValue(server))
1029
      {
1030
        while(tablehasrows)
1031
        {
1032
          String recordDoctype = rs.getString(3);
1033
          Vector packagedoctypes = MetaCatUtil.getOptionList(
1034
                                     MetaCatUtil.getOption("packagedoctype"));
1035
          //if this is a package file, put it at the end
1036
          //because if a package file is read before all of the files it
1037
          //refers to are loaded then there is an error
1038
          if(!packagedoctypes.contains(recordDoctype))
1039
          {   
1040
              //If this is not data file
1041
              if (!recordDoctype.equals("BIN"))
1042
              {
1043
                //for non-data file document
1044
                doclist.append("<updatedDocument>");
1045
                doclist.append("<docid>").append(rs.getString(1));
1046
                doclist.append("</docid><rev>").append(rs.getInt(2));
1047
                doclist.append("</rev>");
1048
                doclist.append("</updatedDocument>");
1049
              }//if
1050
              else
1051
              {
1052
                //for data file document, in datafile attributes
1053
                //we put "datafile" value there
1054
                doclist.append("<updatedDocument>");
1055
                doclist.append("<docid>").append(rs.getString(1));
1056
                doclist.append("</docid><rev>").append(rs.getInt(2));
1057
                doclist.append("</rev>");
1058
                doclist.append("<datafile>");
1059
                doclist.append(MetaCatUtil.getOption("datafileflag"));
1060
                doclist.append("</datafile>");
1061
                doclist.append("</updatedDocument>");
1062
              }//else 
1063
          }//if packagedoctpes
1064
          else
1065
          { //the package files are saved to be put into the xml later.
1066
              Vector v = new Vector();
1067
              v.add(new String(rs.getString(1)));
1068
              v.add(new Integer(rs.getInt(2)));
1069
              packageFiles.add(new Vector(v));
1070
          }//esle
1071
          tablehasrows = rs.next();
1072
        }//while
1073
      }//if
1074
      else //metacat was configured not to send data file
1075
      {
1076
        while(tablehasrows)
1077
        {
1078
          String recordDoctype = rs.getString(3);
1079
          if(!recordDoctype.equals("BIN")) 
1080
          { //don't replicate data files
1081
            Vector packagedoctypes = MetaCatUtil.getOptionList(
1082
                                     MetaCatUtil.getOption("packagedoctype"));
1083
            if(!packagedoctypes.contains(recordDoctype))
1084
            {   //if this is a package file, put it at the end
1085
              //because if a package file is read before all of the files it
1086
              //refers to are loaded then there is an error
1087
              doclist.append("<updatedDocument>");
1088
              doclist.append("<docid>").append(rs.getString(1));
1089
              doclist.append("</docid><rev>").append(rs.getInt(2));
1090
              doclist.append("</rev>");
1091
              doclist.append("</updatedDocument>");
1092
            }
1093
            else
1094
            { //the package files are saved to be put into the xml later.
1095
              Vector v = new Vector();
1096
              v.add(new String(rs.getString(1)));
1097
              v.add(new Integer(rs.getInt(2)));
1098
              packageFiles.add(new Vector(v));
1099
            }
1100
         }//if
1101
         tablehasrows = rs.next();
1102
        }//while
1103
      }//else
1104
      
1105
      pstmt = dbConn.prepareStatement(delsql.toString());
1106
      //usage count should increas 1
1107
      dbConn.increaseUsageCount(1);
1108
      
1109
      pstmt.execute();
1110
      rs = pstmt.getResultSet();
1111
      tablehasrows = rs.next();
1112
      while(tablehasrows)
1113
      { //handle the deleted documents
1114
        doclist.append("<deletedDocument><docid>").append(rs.getString(1));
1115
        doclist.append("</docid><rev></rev></deletedDocument>");
1116
        //note that rev is always empty for deleted docs
1117
        tablehasrows = rs.next();
1118
      }
1119
      
1120
      //now we can put the package files into the xml results
1121
      for(int i=0; i<packageFiles.size(); i++)
1122
      {
1123
        Vector v = (Vector)packageFiles.elementAt(i);
1124
        doclist.append("<updatedDocument>");
1125
        doclist.append("<docid>").append((String)v.elementAt(0));
1126
        doclist.append("</docid><rev>");
1127
        doclist.append(((Integer)v.elementAt(1)).intValue());
1128
        doclist.append("</rev>");
1129
        doclist.append("</updatedDocument>");
1130
      }
1131
      
1132
      doclist.append("</updates></replication>");
1133
      MetaCatUtil.debugMessage("doclist: " + doclist.toString(), 40);
1134
      pstmt.close();
1135
      //conn.close();
1136
      response.setContentType("text/xml");
1137
      out.println(doclist.toString());
1138
     
1139
    }
1140
    catch(Exception e)
1141
    {
1142
      MetaCatUtil.debugMessage("error in MetacatReplication." +
1143
                         "handleupdaterequest: " + e.getMessage(), 30);
1144
      //e.printStackTrace(System.out);
1145
      response.setContentType("text/xml");
1146
      out.println("<error>"+e.getMessage()+"</error>");
1147
    }
1148
    finally
1149
    {
1150
      try
1151
      {
1152
        pstmt.close();
1153
      }//try
1154
      catch (SQLException ee)
1155
      {
1156
        MetaCatUtil.debugMessage("Error in MetacatReplication." +
1157
                "handleUpdaterequest to close pstmt: "+ee.getMessage(), 30);
1158
      }//catch
1159
      finally
1160
      {
1161
        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1162
      }//finally
1163
    }//finally
1164
 
1165
  }//handlUpdateRequest
1166
  
1167
  /**
1168
   * Returns the xml_catalog table encoded in xml
1169
   */
1170
  public static String getCatalogXML()
1171
  {
1172
    return handleGetCatalogRequest(null, null, null, false);
1173
  }
1174
  
1175
  /**
1176
   * Sends the contents of the xml_catalog table encoded in xml
1177
   * The xml format is:
1178
   * <!ELEMENT xml_catalog (row*)>
1179
   * <!ELEMENT row (entry_type, source_doctype, target_doctype, public_id,
1180
   *                system_id)>
1181
   * All of the sub elements of row are #PCDATA
1182
   
1183
   * If printFlag == false then do not print to out.
1184
   */
1185
  private static String handleGetCatalogRequest(PrintWriter out, 
1186
                                                Hashtable params,
1187
                                                HttpServletResponse response,
1188
                                                boolean printFlag)
1189
  {
1190
    DBConnection dbConn = null;
1191
    int serialNumber = -1;
1192
    PreparedStatement pstmt = null;
1193
    try
1194
    { 
1195
      /*conn = MetacatReplication.getDBConnection("MetacatReplication." +
1196
                                                "handleGetCatalogRequest");*/
1197
      dbConn=DBConnectionPool.
1198
                 getDBConnection("MetacatReplication.handleGetCatalogRequest");
1199
      serialNumber=dbConn.getCheckOutSerialNumber();
1200
      pstmt = dbConn.prepareStatement("select entry_type, " +
1201
                              "source_doctype, target_doctype, public_id, " +
1202
                              "system_id from xml_catalog");
1203
      pstmt.execute();
1204
      ResultSet rs = pstmt.getResultSet();
1205
      boolean tablehasrows = rs.next();
1206
      StringBuffer sb = new StringBuffer();
1207
      sb.append("<?xml version=\"1.0\"?><xml_catalog>");
1208
      while(tablehasrows)
1209
      {
1210
        sb.append("<row><entry_type>").append(rs.getString(1));
1211
        sb.append("</entry_type><source_doctype>").append(rs.getString(2));
1212
        sb.append("</source_doctype><target_doctype>").append(rs.getString(3));
1213
        sb.append("</target_doctype><public_id>").append(rs.getString(4));
1214
        sb.append("</public_id><system_id>").append(rs.getString(5));
1215
        sb.append("</system_id></row>");
1216
      
1217
        tablehasrows = rs.next();
1218
      }
1219
      sb.append("</xml_catalog>");
1220
      //conn.close();
1221
      if(printFlag)
1222
      {
1223
        response.setContentType("text/xml");
1224
        out.println(sb.toString());
1225
      }
1226
      pstmt.close();
1227
      return sb.toString();
1228
    }
1229
    catch(Exception e)
1230
    {
1231
      
1232
      System.out.println("error in MetacatReplication.handleGetCatalogRequest:"+ 
1233
                          e.getMessage());
1234
      e.printStackTrace(System.out);
1235
      if(printFlag)
1236
      {
1237
        out.println("<error>"+e.getMessage()+"</error>");
1238
      }
1239
    }
1240
    finally
1241
    {
1242
      try
1243
      {
1244
        pstmt.close();
1245
      }//try
1246
      catch (SQLException ee)
1247
      {
1248
        MetaCatUtil.
1249
           debugMessage("Error in MetacatReplication.handleGetCatalogRequest: "
1250
           +ee.getMessage(), 30);
1251
      }//catch
1252
      finally
1253
      {
1254
        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1255
      }//finally
1256
    }//finally
1257
      
1258
    return null;
1259
  }
1260
  
1261
  /**
1262
   * Sends the current system date to the remote server.  Using this action
1263
   * for replication gets rid of any problems with syncronizing clocks 
1264
   * because a time specific to a document is always kept on its home server.
1265
   */
1266
  private void handleGetTimeRequest(PrintWriter out, Hashtable params, 
1267
                                    HttpServletResponse response)
1268
  {
1269
    SimpleDateFormat formatter = new SimpleDateFormat ("yy-MM-dd HH:mm:ss");
1270
    java.util.Date localtime = new java.util.Date();
1271
    String dateString = formatter.format(localtime);
1272
    response.setContentType("text/xml");
1273
    
1274
    out.println("<timestamp>" + dateString + "</timestamp>");
1275
  }
1276
  
1277
  /**
1278
   * this method handles the timeout for a file lock.  when a lock is 
1279
   * granted it is granted for 30 seconds.  When this thread runs out
1280
   * it deletes the docid from the queue, thus eliminating the lock.
1281
   */
1282
  public void run()
1283
  {
1284
    try
1285
    {
1286
      MetaCatUtil.debugMessage("thread started for docid: " + 
1287
                               (String)fileLocks.elementAt(0), 45);
1288
      
1289
      Thread.sleep(30000); //the lock will expire in 30 seconds
1290
      MetaCatUtil.debugMessage("thread for docid: " + 
1291
                             (String)fileLocks.elementAt(fileLocks.size() - 1) + 
1292
                              " exiting.", 45);
1293
      
1294
      fileLocks.remove(fileLocks.size() - 1);
1295
      //fileLocks is treated as a FIFO queue.  If there are more than one lock
1296
      //in the vector, the first one inserted will be removed.
1297
    }
1298
    catch(Exception e)
1299
    {
1300
      MetaCatUtil.debugMessage("error in file lock thread from " + 
1301
                                "MetacatReplication.run: " + e.getMessage(), 30);
1302
    }
1303
  }
1304
  
1305
  /**
1306
   * Returns the name of a server given a serverCode
1307
   * @param serverCode the serverid of the server
1308
   * @return the servername or null if the specified serverCode does not
1309
   *         exist.
1310
   */
1311
  public static String getServerNameForServerCode(int serverCode)
1312
  {
1313
    //System.out.println("serverid: " + serverCode);
1314
    DBConnection dbConn = null;
1315
    int serialNumber = -1;
1316
    PreparedStatement pstmt = null;
1317
    try
1318
    {
1319
      dbConn=DBConnectionPool.
1320
                  getDBConnection("MetacatReplication.getServer");
1321
      serialNumber=dbConn.getCheckOutSerialNumber();
1322
      String sql = new String("select server from " +
1323
                              "xml_replication where serverid = " + 
1324
                              serverCode);
1325
      pstmt = dbConn.prepareStatement(sql);
1326
      //System.out.println("getserver sql: " + sql);
1327
      pstmt.execute();
1328
      ResultSet rs = pstmt.getResultSet();
1329
      boolean tablehasrows = rs.next();
1330
      if(tablehasrows)
1331
      {
1332
        //System.out.println("server: " + rs.getString(1));
1333
        return rs.getString(1);
1334
      }
1335
      
1336
      //conn.close();
1337
    }
1338
    catch(Exception e)
1339
    {
1340
      System.out.println("Error in MetacatReplication.getServer: " + 
1341
                          e.getMessage());
1342
    }
1343
    finally
1344
    {
1345
      try
1346
      {
1347
        pstmt.close();
1348
      }//try
1349
      catch (SQLException ee)
1350
      {
1351
        MetaCatUtil.debugMessage("Error in MetacactReplication.getserver: "+
1352
                                    ee.getMessage(), 30);
1353
      }//catch
1354
      finally
1355
      {
1356
        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1357
      }//fianlly
1358
    }//finally
1359
        
1360
      
1361
        
1362
    return null;
1363
      //return null if the server does not exist
1364
  }
1365
  
1366
  /**
1367
   * Returns a server code given a server name
1368
   * @param server the name of the server
1369
   * @return integer > 0 representing the code of the server, 0 if the server
1370
   *  does not exist.
1371
   */
1372
  public static int getServerCodeForServerName(String server) throws Exception
1373
  {
1374
    DBConnection dbConn = null;
1375
    int serialNumber = -1;
1376
    PreparedStatement pstmt = null;
1377
    int serverCode = 0;
1378

    
1379
    try {
1380

    
1381
      //conn = util.openDBConnection();
1382
      dbConn=DBConnectionPool.
1383
                  getDBConnection("MetacatReplication.getServerCode");
1384
      serialNumber=dbConn.getCheckOutSerialNumber();
1385
      pstmt = dbConn.prepareStatement("SELECT serverid FROM xml_replication " +
1386
                                    "WHERE server LIKE '" + server + "'");
1387
      pstmt.execute();
1388
      ResultSet rs = pstmt.getResultSet();
1389
      boolean tablehasrows = rs.next();
1390
      if ( tablehasrows ) {  
1391
        serverCode = rs.getInt(1);
1392
        pstmt.close();
1393
        //conn.close();
1394
        return serverCode;
1395
      }
1396
      
1397
    } catch(Exception e) {
1398
      throw e;
1399

    
1400
    } finally {
1401
      try 
1402
      {
1403
        pstmt.close();
1404
        //conn.close();
1405
       }//try
1406
       catch(Exception ee) 
1407
       {
1408
         MetaCatUtil.debugMessage("Error in MetacatReplicatio.getServerCode: "
1409
                                  +ee.getMessage(), 30);
1410
                           
1411
       }//catch
1412
       finally
1413
       {
1414
         DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1415
       }//finally
1416
    }//finally
1417
    
1418
    return serverCode;
1419
  }
1420
  
1421
  /**
1422
   * Method to get a host server information for given docid
1423
   * @param conn a connection to the database
1424
   */
1425
  public static Hashtable getHomeServerInfoForDocId(String docId)
1426
  {
1427
    Hashtable sl = new Hashtable();
1428
    DBConnection dbConn = null;
1429
    int serialNumber = -1;
1430
    //MetaCatUtil ut=new MetaCatUtil();
1431
    docId=MetaCatUtil.getDocIdFromString(docId);
1432
    PreparedStatement pstmt=null;
1433
    int serverLocation;
1434
    try
1435
    {
1436
      //get conection
1437
      dbConn=DBConnectionPool.
1438
                  getDBConnection("ReplicationHandler.getHomeServer");
1439
      serialNumber=dbConn.getCheckOutSerialNumber();
1440
      //get a server location from xml_document table
1441
      pstmt=dbConn.prepareStatement("select server_location from xml_documents "
1442
                                            +"where docid = ?");
1443
      pstmt.setString(1, docId);
1444
      pstmt.execute();
1445
      ResultSet serverName = pstmt.getResultSet();
1446
      //get a server location
1447
      if(serverName.next())
1448
      {
1449
        serverLocation=serverName.getInt(1);
1450
        pstmt.close();
1451
      }
1452
      else
1453
      {
1454
        pstmt.close();
1455
        //ut.returnConnection(conn);
1456
        return null;
1457
      }
1458
      pstmt=dbConn.prepareStatement("select server, last_checked, replicate " +
1459
                        "from xml_replication where serverid = ?");
1460
      //increase usage count
1461
      dbConn.increaseUsageCount(1);
1462
      pstmt.setInt(1, serverLocation);
1463
      pstmt.execute();
1464
      ResultSet rs = pstmt.getResultSet();
1465
      boolean tableHasRows = rs.next();
1466
      if (tableHasRows)
1467
      {
1468
        
1469
          String server = rs.getString(1);
1470
          String last_checked = rs.getString(2);
1471
          if(!server.equals("localhost"))
1472
          {
1473
            sl.put(server, last_checked);
1474
          }
1475
        
1476
      }
1477
      else
1478
      {
1479
        pstmt.close();
1480
        //ut.returnConnection(conn);
1481
        return null;
1482
      }
1483
      pstmt.close();
1484
    }
1485
    catch(Exception e)
1486
    {
1487
      System.out.println("error in replicationHandler.getHomeServer(): " +
1488
                         e.getMessage());
1489
    }
1490
    finally
1491
    {
1492
      try
1493
      {
1494
        pstmt.close();
1495
        //ut.returnConnection(conn);
1496
      }
1497
      catch (Exception ee)
1498
      {
1499
        MetaCatUtil.debugMessage("Eror irn rplicationHandler.getHomeServer() "+
1500
                          "to close pstmt: "+ee.getMessage(), 30);
1501
      }
1502
      finally
1503
      {
1504
        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1505
      }
1506
    
1507
    }//finally
1508
    return sl;
1509
  }
1510
  
1511
  /**
1512
   * Returns a home server location  given a accnum
1513
   * @param accNum , given accNum for a document
1514
   * 
1515
   */
1516
  public static int getHomeServerCodeForDocId(String accNum) throws Exception
1517
  {
1518
    DBConnection dbConn = null;
1519
    int serialNumber = -1;
1520
    PreparedStatement pstmt = null;
1521
    int serverCode = 1;
1522
    //MetaCatUtil ut = new MetaCatUtil();
1523
    String docId=MetaCatUtil.getDocIdFromString(accNum);
1524

    
1525
    try 
1526
    {
1527

    
1528
      // Get DBConnection
1529
      dbConn=DBConnectionPool.
1530
                  getDBConnection("ReplicationHandler.getServerLocation");
1531
      serialNumber=dbConn.getCheckOutSerialNumber();
1532
      pstmt=dbConn.prepareStatement("SELECT server_location FROM xml_documents " 
1533
                              + "WHERE docid LIKE '" + docId + "'");
1534
      pstmt.execute();
1535
      ResultSet rs = pstmt.getResultSet();
1536
      boolean tablehasrows = rs.next();
1537
      //If a document is find, return the server location for it
1538
      if ( tablehasrows ) 
1539
      {  
1540
        serverCode = rs.getInt(1);
1541
        pstmt.close();
1542
        //conn.close();
1543
        return serverCode;
1544
      }
1545
      //if couldn't find in xml_documents table, we think server code is 1
1546
      //(this is new document)
1547
      else
1548
      {
1549
        pstmt.close();
1550
        //conn.close();
1551
        return serverCode;
1552
      }
1553
      
1554
    } 
1555
    catch(Exception e) 
1556
    {
1557
      
1558
      throw e;
1559

    
1560
    } 
1561
    finally 
1562
    {
1563
      try 
1564
      {
1565
        pstmt.close();
1566
        //conn.close();
1567
        
1568
      } 
1569
      catch(Exception ee) 
1570
      {
1571
        MetaCatUtil.debugMessage("Erorr in Replication.getServerLocation "+
1572
                     "to close pstmt"+ee.getMessage(), 30);
1573
      }
1574
      finally
1575
      {
1576
        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1577
      }//finally
1578
    }//finally
1579
   //return serverCode;
1580
  }
1581
  
1582
  
1583
  
1584
  /**
1585
   * This method returns the content of a url
1586
   * @param u the url to return the content from
1587
   * @return a string representing the content of the url
1588
   * @throws java.io.IOException
1589
   */
1590
  public static String getURLContent(URL u) throws java.io.IOException
1591
  {
1592
    //System.out.println("url: " + u.toString());
1593
    char istreamChar;
1594
    int istreamInt;
1595
    InputStreamReader istream = new InputStreamReader(u.openStream());
1596
    StringBuffer serverResponse = new StringBuffer();
1597
    while((istreamInt = istream.read()) != -1)
1598
    {
1599
      istreamChar = (char)istreamInt;
1600
      serverResponse.append(istreamChar);
1601
    }
1602
    
1603
    return serverResponse.toString();
1604
  }
1605
  
1606
  /**
1607
   * Method for writing replication messages to a log file specified in 
1608
   * metacat.properties
1609
   */
1610
  public static void replLog(String message)
1611
  {
1612
    try
1613
    {
1614
      FileOutputStream fos = new FileOutputStream(
1615
                                 util.getOption("replicationlog"), true);
1616
      PrintWriter pw = new PrintWriter(fos);
1617
      SimpleDateFormat formatter = new SimpleDateFormat ("yy-MM-dd HH:mm:ss");
1618
      java.util.Date localtime = new java.util.Date();
1619
      String dateString = formatter.format(localtime);
1620
      dateString += " :: " + message;
1621
      //time stamp each entry
1622
      pw.println(dateString);
1623
      pw.flush();
1624
    }
1625
    catch(Exception e)
1626
    {
1627
      System.out.println("error writing to replication log from " +
1628
                         "MetacatReplication.replLog: " + e.getMessage());
1629
      //e.printStackTrace(System.out);
1630
    }
1631
  }
1632
  
1633
  /**
1634
   * Method for writing replication messages to a log file specified in 
1635
   * metacat.properties
1636
   */
1637
  public static void replErrorLog(String message)
1638
  {
1639
    try
1640
    {
1641
      FileOutputStream fos = new FileOutputStream(
1642
                                 util.getOption("replicationerrorlog"), true);
1643
      PrintWriter pw = new PrintWriter(fos);
1644
      SimpleDateFormat formatter = new SimpleDateFormat ("yy-MM-dd HH:mm:ss");
1645
      java.util.Date localtime = new java.util.Date();
1646
      String dateString = formatter.format(localtime);
1647
      dateString += " :: " + message;
1648
      //time stamp each entry
1649
      pw.println(dateString);
1650
      pw.flush();
1651
    }
1652
    catch(Exception e)
1653
    {
1654
      System.out.println("error writing to replication log from " +
1655
                         "MetacatReplication.replLog: " + e.getMessage());
1656
      //e.printStackTrace(System.out);
1657
    }
1658
  }
1659
  
1660
  /**
1661
   * Returns true if the replicate field for server in xml_replication is 1.
1662
   * Returns false otherwise
1663
   */
1664
  public static boolean replToServer(String server)
1665
  {
1666
    DBConnection dbConn = null;
1667
    int serialNumber = -1;
1668
    PreparedStatement pstmt = null;
1669
    try
1670
    {
1671
      dbConn=DBConnectionPool.
1672
                  getDBConnection("MetacatReplication.repltoServer");
1673
      serialNumber=dbConn.getCheckOutSerialNumber();
1674
      pstmt = dbConn.prepareStatement("select replicate from " + 
1675
                                    "xml_replication where server like '" +
1676
                                     server + "'");
1677
      pstmt.execute();
1678
      ResultSet rs = pstmt.getResultSet();
1679
      boolean tablehasrows = rs.next();
1680
      if(tablehasrows)
1681
      {
1682
        int i = rs.getInt(1);
1683
        if(i == 1)
1684
        {
1685
          pstmt.close();
1686
          //conn.close();
1687
          return true;
1688
        }
1689
        else
1690
        {
1691
          pstmt.close();
1692
          //conn.close();
1693
          return false;
1694
        }
1695
      }
1696
    }
1697
    catch(Exception e)
1698
    {
1699
      System.out.println("error in MetacatReplication.replToServer: " + 
1700
                         e.getMessage());
1701
    }
1702
    finally
1703
    {
1704
      try
1705
      {
1706
        pstmt.close();
1707
        //conn.close();
1708
      }//try
1709
      catch(Exception ee)
1710
      {
1711
        MetaCatUtil.debugMessage("Error in MetacatReplication.replToServer: "
1712
                                  +ee.getMessage(), 30);
1713
      }//catch
1714
      finally
1715
      {
1716
        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1717
      }//finally
1718
    }//finally
1719
    return false;
1720
    //the default if this server does not exist is to not replicate to it.
1721
  }
1722
  
1723
  
1724
}
(42-42/57)