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
 *
8
 *   '$Author: daigle $'
9
 *     '$Date: 2009-03-25 14:41:15 -0700 (Wed, 25 Mar 2009) $'
10
 * '$Revision: 4861 $'
11
 *
12
 * This program is free software; you can redistribute it and/or modify
13
 * it under the terms of the GNU General Public License as published by
14
 * the Free Software Foundation; either version 2 of the License, or
15
 * (at your option) any later version.
16
 *
17
 * This program is distributed in the hope that it will be useful,
18
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20
 * GNU General Public License for more details.
21
 *
22
 * You should have received a copy of the GNU General Public License
23
 * along with this program; if not, write to the Free Software
24
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
25
 */
26

    
27
package edu.ucsb.nceas.metacat;
28

    
29
import java.util.*;
30
import java.util.Date;
31
import java.io.*;
32
import java.sql.*;
33
import java.net.*;
34
import java.text.*;
35

    
36
import javax.servlet.*;
37
import javax.servlet.http.*;
38

    
39
import edu.ucsb.nceas.metacat.service.DatabaseService;
40
import edu.ucsb.nceas.metacat.service.PropertyService;
41
import edu.ucsb.nceas.metacat.service.SessionService;
42
import edu.ucsb.nceas.metacat.util.AuthUtil;
43
import edu.ucsb.nceas.metacat.util.MetacatUtil;
44
import edu.ucsb.nceas.metacat.util.SessionData;
45
import edu.ucsb.nceas.metacat.util.SystemUtil;
46
import edu.ucsb.nceas.utilities.FileUtil;
47
import edu.ucsb.nceas.utilities.GeneralPropertyException;
48
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
49

    
50
import org.apache.log4j.Logger;
51
import org.xml.sax.*;
52

    
53
public class MetacatReplication extends HttpServlet implements Runnable
54
{
55

    
56
  private static final long serialVersionUID = -2898600143193513155L;
57
  private long timeInterval;
58
  private Date firstTime;
59
  private boolean timedReplicationIsOn = false;
60
  Timer replicationDaemon;
61
  private Vector<String> fileLocks = new Vector<String>();
62
  private Thread lockThread = null;
63
  public static final String FORCEREPLICATEDELETE = "forcereplicatedelete";
64
  private static final String TIMEREPLICATION = "replication.timedreplication";
65
  private static final String TIMEREPLICATIONINTERVAl = "replication.timedreplicationinterval";
66
  private static final String FIRSTTIME  = "replication.firsttimedreplication";
67
  private static final int    TIMEINTERVALLIMIT = 7200000;
68
  private static Logger logMetacat = Logger.getLogger(MetacatReplication.class);
69
  public static final String REPLICATIONUSER = "replication";
70

    
71
  /**
72
   * Initialize the servlet by creating appropriate database connections
73
   */
74
  public void init(ServletConfig config) throws ServletException
75
  {
76
     //initialize db connections to handle any update requests
77
    //deltaT = util.getProperty("replication.deltaT");
78
    //the default deltaT can be set from metacat.properties
79
    //create a thread to do the delta-T check but don't execute it yet
80
    replicationDaemon = new Timer(true);
81
    try
82
    {
83
       timedReplicationIsOn = (new Boolean(PropertyService.getProperty(TIMEREPLICATION ).trim())).booleanValue();
84
       logMetacat.info("The timed replication on is"+timedReplicationIsOn);
85
       timeInterval = (new Long(PropertyService.getProperty(TIMEREPLICATIONINTERVAl).trim())).longValue();
86
       logMetacat.warn("The timed replication time Inerval is "+ timeInterval);
87
       String firstTimeStr = PropertyService.getProperty(FIRSTTIME);
88
       logMetacat.warn("first replication time form property is "+firstTimeStr);
89
       firstTime = ReplicationHandler.combinateCurrentDateAndGivenTime(firstTimeStr);
90
       logMetacat.warn("After combine current time, the real first time is "
91
                                +firstTime.toString()+" minisec");
92
       // set up time replication if it is on
93
       if (timedReplicationIsOn)
94
       {
95
           replicationDaemon.scheduleAtFixedRate(new ReplicationHandler(), firstTime, timeInterval);
96
           MetacatReplication.replLog("deltaT handler started with rate=" +
97
                   timeInterval + " mini seconds at " +firstTime.toString());
98
       }
99
		       
100
       String logFilePath = 
101
    	   PropertyService.getProperty("replication.logdir") + "/metacatreplicationerror.log";
102
       if (FileUtil.getFileStatus(logFilePath) == FileUtil.DOES_NOT_EXIST) {
103
    	   FileUtil.createFile(logFilePath);
104
       }
105
       
106
       if (FileUtil.getFileStatus(logFilePath) < FileUtil.EXISTS_READ_WRITABLE) {
107
    	   logMetacat.error(logFilePath + " does not exist read/writable.");
108
       }
109
       
110
    }
111
    catch (Exception e)
112
    {
113
        // the timed replication in Metacat.properties file has problem
114
        // so timed replication is setting to false;
115
        logMetacat.error("Couldn't set up timed replication "+
116
                     " in Metacat replication servlet init because " +
117
                 e.getMessage());
118
        MetacatReplication.replErrorLog("Couldn't set up timed replication "+
119
                " in Metacat replication servlet init because " +
120
                e.getMessage());
121
        timedReplicationIsOn = false;
122
    }
123
    
124
  }
125

    
126
  public void destroy()
127
  {
128
    replicationDaemon.cancel();
129
   
130
  }
131

    
132
  public void doGet (HttpServletRequest request, HttpServletResponse response)
133
                     throws ServletException, IOException
134
  {
135
    // Process the data and send back the response
136
    handleGetOrPost(request, response);
137
  }
138

    
139
  public void doPost(HttpServletRequest request, HttpServletResponse response)
140
                     throws ServletException, IOException
141
  {
142
    // Process the data and send back the response
143
    handleGetOrPost(request, response);
144
  }
145

    
146
  private void handleGetOrPost(HttpServletRequest request,
147
                               HttpServletResponse response)
148
                               throws ServletException, IOException
149
  {
150
    //PrintWriter out = response.getWriter();
151
    //ServletOutputStream outPut = response.getOutputStream();
152
    Hashtable<String, String[]> params = new Hashtable<String, String[]>();
153
    Enumeration<String> paramlist = request.getParameterNames();
154

    
155

    
156

    
157
// NOT NEEDED - doesn't provide enough security because of possible IP spoofing
158
// REPLACED with running replication comminications over HTTPS
159
//    String requestingServerIP = request.getRemoteAddr();
160
//    InetAddress iaddr = InetAddress.getByName(requestingServerIP);
161
//    String requestingServer = iaddr.getHostName();
162

    
163
    while (paramlist.hasMoreElements()) {
164
      String name = (String)paramlist.nextElement();
165
      String[] value = request.getParameterValues(name);
166
      params.put(name, value);
167
    }
168

    
169
    String action = "";
170
    if (!params.isEmpty() && params.get("action") != null) {
171
    	action = ((String[])params.get("action"))[0];
172
    }
173
    String server = null;
174

    
175
    try {
176
      // check if the server is included in the list of replicated servers
177
      if ( !action.equals("servercontrol") &&
178
           !action.equals("stop") &&
179
           !action.equals("start") &&
180
           !action.equals("getall") ) {
181

    
182
        server = ((String[])params.get("server"))[0];
183
        if ( getServerCodeForServerName(server) == 0 ) {
184
        	logMetacat.debug("Action \"" + action +
185
                             "\" rejected for server: " + server);
186
          return;
187
        } else {
188
        	logMetacat.debug("Action \"" + action +
189
                             "\" accepted for server: " + server);
190
        }
191
      }
192
      else
193
      {
194
          // start, stop, getall and servercontrol need to check
195
          // if user is administor
196
          HttpSession sess = request.getSession(true);
197
          SessionData sessionData = null;
198
          String sess_id = "";
199
          String username = "";
200
          String[] groupnames = {""};
201

    
202
          if (params.containsKey("sessionid")) 
203
          {
204
             sess_id = ((String[]) params.get("sessionid"))[0];
205
             logMetacat.info("in has sessionid "+ sess_id);
206
             if (SessionService.isSessionRegistered(sess_id)) 
207
             {
208
                  logMetacat.info("find the id " + sess_id + " in hash table");
209
                  sessionData = SessionService.getRegisteredSession(sess_id);
210
             }
211
           } 
212
          if (sessionData == null) {
213
        	  sessionData = new SessionData(sess.getId(), 
214
					(String) sess.getAttribute("username"), 
215
					(String[]) sess.getAttribute("groups"),
216
					(String) sess.getAttribute("password"));
217
          }
218
          
219
           username = sessionData.getUserName();
220
           logMetacat.warn("The user name from session is: "+ username);
221
           groupnames = sessionData.getGroupNames();
222
           if (!AuthUtil.isAdministrator(username, groupnames)) 
223
           {
224
               PrintWriter out = response.getWriter();
225
               out.print("<error>");
226
               out.print("The user \"" + username +
227
                       "\" is not authorized for this action.");
228
               out.print("</error>");
229
               out.close();
230
               logMetacat.warn("The user \"" + username +
231
                       "\" is not authorized for this action: " +action);
232
               replErrorLog("The user \"" + username +
233
                       "\" is not authorized for this action: " +action);
234
               return;
235
           }
236
                        
237
      }// this is final else
238
    } catch (Exception e) {
239
      logMetacat.error("Error in MetacatReplication.handleGetOrPost: " +
240
                         e.getMessage() );
241
      return;
242
    }
243
    
244
    if ( action.equals("readdata") )
245
    {
246
      OutputStream outStream = response.getOutputStream();
247
      //to get the data file.
248
      handleGetDataFileRequest(outStream, params, response);
249
      outStream.close();
250
    }
251
    else if ( action.equals("forcereplicatedatafile") )
252
    {
253
      //read a specific docid from remote host, and store it into local host
254
      handleForceReplicateDataFileRequest(params, request);
255

    
256
    }
257
    else
258
    {
259
    PrintWriter out = response.getWriter();
260
    if ( action.equals("stop") ) {
261
      //stop the replication server
262
      replicationDaemon.cancel();
263
      replicationDaemon = new Timer(true);
264
      timedReplicationIsOn = false;
265
      try {
266
    	  PropertyService.setProperty(TIMEREPLICATION, (new Boolean(timedReplicationIsOn)).toString());
267
      } catch (GeneralPropertyException gpe) {
268
    	  logMetacat.warn("Could not set " + TIMEREPLICATION + " property: " + gpe.getMessage());
269
      }
270
      out.println("Replication Handler Stopped");
271
      MetacatReplication.replLog("deltaT handler stopped");
272

    
273

    
274
    } else if ( action.equals("start") ) {
275
       String firstTimeStr = "";
276
      //start the replication server
277
       if ( params.containsKey("rate") ) {
278
        timeInterval = new Long(
279
               new String(((String[])params.get("rate"))[0])).longValue();
280
        if(timeInterval < TIMEINTERVALLIMIT) {
281
            out.println("Replication deltaT rate cannot be less than "+
282
                    TIMEINTERVALLIMIT + " millisecs and system automatically setup the rate to "+TIMEINTERVALLIMIT);
283
            //deltaT<30 is a timing mess!
284
            timeInterval = TIMEINTERVALLIMIT;
285
        }
286
      } else {
287
        timeInterval = TIMEINTERVALLIMIT ;
288
      }
289
      logMetacat.info("New rate is: " + timeInterval + " mini seconds.");
290
      if ( params.containsKey("firsttime"))
291
      {
292
         firstTimeStr = ((String[])params.get("firsttime"))[0];
293
         try
294
         {
295
           firstTime = ReplicationHandler.combinateCurrentDateAndGivenTime(firstTimeStr);
296
           logMetacat.info("The first time setting is "+firstTime.toString());
297
         }
298
         catch (Exception e)
299
         {
300
            throw new ServletException(e.getMessage());
301
         }
302
         logMetacat.warn("After combine current time, the real first time is "
303
                                  +firstTime.toString()+" minisec");
304
      }
305
      else
306
      {
307
          MetacatReplication.replErrorLog("You should specify the first time " +
308
                                          "to start a time replication");
309
          logMetacat.warn("You should specify the first time " +
310
                                  "to start a time replication");
311
          return;
312
      }
313
      
314
      timedReplicationIsOn = true;
315
      try {
316
      // save settings to property file
317
      PropertyService.setProperty(TIMEREPLICATION, (new Boolean(timedReplicationIsOn)).toString());
318
      // note we couldn't use firstTime object because it has date info
319
      // we only need time info such as 10:00 PM
320
      PropertyService.setProperty(FIRSTTIME, firstTimeStr);
321
      PropertyService.setProperty(TIMEREPLICATIONINTERVAl, (new Long(timeInterval)).toString());
322
      } catch (GeneralPropertyException gpe) {
323
    	  logMetacat.warn("Could not set property: " + gpe.getMessage());
324
      }
325
      replicationDaemon.cancel();
326
      replicationDaemon = new Timer(true);
327
      replicationDaemon.scheduleAtFixedRate(new ReplicationHandler(), firstTime,
328
                                            timeInterval);
329
      out.println("Replication Handler Started");
330
      MetacatReplication.replLog("deltaT handler started with rate=" +
331
                                    timeInterval + " milliseconds at " +firstTime.toString());
332

    
333

    
334
    } else if ( action.equals("getall") ) {
335
      //updates this server exactly once
336
      replicationDaemon.schedule(new ReplicationHandler(), 0);
337
      response.setContentType("text/html");
338
      out.println("<html><body>\"Get All\" Done</body></html>");
339

    
340
    } else if ( action.equals("forcereplicate") ) {
341
      //read a specific docid from remote host, and store it into local host
342
      handleForceReplicateRequest(out, params, response, request);
343

    
344
    } else if ( action.equals(FORCEREPLICATEDELETE) ) {
345
      //read a specific docid from remote host, and store it into local host
346
      handleForceReplicateDeleteRequest(out, params, response, request);
347

    
348
    } else if ( action.equals("update") ) {
349
      //request an update list from the server
350
      handleUpdateRequest(out, params, response);
351

    
352
    } else if ( action.equals("read") ) {
353
      //request a specific document from the server
354
      //note that this could be replaced by a call to metacatServlet
355
      //handleGetDocumentAction().
356
      handleGetDocumentRequest(out, params, response);
357
    } else if ( action.equals("getlock") ) {
358
      handleGetLockRequest(out, params, response);
359

    
360
    } else if ( action.equals("getdocumentinfo") ) {
361
      handleGetDocumentInfoRequest(out, params, response);
362

    
363
    } else if ( action.equals("gettime") ) {
364
      handleGetTimeRequest(out, params, response);
365

    
366
    } else if ( action.equals("getcatalog") ) {
367
      handleGetCatalogRequest(out, params, response, true);
368

    
369
    } else if ( action.equals("servercontrol") ) {
370
      handleServerControlRequest(out, params, response);
371
    } else if ( action.equals("test") ) {
372
      response.setContentType("text/html");
373
      out.println("<html><body>Test successfully</body></html>");
374
    }
375

    
376
    out.close();
377
    }//else
378
  }
379

    
380
  /**
381
   * This method can add, delete and list the servers currently included in
382
   * xml_replication.
383
   * action           subaction            other needed params
384
   * ---------------------------------------------------------
385
   * servercontrol    add                  server
386
   * servercontrol    delete               server
387
   * servercontrol    list
388
   */
389
  private void handleServerControlRequest(PrintWriter out, Hashtable<String, String[]> params,
390
                                          HttpServletResponse response)
391
  {
392
    String subaction = ((String[])params.get("subaction"))[0];
393
    DBConnection dbConn = null;
394
    int serialNumber = -1;
395
    PreparedStatement pstmt = null;
396
    String replicate =null;
397
    String server = null;
398
    String dataReplicate = null;
399
    String hub = null;
400
    try {
401
      //conn = util.openDBConnection();
402
      dbConn=DBConnectionPool.
403
               getDBConnection("MetacatReplication.handleServerControlRequest");
404
      serialNumber=dbConn.getCheckOutSerialNumber();
405

    
406
      // add server to server list
407
      if ( subaction.equals("add") ) {
408
        replicate = ((String[])params.get("replicate"))[0];
409
        server = ((String[])params.get("server"))[0];
410

    
411
        //Get data replication value
412
        dataReplicate = ((String[])params.get("datareplicate"))[0];
413
        //Get hub value
414
        hub = ((String[])params.get("hub"))[0];
415

    
416
        /*pstmt = dbConn.prepareStatement("INSERT INTO xml_replication " +
417
                  "(server, last_checked, replicate, datareplicate, hub) " +
418
                                      "VALUES ('" + server + "', to_date(" +
419
                                      "'01/01/00', 'MM/DD/YY'), '" +
420
                                      replicate +"', '" +dataReplicate+"', '"
421
                                      + hub +"')");*/
422
        pstmt = dbConn.prepareStatement("INSERT INTO xml_replication " +
423
                  "(server, last_checked, replicate, datareplicate, hub) " +
424
                                      "VALUES ('" + server + "', "+
425
                                      DatabaseService.getDBAdapter().toDate("01/01/1980", "MM/DD/YYYY")
426
                                      + ", '" +
427
                                      replicate +"', '" +dataReplicate+"', '"
428
                                      + hub +"')");
429

    
430
        pstmt.execute();
431
        pstmt.close();
432
        dbConn.commit();
433
        out.println("Server " + server + " added");
434
        response.setContentType("text/html");
435
        out.println("<html><body><table border=\"1\">");
436
        out.println("<tr><td><b>server</b></td><td><b>last_checked</b></td><td>");
437
        out.println("<b>replicate</b></td>");
438
        out.println("<td><b>datareplicate</b></td>");
439
        out.println("<td><b>hub</b></td></tr>");
440
        pstmt = dbConn.prepareStatement("SELECT * FROM xml_replication");
441
        //increase dbconnection usage
442
        dbConn.increaseUsageCount(1);
443

    
444
        pstmt.execute();
445
        ResultSet rs = pstmt.getResultSet();
446
        boolean tablehasrows = rs.next();
447
        while(tablehasrows) {
448
          out.println("<tr><td>" + rs.getString(2) + "</td><td>");
449
          out.println(rs.getString(3) + "</td><td>");
450
          out.println(rs.getString(4) + "</td><td>");
451
          out.println(rs.getString(5) + "</td><td>");
452
          out.println(rs.getString(6) + "</td></tr>");
453

    
454
          tablehasrows = rs.next();
455
        }
456
        out.println("</table></body></html>");
457

    
458
        // download certificate with the public key on this server
459
        // and import it as a trusted certificate
460
        String certURL = ((String[])params.get("certificate"))[0];
461
        downloadCertificate(certURL);
462

    
463
      // delete server from server list
464
      } else if ( subaction.equals("delete") ) {
465
        server = ((String[])params.get("server"))[0];
466
        pstmt = dbConn.prepareStatement("DELETE FROM xml_replication " +
467
                                      "WHERE server LIKE '" + server + "'");
468
        pstmt.execute();
469
        pstmt.close();
470
        dbConn.commit();
471
        out.println("Server " + server + " deleted");
472
        response.setContentType("text/html");
473
        out.println("<html><body><table border=\"1\">");
474
        out.println("<tr><td><b>server</b></td><td><b>last_checked</b></td><td>");
475
        out.println("<b>replicate</b></td>");
476
        out.println("<td><b>datareplicate</b></td>");
477
        out.println("<td><b>hub</b></td></tr>");
478

    
479
        pstmt = dbConn.prepareStatement("SELECT * FROM xml_replication");
480
        //increase dbconnection usage
481
        dbConn.increaseUsageCount(1);
482
        pstmt.execute();
483
        ResultSet rs = pstmt.getResultSet();
484
        boolean tablehasrows = rs.next();
485
        while(tablehasrows)
486
        {
487
          out.println("<tr><td>" + rs.getString(2) + "</td><td>");
488
          out.println(rs.getString(3) + "</td><td>");
489
          out.println(rs.getString(4) + "</td><td>");
490
          out.println(rs.getString(5) + "</td><td>");
491
          out.println(rs.getString(6) + "</td></tr>");
492
          tablehasrows = rs.next();
493
        }
494
        out.println("</table></body></html>");
495

    
496
      // list servers in server list
497
      } else if ( subaction.equals("list") ) {
498
        response.setContentType("text/html");
499
        out.println("<html><body><table border=\"1\">");
500
        out.println("<tr><td><b>server</b></td><td><b>last_checked</b></td><td>");
501
        out.println("<b>replicate</b></td>");
502
        out.println("<td><b>datareplicate</b></td>");
503
        out.println("<td><b>hub</b></td></tr>");
504
        pstmt = dbConn.prepareStatement("SELECT * FROM xml_replication");
505
        pstmt.execute();
506
        ResultSet rs = pstmt.getResultSet();
507
        boolean tablehasrows = rs.next();
508
        while(tablehasrows) {
509
          out.println("<tr><td>" + rs.getString(2) + "</td><td>");
510
          out.println(rs.getString(3) + "</td><td>");
511
          out.println(rs.getString(4) + "</td><td>");
512
          out.println(rs.getString(5) + "</td><td>");
513
          out.println(rs.getString(6) + "</td></tr>");
514
          tablehasrows = rs.next();
515
        }
516
        out.println("</table></body></html>");
517
      }
518
      else
519
      {
520

    
521
        out.println("<error>Unkonwn subaction</error>");
522

    
523
      }
524
      pstmt.close();
525
      //conn.close();
526

    
527
    } catch(Exception e) {
528
      logMetacat.error("Error in " +
529
                         "MetacatReplication.handleServerControlRequest " +
530
                         e.getMessage());
531
      e.printStackTrace(System.out);
532
    }
533
    finally
534
    {
535
      try
536
      {
537
        pstmt.close();
538
      }//try
539
      catch (SQLException ee)
540
      {
541
        logMetacat.error("Error in " +
542
                "MetacatReplication.handleServerControlRequest to close pstmt "
543
                 + ee.getMessage());
544
      }//catch
545
      finally
546
      {
547
        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
548
      }//finally
549
    }//finally
550

    
551
  }
552

    
553
   	// download certificate with the public key from certURL and
554
	// upload it onto this server; it then must be imported as a
555
	// trusted certificate
556
	private void downloadCertificate(String certURL) throws FileNotFoundException,
557
			IOException, MalformedURLException, PropertyNotFoundException {
558
		
559
		// the path to be uploaded to
560
		String certPath = SystemUtil.getContextDir(); 
561

    
562
		// get filename from the URL of the certificate
563
		String filename = certURL;
564
		int slash = Math.max(filename.lastIndexOf('/'), filename.lastIndexOf('\\'));
565
		if (slash > -1) {
566
			filename = filename.substring(slash + 1);
567
		}
568

    
569
		// open file output strem to write the input into it
570
		File f = new File(certPath, filename);
571
		synchronized (f) {
572
			try {
573
				if (f.exists()) {
574
					throw new IOException("File already exist: " + f.getCanonicalFile());
575
					// if ( f.exists() && !f.canWrite() ) {
576
					// throw new IOException("Not writable: " +
577
					// f.getCanonicalFile());
578
				}
579
			} catch (SecurityException se) {
580
				// if a security manager exists,
581
				// its checkRead method is called for f.exist()
582
				// or checkWrite method is called for f.canWrite()
583
				throw se;
584
			}
585

    
586
			// create a buffered byte output stream
587
			// that uses a default-sized output buffer
588
			FileOutputStream fos = new FileOutputStream(f);
589
			BufferedOutputStream out = new BufferedOutputStream(fos);
590

    
591
			// this should be http url
592
			URL url = new URL(certURL);
593
			BufferedInputStream bis = null;
594
			try {
595
				bis = new BufferedInputStream(url.openStream());
596
				byte[] buf = new byte[4 * 1024]; // 4K buffer
597
				int b = bis.read(buf);
598
				while (b != -1) {
599
					out.write(buf, 0, b);
600
					b = bis.read(buf);
601
				}
602
			} finally {
603
				if (bis != null)
604
					bis.close();
605
			}
606
			// the input and the output streams must be closed
607
			bis.close();
608
			out.flush();
609
			out.close();
610
			fos.close();
611
		} // end of synchronized(f)
612
	}
613

    
614
  /**
615
	 * when a forcereplication request comes in, local host sends a read request
616
	 * to the requesting server (remote server) for the specified docid. Then
617
	 * store it in local database.
618
	 */
619
  private void handleForceReplicateRequest(PrintWriter out, Hashtable<String, String[]> params,
620
                                           HttpServletResponse response, HttpServletRequest request)
621
  {
622
    String server = ((String[])params.get("server"))[0]; // the server that
623
    String docid = ((String[])params.get("docid"))[0]; // sent the document
624
    String dbaction = "UPDATE"; // the default action is UPDATE
625
//    boolean override = false;
626
//    int serverCode = 1;
627
    DBConnection dbConn = null;
628
    int serialNumber = -1;
629

    
630
    try {
631
      //if the url contains a dbaction then the default action is overridden
632
      if(params.containsKey("dbaction")) {
633
        dbaction = ((String[])params.get("dbaction"))[0];
634
        //serverCode = MetacatReplication.getServerCode(server);
635
        //override = true; //we are now overriding the default action
636
      }
637
      MetacatReplication.replLog("force replication request from " + server);
638
      logMetacat.info("Force replication request from: "+ server);
639
      logMetacat.info("Force replication docid: "+docid);
640
      logMetacat.info("Force replication action: "+dbaction);
641
      // sending back read request to remote server
642
      URL u = new URL("https://" + server + "?server="
643
                +MetacatUtil.getLocalReplicationServerName()
644
                +"&action=read&docid=" + docid);
645
      String xmldoc = MetacatReplication.getURLContent(u);
646

    
647
      // get the document info from server
648
      URL docinfourl = new URL("https://" + server +
649
                               "?server="+MetacatUtil.getLocalReplicationServerName()
650
                               +"&action=getdocumentinfo&docid=" + docid);
651

    
652
      String docInfoStr = MetacatReplication.getURLContent(docinfourl);
653

    
654
      //dih is the parser for the docinfo xml format
655
      DocInfoHandler dih = new DocInfoHandler();
656
      XMLReader docinfoParser = ReplicationHandler.initParser(dih);
657
      docinfoParser.parse(new InputSource(new StringReader(docInfoStr)));
658
//      Hashtable<String,Vector<AccessControlForSingleFile>> docinfoHash = dih.getDocInfo();
659
      Hashtable<String,String> docinfoHash = dih.getDocInfo();
660

    
661
      // Get user owner of this docid
662
      String user = (String)docinfoHash.get("user_owner");
663
      // Get home server of this docid
664
      String homeServer=(String)docinfoHash.get("home_server");
665
      String createdDate = (String)docinfoHash.get("date_created");
666
      String updatedDate = (String)docinfoHash.get("date_updated");
667
      logMetacat.info("homeServer: "+homeServer);
668
      // Get Document type
669
      String docType = (String)docinfoHash.get("doctype");
670
      logMetacat.info("docType: "+docType);
671
      String parserBase = null;
672
      // this for eml2 and we need user eml2 parser
673
      if (docType != null &&
674
          (docType.trim()).equals(DocumentImpl.EML2_0_0NAMESPACE))
675
      {
676
         logMetacat.warn("This is an eml200 document!");
677
         parserBase = DocumentImpl.EML200;
678
      }
679
      else if (docType != null && (docType.trim()).equals(DocumentImpl.EML2_0_1NAMESPACE))
680
      {
681
         logMetacat.warn("This is an eml2.0.1 document!");
682
         parserBase = DocumentImpl.EML200;
683
      }
684
      else if (docType != null && (docType.trim()).equals(DocumentImpl.EML2_1_0NAMESPACE))
685
      {
686
         logMetacat.warn("This is an eml2.1.0 document!");
687
         parserBase = DocumentImpl.EML210;
688
      }
689
      logMetacat.warn("The parserBase is: "+parserBase);
690

    
691
      // Get DBConnection from pool
692
      dbConn=DBConnectionPool.
693
              getDBConnection("MetacatReplication.handleForceReplicateRequest");
694
      serialNumber=dbConn.getCheckOutSerialNumber();
695
      // write the document to local database
696
      DocumentImplWrapper wrapper = new DocumentImplWrapper(parserBase, false);
697
      //try this independently so we can set
698
      Exception writeException = null; 
699
      try {
700
	      wrapper.writeReplication(dbConn, new StringReader(xmldoc), null, null,
701
	                               dbaction, docid, user, null, homeServer, 
702
	                               server, createdDate, updatedDate);
703
      }
704
      catch (Exception e) {
705
    	  writeException = e;
706
      }
707

    
708
      //process extra access rules before dealing with the write exception (doc exist already)
709
      Vector<AccessControlForSingleFile> accessControlList = dih.getAccessControlList();
710
      if (accessControlList != null) {
711
    	  for (int i = 0; i < accessControlList.size(); i++) {
712
        	  AccessControlForSingleFile acfsf = (AccessControlForSingleFile) accessControlList.get(i);
713
        	  if (!acfsf.accessControlExists()) {
714
	        	  acfsf.insertPermissions();
715
	        	  MetacatReplication.replLog("document " + docid + " permissions added to DB");
716
        	  }
717
          }
718
      }
719
      
720
      if (writeException != null) {
721
    	  throw writeException;
722
      }
723
      
724
      MetacatReplication.replLog("document " + docid + " added to DB with " +
725
                                 "action " + dbaction);
726
      EventLog.getInstance().log(request.getRemoteAddr(), REPLICATIONUSER, docid, dbaction);
727
    }//try
728
    catch(Exception e)
729
    {
730
      MetacatReplication.replErrorLog("document " + docid +
731
                                      " failed to added to DB with " +
732
                                      "action " + dbaction + " because "+
733
                                       e.getMessage());
734
      logMetacat.error("ERROR in MetacatReplication.handleForceReplicate" +
735
                         "Request(): " + e.getMessage());
736

    
737
    }//catch
738
    finally
739
    {
740
      // Return the checked out DBConnection
741
      DBConnectionPool.returnDBConnection(dbConn, serialNumber);
742
    }//finally
743
  }
744

    
745
/*
746
 * when a forcereplication delete request comes in, local host will delete this
747
 * document
748
 */
749
private void handleForceReplicateDeleteRequest(PrintWriter out, Hashtable<String, String[]> params,
750
                                         HttpServletResponse response, HttpServletRequest request)
751
{
752
  String server = ((String[])params.get("server"))[0]; // the server that
753
  String docid = ((String[])params.get("docid"))[0]; // sent the document
754
  try
755
  {
756
    MetacatReplication.replLog("force replication delete request from " + server);
757
    MetacatReplication.replLog("force replication delete docid " + docid);
758
    logMetacat.info("Force replication delete request from: "+ server);
759
    logMetacat.info("Force replication delete docid: "+docid);
760
    DocumentImpl.delete(docid, null, null, server);
761
    MetacatReplication.replLog("document " + docid + " was successfully deleted ");
762
    EventLog.getInstance().log(request.getRemoteAddr(), REPLICATIONUSER, docid, "delete");
763
    logMetacat.info("document " + docid + " was successfully deleted ");
764
  }
765
  catch(Exception e)
766
  {
767
    MetacatReplication.replErrorLog("document " + docid +
768
                                    " failed to delete because "+
769
                                     e.getMessage());
770
    logMetacat.error("ERROR in MetacatReplication.handleForceDeleteReplicate" +
771
                       "Request(): " + e.getMessage());
772

    
773
  }//catch
774

    
775
}
776

    
777

    
778
  /**
779
   * when a forcereplication data file request comes in, local host sends a
780
   * readdata request to the requesting server (remote server) for the specified
781
   * docid. Then store it in local database and file system
782
   */
783
  private void handleForceReplicateDataFileRequest(Hashtable<String, String[]> params, HttpServletRequest request)
784
  {
785

    
786
    //make sure there is some parameters
787
    if(params.isEmpty())
788
    {
789
      return;
790
    }
791
    // Get remote server
792
    String server = ((String[])params.get("server"))[0];
793
    // the docid should include rev number
794
    String docid = ((String[])params.get("docid"))[0];
795
    // Make sure there is a docid and server
796
    if (docid==null || server==null || server.equals(""))
797
    {
798
      logMetacat.error("Didn't specify docid or server for replication");
799
      return;
800
    }
801

    
802
    // Overide or not
803
//    boolean override = false;
804
    // dbaction - update or insert
805
    String dbaction=null;
806

    
807
    try
808
    {
809
      //docid was switch to two parts uinque code and rev
810
      //String uniqueCode=MetacatUtil.getDocIdFromString(docid);
811
      //int rev=MetacatUtil.getVersionFromString(docid);
812
      if(params.containsKey("dbaction"))
813
      {
814
        dbaction = ((String[])params.get("dbaction"))[0];
815
      }
816
      else//default value is update
817
      {
818
        dbaction = "update";
819
      }
820

    
821
      MetacatReplication.replLog("force replication request from " + server);
822
      logMetacat.info("Force replication request from: "+ server);
823
      logMetacat.info("Force replication docid: "+docid);
824
      logMetacat.info("Force replication action: "+dbaction);
825
      // get the document info from server
826
      URL docinfourl = new URL("https://" + server +
827
                               "?server="+MetacatUtil.getLocalReplicationServerName()
828
                               +"&action=getdocumentinfo&docid=" + docid);
829

    
830
      String docInfoStr = MetacatReplication.getURLContent(docinfourl);
831

    
832
      //dih is the parser for the docinfo xml format
833
      DocInfoHandler dih = new DocInfoHandler();
834
      XMLReader docinfoParser = ReplicationHandler.initParser(dih);
835
      docinfoParser.parse(new InputSource(new StringReader(docInfoStr)));
836
      Hashtable<String,String> docinfoHash = dih.getDocInfo();
837
      String user = (String)docinfoHash.get("user_owner");
838

    
839
      String docName = (String)docinfoHash.get("docname");
840

    
841
      String docType = (String)docinfoHash.get("doctype");
842

    
843
      String docHomeServer= (String)docinfoHash.get("home_server");
844
      
845
      String createdDate = (String)docinfoHash.get("date_created");
846
      
847
      String updatedDate = (String)docinfoHash.get("date_updated");
848
      logMetacat.info("docHomeServer of datafile: "+docHomeServer);
849

    
850

    
851

    
852
      //if action is delete, we don't delete the data file. Just archieve
853
      //the xml_documents
854
      /*if (dbaction.equals("delete"))
855
      {
856
        //conn = util.getConnection();
857
        DocumentImpl.delete(docid,user,null);
858
        //util.returnConnection(conn);
859
      }*/
860
      //To data file insert or update is same
861
      if (dbaction.equals("insert")||dbaction.equals("update"))
862
      {
863
        //Get data file and store it into local file system.
864
        // sending back readdata request to server
865
        URL url = new URL("https://" + server + "?server="
866
                +MetacatUtil.getLocalReplicationServerName()
867
                +"&action=readdata&docid=" + docid);
868
        String datafilePath = PropertyService.getProperty("application.datafilepath");
869
        
870
        Exception writeException = null;
871
        //register data file into xml_documents table and wite data file
872
        //into file system
873
        try {
874
        	DocumentImpl.writeDataFileInReplication(url.openStream(), datafilePath,
875
                            docName, docType, docid, user,docHomeServer,server, 
876
                            DocumentImpl.DOCUMENTTABLE, false, createdDate, updatedDate);
877
        }
878
        catch (Exception e) {
879
        	writeException = e;
880
		}
881
        //process extra access rules
882
        Vector<AccessControlForSingleFile> accessControlList = dih.getAccessControlList();
883
        if (accessControlList != null) {
884
      	  for (int i = 0; i < accessControlList.size(); i++) {
885
          	  AccessControlForSingleFile acfsf = (AccessControlForSingleFile) accessControlList.get(i);
886
          	  if (!acfsf.accessControlExists()) {
887
          		  acfsf.insertPermissions();
888
          		  MetacatReplication.replLog("datafile " + docid + " permissions added to DB");
889
          	  }
890
            }
891
        }
892
        
893
        if (writeException != null) {
894
        	throw writeException;
895
        }
896
        
897
        //false means non-timed replication
898
        MetacatReplication.replLog("datafile " + docid + " added to DB with " +
899
                "action " + dbaction);
900
        EventLog.getInstance().log(request.getRemoteAddr(), REPLICATIONUSER, docid, dbaction);
901
     }
902
    
903
    }
904
    catch(Exception e)
905
    {
906

    
907
      MetacatReplication.replErrorLog("Datafile " + docid +
908
                                      " failed to added to DB with " +
909
                                      "action " + dbaction + " because "+
910
                                       e.getMessage());
911
      logMetacat.error
912
              ("ERROR in MetacatReplication.handleForceDataFileReplicate" +
913
                         "Request(): " + e.getMessage());
914
    }
915
  }
916
  /**
917
   * Grants or denies a lock to a requesting host.
918
   * The servlet parameters of interrest are:
919
   * docid: the docid of the file the lock is being requested for
920
   * currentdate: the timestamp of the document on the remote server
921
   *
922
   */
923
  private void handleGetLockRequest(PrintWriter out, Hashtable<String, String[]> params,
924
                                    HttpServletResponse response)
925
  {
926

    
927
    try
928
    {
929

    
930
      String docid = ((String[])params.get("docid"))[0];
931
      String remoteRev = ((String[])params.get("updaterev"))[0];
932
      DocumentImpl requestDoc = new DocumentImpl(docid);
933
      MetacatReplication.replLog("lock request for " + docid);
934
      int localRevInt = requestDoc.getRev();
935
      int remoteRevInt = Integer.parseInt(remoteRev);
936

    
937
      if(remoteRevInt >= localRevInt)
938
      {
939
        if(!fileLocks.contains(docid))
940
        { //grant the lock if it is not already locked
941
          fileLocks.add(0, docid); //insert at the beginning of the queue Vector
942
          //send a message back to the the remote host authorizing the insert
943
          out.println("<lockgranted><docid>" +docid+ "</docid></lockgranted>");
944
          lockThread = new Thread(this);
945
          lockThread.setPriority(Thread.MIN_PRIORITY);
946
          lockThread.start();
947
          MetacatReplication.replLog("lock granted for " + docid);
948
        }
949
        else
950
        { //deny the lock
951
          out.println("<filelocked><docid>" + docid + "</docid></filelocked>");
952
          MetacatReplication.replLog("lock denied for " + docid +
953
                                     "reason: file already locked");
954
        }
955
      }
956
      else
957
      {//deny the lock.
958
        out.println("<outdatedfile><docid>" + docid + "</docid></filelocked>");
959
        MetacatReplication.replLog("lock denied for " + docid +
960
                                   "reason: client has outdated file");
961
      }
962
      //conn.close();
963
    }
964
    catch(Exception e)
965
    {
966
      logMetacat.error("error requesting file lock from MetacatReplication." +
967
                         "handleGetLockRequest: " + e.getMessage());
968
      e.printStackTrace(System.out);
969
    }
970
  }
971

    
972
  /**
973
   * Sends all of the xml_documents information encoded in xml to a requestor
974
   * the format is:
975
   * <!ELEMENT documentinfo (docid, docname, doctype, doctitle, user_owner,
976
   *                  user_updated, home_server, public_access, rev)/>
977
   * all of the subelements of document info are #PCDATA
978
   */
979
  private void handleGetDocumentInfoRequest(PrintWriter out, Hashtable<String, String[]> params,
980
                                        HttpServletResponse response)
981
  {
982
    String docid = ((String[])(params.get("docid")))[0];
983
    StringBuffer sb = new StringBuffer();
984

    
985
    try
986
    {
987

    
988
      DocumentImpl doc = new DocumentImpl(docid);
989
      sb.append("<documentinfo><docid>").append(docid);
990
      sb.append("</docid><docname>").append(doc.getDocname());
991
      sb.append("</docname><doctype>").append(doc.getDoctype());
992
      sb.append("</doctype>");
993
      sb.append("<user_owner>").append(doc.getUserowner());
994
      sb.append("</user_owner><user_updated>").append(doc.getUserupdated());
995
      sb.append("</user_updated>");
996
      sb.append("<date_created>");
997
      sb.append(doc.getCreateDate());
998
      sb.append("</date_created>");
999
      sb.append("<date_updated>");
1000
      sb.append(doc.getUpdateDate());
1001
      sb.append("</date_updated>");
1002
      sb.append("<home_server>");
1003
      sb.append(doc.getDocHomeServer());
1004
      sb.append("</home_server>");
1005
      sb.append("<public_access>").append(doc.getPublicaccess());
1006
      sb.append("</public_access><rev>").append(doc.getRev());
1007
      sb.append("</rev>");
1008
      
1009
      //permissions on the document
1010
      PermissionController permController = new PermissionController(docid);
1011
      Vector<AccessControlForSingleFile> accessControlList = permController.getAccessControl();
1012
      sb.append("<accessControl>");
1013
      for (int i = 0; i < accessControlList.size(); i++) {
1014
    	  AccessControlForSingleFile acfsf = (AccessControlForSingleFile) accessControlList.get(i);
1015
    	  sb.append(acfsf.getAccessString());
1016
      }
1017
      sb.append("</accessControl>");
1018
      
1019
      sb.append("</documentinfo>");
1020
      response.setContentType("text/xml");
1021
      out.println(sb.toString());
1022

    
1023
    }
1024
    catch (Exception e)
1025
    {
1026
      logMetacat.error("error in metacatReplication.handlegetdocumentinforequest " 
1027
    		  + "for doc: " + docid + " : " + e.getMessage());
1028
    }
1029

    
1030
  }
1031

    
1032
  /**
1033
   * Sends a datafile to a remote host
1034
   */
1035
  private void handleGetDataFileRequest(OutputStream outPut,
1036
                            Hashtable<String, String[]> params, HttpServletResponse response)
1037

    
1038
  {
1039
    // File path for data file
1040
    String filepath;
1041
    // Request docid
1042
    String docId = ((String[])(params.get("docid")))[0];
1043
    //check if the doicd is null
1044
    if (docId==null)
1045
    {
1046
      logMetacat.error("Didn't specify docid for replication");
1047
      return;
1048
    }
1049

    
1050
    //try to open a https stream to test if the request server's public key
1051
    //in the key store, this is security issue
1052
    try
1053
    {
1054
      filepath = PropertyService.getProperty("application.datafilepath");
1055
      String server = params.get("server")[0];
1056
      URL u = new URL("https://" + server + "?server="
1057
                +MetacatUtil.getLocalReplicationServerName()
1058
                +"&action=test");
1059
      String test = MetacatReplication.getURLContent(u);
1060
      //couldn't pass the test
1061
      if (test.indexOf("successfully")==-1)
1062
      {
1063
        //response.setContentType("text/xml");
1064
        //outPut.println("<error>Couldn't pass the trust test</error>");
1065
        logMetacat.error("Couldn't pass the trust test");
1066
        return;
1067
      }
1068
    }//try
1069
    catch (Exception ee)
1070
    {
1071
      return;
1072
    }//catch
1073

    
1074
    if(!filepath.endsWith("/"))
1075
    {
1076
          filepath += "/";
1077
    }
1078
    // Get file aboslute file name
1079
    String filename = filepath + docId;
1080

    
1081
    //MIME type
1082
    String contentType = null;
1083
    if (filename.endsWith(".xml"))
1084
    {
1085
        contentType="text/xml";
1086
    }
1087
    else if (filename.endsWith(".css"))
1088
    {
1089
        contentType="text/css";
1090
    }
1091
    else if (filename.endsWith(".dtd"))
1092
    {
1093
        contentType="text/plain";
1094
    }
1095
    else if (filename.endsWith(".xsd"))
1096
    {
1097
        contentType="text/xml";
1098
    }
1099
    else if (filename.endsWith("/"))
1100
    {
1101
        contentType="text/html";
1102
    }
1103
    else
1104
    {
1105
        File f = new File(filename);
1106
        if ( f.isDirectory() )
1107
        {
1108
           contentType="text/html";
1109
        }
1110
        else
1111
        {
1112
           contentType="application/octet-stream";
1113
        }
1114
     }
1115

    
1116
   // Set the mime type
1117
   response.setContentType(contentType);
1118

    
1119
   // Get the content of the file
1120
   FileInputStream fin = null;
1121
   try
1122
   {
1123
      // FileInputStream to metacat
1124
      fin = new FileInputStream(filename);
1125
      // 4K buffer
1126
      byte[] buf = new byte[4 * 1024];
1127
      // Read data from file input stream to byte array
1128
      int b = fin.read(buf);
1129
      // Write to outStream from byte array
1130
      while (b != -1)
1131
      {
1132
        outPut.write(buf, 0, b);
1133
        b = fin.read(buf);
1134
      }
1135
      // close file input stream
1136
      fin.close();
1137

    
1138
   }//try
1139
   catch(Exception e)
1140
   {
1141
      logMetacat.error("error getting data file from MetacatReplication." +
1142
                         "handlGetDataFileRequest " + e.getMessage());
1143
      e.printStackTrace(System.out);
1144
   }//catch
1145

    
1146
}
1147

    
1148

    
1149
  	/**
1150
	 * Sends a document to a remote host
1151
	 */
1152
	private void handleGetDocumentRequest(PrintWriter out,
1153
			Hashtable<String, String[]> params, HttpServletResponse response) {
1154

    
1155
		String urlString = null;
1156
		String documentPath = null;
1157
		try {
1158
			// try to open a https stream to test if the request server's public
1159
			// key
1160
			// in the key store, this is security issue
1161
			String server = params.get("server")[0];
1162
			urlString = "https://" + server + "?server="
1163
					+ MetacatUtil.getLocalReplicationServerName() + "&action=test";
1164
			URL u = new URL(urlString);
1165
			String test = MetacatReplication.getURLContent(u);
1166
			// couldn't pass the test
1167
			if (test.indexOf("successfully") == -1) {
1168
				response.setContentType("text/xml");
1169
				out.println("<error>Couldn't pass the trust test " + test + " </error>");
1170
				out.close();
1171
				return;
1172
			}
1173

    
1174
			String docid = params.get("docid")[0];
1175
			logMetacat.debug("MetacatReplication.handleGetDocumentRequest for docid: " + docid);
1176
			DocumentImpl di = new DocumentImpl(docid);
1177

    
1178
			String documentDir = PropertyService.getProperty("application.documentfilepath");
1179
			documentPath = documentDir + FileUtil.getFS() + docid;
1180

    
1181
			// if the document does not exist on disk, read it from db and write
1182
			// it to disk.
1183
			if (FileUtil.getFileStatus(documentPath) == FileUtil.DOES_NOT_EXIST
1184
					|| FileUtil.getFileSize(documentPath) == 0) {
1185
				FileWriter fileWriter = new FileWriter(documentPath);
1186
				di.toXml(fileWriter, null, null, true);
1187
			}
1188

    
1189
			// read the file from disk and sent it to PrintWriter
1190
			// PrintWriter out = new PrintWriter(streamOut);
1191
			di.readFromFileSystem(out, null, null, documentPath);
1192

    
1193
			// response.setContentType("text/xml");
1194
			// out.print(di.toString(null, null, true));
1195

    
1196
			MetacatReplication.replLog("document " + docid + " sent");
1197

    
1198
		} catch (MalformedURLException mue) {
1199
			logMetacat.error("Url error when getting document from MetacatReplication."
1200
					+ "handlGetDocumentRequest for url: " + urlString + " : "
1201
					+ mue.getMessage());
1202
			// e.printStackTrace(System.out);
1203
			response.setContentType("text/xml");
1204
			out.println("<error>" + mue.getMessage() + "</error>");
1205
		} catch (IOException ioe) {
1206
			logMetacat.error("I/O error when getting document from MetacatReplication."
1207
					+ "handlGetDocumentRequest for file: " + documentPath + " : " + ioe.getMessage());
1208
			// e.printStackTrace(System.out);
1209
			response.setContentType("text/xml");
1210
			out.println("<error>" + ioe.getMessage() + "</error>");
1211
		} catch (PropertyNotFoundException pnfe) {
1212
			logMetacat.error("Error getting property when getting document from MetacatReplication."
1213
					+ "handlGetDocumentRequest for file: " + documentPath + " : " + pnfe.getMessage());
1214
			// e.printStackTrace(System.out);
1215
			response.setContentType("text/xml");
1216
			out.println("<error>" + pnfe.getMessage() + "</error>");
1217
		} catch (McdbException me) {
1218
			logMetacat.error("Document implementation error  getting property when getting document from MetacatReplication."
1219
					+ "handlGetDocumentRequest for file: " + documentPath + " : " + me.getMessage());
1220
			// e.printStackTrace(System.out);
1221
			response.setContentType("text/xml");
1222
			out.println("<error>" + me.getMessage() + "</error>");
1223
		}
1224

    
1225
	}
1226

    
1227
  /**
1228
	 * Sends a list of all of the documents on this sever along with their
1229
	 * revision numbers. The format is: <!ELEMENT replication (server, updates)>
1230
	 * <!ELEMENT server (#PCDATA)> <!ELEMENT updates ((updatedDocument |
1231
	 * deleteDocument | revisionDocument)*)> <!ELEMENT updatedDocument (docid,
1232
	 * rev, datafile*)> <!ELEMENT deletedDocument (docid, rev)> <!ELEMENT
1233
	 * revisionDocument (docid, rev, datafile*)> <!ELEMENT docid (#PCDATA)>
1234
	 * <!ELEMENT rev (#PCDATA)> <!ELEMENT datafile (#PCDATA)> note that the rev
1235
	 * in deletedDocument is always empty. I just left it in there to make the
1236
	 * parser implementation easier.
1237
	 */
1238
  private void handleUpdateRequest(PrintWriter out, Hashtable<String, String[]> params,
1239
                                    HttpServletResponse response)
1240
  {
1241
    // Checked out DBConnection
1242
    DBConnection dbConn = null;
1243
    // DBConenction serial number when checked it out
1244
    int serialNumber = -1;
1245
    PreparedStatement pstmt = null;
1246
    // Server list to store server info of xml_replication table
1247
    ReplicationServerList serverList = null;
1248

    
1249
    try
1250
    {
1251
      // Check out a DBConnection from pool
1252
      dbConn=DBConnectionPool.
1253
                  getDBConnection("MetacatReplication.handleUpdateRequest");
1254
      serialNumber=dbConn.getCheckOutSerialNumber();
1255
      // Create a server list from xml_replication table
1256
      serverList = new ReplicationServerList();
1257

    
1258
      // Get remote server name from param
1259
      String server = ((String[])params.get("server"))[0];
1260
      // If no servr name in param, return a error
1261
      if ( server == null || server.equals(""))
1262
      {
1263
        response.setContentType("text/xml");
1264
        out.println("<error>Request didn't specify server name</error>");
1265
        out.close();
1266
        return;
1267
      }//if
1268

    
1269
      //try to open a https stream to test if the request server's public key
1270
      //in the key store, this is security issue
1271
      URL u = new URL("https://" + server + "?server="
1272
                +MetacatUtil.getLocalReplicationServerName()
1273
                +"&action=test");
1274
      String test = MetacatReplication.getURLContent(u);
1275
      //couldn't pass the test
1276
      if (test.indexOf("successfully")==-1)
1277
      {
1278
        response.setContentType("text/xml");
1279
        out.println("<error>Couldn't pass the trust test</error>");
1280
        out.close();
1281
        return;
1282
      }
1283

    
1284

    
1285
      // Check if local host configure to replicate xml documents to remote
1286
      // server. If not send back a error message
1287
      if (!serverList.getReplicationValue(server))
1288
      {
1289
        response.setContentType("text/xml");
1290
        out.println
1291
        ("<error>Configuration not allow to replicate document to you</error>");
1292
        out.close();
1293
        return;
1294
      }//if
1295

    
1296
      // Store the sql command
1297
      StringBuffer docsql = new StringBuffer();
1298
      StringBuffer revisionSql = new StringBuffer();
1299
      // Stroe the docid list
1300
      StringBuffer doclist = new StringBuffer();
1301
      // Store the deleted docid list
1302
      StringBuffer delsql = new StringBuffer();
1303
      // Store the data set file
1304
      Vector<Vector<String>> packageFiles = new Vector<Vector<String>>();
1305

    
1306
      // Append local server's name and replication servlet to doclist
1307
      doclist.append("<?xml version=\"1.0\"?><replication>");
1308
      doclist.append("<server>").append(MetacatUtil.getLocalReplicationServerName());
1309
      //doclist.append(util.getProperty("replicationpath"));
1310
      doclist.append("</server><updates>");
1311

    
1312
      // Get correct docid that reside on this server according the requesting
1313
      // server's replicate and data replicate value in xml_replication table
1314
      docsql.append(DatabaseService.getDBAdapter().getReplicationDocumentListSQL());
1315
      //docsql.append("select docid, rev, doctype from xml_documents where (docid not in (select a.docid from xml_documents a, xml_revisions b where a.docid=b.docid and a.rev<=b.rev)) ");
1316
      revisionSql.append("select docid, rev, doctype from xml_revisions ");
1317
      // If the localhost is not a hub to the remote server, only replicate
1318
      // the docid' which home server is local host (server_location =1)
1319
      if (!serverList.getHubValue(server))
1320
      {
1321
    	String serverLocationDoc = " and a.server_location = 1";
1322
        String serverLocationRev = "where server_location = 1";
1323
        docsql.append(serverLocationDoc);
1324
        revisionSql.append(serverLocationRev);
1325
      }
1326
      logMetacat.info("Doc sql: "+docsql.toString());
1327

    
1328
      // Get any deleted documents
1329
      delsql.append("select distinct docid from ");
1330
      delsql.append("xml_revisions where docid not in (select docid from ");
1331
      delsql.append("xml_documents) ");
1332
      // If the localhost is not a hub to the remote server, only replicate
1333
      // the docid' which home server is local host (server_location =1)
1334
      if (!serverList.getHubValue(server))
1335
      {
1336
        delsql.append("and server_location = 1");
1337
      }
1338
      logMetacat.info("Deleted sql: "+delsql.toString());
1339

    
1340

    
1341

    
1342
      // Get docid list of local host
1343
      pstmt = dbConn.prepareStatement(docsql.toString());
1344
      pstmt.execute();
1345
      ResultSet rs = pstmt.getResultSet();
1346
      boolean tablehasrows = rs.next();
1347
      //If metacat configed to replicate data file
1348
      //if ((util.getProperty("replicationsenddata")).equals("on"))
1349
      boolean replicateData = serverList.getDataReplicationValue(server);
1350
      if (replicateData)
1351
      {
1352
        while(tablehasrows)
1353
        {
1354
          String recordDoctype = rs.getString(3);
1355
          Vector<String> packagedoctypes = MetacatUtil.getOptionList(
1356
                                     PropertyService.getProperty("xml.packagedoctype"));
1357
          //if this is a package file, put it at the end
1358
          //because if a package file is read before all of the files it
1359
          //refers to are loaded then there is an error
1360
          if(recordDoctype != null && !packagedoctypes.contains(recordDoctype))
1361
          {
1362
              //If this is not data file
1363
              if (!recordDoctype.equals("BIN"))
1364
              {
1365
                //for non-data file document
1366
                doclist.append("<updatedDocument>");
1367
                doclist.append("<docid>").append(rs.getString(1));
1368
                doclist.append("</docid><rev>").append(rs.getInt(2));
1369
                doclist.append("</rev>");
1370
                doclist.append("</updatedDocument>");
1371
              }//if
1372
              else
1373
              {
1374
                //for data file document, in datafile attributes
1375
                //we put "datafile" value there
1376
                doclist.append("<updatedDocument>");
1377
                doclist.append("<docid>").append(rs.getString(1));
1378
                doclist.append("</docid><rev>").append(rs.getInt(2));
1379
                doclist.append("</rev>");
1380
                doclist.append("<datafile>");
1381
                doclist.append(PropertyService.getProperty("replication.datafileflag"));
1382
                doclist.append("</datafile>");
1383
                doclist.append("</updatedDocument>");
1384
              }//else
1385
          }//if packagedoctpes
1386
          else
1387
          { //the package files are saved to be put into the xml later.
1388
              Vector<String> v = new Vector<String>();
1389
              v.add(rs.getString(1));
1390
              v.add(String.valueOf(rs.getInt(2)));
1391
              packageFiles.add(v);
1392
          }//esle
1393
          tablehasrows = rs.next();
1394
        }//while
1395
      }//if
1396
      else //metacat was configured not to send data file
1397
      {
1398
        while(tablehasrows)
1399
        {
1400
          String recordDoctype = rs.getString(3);
1401
          if(!recordDoctype.equals("BIN"))
1402
          { //don't replicate data files
1403
            Vector<String> packagedoctypes = MetacatUtil.getOptionList(
1404
                                     PropertyService.getProperty("xml.packagedoctype"));
1405
            if(recordDoctype != null && !packagedoctypes.contains(recordDoctype))
1406
            {   //if this is a package file, put it at the end
1407
              //because if a package file is read before all of the files it
1408
              //refers to are loaded then there is an error
1409
              doclist.append("<updatedDocument>");
1410
              doclist.append("<docid>").append(rs.getString(1));
1411
              doclist.append("</docid><rev>").append(rs.getInt(2));
1412
              doclist.append("</rev>");
1413
              doclist.append("</updatedDocument>");
1414
            }
1415
            else
1416
            { //the package files are saved to be put into the xml later.
1417
              Vector<String> v = new Vector<String>();
1418
              v.add(rs.getString(1));
1419
              v.add(String.valueOf(rs.getInt(2)));
1420
              packageFiles.add(v);
1421
            }
1422
         }//if
1423
         tablehasrows = rs.next();
1424
        }//while
1425
      }//else
1426

    
1427
      pstmt = dbConn.prepareStatement(delsql.toString());
1428
      //usage count should increas 1
1429
      dbConn.increaseUsageCount(1);
1430

    
1431
      pstmt.execute();
1432
      rs = pstmt.getResultSet();
1433
      tablehasrows = rs.next();
1434
      while(tablehasrows)
1435
      { //handle the deleted documents
1436
        doclist.append("<deletedDocument><docid>").append(rs.getString(1));
1437
        doclist.append("</docid><rev></rev></deletedDocument>");
1438
        //note that rev is always empty for deleted docs
1439
        tablehasrows = rs.next();
1440
      }
1441

    
1442
      //now we can put the package files into the xml results
1443
      for(int i=0; i<packageFiles.size(); i++)
1444
      {
1445
        Vector<String> v = packageFiles.elementAt(i);
1446
        doclist.append("<updatedDocument>");
1447
        doclist.append("<docid>").append(v.elementAt(0));
1448
        doclist.append("</docid><rev>");
1449
        doclist.append(v.elementAt(1));
1450
        doclist.append("</rev>");
1451
        doclist.append("</updatedDocument>");
1452
      }
1453
      // add revision doc list  
1454
      doclist.append(prepareRevisionDoc(dbConn,revisionSql.toString(),replicateData));
1455
        
1456
      doclist.append("</updates></replication>");
1457
      logMetacat.info("doclist: " + doclist.toString());
1458
      pstmt.close();
1459
      //conn.close();
1460
      response.setContentType("text/xml");
1461
      out.println(doclist.toString());
1462

    
1463
    }
1464
    catch(Exception e)
1465
    {
1466
      logMetacat.error("error in MetacatReplication." +
1467
                         "handleupdaterequest: " + e.getMessage());
1468
      //e.printStackTrace(System.out);
1469
      response.setContentType("text/xml");
1470
      out.println("<error>"+e.getMessage()+"</error>");
1471
    }
1472
    finally
1473
    {
1474
      try
1475
      {
1476
        pstmt.close();
1477
      }//try
1478
      catch (SQLException ee)
1479
      {
1480
        logMetacat.error("Error in MetacatReplication." +
1481
                "handleUpdaterequest to close pstmt: "+ee.getMessage());
1482
      }//catch
1483
      finally
1484
      {
1485
        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1486
      }//finally
1487
    }//finally
1488

    
1489
  }//handlUpdateRequest
1490
  
1491
  /*
1492
   * This method will get the xml string for document in xml_revision
1493
   * The schema look like <!ELEMENT revisionDocument (docid, rev, datafile*)>
1494
   */
1495
  private String prepareRevisionDoc(DBConnection dbConn, String revSql, 
1496
                            boolean replicateData) throws Exception
1497
  {
1498
      logMetacat.warn("The revision document sql is "+ revSql);
1499
      StringBuffer revDocList = new StringBuffer();
1500
      PreparedStatement pstmt = dbConn.prepareStatement(revSql);
1501
      //usage count should increas 1
1502
      dbConn.increaseUsageCount(1);
1503

    
1504
      pstmt.execute();
1505
      ResultSet rs = pstmt.getResultSet();
1506
      boolean tablehasrows = rs.next();
1507
      while(tablehasrows)
1508
      {
1509
        String recordDoctype = rs.getString(3);
1510
        
1511
        //If this is data file and it isn't configured to replicate data
1512
        if (recordDoctype.equals("BIN") && !replicateData)
1513
        {  
1514
            // do nothing
1515
            continue;
1516
        }
1517
        else
1518
        {  
1519
            
1520
            revDocList.append("<revisionDocument>");
1521
            revDocList.append("<docid>").append(rs.getString(1));
1522
            revDocList.append("</docid><rev>").append(rs.getInt(2));
1523
            revDocList.append("</rev>");
1524
            // data file
1525
            if (recordDoctype.equals("BIN"))
1526
            {
1527
                revDocList.append("<datafile>");
1528
                revDocList.append(PropertyService.getProperty("replication.datafileflag"));
1529
                revDocList.append("</datafile>");
1530
            }
1531
            revDocList.append("</revisionDocument>");
1532
        
1533
         }//else
1534
         tablehasrows = rs.next();
1535
      }
1536
      //System.out.println("The revision list is"+ revDocList.toString());
1537
      return revDocList.toString();
1538
  }
1539

    
1540
  /**
1541
   * Returns the xml_catalog table encoded in xml
1542
   */
1543
  public static String getCatalogXML()
1544
  {
1545
    return handleGetCatalogRequest(null, null, null, false);
1546
  }
1547

    
1548
  /**
1549
   * Sends the contents of the xml_catalog table encoded in xml
1550
   * The xml format is:
1551
   * <!ELEMENT xml_catalog (row*)>
1552
   * <!ELEMENT row (entry_type, source_doctype, target_doctype, public_id,
1553
   *                system_id)>
1554
   * All of the sub elements of row are #PCDATA
1555

    
1556
   * If printFlag == false then do not print to out.
1557
   */
1558
  private static String handleGetCatalogRequest(PrintWriter out,
1559
                                                Hashtable<String, String[]> params,
1560
                                                HttpServletResponse response,
1561
                                                boolean printFlag)
1562
  {
1563
    DBConnection dbConn = null;
1564
    int serialNumber = -1;
1565
    PreparedStatement pstmt = null;
1566
    try
1567
    {
1568
      /*conn = MetacatReplication.getDBConnection("MetacatReplication." +
1569
                                                "handleGetCatalogRequest");*/
1570
      dbConn=DBConnectionPool.
1571
                 getDBConnection("MetacatReplication.handleGetCatalogRequest");
1572
      serialNumber=dbConn.getCheckOutSerialNumber();
1573
      pstmt = dbConn.prepareStatement("select entry_type, " +
1574
                              "source_doctype, target_doctype, public_id, " +
1575
                              "system_id from xml_catalog");
1576
      pstmt.execute();
1577
      ResultSet rs = pstmt.getResultSet();
1578
      boolean tablehasrows = rs.next();
1579
      StringBuffer sb = new StringBuffer();
1580
      sb.append("<?xml version=\"1.0\"?><xml_catalog>");
1581
      while(tablehasrows)
1582
      {
1583
        sb.append("<row><entry_type>").append(rs.getString(1));
1584
        sb.append("</entry_type><source_doctype>").append(rs.getString(2));
1585
        sb.append("</source_doctype><target_doctype>").append(rs.getString(3));
1586
        sb.append("</target_doctype><public_id>").append(rs.getString(4));
1587
        // system id may not have server url on front.  Add it if not.
1588
        String systemID = rs.getString(5);
1589
        if (!systemID.startsWith("http://")) {
1590
        	systemID = SystemUtil.getContextURL() + systemID;
1591
        }
1592
        sb.append("</public_id><system_id>").append(systemID);
1593
        sb.append("</system_id></row>");
1594

    
1595
        tablehasrows = rs.next();
1596
      }
1597
      sb.append("</xml_catalog>");
1598
      //conn.close();
1599
      if(printFlag)
1600
      {
1601
        response.setContentType("text/xml");
1602
        out.println(sb.toString());
1603
      }
1604
      pstmt.close();
1605
      return sb.toString();
1606
    }
1607
    catch(Exception e)
1608
    {
1609

    
1610
      logMetacat.error("error in MetacatReplication.handleGetCatalogRequest:"+
1611
                          e.getMessage());
1612
      e.printStackTrace(System.out);
1613
      if(printFlag)
1614
      {
1615
        out.println("<error>"+e.getMessage()+"</error>");
1616
      }
1617
    }
1618
    finally
1619
    {
1620
      try
1621
      {
1622
        pstmt.close();
1623
      }//try
1624
      catch (SQLException ee)
1625
      {
1626
        logMetacat.error("Error in MetacatReplication.handleGetCatalogRequest: "
1627
           +ee.getMessage());
1628
      }//catch
1629
      finally
1630
      {
1631
        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1632
      }//finally
1633
    }//finally
1634

    
1635
    return null;
1636
  }
1637

    
1638
  /**
1639
   * Sends the current system date to the remote server.  Using this action
1640
   * for replication gets rid of any problems with syncronizing clocks
1641
   * because a time specific to a document is always kept on its home server.
1642
   */
1643
  private void handleGetTimeRequest(PrintWriter out, Hashtable<String, String[]> params,
1644
                                    HttpServletResponse response)
1645
  {
1646
    SimpleDateFormat formatter = new SimpleDateFormat ("MM/dd/yy HH:mm:ss");
1647
    java.util.Date localtime = new java.util.Date();
1648
    String dateString = formatter.format(localtime);
1649
    response.setContentType("text/xml");
1650

    
1651
    out.println("<timestamp>" + dateString + "</timestamp>");
1652
  }
1653

    
1654
  /**
1655
   * this method handles the timeout for a file lock.  when a lock is
1656
   * granted it is granted for 30 seconds.  When this thread runs out
1657
   * it deletes the docid from the queue, thus eliminating the lock.
1658
   */
1659
  public void run()
1660
  {
1661
    try
1662
    {
1663
      logMetacat.info("thread started for docid: " +
1664
                               (String)fileLocks.elementAt(0));
1665

    
1666
      Thread.sleep(30000); //the lock will expire in 30 seconds
1667
      logMetacat.info("thread for docid: " +
1668
                             (String)fileLocks.elementAt(fileLocks.size() - 1) +
1669
                              " exiting.");
1670

    
1671
      fileLocks.remove(fileLocks.size() - 1);
1672
      //fileLocks is treated as a FIFO queue.  If there are more than one lock
1673
      //in the vector, the first one inserted will be removed.
1674
    }
1675
    catch(Exception e)
1676
    {
1677
      logMetacat.error("error in file lock thread from " +
1678
                                "MetacatReplication.run: " + e.getMessage());
1679
    }
1680
  }
1681

    
1682
  /**
1683
   * Returns the name of a server given a serverCode
1684
   * @param serverCode the serverid of the server
1685
   * @return the servername or null if the specified serverCode does not
1686
   *         exist.
1687
   */
1688
  public static String getServerNameForServerCode(int serverCode)
1689
  {
1690
    //System.out.println("serverid: " + serverCode);
1691
    DBConnection dbConn = null;
1692
    int serialNumber = -1;
1693
    PreparedStatement pstmt = null;
1694
    try
1695
    {
1696
      dbConn=DBConnectionPool.
1697
                  getDBConnection("MetacatReplication.getServer");
1698
      serialNumber=dbConn.getCheckOutSerialNumber();
1699
      String sql = new String("select server from " +
1700
                              "xml_replication where serverid = " +
1701
                              serverCode);
1702
      pstmt = dbConn.prepareStatement(sql);
1703
      //System.out.println("getserver sql: " + sql);
1704
      pstmt.execute();
1705
      ResultSet rs = pstmt.getResultSet();
1706
      boolean tablehasrows = rs.next();
1707
      if(tablehasrows)
1708
      {
1709
        //System.out.println("server: " + rs.getString(1));
1710
        return rs.getString(1);
1711
      }
1712

    
1713
      //conn.close();
1714
    }
1715
    catch(Exception e)
1716
    {
1717
      logMetacat.error("Error in MetacatReplication.getServer: " +
1718
                          e.getMessage());
1719
    }
1720
    finally
1721
    {
1722
      try
1723
      {
1724
        pstmt.close();
1725
      }//try
1726
      catch (SQLException ee)
1727
      {
1728
        logMetacat.error("Error in MetacactReplication.getserver: "+
1729
                                    ee.getMessage());
1730
      }//catch
1731
      finally
1732
      {
1733
        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1734
      }//fianlly
1735
    }//finally
1736

    
1737

    
1738

    
1739
    return null;
1740
      //return null if the server does not exist
1741
  }
1742

    
1743
  /**
1744
   * Returns a server code given a server name
1745
   * @param server the name of the server
1746
   * @return integer > 0 representing the code of the server, 0 if the server
1747
   *  does not exist.
1748
   */
1749
  public static int getServerCodeForServerName(String server) throws Exception
1750
  {
1751
    DBConnection dbConn = null;
1752
    int serialNumber = -1;
1753
    PreparedStatement pstmt = null;
1754
    int serverCode = 0;
1755

    
1756
    try {
1757

    
1758
      //conn = util.openDBConnection();
1759
      dbConn=DBConnectionPool.
1760
                  getDBConnection("MetacatReplication.getServerCode");
1761
      serialNumber=dbConn.getCheckOutSerialNumber();
1762
      pstmt = dbConn.prepareStatement("SELECT serverid FROM xml_replication " +
1763
                                    "WHERE server LIKE '" + server + "'");
1764
      pstmt.execute();
1765
      ResultSet rs = pstmt.getResultSet();
1766
      boolean tablehasrows = rs.next();
1767
      if ( tablehasrows ) {
1768
        serverCode = rs.getInt(1);
1769
        pstmt.close();
1770
        //conn.close();
1771
        return serverCode;
1772
      }
1773

    
1774
    } catch(Exception e) {
1775
      throw e;
1776

    
1777
    } finally {
1778
      try
1779
      {
1780
        pstmt.close();
1781
        //conn.close();
1782
       }//try
1783
       catch(Exception ee)
1784
       {
1785
         logMetacat.error("Error in MetacatReplicatio.getServerCode: "
1786
                                  +ee.getMessage());
1787

    
1788
       }//catch
1789
       finally
1790
       {
1791
         DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1792
       }//finally
1793
    }//finally
1794

    
1795
    return serverCode;
1796
  }
1797

    
1798
  /**
1799
   * Method to get a host server information for given docid
1800
   * @param conn a connection to the database
1801
   */
1802
  public static Hashtable<String,String> getHomeServerInfoForDocId(String docId)
1803
  {
1804
    Hashtable<String,String> sl = new Hashtable<String,String>();
1805
    DBConnection dbConn = null;
1806
    int serialNumber = -1;
1807
    docId=MetacatUtil.getDocIdFromString(docId);
1808
    PreparedStatement pstmt=null;
1809
    int serverLocation;
1810
    try
1811
    {
1812
      //get conection
1813
      dbConn=DBConnectionPool.
1814
                  getDBConnection("ReplicationHandler.getHomeServer");
1815
      serialNumber=dbConn.getCheckOutSerialNumber();
1816
      //get a server location from xml_document table
1817
      pstmt=dbConn.prepareStatement("select server_location from xml_documents "
1818
                                            +"where docid = ?");
1819
      pstmt.setString(1, docId);
1820
      pstmt.execute();
1821
      ResultSet serverName = pstmt.getResultSet();
1822
      //get a server location
1823
      if(serverName.next())
1824
      {
1825
        serverLocation=serverName.getInt(1);
1826
        pstmt.close();
1827
      }
1828
      else
1829
      {
1830
        pstmt.close();
1831
        //ut.returnConnection(conn);
1832
        return null;
1833
      }
1834
      pstmt=dbConn.prepareStatement("select server, last_checked, replicate " +
1835
                        "from xml_replication where serverid = ?");
1836
      //increase usage count
1837
      dbConn.increaseUsageCount(1);
1838
      pstmt.setInt(1, serverLocation);
1839
      pstmt.execute();
1840
      ResultSet rs = pstmt.getResultSet();
1841
      boolean tableHasRows = rs.next();
1842
      if (tableHasRows)
1843
      {
1844

    
1845
          String server = rs.getString(1);
1846
          String last_checked = rs.getString(2);
1847
          if(!server.equals("localhost"))
1848
          {
1849
            sl.put(server, last_checked);
1850
          }
1851

    
1852
      }
1853
      else
1854
      {
1855
        pstmt.close();
1856
        //ut.returnConnection(conn);
1857
        return null;
1858
      }
1859
      pstmt.close();
1860
    }
1861
    catch(Exception e)
1862
    {
1863
      logMetacat.error("error in replicationHandler.getHomeServer(): " +
1864
                         e.getMessage());
1865
    }
1866
    finally
1867
    {
1868
      try
1869
      {
1870
        pstmt.close();
1871
        //ut.returnConnection(conn);
1872
      }
1873
      catch (Exception ee)
1874
      {
1875
        logMetacat.error("Eror irn rplicationHandler.getHomeServer() "+
1876
                          "to close pstmt: "+ee.getMessage());
1877
      }
1878
      finally
1879
      {
1880
        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1881
      }
1882

    
1883
    }//finally
1884
    return sl;
1885
  }
1886

    
1887
  /**
1888
   * Returns a home server location  given a accnum
1889
   * @param accNum , given accNum for a document
1890
   *
1891
   */
1892
  public static int getHomeServerCodeForDocId(String accNum) throws Exception
1893
  {
1894
    DBConnection dbConn = null;
1895
    int serialNumber = -1;
1896
    PreparedStatement pstmt = null;
1897
    int serverCode = 1;
1898
    String docId=MetacatUtil.getDocIdFromString(accNum);
1899

    
1900
    try
1901
    {
1902

    
1903
      // Get DBConnection
1904
      dbConn=DBConnectionPool.
1905
                  getDBConnection("ReplicationHandler.getServerLocation");
1906
      serialNumber=dbConn.getCheckOutSerialNumber();
1907
      pstmt=dbConn.prepareStatement("SELECT server_location FROM xml_documents "
1908
                              + "WHERE docid LIKE '" + docId + "'");
1909
      pstmt.execute();
1910
      ResultSet rs = pstmt.getResultSet();
1911
      boolean tablehasrows = rs.next();
1912
      //If a document is find, return the server location for it
1913
      if ( tablehasrows )
1914
      {
1915
        serverCode = rs.getInt(1);
1916
        pstmt.close();
1917
        //conn.close();
1918
        return serverCode;
1919
      }
1920
      //if couldn't find in xml_documents table, we think server code is 1
1921
      //(this is new document)
1922
      else
1923
      {
1924
        pstmt.close();
1925
        //conn.close();
1926
        return serverCode;
1927
      }
1928

    
1929
    }
1930
    catch(Exception e)
1931
    {
1932

    
1933
      throw e;
1934

    
1935
    }
1936
    finally
1937
    {
1938
      try
1939
      {
1940
        pstmt.close();
1941
        //conn.close();
1942

    
1943
      }
1944
      catch(Exception ee)
1945
      {
1946
        logMetacat.error("Erorr in Replication.getServerLocation "+
1947
                     "to close pstmt"+ee.getMessage());
1948
      }
1949
      finally
1950
      {
1951
        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1952
      }//finally
1953
    }//finally
1954
   //return serverCode;
1955
  }
1956

    
1957

    
1958

    
1959
  /**
1960
   * This method returns the content of a url
1961
   * @param u the url to return the content from
1962
   * @return a string representing the content of the url
1963
   * @throws java.io.IOException
1964
   */
1965
  public static String getURLContent(URL u) throws java.io.IOException
1966
  {
1967
    char istreamChar;
1968
    int istreamInt;
1969
    logMetacat.info("Before open the stream"+u.toString());
1970
    InputStream input = u.openStream();
1971
    logMetacat.info("Afetr open the stream"+u.toString());
1972
    InputStreamReader istream = new InputStreamReader(input);
1973
    StringBuffer serverResponse = new StringBuffer();
1974
    while((istreamInt = istream.read()) != -1)
1975
    {
1976
      istreamChar = (char)istreamInt;
1977
      serverResponse.append(istreamChar);
1978
    }
1979
    istream.close();
1980
    input.close();
1981

    
1982
    return serverResponse.toString();
1983
  }
1984

    
1985
  /**
1986
	 * Method for writing replication messages to a log file specified in
1987
	 * metacat.properties
1988
	 */
1989
	public static void replLog(String message) {
1990
		try {
1991
			FileOutputStream fos = 
1992
				new FileOutputStream(PropertyService.getProperty("replication.logdir")
1993
					+ "/metacatreplication.log", true);
1994
			PrintWriter pw = new PrintWriter(fos);
1995
			SimpleDateFormat formatter = new SimpleDateFormat("yy-MM-dd HH:mm:ss");
1996
			java.util.Date localtime = new java.util.Date();
1997
			String dateString = formatter.format(localtime);
1998
			dateString += " :: " + message;
1999
			// time stamp each entry
2000
			pw.println(dateString);
2001
			pw.flush();
2002
		} catch (Exception e) {
2003
			logMetacat.error("error writing to replication log from "
2004
					+ "MetacatReplication.replLog: " + e.getMessage());
2005
			// e.printStackTrace(System.out);
2006
		}
2007
	}
2008

    
2009
  /**
2010
	 * Method for writing replication messages to a log file specified in
2011
	 * metacat.properties
2012
	 */
2013
  public static void replErrorLog(String message)
2014
  {
2015
    try
2016
    {
2017
    	FileOutputStream fos = 
2018
			new FileOutputStream(PropertyService.getProperty("replication.logdir")
2019
				+ "/metacatreplicationerror.log", true);
2020
      PrintWriter pw = new PrintWriter(fos);
2021
      SimpleDateFormat formatter = new SimpleDateFormat ("yy-MM-dd HH:mm:ss");
2022
      java.util.Date localtime = new java.util.Date();
2023
      String dateString = formatter.format(localtime);
2024
      dateString += " :: " + message;
2025
      //time stamp each entry
2026
      pw.println(dateString);
2027
      pw.flush();
2028
    }
2029
    catch(Exception e)
2030
    {
2031
      logMetacat.error("error writing to replication error log from " +
2032
                         "MetacatReplication.replErrorLog: " + e.getMessage());
2033
      //e.printStackTrace(System.out);
2034
    }
2035
  }
2036

    
2037
  /**
2038
   * Returns true if the replicate field for server in xml_replication is 1.
2039
   * Returns false otherwise
2040
   */
2041
  public static boolean replToServer(String server)
2042
  {
2043
    DBConnection dbConn = null;
2044
    int serialNumber = -1;
2045
    PreparedStatement pstmt = null;
2046
    try
2047
    {
2048
      dbConn=DBConnectionPool.
2049
                  getDBConnection("MetacatReplication.repltoServer");
2050
      serialNumber=dbConn.getCheckOutSerialNumber();
2051
      pstmt = dbConn.prepareStatement("select replicate from " +
2052
                                    "xml_replication where server like '" +
2053
                                     server + "'");
2054
      pstmt.execute();
2055
      ResultSet rs = pstmt.getResultSet();
2056
      boolean tablehasrows = rs.next();
2057
      if(tablehasrows)
2058
      {
2059
        int i = rs.getInt(1);
2060
        if(i == 1)
2061
        {
2062
          pstmt.close();
2063
          //conn.close();
2064
          return true;
2065
        }
2066
        else
2067
        {
2068
          pstmt.close();
2069
          //conn.close();
2070
          return false;
2071
        }
2072
      }
2073
    }
2074
    catch(Exception e)
2075
    {
2076
      logMetacat.error("error in MetacatReplication.replToServer: " +
2077
                         e.getMessage());
2078
    }
2079
    finally
2080
    {
2081
      try
2082
      {
2083
        pstmt.close();
2084
        //conn.close();
2085
      }//try
2086
      catch(Exception ee)
2087
      {
2088
        logMetacat.error("Error in MetacatReplication.replToServer: "
2089
                                  +ee.getMessage());
2090
      }//catch
2091
      finally
2092
      {
2093
        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
2094
      }//finally
2095
    }//finally
2096
    return false;
2097
    //the default if this server does not exist is to not replicate to it.
2098
  }
2099

    
2100

    
2101
}
(51-51/72)