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