Project

General

Profile

1 522 berkley
/**
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$'
9
 *     '$Date$'
10
 * '$Revision$'
11 669 jones
 *
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 522 berkley
 */
26
27
package edu.ucsb.nceas.metacat;
28
29
import java.util.*;
30 2572 tao
import java.util.Date;
31 522 berkley
import java.io.*;
32
import java.sql.*;
33
import java.net.*;
34
import java.text.*;
35 4080 daigle
36 522 berkley
import javax.servlet.*;
37
import javax.servlet.http.*;
38 574 berkley
39 4335 daigle
import edu.ucsb.nceas.metacat.service.DatabaseService;
40 4080 daigle
import edu.ucsb.nceas.metacat.service.PropertyService;
41
import edu.ucsb.nceas.metacat.service.SessionService;
42 4589 daigle
import edu.ucsb.nceas.metacat.util.AuthUtil;
43 4698 daigle
import edu.ucsb.nceas.metacat.util.MetacatUtil;
44 4080 daigle
import edu.ucsb.nceas.metacat.util.SessionData;
45
import edu.ucsb.nceas.metacat.util.SystemUtil;
46 4488 daigle
import edu.ucsb.nceas.utilities.FileUtil;
47 4087 daigle
import edu.ucsb.nceas.utilities.GeneralPropertyException;
48 4080 daigle
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
49
50 2663 sgarg
import org.apache.log4j.Logger;
51 522 berkley
import org.xml.sax.*;
52
53 561 berkley
public class MetacatReplication extends HttpServlet implements Runnable
54 2286 tao
{
55 4335 daigle
56
  private static final long serialVersionUID = -2898600143193513155L;
57 2572 tao
  private long timeInterval;
58
  private Date firstTime;
59
  private boolean timedReplicationIsOn = false;
60 522 berkley
  Timer replicationDaemon;
61 4488 daigle
  private Vector<String> fileLocks = new Vector<String>();
62 561 berkley
  private Thread lockThread = null;
63 2298 tao
  public static final String FORCEREPLICATEDELETE = "forcereplicatedelete";
64 4178 daigle
  private static final String TIMEREPLICATION = "replication.timedreplication";
65
  private static final String TIMEREPLICATIONINTERVAl = "replication.timedreplicationinterval";
66
  private static final String FIRSTTIME  = "replication.firsttimedreplication";
67 2572 tao
  private static final int    TIMEINTERVALLIMIT = 7200000;
68 2663 sgarg
  private static Logger logMetacat = Logger.getLogger(MetacatReplication.class);
69 3233 tao
  public static final String REPLICATIONUSER = "replication";
70 2663 sgarg
71 522 berkley
  /**
72
   * Initialize the servlet by creating appropriate database connections
73
   */
74 2286 tao
  public void init(ServletConfig config) throws ServletException
75 522 berkley
  {
76 1599 tao
     //initialize db connections to handle any update requests
77 4173 daigle
    //deltaT = util.getProperty("replication.deltaT");
78 583 berkley
    //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 522 berkley
    replicationDaemon = new Timer(true);
81 2572 tao
    try
82
    {
83 4080 daigle
       timedReplicationIsOn = (new Boolean(PropertyService.getProperty(TIMEREPLICATION ).trim())).booleanValue();
84 2663 sgarg
       logMetacat.info("The timed replication on is"+timedReplicationIsOn);
85 4080 daigle
       timeInterval = (new Long(PropertyService.getProperty(TIMEREPLICATIONINTERVAl).trim())).longValue();
86 2663 sgarg
       logMetacat.warn("The timed replication time Inerval is "+ timeInterval);
87 4080 daigle
       String firstTimeStr = PropertyService.getProperty(FIRSTTIME);
88 2663 sgarg
       logMetacat.warn("first replication time form property is "+firstTimeStr);
89 2572 tao
       firstTime = ReplicationHandler.combinateCurrentDateAndGivenTime(firstTimeStr);
90 2663 sgarg
       logMetacat.warn("After combine current time, the real first time is "
91
                                +firstTime.toString()+" minisec");
92 2572 tao
       // set up time replication if it is on
93
       if (timedReplicationIsOn)
94 1599 tao
       {
95 2572 tao
           replicationDaemon.scheduleAtFixedRate(new ReplicationHandler(), firstTime, timeInterval);
96
           MetacatReplication.replLog("deltaT handler started with rate=" +
97
                   timeInterval + " mini seconds at " +firstTime.toString());
98
       }
99 4808 daigle
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 2572 tao
    }
111
    catch (Exception e)
112
    {
113
        // the timed replication in Metacat.properties file has problem
114
        // so timed replication is setting to false;
115 2663 sgarg
        logMetacat.error("Couldn't set up timed replication "+
116 2572 tao
                     " in Metacat replication servlet init because " +
117 2663 sgarg
                 e.getMessage());
118 2572 tao
        MetacatReplication.replErrorLog("Couldn't set up timed replication "+
119
                " in Metacat replication servlet init because " +
120
                e.getMessage());
121
        timedReplicationIsOn = false;
122
    }
123
124 522 berkley
  }
125 2286 tao
126
  public void destroy()
127 522 berkley
  {
128
    replicationDaemon.cancel();
129 2572 tao
130 522 berkley
  }
131 2286 tao
132 522 berkley
  public void doGet (HttpServletRequest request, HttpServletResponse response)
133 2286 tao
                     throws ServletException, IOException
134 522 berkley
  {
135
    // Process the data and send back the response
136
    handleGetOrPost(request, response);
137
  }
138
139
  public void doPost(HttpServletRequest request, HttpServletResponse response)
140 2286 tao
                     throws ServletException, IOException
141 522 berkley
  {
142
    // Process the data and send back the response
143
    handleGetOrPost(request, response);
144
  }
145 2286 tao
146
  private void handleGetOrPost(HttpServletRequest request,
147
                               HttpServletResponse response)
148
                               throws ServletException, IOException
149 522 berkley
  {
150 1020 tao
    //PrintWriter out = response.getWriter();
151
    //ServletOutputStream outPut = response.getOutputStream();
152 4488 daigle
    Hashtable<String, String[]> params = new Hashtable<String, String[]>();
153
    Enumeration<String> paramlist = request.getParameterNames();
154 2286 tao
155
156
157 837 bojilova
// 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 2286 tao
163 837 bojilova
    while (paramlist.hasMoreElements()) {
164 522 berkley
      String name = (String)paramlist.nextElement();
165
      String[] value = request.getParameterValues(name);
166 2286 tao
      params.put(name, value);
167 522 berkley
    }
168 2286 tao
169 4808 daigle
    String action = "";
170
    if (!params.isEmpty() && params.get("action") != null) {
171
    	action = ((String[])params.get("action"))[0];
172
    }
173 840 bojilova
    String server = null;
174 2286 tao
175 837 bojilova
    try {
176
      // check if the server is included in the list of replicated servers
177 2286 tao
      if ( !action.equals("servercontrol") &&
178 840 bojilova
           !action.equals("stop") &&
179
           !action.equals("start") &&
180
           !action.equals("getall") ) {
181
182
        server = ((String[])params.get("server"))[0];
183 1292 tao
        if ( getServerCodeForServerName(server) == 0 ) {
184 2286 tao
          System.out.println("Action \"" + action +
185 840 bojilova
                             "\" rejected for server: " + server);
186
          return;
187
        } else {
188 2286 tao
          System.out.println("Action \"" + action +
189 840 bojilova
                             "\" accepted for server: " + server);
190
        }
191 727 berkley
      }
192 2586 tao
      else
193
      {
194
          // start, stop, getall and servercontrol need to check
195
          // if user is administor
196
          HttpSession sess = request.getSession(true);
197 4080 daigle
          SessionData sessionData = null;
198 2586 tao
          String sess_id = "";
199
          String username = "";
200
          String[] groupnames = {""};
201 4080 daigle
202 2586 tao
          if (params.containsKey("sessionid"))
203
          {
204
             sess_id = ((String[]) params.get("sessionid"))[0];
205 2663 sgarg
             logMetacat.info("in has sessionid "+ sess_id);
206 4080 daigle
             if (SessionService.isSessionRegistered(sess_id))
207 2586 tao
             {
208 2663 sgarg
                  logMetacat.info("find the id " + sess_id + " in hash table");
209 4080 daigle
                  sessionData = SessionService.getRegisteredSession(sess_id);
210 2586 tao
             }
211
           }
212 4080 daigle
          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 2663 sgarg
           logMetacat.warn("The user name from session is: "+ username);
221 4080 daigle
           groupnames = sessionData.getGroupNames();
222 4589 daigle
           if (!AuthUtil.isAdministrator(username, groupnames))
223 2586 tao
           {
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 2663 sgarg
               logMetacat.warn("The user \"" + username +
231
                       "\" is not authorized for this action: " +action);
232 2586 tao
               replErrorLog("The user \"" + username +
233
                       "\" is not authorized for this action: " +action);
234
               return;
235
           }
236
237
      }// this is final else
238 837 bojilova
    } catch (Exception e) {
239
      System.out.println("Error in MetacatReplication.handleGetOrPost: " +
240
                         e.getMessage() );
241 727 berkley
      return;
242
    }
243 2586 tao
244 2286 tao
    if ( action.equals("readdata") )
245 1020 tao
    {
246 2586 tao
      OutputStream outStream = response.getOutputStream();
247 1020 tao
      //to get the data file.
248 2586 tao
      handleGetDataFileRequest(outStream, params, response);
249
      outStream.close();
250 1020 tao
    }
251 2286 tao
    else if ( action.equals("forcereplicatedatafile") )
252 1023 tao
    {
253
      //read a specific docid from remote host, and store it into local host
254 3233 tao
      handleForceReplicateDataFileRequest(params, request);
255 2286 tao
256 1023 tao
    }
257 1020 tao
    else
258
    {
259
    PrintWriter out = response.getWriter();
260 840 bojilova
    if ( action.equals("stop") ) {
261 837 bojilova
      //stop the replication server
262
      replicationDaemon.cancel();
263
      replicationDaemon = new Timer(true);
264 2572 tao
      timedReplicationIsOn = false;
265 4087 daigle
      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 837 bojilova
      out.println("Replication Handler Stopped");
271
      MetacatReplication.replLog("deltaT handler stopped");
272
273 2286 tao
274 840 bojilova
    } else if ( action.equals("start") ) {
275 2572 tao
       String firstTimeStr = "";
276 837 bojilova
      //start the replication server
277 2572 tao
       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 583 berkley
            //deltaT<30 is a timing mess!
284 2572 tao
            timeInterval = TIMEINTERVALLIMIT;
285 549 berkley
        }
286 837 bojilova
      } else {
287 2572 tao
        timeInterval = TIMEINTERVALLIMIT ;
288 837 bojilova
      }
289 2663 sgarg
      logMetacat.info("New rate is: " + timeInterval + " mini seconds.");
290 2572 tao
      if ( params.containsKey("firsttime"))
291
      {
292
         firstTimeStr = ((String[])params.get("firsttime"))[0];
293
         try
294
         {
295
           firstTime = ReplicationHandler.combinateCurrentDateAndGivenTime(firstTimeStr);
296 2663 sgarg
           logMetacat.info("The first time setting is "+firstTime.toString());
297 2572 tao
         }
298
         catch (Exception e)
299
         {
300
            throw new ServletException(e.getMessage());
301
         }
302 2663 sgarg
         logMetacat.warn("After combine current time, the real first time is "
303
                                  +firstTime.toString()+" minisec");
304 2572 tao
      }
305
      else
306
      {
307
          MetacatReplication.replErrorLog("You should specify the first time " +
308
                                          "to start a time replication");
309 2663 sgarg
          logMetacat.warn("You should specify the first time " +
310
                                  "to start a time replication");
311 2572 tao
          return;
312
      }
313
314
      timedReplicationIsOn = true;
315 4087 daigle
      try {
316 2572 tao
      // save settings to property file
317 4080 daigle
      PropertyService.setProperty(TIMEREPLICATION, (new Boolean(timedReplicationIsOn)).toString());
318 2572 tao
      // note we couldn't use firstTime object because it has date info
319
      // we only need time info such as 10:00 PM
320 4080 daigle
      PropertyService.setProperty(FIRSTTIME, firstTimeStr);
321
      PropertyService.setProperty(TIMEREPLICATIONINTERVAl, (new Long(timeInterval)).toString());
322 4087 daigle
      } catch (GeneralPropertyException gpe) {
323
    	  logMetacat.warn("Could not set property: " + gpe.getMessage());
324
      }
325 837 bojilova
      replicationDaemon.cancel();
326
      replicationDaemon = new Timer(true);
327 2572 tao
      replicationDaemon.scheduleAtFixedRate(new ReplicationHandler(), firstTime,
328
                                            timeInterval);
329 837 bojilova
      out.println("Replication Handler Started");
330 2286 tao
      MetacatReplication.replLog("deltaT handler started with rate=" +
331 2572 tao
                                    timeInterval + " milliseconds at " +firstTime.toString());
332 837 bojilova
333 2286 tao
334 840 bojilova
    } else if ( action.equals("getall") ) {
335 837 bojilova
      //updates this server exactly once
336 2572 tao
      replicationDaemon.schedule(new ReplicationHandler(), 0);
337 837 bojilova
      response.setContentType("text/html");
338
      out.println("<html><body>\"Get All\" Done</body></html>");
339
340 840 bojilova
    } else if ( action.equals("forcereplicate") ) {
341 1020 tao
      //read a specific docid from remote host, and store it into local host
342 3233 tao
      handleForceReplicateRequest(out, params, response, request);
343 2286 tao
344 2298 tao
    } else if ( action.equals(FORCEREPLICATEDELETE) ) {
345
      //read a specific docid from remote host, and store it into local host
346 3233 tao
      handleForceReplicateDeleteRequest(out, params, response, request);
347 2298 tao
348 840 bojilova
    } else if ( action.equals("update") ) {
349 837 bojilova
      //request an update list from the server
350
      handleUpdateRequest(out, params, response);
351
352 840 bojilova
    } else if ( action.equals("read") ) {
353 837 bojilova
      //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 840 bojilova
    } else if ( action.equals("getlock") ) {
358 837 bojilova
      handleGetLockRequest(out, params, response);
359
360 840 bojilova
    } else if ( action.equals("getdocumentinfo") ) {
361 837 bojilova
      handleGetDocumentInfoRequest(out, params, response);
362
363 840 bojilova
    } else if ( action.equals("gettime") ) {
364 837 bojilova
      handleGetTimeRequest(out, params, response);
365
366 840 bojilova
    } else if ( action.equals("getcatalog") ) {
367 837 bojilova
      handleGetCatalogRequest(out, params, response, true);
368
369 840 bojilova
    } else if ( action.equals("servercontrol") ) {
370 837 bojilova
      handleServerControlRequest(out, params, response);
371 1097 tao
    } else if ( action.equals("test") ) {
372
      response.setContentType("text/html");
373
      out.println("<html><body>Test successfully</body></html>");
374 837 bojilova
    }
375 2286 tao
376 840 bojilova
    out.close();
377 1020 tao
    }//else
