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