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