378 522 berkley
  }
379 2286 tao
380
  /**
381 595 berkley
   * 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 2286 tao
   * servercontrol    list
388 595 berkley
   */
389 4488 daigle
  private void handleServerControlRequest(PrintWriter out, Hashtable<String, String[]> params,
390 595 berkley
                                          HttpServletResponse response)
391
  {
392
    String subaction = ((String[])params.get("subaction"))[0];
393 1217 tao
    DBConnection dbConn = null;
394
    int serialNumber = -1;
395
    PreparedStatement pstmt = null;
396 1292 tao
    String replicate =null;
397
    String server = null;
398
    String dataReplicate = null;
399
    String hub = null;
400 837 bojilova
    try {
401 1217 tao
      //conn = util.openDBConnection();
402
      dbConn=DBConnectionPool.
403
               getDBConnection("MetacatReplication.handleServerControlRequest");
404
      serialNumber=dbConn.getCheckOutSerialNumber();
405 2286 tao
406 837 bojilova
      // add server to server list
407
      if ( subaction.equals("add") ) {
408 1292 tao
        replicate = ((String[])params.get("replicate"))[0];
409
        server = ((String[])params.get("server"))[0];
410 2286 tao
411 1292 tao
        //Get data replication value
412
        dataReplicate = ((String[])params.get("datareplicate"))[0];
413
        //Get hub value
414
        hub = ((String[])params.get("hub"))[0];
415 2286 tao
416 1751 tao
        /*pstmt = dbConn.prepareStatement("INSERT INTO xml_replication " +
417 1292 tao
                  "(server, last_checked, replicate, datareplicate, hub) " +
418 837 bojilova
                                      "VALUES ('" + server + "', to_date(" +
419
                                      "'01/01/00', 'MM/DD/YY'), '" +
420 1292 tao
                                      replicate +"', '" +dataReplicate+"', '"
421 1751 tao
                                      + hub +"')");*/
422
        pstmt = dbConn.prepareStatement("INSERT INTO xml_replication " +
423
                  "(server, last_checked, replicate, datareplicate, hub) " +
424 2286 tao
                                      "VALUES ('" + server + "', "+
425 4335 daigle
                                      DatabaseService.getDBAdapter().toDate("01/01/1980", "MM/DD/YYYY")
426 1751 tao
                                      + ", '" +
427
                                      replicate +"', '" +dataReplicate+"', '"
428 1292 tao
                                      + hub +"')");
429 2286 tao
430 595 berkley
        pstmt.execute();
431 837 bojilova
        pstmt.close();
432 1217 tao
        dbConn.commit();
433 2286 tao
        out.println("Server " + server + " added");
434 631 berkley
        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 1292 tao
        out.println("<b>replicate</b></td>");
438
        out.println("<td><b>datareplicate</b></td>");
439
        out.println("<td><b>hub</b></td></tr>");
440 1217 tao
        pstmt = dbConn.prepareStatement("SELECT * FROM xml_replication");
441
        //increase dbconnection usage
442
        dbConn.increaseUsageCount(1);
443 2286 tao
444 631 berkley
        pstmt.execute();
445
        ResultSet rs = pstmt.getResultSet();
446
        boolean tablehasrows = rs.next();
447 837 bojilova
        while(tablehasrows) {
448 631 berkley
          out.println("<tr><td>" + rs.getString(2) + "</td><td>");
449
          out.println(rs.getString(3) + "</td><td>");
450 1292 tao
          out.println(rs.getString(4) + "</td><td>");
451
          out.println(rs.getString(5) + "</td><td>");
452
          out.println(rs.getString(6) + "</td></tr>");
453 2286 tao
454 631 berkley
          tablehasrows = rs.next();
455
        }
456
        out.println("</table></body></html>");
457 2286 tao
458 840 bojilova
        // 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 2286 tao
463 837 bojilova
      // delete server from server list
464
      } else if ( subaction.equals("delete") ) {
465 1292 tao
        server = ((String[])params.get("server"))[0];
466 1217 tao
        pstmt = dbConn.prepareStatement("DELETE FROM xml_replication " +
467 837 bojilova
                                      "WHERE server LIKE '" + server + "'");
468 595 berkley
        pstmt.execute();
469 837 bojilova
        pstmt.close();
470 1217 tao
        dbConn.commit();
471 837 bojilova
        out.println("Server " + server + " deleted");
472 631 berkley
        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 1292 tao
        out.println("<b>replicate</b></td>");
476
        out.println("<td><b>datareplicate</b></td>");
477
        out.println("<td><b>hub</b></td></tr>");
478 2286 tao
479 1217 tao
        pstmt = dbConn.prepareStatement("SELECT * FROM xml_replication");
480
        //increase dbconnection usage
481
        dbConn.increaseUsageCount(1);
482 631 berkley
        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 1292 tao
          out.println(rs.getString(4) + "</td><td>");
490
          out.println(rs.getString(5) + "</td><td>");
491
          out.println(rs.getString(6) + "</td></tr>");
492 631 berkley
          tablehasrows = rs.next();
493
        }
494
        out.println("</table></body></html>");
495 837 bojilova
496
      // list servers in server list
497
      } else if ( subaction.equals("list") ) {
498 595 berkley
        response.setContentType("text/html");
499
        out.println("<html><body><table border=\"1\">");
500 629 berkley
        out.println("<tr><td><b>server</b></td><td><b>last_checked</b></td><td>");
501 1292 tao
        out.println("<b>replicate</b></td>");
502
        out.println("<td><b>datareplicate</b></td>");
503
        out.println("<td><b>hub</b></td></tr>");
504 1217 tao
        pstmt = dbConn.prepareStatement("SELECT * FROM xml_replication");
505 595 berkley
        pstmt.execute();
506
        ResultSet rs = pstmt.getResultSet();
507
        boolean tablehasrows = rs.next();
508 837 bojilova
        while(tablehasrows) {
509 595 berkley
          out.println("<tr><td>" + rs.getString(2) + "</td><td>");
510 629 berkley
          out.println(rs.getString(3) + "</td><td>");
511 1292 tao
          out.println(rs.getString(4) + "</td><td>");
512
          out.println(rs.getString(5) + "</td><td>");
513
          out.println(rs.getString(6) + "</td></tr>");
514 595 berkley
          tablehasrows = rs.next();
515
        }
516
        out.println("</table></body></html>");
517 2286 tao
      }
518 1292 tao
      else
519
      {
520 2286 tao
521 1292 tao
        out.println("<error>Unkonwn subaction</error>");
522 2286 tao
523 595 berkley
      }
524 667 berkley
      pstmt.close();
525 1217 tao
      //conn.close();
526 837 bojilova
527
    } catch(Exception e) {
528 2286 tao
      System.out.println("Error in " +
529
                         "MetacatReplication.handleServerControlRequest " +
530 595 berkley
                         e.getMessage());
531
      e.printStackTrace(System.out);
532
    }
