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