533 1217 tao
    finally
534
    {
535
      try
536
      {
537
        pstmt.close();
538
      }//try
539
      catch (SQLException ee)
540
      {
541 2663 sgarg
        logMetacat.error("Error in " +
542 1217 tao
                "MetacatReplication.handleServerControlRequest to close pstmt "
543 2663 sgarg
                 + ee.getMessage());
544 1217 tao
      }//catch
545
      finally
546
      {
547
        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
548
      }//finally
549
    }//finally
550 2286 tao
551 595 berkley
  }
552 2286 tao
553 4080 daigle
   	// 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 4139 daigle
		String certPath = SystemUtil.getContextDir();
561 2286 tao
562 4080 daigle
		// 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 2286 tao
569 4080 daigle
		// 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 2286 tao
586 4080 daigle
			// 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 840 bojilova
591 4080 daigle
			// 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 2286 tao
614 583 berkley
  /**
615 4080 daigle
	 * 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 4488 daigle
  private void handleForceReplicateRequest(PrintWriter out, Hashtable<String, String[]> params,
620 3233 tao
                                           HttpServletResponse response, HttpServletRequest request)
621 574 berkley
  {
622 837 bojilova
    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 4488 daigle
//    boolean override = false;
626
//    int serverCode = 1;
627 1217 tao
    DBConnection dbConn = null;
628
    int serialNumber = -1;
629 2286 tao
630 837 bojilova
    try {
631
      //if the url contains a dbaction then the default action is overridden
632
      if(params.containsKey("dbaction")) {
633 577 berkley
        dbaction = ((String[])params.get("dbaction"))[0];
634 1057 tao
        //serverCode = MetacatReplication.getServerCode(server);
635
        //override = true; //we are now overriding the default action
636 577 berkley
      }
637 1292 tao
      MetacatReplication.replLog("force replication request from " + server);
638 2663 sgarg
      logMetacat.info("Force replication request from: "+ server);
639
      logMetacat.info("Force replication docid: "+docid);
640
      logMetacat.info("Force replication action: "+dbaction);
641 1292 tao
      // sending back read request to remote server
642 1014 tao
      URL u = new URL("https://" + server + "?server="
643 4698 daigle
                +MetacatUtil.getLocalReplicationServerName()
644 1014 tao
                +"&action=read&docid=" + docid);
645 574 berkley
      String xmldoc = MetacatReplication.getURLContent(u);
646 2286 tao
647 837 bojilova
      // get the document info from server
648 2286 tao
      URL docinfourl = new URL("https://" + server +
649 4698 daigle
                               "?server="+MetacatUtil.getLocalReplicationServerName()
650 1014 tao
                               +"&action=getdocumentinfo&docid=" + docid);
651 2286 tao
652 574 berkley
      String docInfoStr = MetacatReplication.getURLContent(docinfourl);
653 2286 tao
654 837 bojilova
      //dih is the parser for the docinfo xml format
655 574 berkley
      DocInfoHandler dih = new DocInfoHandler();
656
      XMLReader docinfoParser = ReplicationHandler.initParser(dih);
657
      docinfoParser.parse(new InputSource(new StringReader(docInfoStr)));
658 4488 daigle
//      Hashtable<String,Vector<AccessControlForSingleFile>> docinfoHash = dih.getDocInfo();
659
      Hashtable<String,String> docinfoHash = dih.getDocInfo();
660 2286 tao
661 1292 tao
      // Get user owner of this docid
662 574 berkley
      String user = (String)docinfoHash.get("user_owner");
663 1292 tao
      // Get home server of this docid
664 1057 tao
      String homeServer=(String)docinfoHash.get("home_server");
665 2624 tao
      String createdDate = (String)docinfoHash.get("date_created");
666
      String updatedDate = (String)docinfoHash.get("date_updated");
667 2663 sgarg
      logMetacat.info("homeServer: "+homeServer);
668 1561 tao
      // Get Document type
669
      String docType = (String)docinfoHash.get("doctype");
670 2663 sgarg
      logMetacat.info("docType: "+docType);
671 1561 tao
      String parserBase = null;
672
      // this for eml2 and we need user eml2 parser
673 2286 tao
      if (docType != null &&
674 2169 sgarg
          (docType.trim()).equals(DocumentImpl.EML2_0_0NAMESPACE))
675 1561 tao
      {
676 2663 sgarg
         logMetacat.warn("This is an eml200 document!");
677 2163 tao
         parserBase = DocumentImpl.EML200;
678 1561 tao
      }
679 2286 tao
      else if (docType != null && (docType.trim()).equals(DocumentImpl.EML2_0_1NAMESPACE))
680
      {
681 2663 sgarg
         logMetacat.warn("This is an eml2.0.1 document!");
682 2286 tao
         parserBase = DocumentImpl.EML200;
683
      }
684
      else if (docType != null && (docType.trim()).equals(DocumentImpl.EML2_1_0NAMESPACE))
685
      {
686 2663 sgarg
         logMetacat.warn("This is an eml2.1.0 document!");
687 2286 tao
         parserBase = DocumentImpl.EML210;
688
      }
689 2663 sgarg
      logMetacat.warn("The parserBase is: "+parserBase);
690 2286 tao
691 1292 tao
      // Get DBConnection from pool
692 1217 tao
      dbConn=DBConnectionPool.
693
              getDBConnection("MetacatReplication.handleForceReplicateRequest");
694
      serialNumber=dbConn.getCheckOutSerialNumber();
695 1292 tao
      // write the document to local database
696 1561 tao
      DocumentImplWrapper wrapper = new DocumentImplWrapper(parserBase, false);
697 4449 leinfelder
      //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 3230 tao
708 4449 leinfelder
      //process extra access rules before dealing with the write exception (doc exist already)
709 4488 daigle
      Vector<AccessControlForSingleFile> accessControlList = dih.getAccessControlList();
710 4419 leinfelder
      if (accessControlList != null) {
711
    	  for (int i = 0; i < accessControlList.size(); i++) {
712
        	  AccessControlForSingleFile acfsf = (AccessControlForSingleFile) accessControlList.get(i);
713 4450 leinfelder
        	  if (!acfsf.accessControlExists()) {
714
	        	  acfsf.insertPermissions();
715
	        	  MetacatReplication.replLog("document " + docid + " permissions added to DB");
716
        	  }
717 4419 leinfelder
          }
718
      }
719
720 4449 leinfelder
      if (writeException != null) {
721
    	  throw writeException;
722
      }
723
724 584 berkley
      MetacatReplication.replLog("document " + docid + " added to DB with " +
725
                                 "action " + dbaction);
726 3233 tao
      EventLog.getInstance().log(request.getRemoteAddr(), REPLICATIONUSER, docid, dbaction);
727 1292 tao
    }//try
728 2286 tao
    catch(Exception e)
729 1292 tao
    {
730 2286 tao
      MetacatReplication.replErrorLog("document " + docid +
731 1583 tao
                                      " failed to added to DB with " +
732
                                      "action " + dbaction + " because "+
733
                                       e.getMessage());
734 2663 sgarg
      logMetacat.error("ERROR in MetacatReplication.handleForceReplicate" +
735
                         "Request(): " + e.getMessage());
736 2286 tao
737 1292 tao
    }//catch
738 1217 tao
    finally
739
    {
740 1292 tao
      // Return the checked out DBConnection
741 1217 tao
      DBConnectionPool.returnDBConnection(dbConn, serialNumber);
742
    }//finally
743 574 berkley
  }
744 2286 tao
745 2298 tao
/*
746
 * when a forcereplication delete request comes in, local host will delete this
747
 * document
748
 */
749 4488 daigle
private void handleForceReplicateDeleteRequest(PrintWriter out, Hashtable<String, String[]> params,
750 3233 tao
                                         HttpServletResponse response, HttpServletRequest request)
751 2298 tao
{
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 2663 sgarg
    logMetacat.info("Force replication delete request from: "+ server);
759
    logMetacat.info("Force replication delete docid: "+docid);
760 3230 tao
    DocumentImpl.delete(docid, null, null, server);
761 2298 tao
    MetacatReplication.replLog("document " + docid + " was successfully deleted ");
762 3233 tao
    EventLog.getInstance().log(request.getRemoteAddr(), REPLICATIONUSER, docid, "delete");
763 2663 sgarg
    logMetacat.info("document " + docid + " was successfully deleted ");
764 2298 tao
  }
765
  catch(Exception e)
766
  {
767
    MetacatReplication.replErrorLog("document " + docid +
768
                                    " failed to delete because "+
769
                                     e.getMessage());
770 2663 sgarg
    logMetacat.error("ERROR in MetacatReplication.handleForceDeleteReplicate" +
771
                       "Request(): " + e.getMessage());
772 2298 tao
773
  }//catch
774
775
}
776
777
778 561 berkley
  /**
779 2286 tao
   * 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 1023 tao
   * docid. Then store it in local database and file system
782
   */
783 4488 daigle
  private void handleForceReplicateDataFileRequest(Hashtable<String, String[]> params, HttpServletRequest request)
784 1023 tao
  {
785 2286 tao
786 1023 tao
    //make sure there is some parameters
787
    if(params.isEmpty())
788
    {
789
      return;
790
    }
791 2286 tao
    // Get remote server
792
    String server = ((String[])params.get("server"))[0];
793 1292 tao
    // the docid should include rev number
794 2286 tao
    String docid = ((String[])params.get("docid"))[0];
795 1292 tao
    // Make sure there is a docid and server
796
    if (docid==null || server==null || server.equals(""))
797 1023 tao
    {
798 2663 sgarg
      logMetacat.error("Didn't specify docid or server for replication");
799 1023 tao
      return;
800
    }
801 2286 tao
802 1292 tao
    // Overide or not
803 4488 daigle
//    boolean override = false;
804 1292 tao
    // dbaction - update or insert
805 1023 tao
    String dbaction=null;
806 2286 tao
807
    try
808 1023 tao
    {
809 1292 tao
      //docid was switch to two parts uinque code and rev
810 4698 daigle
      //String uniqueCode=MetacatUtil.getDocIdFromString(docid);
811
      //int rev=MetacatUtil.getVersionFromString(docid);
812 2286 tao
      if(params.containsKey("dbaction"))
813 1023 tao
      {
814
        dbaction = ((String[])params.get("dbaction"))[0];
815
      }
816
      else//default value is update
817
      {
818
        dbaction = "update";
819
      }
820 2286 tao
821
      MetacatReplication.replLog("force replication request from " + server);
822 2663 sgarg
      logMetacat.info("Force replication request from: "+ server);
823
      logMetacat.info("Force replication docid: "+docid);
824
      logMetacat.info("Force replication action: "+dbaction);
825 1023 tao
      // get the document info from server
826 2286 tao
      URL docinfourl = new URL("https://" + server +
827 4698 daigle
                               "?server="+MetacatUtil.getLocalReplicationServerName()
828 2650 tao
                               +"&action=getdocumentinfo&docid=" + docid);
829 2286 tao
830 1023 tao
      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 4488 daigle
      Hashtable<String,String> docinfoHash = dih.getDocInfo();
837 1023 tao
      String user = (String)docinfoHash.get("user_owner");
838 2286 tao
839 1023 tao
      String docName = (String)docinfoHash.get("docname");
840 2286 tao
841 1023 tao
      String docType = (String)docinfoHash.get("doctype");
842 2286 tao
843 1065 tao
      String docHomeServer= (String)docinfoHash.get("home_server");
844 2624 tao
845
      String createdDate = (String)docinfoHash.get("date_created");
846
847
      String updatedDate = (String)docinfoHash.get("date_updated");
848 2663 sgarg
      logMetacat.info("docHomeServer of datafile: "+docHomeServer);
849 2286 tao
850
851
852 1023 tao
      //if action is delete, we don't delete the data file. Just archieve
853
      //the xml_documents
854 2298 tao
      /*if (dbaction.equals("delete"))
855 1023 tao
      {
856 1217 tao
        //conn = util.getConnection();
857
        DocumentImpl.delete(docid,user,null);
858
        //util.returnConnection(conn);
859 2298 tao
      }*/
860 1031 tao
      //To data file insert or update is same
861 2298 tao
      if (dbaction.equals("insert")||dbaction.equals("update"))
862 1023 tao
      {
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 4698 daigle
                +MetacatUtil.getLocalReplicationServerName()
867 1023 tao
                +"&action=readdata&docid=" + docid);
868 4080 daigle
        String datafilePath = PropertyService.getProperty("application.datafilepath");
869 4449 leinfelder
870
        Exception writeException = null;
871 1031 tao
        //register data file into xml_documents table and wite data file
872
        //into file system
873 4449 leinfelder
        try {
874
        	DocumentImpl.writeDataFileInReplication(url.openStream(), datafilePath,
875 2608 tao
                            docName, docType, docid, user,docHomeServer,server,
876 3230 tao
                            DocumentImpl.DOCUMENTTABLE, false, createdDate, updatedDate);
877 4449 leinfelder
        }
878
        catch (Exception e) {
879
        	writeException = e;
880
		}
881 4419 leinfelder
        //process extra access rules
882 4488 daigle
        Vector<AccessControlForSingleFile> accessControlList = dih.getAccessControlList();
883 4419 leinfelder
        if (accessControlList != null) {
884
      	  for (int i = 0; i < accessControlList.size(); i++) {
885
          	  AccessControlForSingleFile acfsf = (AccessControlForSingleFile) accessControlList.get(i);
886 4450 leinfelder
          	  if (!acfsf.accessControlExists()) {
887
          		  acfsf.insertPermissions();
888
          		  MetacatReplication.replLog("datafile " + docid + " permissions added to DB");
889
          	  }
890 4419 leinfelder
            }
891
        }
892
893 4449 leinfelder
        if (writeException != null) {
894
        	throw writeException;
895
        }
896
897
        //false means non-timed replication
898 3233 tao
        MetacatReplication.replLog("datafile " + docid + " added to DB with " +
899
                "action " + dbaction);
900
        EventLog.getInstance().log(request.getRemoteAddr(), REPLICATIONUSER, docid, dbaction);
901 1023 tao
     }
902 3233 tao
903 2286 tao
    }
904
    catch(Exception e)
905 1023 tao
    {
906 2286 tao
907
      MetacatReplication.replErrorLog("Datafile " + docid +
908 1583 tao
                                      " failed to added to DB with " +
909
                                      "action " + dbaction + " because "+
910
                                       e.getMessage());
911 2663 sgarg
      logMetacat.error
912 1292 tao
              ("ERROR in MetacatReplication.handleForceDataFileReplicate" +
913 2663 sgarg
                         "Request(): " + e.getMessage());
914 1023 tao
    }
915
  }
916
  /**
917 561 berkley
   * 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 2286 tao
   *
922 561 berkley
   */
923 4488 daigle
  private void handleGetLockRequest(PrintWriter out, Hashtable<String, String[]> params,
924 561 berkley
                                    HttpServletResponse response)
925
  {
926 1292 tao
927 561 berkley
    try
928
    {
929 2286 tao
930 561 berkley
      String docid = ((String[])params.get("docid"))[0];
931 580 berkley
      String remoteRev = ((String[])params.get("updaterev"))[0];
932 1217 tao
      DocumentImpl requestDoc = new DocumentImpl(docid);
933 584 berkley
      MetacatReplication.replLog("lock request for " + docid);
934 580 berkley
      int localRevInt = requestDoc.getRev();
935
      int remoteRevInt = Integer.parseInt(remoteRev);
936 2286 tao
937 580 berkley
      if(remoteRevInt >= localRevInt)
938 561 berkley
      {
939
        if(!fileLocks.contains(docid))
940 580 berkley
        { //grant the lock if it is not already locked
941 561 berkley
          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 584 berkley
          MetacatReplication.replLog("lock granted for " + docid);
948 561 berkley
        }
949
        else
950
        { //deny the lock
951
          out.println("<filelocked><docid>" + docid + "</docid></filelocked>");
952 2286 tao
          MetacatReplication.replLog("lock denied for " + docid +
953 584 berkley
                                     "reason: file already locked");
954 561 berkley
        }
955
      }
956
      else
957
      {//deny the lock.
958
        out.println("<outdatedfile><docid>" + docid + "</docid></filelocked>");
959 2286 tao
        MetacatReplication.replLog("lock denied for " + docid +
960 584 berkley
                                   "reason: client has outdated file");
961 561 berkley
      }
962 1217 tao
      //conn.close();
963 561 berkley
    }
964
    catch(Exception e)
965
    {
966 675 berkley
      System.out.println("error requesting file lock from MetacatReplication." +
967
                         "handleGetLockRequest: " + e.getMessage());
968 568 berkley
      e.printStackTrace(System.out);
969 561 berkley
    }
970
  }
971 2286 tao
972 561 berkley
  /**
973
   * Sends all of the xml_documents information encoded in xml to a requestor
974 583 berkley
   * the format is:
975
   * <!ELEMENT documentinfo (docid, docname, doctype, doctitle, user_owner,
976 1057 tao
   *                  user_updated, home_server, public_access, rev)/>
977 583 berkley
   * all of the subelements of document info are #PCDATA
978 561 berkley
   */
979 4488 daigle
  private void handleGetDocumentInfoRequest(PrintWriter out, Hashtable<String, String[]> params,
980 561 berkley
                                        HttpServletResponse response)
981
  {
982
    String docid = ((String[])(params.get("docid")))[0];
983
    StringBuffer sb = new StringBuffer();
984 2286 tao
985 561 berkley
    try
986
    {
987 2286 tao
988 1217 tao
      DocumentImpl doc = new DocumentImpl(docid);
989 561 berkley
      sb.append("<documentinfo><docid>").append(docid);
990
      sb.append("</docid><docname>").append(doc.getDocname());
991
      sb.append("</docname><doctype>").append(doc.getDoctype());
992 692 bojilova
      sb.append("</doctype>");
993
      sb.append("<user_owner>").append(doc.getUserowner());
994 561 berkley
      sb.append("</user_owner><user_updated>").append(doc.getUserupdated());
995 1057 tao
      sb.append("</user_updated>");
996 2624 tao
      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 1057 tao
      sb.append("<home_server>");
1003 1061 tao
      sb.append(doc.getDocHomeServer());
1004 1057 tao
      sb.append("</home_server>");
1005
      sb.append("<public_access>").append(doc.getPublicaccess());
1006 583 berkley
      sb.append("</public_access><rev>").append(doc.getRev());
1007 4419 leinfelder
      sb.append("</rev>");
1008
1009
      //permissions on the document
1010
      PermissionController permController = new PermissionController(docid);
1011 4488 daigle
      Vector<AccessControlForSingleFile> accessControlList = permController.getAccessControl();
1012 4419 leinfelder
      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 561 berkley
      response.setContentType("text/xml");
1021
      out.println(sb.toString());
1022 2286 tao
1023 561 berkley
    }
1024
    catch (Exception e)
1025
    {
1026 675 berkley
      System.out.println("error in " +
1027 2286 tao
                         "metacatReplication.handlegetdocumentinforequest: " +
1028 675 berkley
                          e.getMessage());
1029 561 berkley
    }
1030 2286 tao
1031 561 berkley
  }
1032 2286 tao
1033 1020 tao
  /**
1034
   * Sends a datafile to a remote host
1035
   */
1036 2286 tao
  private void handleGetDataFileRequest(OutputStream outPut,
1037 4488 daigle
                            Hashtable<String, String[]> params, HttpServletResponse response)
1038 2286 tao
1039 1020 tao
  {
1040 2286 tao
    // File path for data file
1041 4080 daigle
    String filepath;
1042 1292 tao
    // Request docid
1043 1020 tao
    String docId = ((String[])(params.get("docid")))[0];
1044 1023 tao
    //check if the doicd is null
1045
    if (docId==null)
1046
    {
1047 2663 sgarg
      logMetacat.error("Didn't specify docid for replication");
1048 1023 tao
      return;
1049
    }
1050 2286 tao
1051 1097 tao
    //try to open a https stream to test if the request server's public key
1052
    //in the key store, this is security issue
1053
    try
1054
    {
1055 4080 daigle
      filepath = PropertyService.getProperty("application.datafilepath");
1056 4488 daigle
      String server = params.get("server")[0];
1057 1097 tao
      URL u = new URL("https://" + server + "?server="
1058 4698 daigle
                +MetacatUtil.getLocalReplicationServerName()
1059 1097 tao
                +"&action=test");
1060
      String test = MetacatReplication.getURLContent(u);
1061
      //couldn't pass the test
1062
      if (test.indexOf("successfully")==-1)
1063
      {
1064
        //response.setContentType("text/xml");
1065
        //outPut.println("<error>Couldn't pass the trust test</error>");
1066 2663 sgarg
        logMetacat.error("Couldn't pass the trust test");
1067 1097 tao
        return;
1068
      }
1069
    }//try
1070
    catch (Exception ee)
1071
    {
1072
      return;
1073
    }//catch
1074 2286 tao
1075
    if(!filepath.endsWith("/"))
1076 1020 tao
    {
1077
          filepath += "/";
1078
    }
1079 1292 tao
    // Get file aboslute file name
1080 2286 tao
    String filename = filepath + docId;
1081
1082 1292 tao
    //MIME type
1083
    String contentType = null;
1084 2286 tao
    if (filename.endsWith(".xml"))
1085 1292 tao
    {
1086
        contentType="text/xml";
1087 2286 tao
    }
1088
    else if (filename.endsWith(".css"))
1089 1292 tao
    {
1090
        contentType="text/css";
1091 2286 tao
    }
1092
    else if (filename.endsWith(".dtd"))
1093 1292 tao
    {
1094
        contentType="text/plain";
1095 2286 tao
    }
1096
    else if (filename.endsWith(".xsd"))
1097 1292 tao
    {
1098
        contentType="text/xml";
1099 2286 tao
    }
1100
    else if (filename.endsWith("/"))
1101 1292 tao
    {
1102
        contentType="text/html";
1103 2286 tao
    }
1104
    else
1105 1292 tao
    {
1106
        File f = new File(filename);
1107 2286 tao
        if ( f.isDirectory() )
1108 1292 tao
        {
1109
           contentType="text/html";
1110 2286 tao
        }
1111 1292 tao
        else
1112
        {
1113
           contentType="application/octet-stream";
1114
        }
1115
     }
1116 2286 tao
1117 1292 tao
   // Set the mime type
1118 1020 tao
   response.setContentType(contentType);
1119 2286 tao
1120 1292 tao
   // Get the content of the file
1121 1020 tao
   FileInputStream fin = null;
1122 2286 tao
   try
1123 1020 tao
   {
1124 1292 tao
      // FileInputStream to metacat
1125 1020 tao
      fin = new FileInputStream(filename);
1126 1292 tao
      // 4K buffer
1127
      byte[] buf = new byte[4 * 1024];
1128
      // Read data from file input stream to byte array
1129 1020 tao
      int b = fin.read(buf);
1130 1292 tao
      // Write to outStream from byte array
1131 2286 tao
      while (b != -1)
1132 1020 tao
      {
1133
        outPut.write(buf, 0, b);
1134
        b = fin.read(buf);
1135
      }
1136 1292 tao
      // close file input stream
1137 1020 tao
      fin.close();
1138 2286 tao
1139 1292 tao
   }//try
1140 1020 tao
   catch(Exception e)
1141
   {
1142
      System.out.println("error getting data file from MetacatReplication." +
1143
                         "handlGetDataFileRequest " + e.getMessage());
1144
      e.printStackTrace(System.out);
1145 1292 tao
   }//catch
1146 2286 tao
1147 1020 tao
}
1148 2286 tao
1149
1150 561 berkley
  /**
1151
   * Sends a document to a remote host
1152
   */
1153 4488 daigle
  private void handleGetDocumentRequest(PrintWriter out, Hashtable<String, String[]> params,
1154 561 berkley
                                        HttpServletResponse response)
1155 534 berkley
  {
1156 2286 tao
1157 534 berkley
    try
1158
    {
1159 1097 tao
      //try to open a https stream to test if the request server's public key
1160
      //in the key store, this is security issue
1161 4488 daigle
      String server = params.get("server")[0];
1162 1097 tao
      URL u = new URL("https://" + server + "?server="
1163 4698 daigle
                +MetacatUtil.getLocalReplicationServerName()
1164 1097 tao
                +"&action=test");
1165
      String test = MetacatReplication.getURLContent(u);
1166
      //couldn't pass the test
1167
      if (test.indexOf("successfully")==-1)
1168
      {
1169
        response.setContentType("text/xml");
1170 2717 tao
        out.println("<error>Couldn't pass the trust test "+test+" </error>");
1171 1292 tao
        out.close();
1172 1097 tao
        return;
1173
      }
1174 2286 tao
1175 4488 daigle
      String docid = params.get("docid")[0];
1176 1217 tao
      DocumentImpl di = new DocumentImpl(docid);
1177 4488 daigle
1178
      String documentDir = PropertyService.getProperty("application.documentfilepath");
1179
      String 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
	    FileWriter fileWriter = new FileWriter(documentPath);
1185
		di.toXml(fileWriter, null, null, true);
1186
	  }
1187
1188
	  // read the file from disk and sent it to PrintWriter
1189
//		PrintWriter out = new PrintWriter(streamOut);
1190
	  di.readFromFileSystem(out, null, null, documentPath);
1191 2286 tao
1192 4488 daigle
//      response.setContentType("text/xml");
1193
//      out.print(di.toString(null, null, true));
1194
1195 584 berkley
      MetacatReplication.replLog("document " + docid + " sent");
1196 2286 tao
1197 534 berkley
    }
1198
    catch(Exception e)
1199
    {
1200 2663 sgarg
      logMetacat.error("error getting document from MetacatReplication."
1201
                          +"handlGetDocumentRequest " + e.getMessage());
1202 1099 tao
      //e.printStackTrace(System.out);
1203
      response.setContentType("text/xml");
1204 1292 tao
      out.println("<error>"+e.getMessage()+"</error>");
1205 534 berkley
    }
1206 2286 tao
1207 534 berkley
  }
1208 2286 tao
1209 573 berkley
  /**
1210 583 berkley
   * Sends a list of all of the documents on this sever along with their
1211 2286 tao
   * revision numbers.
1212 583 berkley
   * The format is:
1213
   * <!ELEMENT replication (server, updates)>
1214
   * <!ELEMENT server (#PCDATA)>
1215 2597 tao
   * <!ELEMENT updates ((updatedDocument | deleteDocument | revisionDocument)*)>
1216 1020 tao
   * <!ELEMENT updatedDocument (docid, rev, datafile*)>
1217 1035 tao
   * <!ELEMENT deletedDocument (docid, rev)>
1218 2597 tao
   * <!ELEMENT revisionDocument (docid, rev, datafile*)>
1219 583 berkley
   * <!ELEMENT docid (#PCDATA)>
1220
   * <!ELEMENT rev (#PCDATA)>
1221 1020 tao
   * <!ELEMENT datafile (#PCDATA)>
1222 583 berkley
   * note that the rev in deletedDocument is always empty.  I just left
1223
   * it in there to make the parser implementation easier.
1224 573 berkley
   */
1225 4488 daigle
  private void handleUpdateRequest(PrintWriter out, Hashtable<String, String[]> params,
1226 577 berkley
                                    HttpServletResponse response)
1227
  {
1228 2286 tao
    // Checked out DBConnection
1229 1217 tao
    DBConnection dbConn = null;
1230 1292 tao
    // DBConenction serial number when checked it out
1231 1217 tao
    int serialNumber = -1;
1232
    PreparedStatement pstmt = null;
1233 1292 tao
    // Server list to store server info of xml_replication table
1234
    ReplicationServerList serverList = null;
1235 2286 tao
1236 577 berkley
    try
1237
    {
1238 1292 tao
      // Check out a DBConnection from pool
1239
      dbConn=DBConnectionPool.
1240
                  getDBConnection("MetacatReplication.handleUpdateRequest");
1241
      serialNumber=dbConn.getCheckOutSerialNumber();
1242
      // Create a server list from xml_replication table
1243
      serverList = new ReplicationServerList();
1244 2286 tao
1245 1292 tao
      // Get remote server name from param
1246
      String server = ((String[])params.get("server"))[0];
1247
      // If no servr name in param, return a error
1248
      if ( server == null || server.equals(""))
1249
      {
1250
        response.setContentType("text/xml");
1251
        out.println("<error>Request didn't specify server name</error>");
1252
        out.close();
1253
        return;
1254
      }//if
1255 2286 tao
1256 1101 tao
      //try to open a https stream to test if the request server's public key
1257
      //in the key store, this is security issue
1258
      URL u = new URL("https://" + server + "?server="
1259 4698 daigle
                +MetacatUtil.getLocalReplicationServerName()
1260 1101 tao
                +"&action=test");
1261
      String test = MetacatReplication.getURLContent(u);
1262
      //couldn't pass the test
1263
      if (test.indexOf("successfully")==-1)
1264
      {
1265
        response.setContentType("text/xml");
1266
        out.println("<error>Couldn't pass the trust test</error>");
1267 1292 tao
        out.close();
1268 1101 tao
        return;
1269
      }
1270 2286 tao
1271
1272 1292 tao
      // Check if local host configure to replicate xml documents to remote
1273
      // server. If not send back a error message
1274
      if (!serverList.getReplicationValue(server))
1275
      {
1276
        response.setContentType("text/xml");
1277
        out.println
1278
        ("<error>Configuration not allow to replicate document to you</error>");
1279
        out.close();
1280
        return;
1281
      }//if
1282 2286 tao
1283 1292 tao
      // Store the sql command
1284 577 berkley
      StringBuffer docsql = new StringBuffer();
1285 2597 tao
      StringBuffer revisionSql = new StringBuffer();
1286 1292 tao
      // Stroe the docid list
1287 577 berkley
      StringBuffer doclist = new StringBuffer();
1288 1292 tao
      // Store the deleted docid list
1289
      StringBuffer delsql = new StringBuffer();
1290
      // Store the data set file
1291 4488 daigle
      Vector<Vector<String>> packageFiles = new Vector<Vector<String>>();
1292 2286 tao
1293 1292 tao
      // Append local server's name and replication servlet to doclist
1294 577 berkley
      doclist.append("<?xml version=\"1.0\"?><replication>");
1295 4698 daigle
      doclist.append("<server>").append(MetacatUtil.getLocalReplicationServerName());
1296 4080 daigle
      //doclist.append(util.getProperty("replicationpath"));
1297 577 berkley
      doclist.append("</server><updates>");
1298 2286 tao
1299 1292 tao
      // Get correct docid that reside on this server according the requesting
1300
      // server's replicate and data replicate value in xml_replication table
1301 4335 daigle
      docsql.append(DatabaseService.getDBAdapter().getReplicationDocumentListSQL());
1302 2724 tao
      //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)) ");
1303 2597 tao
      revisionSql.append("select docid, rev, doctype from xml_revisions ");
1304 1292 tao
      // If the localhost is not a hub to the remote server, only replicate
1305
      // the docid' which home server is local host (server_location =1)
1306
      if (!serverList.getHubValue(server))
1307 1042 tao
      {
1308 2724 tao
    	String serverLocationDoc = " and a.server_location = 1";
1309 2719 tao
        String serverLocationRev = "where server_location = 1";
1310
        docsql.append(serverLocationDoc);
1311
        revisionSql.append(serverLocationRev);
1312 1042 tao
      }
1313 2663 sgarg
      logMetacat.info("Doc sql: "+docsql.toString());
1314 2286 tao
1315 1292 tao
      // Get any deleted documents
1316 577 berkley
      delsql.append("select distinct docid from ");
1317
      delsql.append("xml_revisions where docid not in (select docid from ");
1318 1042 tao
      delsql.append("xml_documents) ");
1319 1292 tao
      // If the localhost is not a hub to the remote server, only replicate
1320
      // the docid' which home server is local host (server_location =1)
1321
      if (!serverList.getHubValue(server))
1322 1042 tao
      {
1323
        delsql.append("and server_location = 1");
1324
      }
1325 2663 sgarg
      logMetacat.info("Deleted sql: "+delsql.toString());
1326 2286 tao
1327
1328
1329 1292 tao
      // Get docid list of local host
1330 1217 tao
      pstmt = dbConn.prepareStatement(docsql.toString());
1331 577 berkley
      pstmt.execute();
1332
      ResultSet rs = pstmt.getResultSet();
1333
      boolean tablehasrows = rs.next();
1334 1035 tao
      //If metacat configed to replicate data file
1335 4080 daigle
      //if ((util.getProperty("replicationsenddata")).equals("on"))
1336 2597 tao
      boolean replicateData = serverList.getDataReplicationValue(server);
1337
      if (replicateData)
1338 577 berkley
      {
1339 1020 tao
        while(tablehasrows)
1340
        {
1341
          String recordDoctype = rs.getString(3);
1342 4698 daigle
          Vector<String> packagedoctypes = MetacatUtil.getOptionList(
1343 4213 daigle
                                     PropertyService.getProperty("xml.packagedoctype"));
1344 1292 tao
          //if this is a package file, put it at the end
1345
          //because if a package file is read before all of the files it
1346
          //refers to are loaded then there is an error
1347 1768 tao
          if(recordDoctype != null && !packagedoctypes.contains(recordDoctype))
1348 2286 tao
          {
1349 1292 tao
              //If this is not data file
1350 1035 tao
              if (!recordDoctype.equals("BIN"))
1351
              {
1352
                //for non-data file document
1353
                doclist.append("<updatedDocument>");
1354
                doclist.append("<docid>").append(rs.getString(1));
1355
                doclist.append("</docid><rev>").append(rs.getInt(2));
1356
                doclist.append("</rev>");
1357
                doclist.append("</updatedDocument>");
1358 1292 tao
              }//if
1359 1035 tao
              else
1360
              {
1361
                //for data file document, in datafile attributes
1362
                //we put "datafile" value there
1363
                doclist.append("<updatedDocument>");
1364
                doclist.append("<docid>").append(rs.getString(1));
1365
                doclist.append("</docid><rev>").append(rs.getInt(2));
1366
                doclist.append("</rev>");
1367
                doclist.append("<datafile>");
1368 4173 daigle
                doclist.append(PropertyService.getProperty("replication.datafileflag"));
1369 1035 tao
                doclist.append("</datafile>");
1370
                doclist.append("</updatedDocument>");
1371 2286 tao
              }//else
1372 1292 tao
          }//if packagedoctpes
1373 1035 tao
          else
1374
          { //the package files are saved to be put into the xml later.
1375 4488 daigle
              Vector<String> v = new Vector<String>();
1376
              v.add(rs.getString(1));
1377
              v.add(String.valueOf(rs.getInt(2)));
1378
              packageFiles.add(v);
1379 1292 tao
          }//esle
1380 1035 tao
          tablehasrows = rs.next();
1381
        }//while
1382
      }//if
1383
      else //metacat was configured not to send data file
1384
      {
1385
        while(tablehasrows)
1386
        {
1387
          String recordDoctype = rs.getString(3);
1388 2286 tao
          if(!recordDoctype.equals("BIN"))
1389 1020 tao
          { //don't replicate data files
1390 4698 daigle
            Vector<String> packagedoctypes = MetacatUtil.getOptionList(
1391 4213 daigle
                                     PropertyService.getProperty("xml.packagedoctype"));
1392 1768 tao
            if(recordDoctype != null && !packagedoctypes.contains(recordDoctype))
1393 1020 tao
            {   //if this is a package file, put it at the end
1394
              //because if a package file is read before all of the files it
1395
              //refers to are loaded then there is an error
1396
              doclist.append("<updatedDocument>");
1397
              doclist.append("<docid>").append(rs.getString(1));
1398
              doclist.append("</docid><rev>").append(rs.getInt(2));
1399
              doclist.append("</rev>");
1400
              doclist.append("</updatedDocument>");
1401
            }
1402
            else
1403
            { //the package files are saved to be put into the xml later.
1404 4488 daigle
              Vector<String> v = new Vector<String>();
1405
              v.add(rs.getString(1));
1406
              v.add(String.valueOf(rs.getInt(2)));
1407
              packageFiles.add(v);
1408 1020 tao
            }
1409
         }//if
1410
         tablehasrows = rs.next();
1411
        }//while
1412 1035 tao
      }//else
1413 2286 tao
1414 1217 tao
      pstmt = dbConn.prepareStatement(delsql.toString());
1415
      //usage count should increas 1
1416
      dbConn.increaseUsageCount(1);
1417 2286 tao
1418 577 berkley
      pstmt.execute();
1419
      rs = pstmt.getResultSet();
1420
      tablehasrows = rs.next();
1421
      while(tablehasrows)
1422
      { //handle the deleted documents
1423
        doclist.append("<deletedDocument><docid>").append(rs.getString(1));
1424
        doclist.append("</docid><rev></rev></deletedDocument>");
1425 583 berkley
        //note that rev is always empty for deleted docs
1426 577 berkley
        tablehasrows = rs.next();
1427
      }
1428 2286 tao
1429 625 berkley
      //now we can put the package files into the xml results
1430
      for(int i=0; i<packageFiles.size(); i++)
1431
      {
1432 4488 daigle
        Vector<String> v = packageFiles.elementAt(i);
1433 625 berkley
        doclist.append("<updatedDocument>");
1434 4488 daigle
        doclist.append("<docid>").append(v.elementAt(0));
1435 625 berkley
        doclist.append("</docid><rev>");
1436 4488 daigle
        doclist.append(v.elementAt(1));
1437 625 berkley
        doclist.append("</rev>");
1438
        doclist.append("</updatedDocument>");
1439
      }
1440 2597 tao
      // add revision doc list
1441
      doclist.append(prepareRevisionDoc(dbConn,revisionSql.toString(),replicateData));
1442
1443 577 berkley
      doclist.append("</updates></replication>");
1444 2663 sgarg
      logMetacat.info("doclist: " + doclist.toString());
1445 667 berkley
      pstmt.close();
1446 1217 tao
      //conn.close();
1447 577 berkley
      response.setContentType("text/xml");
1448
      out.println(doclist.toString());
1449 2286 tao
1450 577 berkley
    }
1451
    catch(Exception e)
1452
    {
1453 2663 sgarg
      logMetacat.error("error in MetacatReplication." +
1454
                         "handleupdaterequest: " + e.getMessage());
1455 1101 tao
      //e.printStackTrace(System.out);
1456
      response.setContentType("text/xml");
1457 1292 tao
      out.println("<error>"+e.getMessage()+"</error>");
1458 577 berkley
    }
1459 1217 tao
    finally
1460
    {
1461
      try
1462
      {
1463
        pstmt.close();
1464
      }//try
1465
      catch (SQLException ee)
1466
      {
1467 2663 sgarg
        logMetacat.error("Error in MetacatReplication." +
1468
                "handleUpdaterequest to close pstmt: "+ee.getMessage());
1469 1217 tao
      }//catch
1470
      finally
1471
      {
1472
        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1473
      }//finally
1474
    }//finally
1475 2286 tao
1476 1292 tao
  }//handlUpdateRequest
1477 2597 tao
1478
  /*
1479
   * This method will get the xml string for document in xml_revision
1480
   * The schema look like <!ELEMENT revisionDocument (docid, rev, datafile*)>
1481
   */
1482
  private String prepareRevisionDoc(DBConnection dbConn, String revSql,
1483
                            boolean replicateData) throws Exception
1484
  {
1485 2663 sgarg
      logMetacat.warn("The revision document sql is "+ revSql);
1486 2597 tao
      StringBuffer revDocList = new StringBuffer();
1487 2619 tao
      PreparedStatement pstmt = dbConn.prepareStatement(revSql);
1488 2597 tao
      //usage count should increas 1
1489
      dbConn.increaseUsageCount(1);
1490 2286 tao
1491 2597 tao
      pstmt.execute();
1492
      ResultSet rs = pstmt.getResultSet();
1493
      boolean tablehasrows = rs.next();
1494
      while(tablehasrows)
1495
      {
1496
        String recordDoctype = rs.getString(3);
1497
1498
        //If this is data file and it isn't configured to replicate data
1499
        if (recordDoctype.equals("BIN") && !replicateData)
1500
        {
1501
            // do nothing
1502
            continue;
1503
        }
1504
        else
1505
        {
1506
1507
            revDocList.append("<revisionDocument>");
1508
            revDocList.append("<docid>").append(rs.getString(1));
1509
            revDocList.append("</docid><rev>").append(rs.getInt(2));
1510
            revDocList.append("</rev>");
1511
            // data file
1512
            if (recordDoctype.equals("BIN"))
1513
            {
1514
                revDocList.append("<datafile>");
1515 4173 daigle
                revDocList.append(PropertyService.getProperty("replication.datafileflag"));
1516 2597 tao
                revDocList.append("</datafile>");
1517
            }
1518 2619 tao
            revDocList.append("</revisionDocument>");
1519 2597 tao
1520
         }//else
1521 2619 tao
         tablehasrows = rs.next();
1522 2597 tao
      }
1523 2619 tao
      //System.out.println("The revision list is"+ revDocList.toString());
1524 2597 tao
      return revDocList.toString();
1525
  }
1526
1527 577 berkley
  /**
1528 590 berkley
   * Returns the xml_catalog table encoded in xml
1529
   */
1530
  public static String getCatalogXML()
1531
  {
1532
    return handleGetCatalogRequest(null, null, null, false);
1533
  }
1534 2286 tao
1535 590 berkley
  /**
1536
   * Sends the contents of the xml_catalog table encoded in xml
1537
   * The xml format is:
1538
   * <!ELEMENT xml_catalog (row*)>
1539
   * <!ELEMENT row (entry_type, source_doctype, target_doctype, public_id,
1540
   *                system_id)>
1541
   * All of the sub elements of row are #PCDATA
1542 2286 tao
1543 590 berkley
   * If printFlag == false then do not print to out.
1544
   */
1545 2286 tao
  private static String handleGetCatalogRequest(PrintWriter out,
1546 4488 daigle
                                                Hashtable<String, String[]> params,
1547 590 berkley
                                                HttpServletResponse response,
1548
                                                boolean printFlag)
1549
  {
1550 1217 tao
    DBConnection dbConn = null;
1551
    int serialNumber = -1;
1552 667 berkley
    PreparedStatement pstmt = null;
1553 590 berkley
    try
1554 2286 tao
    {
1555 1217 tao
      /*conn = MetacatReplication.getDBConnection("MetacatReplication." +
1556
                                                "handleGetCatalogRequest");*/
1557
      dbConn=DBConnectionPool.
1558
                 getDBConnection("MetacatReplication.handleGetCatalogRequest");
1559
      serialNumber=dbConn.getCheckOutSerialNumber();
1560
      pstmt = dbConn.prepareStatement("select entry_type, " +
1561 590 berkley
                              "source_doctype, target_doctype, public_id, " +
1562
                              "system_id from xml_catalog");
1563
      pstmt.execute();
1564
      ResultSet rs = pstmt.getResultSet();
1565
      boolean tablehasrows = rs.next();
1566
      StringBuffer sb = new StringBuffer();
1567
      sb.append("<?xml version=\"1.0\"?><xml_catalog>");
1568
      while(tablehasrows)
1569
      {
1570
        sb.append("<row><entry_type>").append(rs.getString(1));
1571
        sb.append("</entry_type><source_doctype>").append(rs.getString(2));
1572
        sb.append("</source_doctype><target_doctype>").append(rs.getString(3));
1573
        sb.append("</target_doctype><public_id>").append(rs.getString(4));
1574 4080 daigle
        // system id may not have server url on front.  Add it if not.
1575
        String systemID = rs.getString(5);
1576
        if (!systemID.startsWith("http://")) {
1577 4123 daigle
        	systemID = SystemUtil.getContextURL() + systemID;
1578 4080 daigle
        }
1579
        sb.append("</public_id><system_id>").append(systemID);
1580 590 berkley
        sb.append("</system_id></row>");
1581 2286 tao
1582 590 berkley
        tablehasrows = rs.next();
1583
      }
1584
      sb.append("</xml_catalog>");
1585 1217 tao
      //conn.close();
1586 590 berkley
      if(printFlag)
1587
      {
1588
        response.setContentType("text/xml");
1589
        out.println(sb.toString());
1590
      }
1591 667 berkley
      pstmt.close();
1592 590 berkley
      return sb.toString();
1593
    }
1594
    catch(Exception e)
1595
    {
1596 2286 tao
1597 2663 sgarg
      logMetacat.error("error in MetacatReplication.handleGetCatalogRequest:"+
1598
                          e.getMessage());
1599 590 berkley
      e.printStackTrace(System.out);
1600 1292 tao
      if(printFlag)
1601
      {
1602
        out.println("<error>"+e.getMessage()+"</error>");
1603
      }
1604 590 berkley
    }
1605 1217 tao
    finally
1606
    {
1607
      try
1608
      {
1609
        pstmt.close();
1610
      }//try
1611
      catch (SQLException ee)
1612
      {
1613 2663 sgarg
        logMetacat.error("Error in MetacatReplication.handleGetCatalogRequest: "
1614
           +ee.getMessage());
1615 1217 tao
      }//catch
1616
      finally
1617
      {
1618
        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1619
      }//finally
1620
    }//finally
1621 2286 tao
1622 590 berkley
    return null;
1623
  }
1624 2286 tao
1625 590 berkley
  /**
1626 568 berkley
   * Sends the current system date to the remote server.  Using this action
1627 2286 tao
   * for replication gets rid of any problems with syncronizing clocks
1628 568 berkley
   * because a time specific to a document is always kept on its home server.
1629
   */
1630 4488 daigle
  private void handleGetTimeRequest(PrintWriter out, Hashtable<String, String[]> params,
1631 568 berkley
                                    HttpServletResponse response)
1632
  {
1633 1752 tao
    SimpleDateFormat formatter = new SimpleDateFormat ("MM/dd/yy HH:mm:ss");
1634 568 berkley
    java.util.Date localtime = new java.util.Date();
1635
    String dateString = formatter.format(localtime);
1636
    response.setContentType("text/xml");
1637 2286 tao
1638 568 berkley
    out.println("<timestamp>" + dateString + "</timestamp>");
1639
  }
1640 2286 tao
1641 568 berkley
  /**
1642 2286 tao
   * this method handles the timeout for a file lock.  when a lock is
1643 583 berkley
   * granted it is granted for 30 seconds.  When this thread runs out
1644
   * it deletes the docid from the queue, thus eliminating the lock.
1645 561 berkley
   */
1646
  public void run()
1647
  {
1648
    try
1649
    {
1650 2663 sgarg
      logMetacat.info("thread started for docid: " +
1651
                               (String)fileLocks.elementAt(0));
1652 2286 tao
1653 561 berkley
      Thread.sleep(30000); //the lock will expire in 30 seconds
1654 2663 sgarg
      logMetacat.info("thread for docid: " +
1655 2286 tao
                             (String)fileLocks.elementAt(fileLocks.size() - 1) +
1656 2663 sgarg
                              " exiting.");
1657 2286 tao
1658 561 berkley
      fileLocks.remove(fileLocks.size() - 1);
1659 568 berkley
      //fileLocks is treated as a FIFO queue.  If there are more than one lock
1660 561 berkley
      //in the vector, the first one inserted will be removed.
1661
    }
1662
    catch(Exception e)
1663
    {
1664 2663 sgarg
      logMetacat.error("error in file lock thread from " +
1665
                                "MetacatReplication.run: " + e.getMessage());
1666 561 berkley
    }
1667
  }
1668 2286 tao
1669 561 berkley
  /**
1670
   * Returns the name of a server given a serverCode
1671
   * @param serverCode the serverid of the server
1672
   * @return the servername or null if the specified serverCode does not
1673
   *         exist.
1674
   */
1675 1292 tao
  public static String getServerNameForServerCode(int serverCode)
1676 561 berkley
  {
1677 569 berkley
    //System.out.println("serverid: " + serverCode);
1678 1217 tao
    DBConnection dbConn = null;
1679
    int serialNumber = -1;
1680
    PreparedStatement pstmt = null;
1681 561 berkley
    try
1682
    {
1683 1217 tao
      dbConn=DBConnectionPool.
1684
                  getDBConnection("MetacatReplication.getServer");
1685
      serialNumber=dbConn.getCheckOutSerialNumber();
1686 569 berkley
      String sql = new String("select server from " +
1687 2286 tao
                              "xml_replication where serverid = " +
1688 561 berkley
                              serverCode);
1689 1217 tao
      pstmt = dbConn.prepareStatement(sql);
1690 569 berkley
      //System.out.println("getserver sql: " + sql);
1691 561 berkley
      pstmt.execute();
1692
      ResultSet rs = pstmt.getResultSet();
1693
      boolean tablehasrows = rs.next();
1694
      if(tablehasrows)
1695
      {
1696 569 berkley
        //System.out.println("server: " + rs.getString(1));
1697 561 berkley
        return rs.getString(1);
1698
      }
1699 2286 tao
1700 1217 tao
      //conn.close();
1701 561 berkley
    }
1702
    catch(Exception e)
1703
    {
1704 2286 tao
      System.out.println("Error in MetacatReplication.getServer: " +
1705 561 berkley
                          e.getMessage());
1706
    }
1707 1217 tao
    finally
1708
    {
1709
      try
1710
      {
1711
        pstmt.close();
1712
      }//try
1713
      catch (SQLException ee)
1714
      {
1715 2663 sgarg
        logMetacat.error("Error in MetacactReplication.getserver: "+
1716
                                    ee.getMessage());
1717 1217 tao
      }//catch
1718
      finally
1719
      {
1720
        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1721
      }//fianlly
1722
    }//finally
1723 2286 tao
1724
1725
1726 561 berkley
    return null;
1727
      //return null if the server does not exist
1728
  }
1729 2286 tao
1730 569 berkley
  /**
1731
   * Returns a server code given a server name
1732
   * @param server the name of the server
1733
   * @return integer > 0 representing the code of the server, 0 if the server
1734
   *  does not exist.
1735
   */
1736 1292 tao
  public static int getServerCodeForServerName(String server) throws Exception
1737 569 berkley
  {
1738 1217 tao
    DBConnection dbConn = null;
1739
    int serialNumber = -1;
1740 667 berkley
    PreparedStatement pstmt = null;
1741 837 bojilova
    int serverCode = 0;
1742
1743
    try {
1744
1745 1217 tao
      //conn = util.openDBConnection();
1746
      dbConn=DBConnectionPool.
1747
                  getDBConnection("MetacatReplication.getServerCode");
1748
      serialNumber=dbConn.getCheckOutSerialNumber();
1749
      pstmt = dbConn.prepareStatement("SELECT serverid FROM xml_replication " +
1750 837 bojilova
                                    "WHERE server LIKE '" + server + "'");
1751 569 berkley
      pstmt.execute();
1752
      ResultSet rs = pstmt.getResultSet();
1753
      boolean tablehasrows = rs.next();
1754 2286 tao
      if ( tablehasrows ) {
1755 837 bojilova
        serverCode = rs.getInt(1);
1756 667 berkley
        pstmt.close();
1757 1217 tao
        //conn.close();
1758 837 bojilova
        return serverCode;
1759 569 berkley
      }
1760 2286 tao
1761 837 bojilova
    } catch(Exception e) {
1762
      throw e;
1763
1764
    } finally {
1765 2286 tao
      try
1766 1217 tao
      {
1767 667 berkley
        pstmt.close();
1768 1217 tao
        //conn.close();
1769
       }//try
1770 2286 tao
       catch(Exception ee)
1771 1217 tao
       {
1772 2663 sgarg
         logMetacat.error("Error in MetacatReplicatio.getServerCode: "
1773
                                  +ee.getMessage());
1774 2286 tao
1775 1217 tao
       }//catch
1776
       finally
1777
       {
1778
         DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1779
       }//finally
1780
    }//finally
1781 2286 tao
1782 837 bojilova
    return serverCode;
1783 569 berkley
  }
1784 2286 tao
1785 569 berkley
  /**
1786 1292 tao
   * Method to get a host server information for given docid
1787
   * @param conn a connection to the database
1788
   */
1789 4488 daigle
  public static Hashtable<String,String> getHomeServerInfoForDocId(String docId)
1790 1292 tao
  {
1791 4488 daigle
    Hashtable<String,String> sl = new Hashtable<String,String>();
1792 1292 tao
    DBConnection dbConn = null;
1793
    int serialNumber = -1;
1794 4698 daigle
    docId=MetacatUtil.getDocIdFromString(docId);
1795 1292 tao
    PreparedStatement pstmt=null;
1796
    int serverLocation;
1797
    try
1798
    {
1799
      //get conection
1800
      dbConn=DBConnectionPool.
1801
                  getDBConnection("ReplicationHandler.getHomeServer");
1802
      serialNumber=dbConn.getCheckOutSerialNumber();
1803
      //get a server location from xml_document table
1804
      pstmt=dbConn.prepareStatement("select server_location from xml_documents "
1805
                                            +"where docid = ?");
1806
      pstmt.setString(1, docId);
1807
      pstmt.execute();
1808
      ResultSet serverName = pstmt.getResultSet();
1809
      //get a server location
1810
      if(serverName.next())
1811
      {
1812
        serverLocation=serverName.getInt(1);
1813
        pstmt.close();
1814
      }
1815
      else
1816
      {
1817
        pstmt.close();
1818
        //ut.returnConnection(conn);
1819
        return null;
1820
      }
1821
      pstmt=dbConn.prepareStatement("select server, last_checked, replicate " +
1822
                        "from xml_replication where serverid = ?");
1823
      //increase usage count
1824
      dbConn.increaseUsageCount(1);
1825
      pstmt.setInt(1, serverLocation);
1826
      pstmt.execute();
1827
      ResultSet rs = pstmt.getResultSet();
1828
      boolean tableHasRows = rs.next();
1829
      if (tableHasRows)
1830
      {
1831 2286 tao
1832 1292 tao
          String server = rs.getString(1);
1833
          String last_checked = rs.getString(2);
1834
          if(!server.equals("localhost"))
1835
          {
1836
            sl.put(server, last_checked);
1837
          }
1838 2286 tao
1839 1292 tao
      }
1840
      else
1841
      {
1842
        pstmt.close();
1843
        //ut.returnConnection(conn);
1844
        return null;
1845
      }
1846
      pstmt.close();
1847
    }
1848
    catch(Exception e)
1849
    {
1850
      System.out.println("error in replicationHandler.getHomeServer(): " +
1851
                         e.getMessage());
1852
    }
1853
    finally
1854
    {
1855
      try
1856
      {
1857
        pstmt.close();
1858
        //ut.returnConnection(conn);
1859
      }
1860
      catch (Exception ee)
1861
      {
1862 2663 sgarg
        logMetacat.error("Eror irn rplicationHandler.getHomeServer() "+
1863
                          "to close pstmt: "+ee.getMessage());
1864 1292 tao
      }
1865
      finally
1866
      {
1867
        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1868
      }
1869 2286 tao
1870 1292 tao
    }//finally
1871
    return sl;
1872
  }
1873 2286 tao
1874 1292 tao
  /**
1875
   * Returns a home server location  given a accnum
1876
   * @param accNum , given accNum for a document
1877 2286 tao
   *
1878 1292 tao
   */
1879
  public static int getHomeServerCodeForDocId(String accNum) throws Exception
1880
  {
1881
    DBConnection dbConn = null;
1882
    int serialNumber = -1;
1883
    PreparedStatement pstmt = null;
1884
    int serverCode = 1;
1885 4698 daigle
    String docId=MetacatUtil.getDocIdFromString(accNum);
1886 1292 tao
1887 2286 tao
    try
1888 1292 tao
    {
1889
1890
      // Get DBConnection
1891
      dbConn=DBConnectionPool.
1892
                  getDBConnection("ReplicationHandler.getServerLocation");
1893
      serialNumber=dbConn.getCheckOutSerialNumber();
1894 2286 tao
      pstmt=dbConn.prepareStatement("SELECT server_location FROM xml_documents "
1895 1292 tao
                              + "WHERE docid LIKE '" + docId + "'");
1896
      pstmt.execute();
1897
      ResultSet rs = pstmt.getResultSet();
1898
      boolean tablehasrows = rs.next();
1899
      //If a document is find, return the server location for it
1900 2286 tao
      if ( tablehasrows )
1901
      {
1902 1292 tao
        serverCode = rs.getInt(1);
1903
        pstmt.close();
1904
        //conn.close();
1905
        return serverCode;
1906
      }
1907
      //if couldn't find in xml_documents table, we think server code is 1
1908
      //(this is new document)
1909
      else
1910
      {
1911
        pstmt.close();
1912
        //conn.close();
1913
        return serverCode;
1914
      }
1915 2286 tao
1916
    }
1917
    catch(Exception e)
1918 1292 tao
    {
1919 2286 tao
1920 1292 tao
      throw e;
1921
1922 2286 tao
    }
1923
    finally
1924 1292 tao
    {
1925 2286 tao
      try
1926 1292 tao
      {
1927
        pstmt.close();
1928
        //conn.close();
1929 2286 tao
1930
      }
1931
      catch(Exception ee)
1932 1292 tao
      {
1933 2663 sgarg
        logMetacat.error("Erorr in Replication.getServerLocation "+
1934
                     "to close pstmt"+ee.getMessage());
1935 1292 tao
      }
1936
      finally
1937
      {
1938
        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1939
      }//finally
1940
    }//finally
1941
   //return serverCode;
1942
  }
1943 2286 tao
1944
1945
1946 1292 tao
  /**
1947 569 berkley
   * This method returns the content of a url
1948
   * @param u the url to return the content from
1949
   * @return a string representing the content of the url
1950
   * @throws java.io.IOException
1951
   */
1952
  public static String getURLContent(URL u) throws java.io.IOException
1953
  {
1954
    char istreamChar;
1955
    int istreamInt;
1956 2663 sgarg
    logMetacat.info("Before open the stream"+u.toString());
1957 1606 tao
    InputStream input = u.openStream();
1958 2663 sgarg
    logMetacat.info("Afetr open the stream"+u.toString());
1959 1606 tao
    InputStreamReader istream = new InputStreamReader(input);
1960 569 berkley
    StringBuffer serverResponse = new StringBuffer();
1961
    while((istreamInt = istream.read()) != -1)
1962
    {
1963
      istreamChar = (char)istreamInt;
1964
      serverResponse.append(istreamChar);
1965
    }
1966 1606 tao
    istream.close();
1967
    input.close();
1968 2286 tao
1969 569 berkley
    return serverResponse.toString();
1970
  }
1971 2286 tao
1972 584 berkley
  /**
1973 4080 daigle
	 * Method for writing replication messages to a log file specified in
1974
	 * metacat.properties
1975
	 */
1976
	public static void replLog(String message) {
1977
		try {
1978
			FileOutputStream fos =
1979 4173 daigle
				new FileOutputStream(PropertyService.getProperty("replication.logdir")
1980
					+ "/metacatreplication.log", true);
1981 4080 daigle
			PrintWriter pw = new PrintWriter(fos);
1982
			SimpleDateFormat formatter = new SimpleDateFormat("yy-MM-dd HH:mm:ss");
1983
			java.util.Date localtime = new java.util.Date();
1984
			String dateString = formatter.format(localtime);
1985
			dateString += " :: " + message;
1986
			// time stamp each entry
1987
			pw.println(dateString);
1988
			pw.flush();
1989
		} catch (Exception e) {
1990
			System.out.println("error writing to replication log from "
1991
					+ "MetacatReplication.replLog: " + e.getMessage());
1992
			// e.printStackTrace(System.out);
1993
		}
1994
	}
1995 2286 tao
1996 629 berkley
  /**
1997 4080 daigle
	 * Method for writing replication messages to a log file specified in
1998
	 * metacat.properties
1999
	 */
2000 1583 tao
  public static void replErrorLog(String message)
2001
  {
2002
    try
2003
    {
2004 4420 leinfelder
    	FileOutputStream fos =
2005
			new FileOutputStream(PropertyService.getProperty("replication.logdir")
2006
				+ "/metacatreplicationerror.log", true);
2007 1583 tao
      PrintWriter pw = new PrintWriter(fos);
2008
      SimpleDateFormat formatter = new SimpleDateFormat ("yy-MM-dd HH:mm:ss");
2009
      java.util.Date localtime = new java.util.Date();
2010
      String dateString = formatter.format(localtime);
2011
      dateString += " :: " + message;
2012
      //time stamp each entry
2013
      pw.println(dateString);
2014
      pw.flush();
2015
    }
2016
    catch(Exception e)
2017
    {
2018 4420 leinfelder
      System.out.println("error writing to replication error log from " +
2019
                         "MetacatReplication.replErrorLog: " + e.getMessage());
2020 1583 tao
      //e.printStackTrace(System.out);
2021
    }
2022
  }
2023 2286 tao
2024 1583 tao
  /**
2025 629 berkley
   * Returns true if the replicate field for server in xml_replication is 1.
2026
   * Returns false otherwise
2027
   */
2028
  public static boolean replToServer(String server)
2029
  {
2030 1217 tao
    DBConnection dbConn = null;
2031
    int serialNumber = -1;
2032 667 berkley
    PreparedStatement pstmt = null;
2033 629 berkley
    try
2034
    {
2035 1217 tao
      dbConn=DBConnectionPool.
2036
                  getDBConnection("MetacatReplication.repltoServer");
2037
      serialNumber=dbConn.getCheckOutSerialNumber();
2038 2286 tao
      pstmt = dbConn.prepareStatement("select replicate from " +
2039 667 berkley
                                    "xml_replication where server like '" +
2040
                                     server + "'");
2041 629 berkley
      pstmt.execute();
2042
      ResultSet rs = pstmt.getResultSet();
2043
      boolean tablehasrows = rs.next();
2044
      if(tablehasrows)
2045
      {
2046
        int i = rs.getInt(1);
2047
        if(i == 1)
2048
        {
2049 667 berkley
          pstmt.close();
2050 1217 tao
          //conn.close();
2051 629 berkley
          return true;
2052
        }
2053
        else
2054
        {
2055 667 berkley
          pstmt.close();
2056 1217 tao
          //conn.close();
2057 629 berkley
          return false;
2058
        }
2059
      }
2060
    }
2061
    catch(Exception e)
2062
    {
2063 2286 tao
      System.out.println("error in MetacatReplication.replToServer: " +
2064 675 berkley
                         e.getMessage());
2065 629 berkley
    }
2066 667 berkley
    finally
2067
    {
2068
      try
2069
      {
2070
        pstmt.close();
2071 1217 tao
        //conn.close();
2072
      }//try
2073 667 berkley
      catch(Exception ee)
2074 1217 tao
      {
2075 2663 sgarg
        logMetacat.error("Error in MetacatReplication.replToServer: "
2076
                                  +ee.getMessage());
2077 1217 tao
      }//catch
2078
      finally
2079
      {
2080
        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
2081
      }//finally
2082
    }//finally
2083 629 berkley
    return false;
2084
    //the default if this server does not exist is to not replicate to it.
2085
  }
2086 2286 tao
2087
2088 522 berkley
}