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
			String xmldoc = ReplicationService.getURLContent(u);
656 2286 tao
657 5014 daigle
			// get the document info from server
658
			URL docinfourl = new URL("https://" + server + "?server="
659
					+ MetacatUtil.getLocalReplicationServerName()
660
					+ "&action=getdocumentinfo&docid=" + docid);
661 5440 berkley
662 2286 tao
663 5014 daigle
			String docInfoStr = ReplicationService.getURLContent(docinfourl);
664 6531 leinfelder
			// strip out the system metadata portion
665
			String systemMetadataXML = ReplicationUtil.getSystemMetadataContent(docInfoStr);
666
			docInfoStr = ReplicationUtil.getContentWithoutSystemMetadata(docInfoStr);
667
668 5014 daigle
			//dih is the parser for the docinfo xml format
669
			DocInfoHandler dih = new DocInfoHandler();
670
			XMLReader docinfoParser = ReplicationHandler.initParser(dih);
671
			docinfoParser.parse(new InputSource(new StringReader(docInfoStr)));
672
			//      Hashtable<String,Vector<AccessControlForSingleFile>> docinfoHash = dih.getDocInfo();
673
			Hashtable<String, String> docinfoHash = dih.getDocInfo();
674 6015 leinfelder
675 5014 daigle
			// Get home server of this docid
676
			String homeServer = (String) docinfoHash.get("home_server");
677 6531 leinfelder
678
			// process system metadata
679 8739 tao
			SystemMetadata sysMeta = null;
680 6531 leinfelder
			if (systemMetadataXML != null) {
681 8739 tao
				sysMeta =
682 6531 leinfelder
					TypeMarshaller.unmarshalTypeFromStream(
683
							SystemMetadata.class,
684
							new ByteArrayInputStream(systemMetadataXML.getBytes("UTF-8")));
685
				// need the guid-to-docid mapping
686 6783 leinfelder
				boolean mappingExists = true;
687 7045 leinfelder
		      	mappingExists = IdentifierManager.getInstance().mappingExists(sysMeta.getIdentifier().getValue());
688 6783 leinfelder
		      	if (!mappingExists) {
689
		      		IdentifierManager.getInstance().createMapping(sysMeta.getIdentifier().getValue(), docid);
690
		      	}
691 6666 leinfelder
				// save the system metadata
692
				HazelcastService.getInstance().getSystemMetadataMap().put(sysMeta.getIdentifier(), sysMeta);
693 8739 tao
694 6531 leinfelder
			}
695 5324 berkley
696 6595 leinfelder
			// dates
697
			String createdDateString = docinfoHash.get("date_created");
698
			String updatedDateString = docinfoHash.get("date_updated");
699 6614 leinfelder
			Date createdDate = DateTimeMarshaller.deserializeDateToUTC(createdDateString);
700
			Date updatedDate = DateTimeMarshaller.deserializeDateToUTC(updatedDateString);
701 6595 leinfelder
702 5014 daigle
			logReplication.info("ReplicationService.handleForceReplicateRequest - homeServer: " + homeServer);
703
			// Get Document type
704
			String docType = (String) docinfoHash.get("doctype");
705
			logReplication.info("ReplicationService.handleForceReplicateRequest - docType: " + docType);
706
			String parserBase = null;
707
			// this for eml2 and we need user eml2 parser
708
			if (docType != null
709
					&& (docType.trim()).equals(DocumentImpl.EML2_0_0NAMESPACE)) {
710
				logReplication.warn("ReplicationService.handleForceReplicateRequest - This is an eml200 document!");
711
				parserBase = DocumentImpl.EML200;
712
			} else if (docType != null
713
					&& (docType.trim()).equals(DocumentImpl.EML2_0_1NAMESPACE)) {
714
				logReplication.warn("ReplicationService.handleForceReplicateRequest - This is an eml2.0.1 document!");
715
				parserBase = DocumentImpl.EML200;
716
			} else if (docType != null
717
					&& (docType.trim()).equals(DocumentImpl.EML2_1_0NAMESPACE)) {
718
				logReplication.warn("ReplicationService.handleForceReplicateRequest - This is an eml2.1.0 document!");
719
				parserBase = DocumentImpl.EML210;
720 5709 leinfelder
			} else if (docType != null
721
					&& (docType.trim()).equals(DocumentImpl.EML2_1_1NAMESPACE)) {
722
				logReplication.warn("ReplicationService.handleForceReplicateRequest - This is an eml2.1.1 document!");
723
				parserBase = DocumentImpl.EML210;
724 5014 daigle
			}
725
			logReplication.warn("ReplicationService.handleForceReplicateRequest - The parserBase is: " + parserBase);
726 2286 tao
727 5014 daigle
			// Get DBConnection from pool
728
			dbConn = DBConnectionPool
729
					.getDBConnection("MetacatReplication.handleForceReplicateRequest");
730
			serialNumber = dbConn.getCheckOutSerialNumber();
731
			// write the document to local database
732 7128 leinfelder
			DocumentImplWrapper wrapper = new DocumentImplWrapper(parserBase, false, false);
733 6079 leinfelder
			//try this independently so we can set access even if the update action is invalid (i.e docid has not changed)
734 5014 daigle
			try {
735 5195 daigle
				wrapper.writeReplication(dbConn, xmldoc, null, null,
736 6015 leinfelder
						dbaction, docid, null, null, homeServer, server, createdDate,
737 5014 daigle
						updatedDate);
738 5195 daigle
			} finally {
739 8739 tao
				if(sysMeta != null) {
740
					// submit for indexing. When the doc writing process fails, the index process will fail as well. But this failure
741
					// will not interrupt the process.
742
					try {
743
						MetacatSolrIndex.getInstance().submit(sysMeta.getIdentifier(), sysMeta, null, true);
744
					} catch (Exception ee) {
745
						logReplication.warn("ReplicationService.handleForceReplicateRequest - couldn't index the doc since "+ee.getMessage());
746
					}
747
748
				}
749 7358 leinfelder
				//process extra access rules before dealing with the write exception (doc exist already)
750
				try {
751
		        	// check if we had a guid -> docid mapping
752
		        	String docidNoRev = DocumentUtil.getDocIdFromAccessionNumber(docid);
753
		        	int rev = DocumentUtil.getRevisionFromAccessionNumber(docid);
754 7382 leinfelder
		        	IdentifierManager.getInstance().getGUID(docidNoRev, rev);
755 7358 leinfelder
		        	// no need to create the mapping if we have it
756
		        } catch (McdbDocNotFoundException mcdbe) {
757
		        	// create mapping if we don't
758
		        	IdentifierManager.getInstance().createMapping(docid, docid);
759
		        }
760 5195 daigle
		        Vector<XMLAccessDAO> accessControlList = dih.getAccessControlList();
761
		        if (accessControlList != null) {
762
		        	AccessControlForSingleFile acfsf = new AccessControlForSingleFile(docid);
763
		        	for (XMLAccessDAO xmlAccessDAO : accessControlList) {
764 7120 leinfelder
		        		try {
765
			        		if (!acfsf.accessControlExists(xmlAccessDAO)) {
766
			        			acfsf.insertPermissions(xmlAccessDAO);
767
								logReplication.info("ReplicationService.handleForceReplicateRequest - document " + docid
768
										+ " permissions added to DB");
769
			        		}
770
		        		} catch (PermOrderException poe) {
771
		        			// this is problematic, but should not prevent us from replicating
772
		        			// see https://redmine.dataone.org/issues/2583
773
		        			String msg = "Could not insert access control for: " + docid + " Message: " + poe.getMessage();
774
		        			logMetacat.error(msg, poe);
775
		        			logReplication.error(msg, poe);
776 5195 daigle
		        		}
777
		            }
778
		        }
779 6015 leinfelder
780
		        // process the real owner and updater
781
				String user = (String) docinfoHash.get("user_owner");
782
				String updated = (String) docinfoHash.get("user_updated");
783
		        updateUserOwner(dbConn, docid, user, updated);
784 2286 tao
785 5195 daigle
				logReplication.info("ReplicationService.handleForceReplicateRequest - document " + docid + " added to DB with "
786
						+ "action " + dbaction);
787 5458 berkley
788 6542 leinfelder
				EventLog.getInstance().log(request.getRemoteAddr(), request.getHeader("User-Agent"), REPLICATIONUSER, docid, dbaction);
789 5014 daigle
			}
790 5195 daigle
		} catch (SQLException sqle) {
791 5014 daigle
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);
792 5195 daigle
			logReplication.error("ReplicationService.handleForceReplicateRequest - SQL error when adding doc " + docid +
793
					" to DB with action " + dbaction + ": " + sqle.getMessage());
794
		} catch (MalformedURLException mue) {
795
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);
796
			logReplication.error("ReplicationService.handleForceReplicateRequest - URL error when adding doc " + docid +
797
					" to DB with action " + dbaction + ": " + mue.getMessage());
798
		} catch (SAXException se) {
799
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);
800
			logReplication.error("ReplicationService.handleForceReplicateRequest - SAX parsing error when adding doc " + docid +
801
					" to DB with action " + dbaction + ": " + se.getMessage());
802
		} catch (HandlerException he) {
803
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);
804
			logReplication.error("ReplicationService.handleForceReplicateRequest - Handler error when adding doc " + docid +
805
					" to DB with action " + dbaction + ": " + he.getMessage());
806
		} catch (IOException ioe) {
807
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);
808
			logReplication.error("ReplicationService.handleForceReplicateRequest - I/O error when adding doc " + docid +
809
					" to DB with action " + dbaction + ": " + ioe.getMessage());
810
		} catch (PermOrderException poe) {
811
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);
812
			logReplication.error("ReplicationService.handleForceReplicateRequest - Permissions order error when adding doc " + docid +
813
					" to DB with action " + dbaction + ": " + poe.getMessage());
814
		} catch (AccessControlException ace) {
815
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);
816
			logReplication.error("ReplicationService.handleForceReplicateRequest - Permissions order error when adding doc " + docid +
817
					" to DB with action " + dbaction + ": " + ace.getMessage());
818
		} catch (Exception e) {
819
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);
820
			logReplication.error("ReplicationService.handleForceReplicateRequest - General error when adding doc " + docid +
821
					" to DB with action " + dbaction + ": " + e.getMessage());
822
		} finally {
823 5014 daigle
			// Return the checked out DBConnection
824
			DBConnectionPool.returnDBConnection(dbConn, serialNumber);
825
		}//finally
826
	}
827 2298 tao
828 5014 daigle
	/*
829
	 * when a forcereplication delete request comes in, local host will delete this
830
	 * document
831
	 */
832 5755 leinfelder
	protected static void handleForceReplicateDeleteRequest(
833 5014 daigle
			Hashtable<String, String[]> params, HttpServletResponse response,
834 7840 leinfelder
			HttpServletRequest request, boolean removeAll) {
835 5014 daigle
		String server = ((String[]) params.get("server"))[0]; // the server that
836
		String docid = ((String[]) params.get("docid"))[0]; // sent the document
837
		try {
838
			logReplication.info("ReplicationService.handleForceReplicateDeleteRequest - force replication delete request from " + server);
839
			logReplication.info("ReplicationService.handleForceReplicateDeleteRequest - force replication delete docid " + docid);
840
			logReplication.info("ReplicationService.handleForceReplicateDeleteRequest - Force replication delete request from: " + server);
841
			logReplication.info("ReplicationService.handleForceReplicateDeleteRequest - Force replication delete docid: " + docid);
842 7840 leinfelder
			DocumentImpl.delete(docid, null, null, server, removeAll);
843 5014 daigle
			logReplication.info("ReplicationService.handleForceReplicateDeleteRequest - document " + docid + " was successfully deleted ");
844 6542 leinfelder
			EventLog.getInstance().log(request.getRemoteAddr(), request.getHeader("User-Agent"), REPLICATIONUSER, docid,
845 5014 daigle
					"delete");
846
			logReplication.info("ReplicationService.handleForceReplicateDeleteRequest - document " + docid + " was successfully deleted ");
847 6001 cjones
		} catch (McdbDocNotFoundException e) {
848
			logMetacat.error("ReplicationService.handleForceReplicateDeleteRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);
849
			logReplication.error("document " + docid
850
					+ " failed to delete because " + e.getMessage());
851
			logReplication.error("ReplicationService.handleForceReplicateDeleteRequest - error: " + e.getMessage());
852
		} catch (InsufficientKarmaException e) {
853
			logMetacat.error("ReplicationService.handleForceReplicateDeleteRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);
854
			logReplication.error("document " + docid
855
					+ " failed to delete because " + e.getMessage());
856
			logReplication.error("ReplicationService.handleForceReplicateDeleteRequest - error: " + e.getMessage());
857
		} catch (SQLException e) {
858
			logMetacat.error("ReplicationService.handleForceReplicateDeleteRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);
859
			logReplication.error("document " + docid
860
					+ " failed to delete because " + e.getMessage());
861
			logReplication.error("ReplicationService.handleForceReplicateDeleteRequest - error: " + e.getMessage());
862 5014 daigle
		} catch (Exception e) {
863
			logMetacat.error("ReplicationService.handleForceReplicateDeleteRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);
864
			logReplication.error("document " + docid
865
					+ " failed to delete because " + e.getMessage());
866
			logReplication.error("ReplicationService.handleForceReplicateDeleteRequest - error: " + e.getMessage());
867 2298 tao
868 5014 daigle
		}//catch
869 2298 tao
870 5014 daigle
	}
871 2286 tao
872 5014 daigle
	/**
873
	 * when a forcereplication data file request comes in, local host sends a
874
	 * readdata request to the requesting server (remote server) for the specified
875
	 * docid. Then store it in local database and file system
876
	 */
877
	protected static void handleForceReplicateDataFileRequest(Hashtable<String, String[]> params,
878
			HttpServletRequest request) {
879 2286 tao
880 5014 daigle
		//make sure there is some parameters
881
		if (params.isEmpty()) {
882
			return;
883
		}
884
		// Get remote server
885
		String server = ((String[]) params.get("server"))[0];
886
		// the docid should include rev number
887
		String docid = ((String[]) params.get("docid"))[0];
888
		// Make sure there is a docid and server
889
		if (docid == null || server == null || server.equals("")) {
890
			logMetacat.error("ReplicationService.handleForceReplicateDataFileRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);
891
			logReplication.error("ReplicationService.handleForceReplicateDataFileRequest - Didn't specify docid or server for replication");
892
			return;
893
		}
894 2286 tao
895 5014 daigle
		// Overide or not
896
		//    boolean override = false;
897
		// dbaction - update or insert
898
		String dbaction = null;
899 2286 tao
900 5014 daigle
		try {
901
			//docid was switch to two parts uinque code and rev
902
			//String uniqueCode=MetacatUtil.getDocIdFromString(docid);
903
			//int rev=MetacatUtil.getVersionFromString(docid);
904
			if (params.containsKey("dbaction")) {
905
				dbaction = ((String[]) params.get("dbaction"))[0];
906
			} else//default value is update
907
			{
908 6782 leinfelder
//				dbaction = "update";
909
				dbaction = null;
910 5014 daigle
			}
911 2286 tao
912 5014 daigle
			logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - Force replication request from: " + server);
913
			logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - Force replication docid: " + docid);
914
			logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - Force replication action: " + dbaction);
915
			// get the document info from server
916
			URL docinfourl = new URL("https://" + server + "?server="
917
					+ MetacatUtil.getLocalReplicationServerName()
918
					+ "&action=getdocumentinfo&docid=" + docid);
919 1023 tao
920 5014 daigle
			String docInfoStr = ReplicationService.getURLContent(docinfourl);
921 6102 leinfelder
922 6531 leinfelder
			// strip out the system metadata portion
923
		    String systemMetadataXML = ReplicationUtil.getSystemMetadataContent(docInfoStr);
924
		   	docInfoStr = ReplicationUtil.getContentWithoutSystemMetadata(docInfoStr);
925
926 5014 daigle
			//dih is the parser for the docinfo xml format
927
			DocInfoHandler dih = new DocInfoHandler();
928
			XMLReader docinfoParser = ReplicationHandler.initParser(dih);
929
			docinfoParser.parse(new InputSource(new StringReader(docInfoStr)));
930
			Hashtable<String, String> docinfoHash = dih.getDocInfo();
931 6015 leinfelder
932 5014 daigle
			String docName = (String) docinfoHash.get("docname");
933 2286 tao
934 5014 daigle
			String docType = (String) docinfoHash.get("doctype");
935 2286 tao
936 5014 daigle
			String docHomeServer = (String) docinfoHash.get("home_server");
937 6595 leinfelder
938
			String createdDateString = docinfoHash.get("date_created");
939
			String updatedDateString = docinfoHash.get("date_updated");
940
941 6614 leinfelder
			Date createdDate = DateTimeMarshaller.deserializeDateToUTC(createdDateString);
942
			Date updatedDate = DateTimeMarshaller.deserializeDateToUTC(updatedDateString);
943 6595 leinfelder
944 5014 daigle
			logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - docHomeServer of datafile: " + docHomeServer);
945
946 6782 leinfelder
			// in case we have a write exception, we still want to track access and sysmeta
947
			Exception writeException = null;
948
949
			// do we need the object content?
950
			if (dbaction != null && (dbaction.equals("insert") || dbaction.equals("update"))) {
951 5014 daigle
				//Get data file and store it into local file system.
952
				// sending back readdata request to server
953
				URL url = new URL("https://" + server + "?server="
954
						+ MetacatUtil.getLocalReplicationServerName()
955
						+ "&action=readdata&docid=" + docid);
956
				String datafilePath = PropertyService
957
						.getProperty("application.datafilepath");
958
959 6611 leinfelder
				InputStream inputStream = getURLStream(url);
960
961 6780 leinfelder
				//register data file into xml_documents table and write data file
962 5014 daigle
				//into file system
963
				try {
964 6611 leinfelder
					DocumentImpl.writeDataFileInReplication(inputStream,
965 6015 leinfelder
							datafilePath, docName, docType, docid, null, docHomeServer,
966 5014 daigle
							server, DocumentImpl.DOCUMENTTABLE, false, createdDate,
967
							updatedDate);
968
				} catch (Exception e) {
969
					writeException = e;
970
				}
971
972
			}
973 6782 leinfelder
974
			// process the real owner and updater
975
			DBConnection dbConn = DBConnectionPool.getDBConnection("ReplicationService.handleForceDataFileRequest");
976
	        int serialNumber = dbConn.getCheckOutSerialNumber();
977
	        dbConn.setAutoCommit(false);
978
			String user = (String) docinfoHash.get("user_owner");
979
			String updated = (String) docinfoHash.get("user_updated");
980
	        updateUserOwner(dbConn, docid, user, updated);
981
	        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
982
983
			// process system metadata
984
	        if (systemMetadataXML != null) {
985
	      	  SystemMetadata sysMeta =
986
	      		TypeMarshaller.unmarshalTypeFromStream(
987
	      				  SystemMetadata.class,
988
	      				  new ByteArrayInputStream(systemMetadataXML.getBytes("UTF-8")));
989
990
	      	  // need the guid-to-docid mapping
991
	      	  boolean mappingExists = true;
992 7045 leinfelder
	      	  mappingExists = IdentifierManager.getInstance().mappingExists(sysMeta.getIdentifier().getValue());
993 6782 leinfelder
	      	  if (!mappingExists) {
994
	      		  IdentifierManager.getInstance().createMapping(sysMeta.getIdentifier().getValue(), docid);
995
	      	  }
996
	      	  // save the system metadata
997
	      	  HazelcastService.getInstance().getSystemMetadataMap().put(sysMeta.getIdentifier(), sysMeta);
998 7812 leinfelder
	      	  // submit for indexing
999 8647 leinfelder
              MetacatSolrIndex.getInstance().submit(sysMeta.getIdentifier(), sysMeta, null, true);
1000 6782 leinfelder
	        }
1001
1002
	        // process the access control
1003 7358 leinfelder
	        try {
1004
	        	// check if we had a guid -> docid mapping
1005
	        	String docidNoRev = DocumentUtil.getDocIdFromAccessionNumber(docid);
1006 7382 leinfelder
	        	int rev = DocumentUtil.getRevisionFromAccessionNumber(docid);
1007
	        	IdentifierManager.getInstance().getGUID(docidNoRev, rev);
1008 7358 leinfelder
	        	// no need to create the mapping if we have it
1009
	        } catch (McdbDocNotFoundException mcdbe) {
1010
	        	// create mapping if we don't
1011
	        	IdentifierManager.getInstance().createMapping(docid, docid);
1012
	        }
1013 6782 leinfelder
	        Vector<XMLAccessDAO> accessControlList = dih.getAccessControlList();
1014
	        if (accessControlList != null) {
1015
	        	AccessControlForSingleFile acfsf = new AccessControlForSingleFile(docid);
1016
	        	for (XMLAccessDAO xmlAccessDAO : accessControlList) {
1017
	        		if (!acfsf.accessControlExists(xmlAccessDAO)) {
1018
	        			acfsf.insertPermissions(xmlAccessDAO);
1019
						logReplication.info("ReplicationService.handleForceReplicateRequest - document " + docid
1020
								+ " permissions added to DB");
1021
	        		}
1022
	            }
1023
	        }
1024
1025
	        // throw the write exception now -- this happens when access changes on an object
1026
			if (writeException != null) {
1027
				throw writeException;
1028
			}
1029 5014 daigle
1030 6782 leinfelder
			logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - datafile " + docid + " added to DB with "
1031
					+ "action " + dbaction);
1032
			EventLog.getInstance().log(request.getRemoteAddr(), request.getHeader("User-Agent"), REPLICATIONUSER,
1033
					docid, dbaction);
1034
1035 5014 daigle
		} catch (Exception e) {
1036 6613 leinfelder
			e.printStackTrace();
1037
			logMetacat.error("ReplicationService.handleForceReplicateDataFileRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG, e);
1038 5014 daigle
			logReplication.error("ReplicationService.handleForceReplicateDataFileRequest - Datafile " + docid
1039
					+ " failed to added to DB with " + "action " + dbaction + " because "
1040
					+ e.getMessage());
1041
			logReplication.error("ReplicationService.handleForceReplicateDataFileRequest - ERROR in MetacatReplication.handleForceDataFileReplicate"
1042
					+ "Request(): " + e.getMessage());
1043 4449 leinfelder
		}
1044 5014 daigle
	}
1045 2286 tao
1046 5014 daigle
	/**
1047
	 * Grants or denies a lock to a requesting host.
1048
	 * The servlet parameters of interrest are:
1049
	 * docid: the docid of the file the lock is being requested for
1050
	 * currentdate: the timestamp of the document on the remote server
1051
	 *
1052
	 */
1053 5755 leinfelder
	protected static void handleGetLockRequest(
1054 5014 daigle
			Hashtable<String, String[]> params, HttpServletResponse response) {
1055 1292 tao
1056 5014 daigle
		try {
1057 2286 tao
1058 5014 daigle
			String docid = ((String[]) params.get("docid"))[0];
1059
			String remoteRev = ((String[]) params.get("updaterev"))[0];
1060
			DocumentImpl requestDoc = new DocumentImpl(docid);
1061
			logReplication.info("ReplicationService.handleGetLockRequest - lock request for " + docid);
1062
			int localRevInt = requestDoc.getRev();
1063
			int remoteRevInt = Integer.parseInt(remoteRev);
1064 2286 tao
1065 5755 leinfelder
			// get a writer for sending back to response
1066
			response.setContentType("text/xml");
1067
			Writer out = response.getWriter();
1068
1069 5014 daigle
			if (remoteRevInt >= localRevInt) {
1070
				if (!fileLocks.contains(docid)) { //grant the lock if it is not already locked
1071
					fileLocks.add(0, docid); //insert at the beginning of the queue Vector
1072
					//send a message back to the the remote host authorizing the insert
1073 5755 leinfelder
					out.write("<lockgranted><docid>" + docid
1074 5014 daigle
									+ "</docid></lockgranted>");
1075
					//          lockThread = new Thread(this);
1076
					//          lockThread.setPriority(Thread.MIN_PRIORITY);
1077
					//          lockThread.start();
1078
					logReplication.info("ReplicationService.handleGetLockRequest - lock granted for " + docid);
1079
				} else { //deny the lock
1080 5755 leinfelder
					out.write("<filelocked><docid>" + docid + "</docid></filelocked>");
1081 5014 daigle
					logReplication.info("ReplicationService.handleGetLockRequest - lock denied for " + docid
1082
							+ "reason: file already locked");
1083
				}
1084
			} else {//deny the lock.
1085 5755 leinfelder
				out.write("<outdatedfile><docid>" + docid + "</docid></filelocked>");
1086 5014 daigle
				logReplication.info("ReplicationService.handleGetLockRequest - lock denied for " + docid
1087
						+ "reason: client has outdated file");
1088
			}
1089 5755 leinfelder
			out.close();
1090 5014 daigle
			//conn.close();
1091
		} catch (Exception e) {
1092
			logMetacat.error("ReplicationService.handleGetLockRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);
1093
			logReplication.error("ReplicationService.handleGetLockRequest - error requesting file lock from MetacatReplication."
1094
					+ "handleGetLockRequest: " + e.getMessage());
1095
			e.printStackTrace(System.out);
1096
		}
1097
	}
1098 2286 tao
1099 5014 daigle
	/**
1100
	 * Sends all of the xml_documents information encoded in xml to a requestor
1101
	 * the format is:
1102
	 * <!ELEMENT documentinfo (docid, docname, doctype, doctitle, user_owner,
1103
	 *                  user_updated, home_server, public_access, rev)/>
1104
	 * all of the subelements of document info are #PCDATA
1105
	 */
1106 5755 leinfelder
	protected static void handleGetDocumentInfoRequest(
1107 5014 daigle
			Hashtable<String, String[]> params, HttpServletResponse response) {
1108
		String docid = ((String[]) (params.get("docid")))[0];
1109 2286 tao
1110 5014 daigle
		try {
1111 6708 leinfelder
			// get docinfo as XML string
1112
			String docinfoXML = getDocumentInfo(docid);
1113 6531 leinfelder
1114 5755 leinfelder
			// get a writer for sending back to response
1115 5014 daigle
			response.setContentType("text/xml");
1116 5755 leinfelder
			Writer out = response.getWriter();
1117 6708 leinfelder
			out.write(docinfoXML);
1118 5755 leinfelder
			out.close();
1119 2286 tao
1120 5014 daigle
		} catch (Exception e) {
1121
			logMetacat.error("ReplicationService.handleGetDocumentInfoRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);
1122
			logReplication.error("ReplicationService.handleGetDocumentInfoRequest - error in metacatReplication.handlegetdocumentinforequest "
1123
					+ "for doc: " + docid + " : " + e.getMessage());
1124
		}
1125 2286 tao
1126 5014 daigle
	}
1127 6118 leinfelder
1128 6708 leinfelder
	public static Hashtable<String, String> getDocumentInfoMap(String docid)
1129
			throws HandlerException, AccessControlException, JiBXException,
1130
			IOException, McdbException, SAXException {
1131
1132
		// Try get docid info from remote server
1133
		DocInfoHandler dih = new DocInfoHandler();
1134
		XMLReader docinfoParser = ReplicationHandler.initParser(dih);
1135
1136
		String docInfoStr = getDocumentInfo(docid);
1137
1138
		// strip out the system metadata portion
1139
		String systemMetadataXML = ReplicationUtil.getSystemMetadataContent(docInfoStr);
1140
		docInfoStr = ReplicationUtil.getContentWithoutSystemMetadata(docInfoStr);
1141
1142
		docinfoParser.parse(new InputSource(new StringReader(docInfoStr)));
1143
		Hashtable<String, String> docinfoHash = dih.getDocInfo();
1144
1145
		return docinfoHash;
1146
	}
1147
1148 6118 leinfelder
	/**
1149 6708 leinfelder
	 * Gets a docInfo XML snippet for the replication API
1150
	 * @param docid
1151
	 * @return
1152
	 * @throws AccessControlException
1153
	 * @throws JiBXException
1154
	 * @throws IOException
1155
	 * @throws McdbException
1156
	 */
1157
	public static String getDocumentInfo(String docid) throws AccessControlException, JiBXException, IOException, McdbException {
1158
		StringBuffer sb = new StringBuffer();
1159
1160
		DocumentImpl doc = new DocumentImpl(docid);
1161
		sb.append("<documentinfo><docid>").append(docid);
1162
		sb.append("</docid>");
1163
1164
		try {
1165
			// serialize the System Metadata as XML for docinfo
1166
			String guid = IdentifierManager.getInstance().getGUID(doc.getDocID(), doc.getRev());
1167
			SystemMetadata systemMetadata = IdentifierManager.getInstance().getSystemMetadata(guid);
1168
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
1169
			TypeMarshaller.marshalTypeToOutputStream(systemMetadata, baos);
1170
			String systemMetadataXML = baos.toString("UTF-8");
1171
			sb.append("<systemMetadata>");
1172
			sb.append(systemMetadataXML);
1173
			sb.append("</systemMetadata>");
1174
		} catch(McdbDocNotFoundException e) {
1175
		  logMetacat.warn("No SystemMetadata found for: " + docid);
1176
		}
1177
1178
		Calendar created = Calendar.getInstance();
1179
		created.setTime(doc.getCreateDate());
1180
		Calendar updated = Calendar.getInstance();
1181
		updated.setTime(doc.getUpdateDate());
1182
1183 7379 leinfelder
		sb.append("<docname><![CDATA[").append(doc.getDocname());
1184
		sb.append("]]></docname><doctype>").append(doc.getDoctype());
1185 6708 leinfelder
		sb.append("</doctype>");
1186
		sb.append("<user_owner>").append(doc.getUserowner());
1187
		sb.append("</user_owner><user_updated>").append(doc.getUserupdated());
1188
		sb.append("</user_updated>");
1189
		sb.append("<date_created>");
1190
		sb.append(DateTimeMarshaller.serializeDateToUTC(doc.getCreateDate()));
1191
		sb.append("</date_created>");
1192
		sb.append("<date_updated>");
1193
		sb.append(DateTimeMarshaller.serializeDateToUTC(doc.getUpdateDate()));
1194
		sb.append("</date_updated>");
1195
		sb.append("<home_server>");
1196
		sb.append(doc.getDocHomeServer());
1197
		sb.append("</home_server>");
1198
		sb.append("<public_access>").append(doc.getPublicaccess());
1199
		sb.append("</public_access><rev>").append(doc.getRev());
1200
		sb.append("</rev>");
1201
1202
		sb.append("<accessControl>");
1203
1204
		AccessControlForSingleFile acfsf = new AccessControlForSingleFile(docid);
1205
		sb.append(acfsf.getAccessString());
1206
1207
		sb.append("</accessControl>");
1208
1209
		sb.append("</documentinfo>");
1210
1211
		return sb.toString();
1212
	}
1213
1214
	/**
1215 6118 leinfelder
	 * Sends System Metadata as XML
1216
	 */
1217
	protected static void handleGetSystemMetadataRequest(
1218
			Hashtable<String, String[]> params, HttpServletResponse response) {
1219
		String guid = ((String[]) (params.get("guid")))[0];
1220
		String systemMetadataXML = null;
1221
		try {
1222
1223
			// serialize the System Metadata as XML
1224
			SystemMetadata systemMetadata = IdentifierManager.getInstance().getSystemMetadata(guid);
1225
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
1226 6367 leinfelder
			TypeMarshaller.marshalTypeToOutputStream(systemMetadata, baos);
1227 6118 leinfelder
			systemMetadataXML = baos.toString("UTF-8");
1228
1229
			// get a writer for sending back to response
1230
			response.setContentType("text/xml");
1231
			Writer out = response.getWriter();
1232
			out.write(systemMetadataXML);
1233
			out.close();
1234 2286 tao
1235 6118 leinfelder
		} catch (Exception e) {
1236
			String msg = "ReplicationService.handleGetSystemMetadataRequest for guid: " + guid + " : " + e.getMessage();
1237
			logMetacat.error(msg);
1238
			logReplication.error(msg);
1239
		}
1240
1241
	}
1242 6119 leinfelder
1243
	/**
1244
	 * when a forcereplication request comes in, local host sends a read request
1245
	 * to the requesting server (remote server) for the specified docid. Then
1246
	 * store it in local database.
1247
	 */
1248
	protected static void handleForceReplicateSystemMetadataRequest(
1249
			Hashtable<String, String[]> params, HttpServletResponse response,
1250
			HttpServletRequest request) {
1251
		String server = ((String[]) params.get("server"))[0]; // the server that
1252
		String guid = ((String[]) params.get("guid"))[0]; // sent the document
1253
1254
		try {
1255
			logReplication.info("ReplicationService.handleForceReplicateSystemMetadataRequest - Force replication system metadata request from: " + server);
1256
			// get the system metadata from server
1257
			URL docinfourl = new URL("https://" + server + "?server="
1258
					+ MetacatUtil.getLocalReplicationServerName()
1259
					+ "&action=getsystemmetadata&guid=" + guid);
1260
1261
			String systemMetadataXML = ReplicationService.getURLContent(docinfourl);
1262
1263
			// process system metadata
1264
			if (systemMetadataXML != null) {
1265
				SystemMetadata sysMeta =
1266 6367 leinfelder
					TypeMarshaller.unmarshalTypeFromStream(
1267 6119 leinfelder
							SystemMetadata.class,
1268
							new ByteArrayInputStream(systemMetadataXML.getBytes("UTF-8")));
1269 6447 leinfelder
				HazelcastService.getInstance().getSystemMetadataMap().put(sysMeta.getIdentifier(), sysMeta);
1270 7812 leinfelder
				// submit for indexing
1271 8647 leinfelder
                MetacatSolrIndex.getInstance().submit(sysMeta.getIdentifier(), sysMeta, null, true);
1272 6119 leinfelder
			}
1273
1274
			logReplication.info("ReplicationService.handleForceReplicateSystemMetadataRequest - processed guid: " + guid);
1275 6542 leinfelder
			EventLog.getInstance().log(request.getRemoteAddr(), request.getHeader("User-Agent"), REPLICATIONUSER, guid, "systemMetadata");
1276 6118 leinfelder
1277 6119 leinfelder
		} catch (Exception e) {
1278
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG, e);
1279
			logReplication.error("ReplicationService.handleForceReplicateRequest - General error when processing guid: " + guid, e);
1280
		}
1281
	}
1282
1283 5014 daigle
	/**
1284
	 * Sends a datafile to a remote host
1285
	 */
1286
	protected static void handleGetDataFileRequest(OutputStream outPut,
1287
			Hashtable<String, String[]> params, HttpServletResponse response)
1288 2286 tao
1289 5014 daigle
	{
1290
		// File path for data file
1291
		String filepath;
1292
		// Request docid
1293
		String docId = ((String[]) (params.get("docid")))[0];
1294
		//check if the doicd is null
1295
		if (docId == null) {
1296
			logMetacat.error("ReplicationService.handleGetDataFileRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);
1297
			logReplication.error("ReplicationService.handleGetDataFileRequest - Didn't specify docid for replication");
1298
			return;
1299
		}
1300 2286 tao
1301 5014 daigle
		//try to open a https stream to test if the request server's public key
1302
		//in the key store, this is security issue
1303
		try {
1304
			filepath = PropertyService.getProperty("application.datafilepath");
1305
			String server = params.get("server")[0];
1306
			URL u = new URL("https://" + server + "?server="
1307
					+ MetacatUtil.getLocalReplicationServerName() + "&action=test");
1308
			String test = ReplicationService.getURLContent(u);
1309
			//couldn't pass the test
1310
			if (test.indexOf("successfully") == -1) {
1311
				//response.setContentType("text/xml");
1312
				//outPut.println("<error>Couldn't pass the trust test</error>");
1313
				logMetacat.error("ReplicationService.handleGetDataFileRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);
1314
				logReplication.error("ReplicationService.handleGetDataFileRequest - Couldn't pass the trust test");
1315
				return;
1316
			}
1317
		}//try
1318
		catch (Exception ee) {
1319
			return;
1320
		}//catch
1321 2286 tao
1322 5014 daigle
		if (!filepath.endsWith("/")) {
1323
			filepath += "/";
1324
		}
1325
		// Get file aboslute file name
1326
		String filename = filepath + docId;
1327 2286 tao
1328 5014 daigle
		//MIME type
1329
		String contentType = null;
1330
		if (filename.endsWith(".xml")) {
1331
			contentType = "text/xml";
1332
		} else if (filename.endsWith(".css")) {
1333
			contentType = "text/css";
1334
		} else if (filename.endsWith(".dtd")) {
1335
			contentType = "text/plain";
1336
		} else if (filename.endsWith(".xsd")) {
1337
			contentType = "text/xml";
1338
		} else if (filename.endsWith("/")) {
1339
			contentType = "text/html";
1340
		} else {
1341
			File f = new File(filename);
1342
			if (f.isDirectory()) {
1343
				contentType = "text/html";
1344
			} else {
1345
				contentType = "application/octet-stream";
1346
			}
1347
		}
1348 2286 tao
1349 5014 daigle
		// Set the mime type
1350
		response.setContentType(contentType);
1351 2286 tao
1352 5014 daigle
		// Get the content of the file
1353
		FileInputStream fin = null;
1354
		try {
1355
			// FileInputStream to metacat
1356
			fin = new FileInputStream(filename);
1357
			// 4K buffer
1358
			byte[] buf = new byte[4 * 1024];
1359
			// Read data from file input stream to byte array
1360
			int b = fin.read(buf);
1361
			// Write to outStream from byte array
1362
			while (b != -1) {
1363
				outPut.write(buf, 0, b);
1364
				b = fin.read(buf);
1365
			}
1366
			// close file input stream
1367
			fin.close();
1368 2286 tao
1369 8304 jones
		} catch (Exception e) {
1370 5014 daigle
			logMetacat.error("ReplicationService.handleGetDataFileRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);
1371
			logReplication.error("ReplicationService.handleGetDataFileRequest - error getting data file from MetacatReplication."
1372
					+ "handlGetDataFileRequest " + e.getMessage());
1373
			e.printStackTrace(System.out);
1374 8304 jones
		} finally {
1375
		    IOUtils.closeQuietly(fin);
1376
		}
1377 2286 tao
1378 5014 daigle
	}
1379
1380
	/**
1381 4854 daigle
	 * Sends a document to a remote host
1382
	 */
1383 5755 leinfelder
	protected static void handleGetDocumentRequest(
1384 4854 daigle
			Hashtable<String, String[]> params, HttpServletResponse response) {
1385 2286 tao
1386 4854 daigle
		String urlString = null;
1387
		String documentPath = null;
1388 5755 leinfelder
		String errorMsg = null;
1389 8297 jones
		FileOutputStream fos = null;
1390 8301 jones
		InputStream is = null;
1391
		OutputStream outputStream = null;
1392 4854 daigle
		try {
1393
			// try to open a https stream to test if the request server's public
1394
			// key
1395
			// in the key store, this is security issue
1396
			String server = params.get("server")[0];
1397
			urlString = "https://" + server + "?server="
1398
					+ MetacatUtil.getLocalReplicationServerName() + "&action=test";
1399
			URL u = new URL(urlString);
1400 5014 daigle
			String test = ReplicationService.getURLContent(u);
1401 4854 daigle
			// couldn't pass the test
1402
			if (test.indexOf("successfully") == -1) {
1403
				response.setContentType("text/xml");
1404 5755 leinfelder
				Writer out = response.getWriter();
1405
				out.write("<error>Couldn't pass the trust test " + test + " </error>");
1406 4854 daigle
				out.close();
1407
				return;
1408
			}
1409 2286 tao
1410 4854 daigle
			String docid = params.get("docid")[0];
1411 5014 daigle
			logReplication.debug("ReplicationService.handleGetDocumentRequest - MetacatReplication.handleGetDocumentRequest for docid: "
1412
					+ docid);
1413 4854 daigle
			DocumentImpl di = new DocumentImpl(docid);
1414 2286 tao
1415 5014 daigle
			String documentDir = PropertyService
1416
					.getProperty("application.documentfilepath");
1417 4854 daigle
			documentPath = documentDir + FileUtil.getFS() + docid;
1418 4488 daigle
1419 4854 daigle
			// if the document does not exist on disk, read it from db and write
1420
			// it to disk.
1421
			if (FileUtil.getFileStatus(documentPath) == FileUtil.DOES_NOT_EXIST
1422
					|| FileUtil.getFileSize(documentPath) == 0) {
1423 8297 jones
				fos = new FileOutputStream(documentPath);
1424 8301 jones
				is = di.toXml(fos, null, null, true);
1425 8297 jones
				fos.close();
1426 8301 jones
				is.close();
1427 4854 daigle
			}
1428 2286 tao
1429 5752 leinfelder
			// read the file from disk and send it to outputstream
1430 8301 jones
			outputStream = response.getOutputStream();
1431
			is = di.readFromFileSystem(outputStream, null, null, documentPath);
1432
			is.close();
1433
			outputStream.close();
1434 2286 tao
1435 5014 daigle
			logReplication.info("ReplicationService.handleGetDocumentRequest - document " + docid + " sent");
1436 4854 daigle
1437 5755 leinfelder
			// return to avoid continuing to the error reporting section at the end
1438
			return;
1439
1440 4854 daigle
		} catch (MalformedURLException mue) {
1441 5014 daigle
			logMetacat.error("ReplicationService.handleGetDocumentRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);
1442
			logReplication.error("ReplicationService.handleGetDocumentRequest - Url error when getting document from MetacatReplication."
1443 4854 daigle
					+ "handlGetDocumentRequest for url: " + urlString + " : "
1444
					+ mue.getMessage());
1445
			// e.printStackTrace(System.out);
1446 5755 leinfelder
1447 4854 daigle
		} catch (IOException ioe) {
1448 5014 daigle
			logMetacat.error("ReplicationService.handleGetDocumentRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);
1449
			logReplication.error("ReplicationService.handleGetDocumentRequest - I/O error when getting document from MetacatReplication."
1450
					+ "handlGetDocumentRequest for file: " + documentPath + " : "
1451
					+ ioe.getMessage());
1452 5755 leinfelder
			errorMsg = ioe.getMessage();
1453 4854 daigle
		} catch (PropertyNotFoundException pnfe) {
1454 5014 daigle
			logMetacat.error("ReplicationService.handleGetDocumentRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);
1455
			logReplication
1456
					.error("ReplicationService.handleGetDocumentRequest - Error getting property when getting document from MetacatReplication."
1457
							+ "handlGetDocumentRequest for file: "
1458
							+ documentPath
1459
							+ " : "
1460
							+ pnfe.getMessage());
1461 4854 daigle
			// e.printStackTrace(System.out);
1462 5755 leinfelder
			errorMsg = pnfe.getMessage();
1463 4854 daigle
		} catch (McdbException me) {
1464 5014 daigle
			logReplication
1465
					.error("ReplicationService.handleGetDocumentRequest - Document implementation error  getting property when getting document from MetacatReplication."
1466
							+ "handlGetDocumentRequest for file: "
1467
							+ documentPath
1468
							+ " : "
1469
							+ me.getMessage());
1470 4854 daigle
			// e.printStackTrace(System.out);
1471 5755 leinfelder
			errorMsg = me.getMessage();
1472 8810 leinfelder
		} catch (Exception e) {
1473
			logReplication
1474
			.error("ReplicationService.handleGetDocumentRequest - General exception encountered."
1475
					+ "handlGetDocumentRequest for file: "
1476
					+ documentPath
1477
					+ " : "
1478
					+ e.getMessage());
1479
			// e.printStackTrace(System.out);
1480
			errorMsg = e.getMessage();
1481 8297 jones
		} finally {
1482 8299 jones
            IOUtils.closeQuietly(fos);
1483 8301 jones
            IOUtils.closeQuietly(is);
1484
            IOUtils.closeQuietly(outputStream);
1485 4854 daigle
		}
1486 5755 leinfelder
1487
		// report any errors if we got here
1488
		response.setContentType("text/xml");
1489
		Writer out = null;
1490
		try {
1491
			response.getWriter();
1492
			out = response.getWriter();
1493
			out.write("<error>" + errorMsg + "</error>");
1494
		} catch (Exception e) {
1495
			logMetacat.error(e.getMessage(), e);
1496
		} finally {
1497
			try {
1498
				out.close();
1499
			} catch (IOException e) {
1500
				logMetacat.error(e.getMessage(), e);
1501
			}
1502
		}
1503
1504 4854 daigle
1505
	}
1506
1507 5014 daigle
	/**
1508 4854 daigle
	 * Sends a list of all of the documents on this sever along with their
1509
	 * revision numbers. The format is: <!ELEMENT replication (server, updates)>
1510
	 * <!ELEMENT server (#PCDATA)> <!ELEMENT updates ((updatedDocument |
1511
	 * deleteDocument | revisionDocument)*)> <!ELEMENT updatedDocument (docid,
1512
	 * rev, datafile*)> <!ELEMENT deletedDocument (docid, rev)> <!ELEMENT
1513
	 * revisionDocument (docid, rev, datafile*)> <!ELEMENT docid (#PCDATA)>
1514
	 * <!ELEMENT rev (#PCDATA)> <!ELEMENT datafile (#PCDATA)> note that the rev
1515
	 * in deletedDocument is always empty. I just left it in there to make the
1516
	 * parser implementation easier.
1517
	 */
1518 5755 leinfelder
	protected static void handleUpdateRequest(Hashtable<String, String[]> params,
1519 5014 daigle
			HttpServletResponse response) {
1520
		// Checked out DBConnection
1521
		DBConnection dbConn = null;
1522
		// DBConenction serial number when checked it out
1523
		int serialNumber = -1;
1524
		PreparedStatement pstmt = null;
1525
		// Server list to store server info of xml_replication table
1526
		ReplicationServerList serverList = null;
1527 5755 leinfelder
1528
		// a writer for response
1529
		Writer out = null;
1530 2286 tao
1531 5014 daigle
		try {
1532 5755 leinfelder
			// get writer, TODO: encoding?
1533
			response.setContentType("text/xml");
1534
			out = response.getWriter();
1535
1536 5014 daigle
			// Check out a DBConnection from pool
1537
			dbConn = DBConnectionPool
1538
					.getDBConnection("MetacatReplication.handleUpdateRequest");
1539
			serialNumber = dbConn.getCheckOutSerialNumber();
1540
			// Create a server list from xml_replication table
1541
			serverList = new ReplicationServerList();
1542 2286 tao
1543 5014 daigle
			// Get remote server name from param
1544
			String server = ((String[]) params.get("server"))[0];
1545
			// If no servr name in param, return a error
1546
			if (server == null || server.equals("")) {
1547 5755 leinfelder
				out.write("<error>Request didn't specify server name</error>");
1548 5014 daigle
				out.close();
1549
				return;
1550
			}//if
1551 2286 tao
1552 5014 daigle
			//try to open a https stream to test if the request server's public key
1553
			//in the key store, this is security issue
1554 5440 berkley
			String testUrl = "https://" + server + "?server="
1555 5441 berkley
            + MetacatUtil.getLocalReplicationServerName() + "&action=test";
1556 5440 berkley
			logReplication.info("Running trust test: " + testUrl);
1557
			URL u = new URL(testUrl);
1558 5014 daigle
			String test = ReplicationService.getURLContent(u);
1559 5441 berkley
			logReplication.info("Ouput from test is '" + test + "'");
1560 5014 daigle
			//couldn't pass the test
1561
			if (test.indexOf("successfully") == -1) {
1562 5441 berkley
			    logReplication.error("Trust test failed.");
1563 5755 leinfelder
				out.write("<error>Couldn't pass the trust test</error>");
1564 5014 daigle
				out.close();
1565
				return;
1566
			}
1567 5441 berkley
			logReplication.info("Trust test succeeded.");
1568 2286 tao
1569 5014 daigle
			// Check if local host configure to replicate xml documents to remote
1570
			// server. If not send back a error message
1571
			if (!serverList.getReplicationValue(server)) {
1572 5755 leinfelder
				out.write("<error>Configuration not allow to replicate document to you</error>");
1573 5014 daigle
				out.close();
1574
				return;
1575
			}//if
1576 2286 tao
1577 5014 daigle
			// Store the sql command
1578
			StringBuffer docsql = new StringBuffer();
1579
			StringBuffer revisionSql = new StringBuffer();
1580 7356 leinfelder
1581 5014 daigle
			// Store the data set file
1582
			Vector<Vector<String>> packageFiles = new Vector<Vector<String>>();
1583 2286 tao
1584 5014 daigle
			// Append local server's name and replication servlet to doclist
1585 7356 leinfelder
			out.append("<?xml version=\"1.0\"?><replication>");
1586
			out.append("<server>")
1587 5014 daigle
					.append(MetacatUtil.getLocalReplicationServerName());
1588
			//doclist.append(util.getProperty("replicationpath"));
1589 7356 leinfelder
			out.append("</server><updates>");
1590 2286 tao
1591 5014 daigle
			// Get correct docid that reside on this server according the requesting
1592
			// server's replicate and data replicate value in xml_replication table
1593 5319 jones
			docsql.append(DatabaseService.getInstance().getDBAdapter().getReplicationDocumentListSQL());
1594 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)) ");
1595
			revisionSql.append("select docid, rev, doctype from xml_revisions ");
1596
			// If the localhost is not a hub to the remote server, only replicate
1597
			// the docid' which home server is local host (server_location =1)
1598
			if (!serverList.getHubValue(server)) {
1599
				String serverLocationDoc = " and a.server_location = 1";
1600
				String serverLocationRev = "where server_location = 1";
1601
				docsql.append(serverLocationDoc);
1602
				revisionSql.append(serverLocationRev);
1603
			}
1604
			logReplication.info("ReplicationService.handleUpdateRequest - Doc sql: " + docsql.toString());
1605 2286 tao
1606 5014 daigle
			// Get any deleted documents
1607 7636 jones
			StringBuffer delsql = new StringBuffer();
1608 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 ");
1609 7636 jones
1610 5014 daigle
			// If the localhost is not a hub to the remote server, only replicate
1611
			// the docid' which home server is local host (server_location =1)
1612
			if (!serverList.getHubValue(server)) {
1613 7636 jones
				delsql.append("and t1.server_location = 1");
1614 5014 daigle
			}
1615
			logReplication.info("ReplicationService.handleUpdateRequest - Deleted sql: " + delsql.toString());
1616 2286 tao
1617 5014 daigle
			// Get docid list of local host
1618
			pstmt = dbConn.prepareStatement(docsql.toString());
1619
			pstmt.execute();
1620
			ResultSet rs = pstmt.getResultSet();
1621
			boolean tablehasrows = rs.next();
1622
			//If metacat configed to replicate data file
1623
			//if ((util.getProperty("replicationsenddata")).equals("on"))
1624
			boolean replicateData = serverList.getDataReplicationValue(server);
1625
			if (replicateData) {
1626
				while (tablehasrows) {
1627
					String recordDoctype = rs.getString(3);
1628
					Vector<String> packagedoctypes = MetacatUtil
1629
							.getOptionList(PropertyService
1630
									.getProperty("xml.packagedoctype"));
1631
					//if this is a package file, put it at the end
1632
					//because if a package file is read before all of the files it
1633
					//refers to are loaded then there is an error
1634
					if (recordDoctype != null && !packagedoctypes.contains(recordDoctype)) {
1635
						//If this is not data file
1636
						if (!recordDoctype.equals("BIN")) {
1637
							//for non-data file document
1638 7356 leinfelder
							out.append("<updatedDocument>");
1639
							out.append("<docid>").append(rs.getString(1));
1640
							out.append("</docid><rev>" + rs.getInt(2));
1641
							out.append("</rev>");
1642
							out.append("</updatedDocument>");
1643 5014 daigle
						}//if
1644
						else {
1645
							//for data file document, in datafile attributes
1646
							//we put "datafile" value there
1647 7356 leinfelder
							out.append("<updatedDocument>");
1648
							out.append("<docid>").append(rs.getString(1));
1649
							out.append("</docid><rev>" + rs.getInt(2));
1650
							out.append("</rev>");
1651
							out.append("<datafile>");
1652
							out.append(DATA_FILE_FLAG);
1653
							out.append("</datafile>");
1654
							out.append("</updatedDocument>");
1655 5014 daigle
						}//else
1656
					}//if packagedoctpes
1657
					else { //the package files are saved to be put into the xml later.
1658
						Vector<String> v = new Vector<String>();
1659
						v.add(rs.getString(1));
1660
						v.add(String.valueOf(rs.getInt(2)));
1661
						packageFiles.add(v);
1662
					}//esle
1663
					tablehasrows = rs.next();
1664
				}//while
1665
			}//if
1666
			else //metacat was configured not to send data file
1667
			{
1668
				while (tablehasrows) {
1669
					String recordDoctype = rs.getString(3);
1670
					if (!recordDoctype.equals("BIN")) { //don't replicate data files
1671
						Vector<String> packagedoctypes = MetacatUtil
1672
								.getOptionList(PropertyService
1673
										.getProperty("xml.packagedoctype"));
1674
						if (recordDoctype != null
1675
								&& !packagedoctypes.contains(recordDoctype)) { //if this is a package file, put it at the end
1676
							//because if a package file is read before all of the files it
1677
							//refers to are loaded then there is an error
1678 7356 leinfelder
							out.append("<updatedDocument>");
1679
							out.append("<docid>" + rs.getString(1));
1680
							out.append("</docid><rev>" + rs.getInt(2));
1681
							out.append("</rev>");
1682
							out.append("</updatedDocument>");
1683 5014 daigle
						} else { //the package files are saved to be put into the xml later.
1684
							Vector<String> v = new Vector<String>();
1685
							v.add(rs.getString(1));
1686
							v.add(String.valueOf(rs.getInt(2)));
1687
							packageFiles.add(v);
1688
						}
1689
					}//if
1690
					tablehasrows = rs.next();
1691
				}//while
1692
			}//else
1693 2286 tao
1694 5014 daigle
			pstmt = dbConn.prepareStatement(delsql.toString());
1695
			//usage count should increas 1
1696
			dbConn.increaseUsageCount(1);
1697 2286 tao
1698 5014 daigle
			pstmt.execute();
1699
			rs = pstmt.getResultSet();
1700
			tablehasrows = rs.next();
1701
			while (tablehasrows) { //handle the deleted documents
1702 7356 leinfelder
				out.append("<deletedDocument><docid>").append(rs.getString(1));
1703
				out.append("</docid><rev></rev></deletedDocument>");
1704 5014 daigle
				//note that rev is always empty for deleted docs
1705
				tablehasrows = rs.next();
1706
			}
1707 2286 tao
1708 5014 daigle
			//now we can put the package files into the xml results
1709
			for (int i = 0; i < packageFiles.size(); i++) {
1710
				Vector<String> v = packageFiles.elementAt(i);
1711 7356 leinfelder
				out.append("<updatedDocument>");
1712
				out.append("<docid>").append(v.elementAt(0));
1713
				out.append("</docid><rev>");
1714
				out.append(v.elementAt(1));
1715
				out.append("</rev>");
1716
				out.append("</updatedDocument>");
1717 5014 daigle
			}
1718
			// add revision doc list
1719 7356 leinfelder
			out.append(prepareRevisionDoc(dbConn, revisionSql.toString(),
1720 5014 daigle
					replicateData));
1721 2286 tao
1722 7356 leinfelder
			out.append("</updates></replication>");
1723
			logReplication.info("ReplicationService.handleUpdateRequest - done writing to output stream.");
1724 5014 daigle
			pstmt.close();
1725
			//conn.close();
1726 2286 tao
1727 5014 daigle
		} catch (Exception e) {
1728
			logMetacat.error("ReplicationService.handleUpdateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);
1729
			logReplication.error("ReplicationService.handleUpdateRequest - error in MetacatReplication." + "handleupdaterequest: "
1730
					+ e.getMessage());
1731
			//e.printStackTrace(System.out);
1732 5755 leinfelder
			try {
1733
				out.write("<error>" + e.getMessage() + "</error>");
1734
			} catch (IOException e1) {
1735
				logMetacat.error(e1.getMessage(), e1);
1736
			}
1737 5014 daigle
		} finally {
1738
			try {
1739
				pstmt.close();
1740
			}//try
1741
			catch (SQLException ee) {
1742
				logMetacat.error("ReplicationService.handleUpdateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);
1743
				logReplication.error("ReplicationService.handleUpdateRequest - Error in MetacatReplication."
1744
						+ "handleUpdaterequest to close pstmt: " + ee.getMessage());
1745
			}//catch
1746
			finally {
1747
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1748
			}//finally
1749 5755 leinfelder
			try {
1750
				out.close();
1751
			} catch (IOException e) {
1752
				logMetacat.error(e.getMessage(), e);
1753
			}
1754 5014 daigle
		}//finally
1755 2286 tao
1756 5014 daigle
	}//handlUpdateRequest
1757 2286 tao
1758 6015 leinfelder
	/**
1759
	 *
1760
	 * @param dbConn connection for doing the update
1761
	 * @param docid the document id to update
1762
	 * @param owner the user_owner
1763
	 * @param updater the user_updated
1764
	 * @throws SQLException
1765
	 */
1766
	public static void updateUserOwner(DBConnection dbConn, String docid, String owner, String updater) throws SQLException {
1767
1768
		String sql =
1769
			"UPDATE xml_documents " +
1770
			"SET user_owner = ?, " +
1771
			"user_updated = ? " +
1772
			"WHERE docid = ?;";
1773
		PreparedStatement pstmt = dbConn.prepareStatement(sql);
1774
		//usage count should increas 1
1775
		dbConn.increaseUsageCount(1);
1776
1777
		docid = DocumentUtil.getSmartDocId(docid);
1778
		pstmt.setString(1, owner);
1779
		pstmt.setString(2, updater);
1780
		pstmt.setString(3, docid);
1781
		pstmt.execute();
1782
		pstmt.close();
1783
1784
		dbConn.commit();
1785
	}
1786
1787 5014 daigle
	/*
1788
	 * This method will get the xml string for document in xml_revision
1789
	 * The schema look like <!ELEMENT revisionDocument (docid, rev, datafile*)>
1790
	 */
1791
	private static String prepareRevisionDoc(DBConnection dbConn, String revSql,
1792
			boolean replicateData) throws Exception {
1793
		logReplication.warn("ReplicationService.prepareRevisionDoc - The revision document sql is " + revSql);
1794
		StringBuffer revDocList = new StringBuffer();
1795
		PreparedStatement pstmt = dbConn.prepareStatement(revSql);
1796
		//usage count should increas 1
1797
		dbConn.increaseUsageCount(1);
1798 2286 tao
1799 5014 daigle
		pstmt.execute();
1800
		ResultSet rs = pstmt.getResultSet();
1801 7337 leinfelder
		logReplication.warn("Processing replication revision for documents");
1802 7338 leinfelder
		while (rs.next()) {
1803 5014 daigle
			String recordDoctype = rs.getString(3);
1804 2286 tao
1805 5014 daigle
			//If this is data file and it isn't configured to replicate data
1806
			if (recordDoctype.equals("BIN") && !replicateData) {
1807 7338 leinfelder
				logMetacat.debug("SKipping data file because data replication is not configured");
1808
1809 5014 daigle
				// do nothing
1810
			} else {
1811 7337 leinfelder
				String docid = rs.getString(1);
1812
				int rev = rs.getInt(2);
1813
				logMetacat.debug("Processing replication revision for docid: " + docid + "." + rev);
1814 2597 tao
1815 5014 daigle
				revDocList.append("<revisionDocument>");
1816 7337 leinfelder
				revDocList.append("<docid>").append(docid);
1817
				revDocList.append("</docid><rev>").append(rev);
1818 5014 daigle
				revDocList.append("</rev>");
1819
				// data file
1820
				if (recordDoctype.equals("BIN")) {
1821
					revDocList.append("<datafile>");
1822 7337 leinfelder
					revDocList.append(DATA_FILE_FLAG);
1823 5014 daigle
					revDocList.append("</datafile>");
1824
				}
1825
				revDocList.append("</revisionDocument>");
1826 2286 tao
1827 5014 daigle
			}//else
1828
		}
1829
		//System.out.println("The revision list is"+ revDocList.toString());
1830
		return revDocList.toString();
1831
	}
1832 2286 tao
1833 5014 daigle
	/**
1834
	 * Returns the xml_catalog table encoded in xml
1835
	 */
1836
	public static String getCatalogXML() {
1837 5755 leinfelder
		return handleGetCatalogRequest(null, null, false);
1838 5014 daigle
	}
1839 2286 tao
1840 5014 daigle
	/**
1841
	 * Sends the contents of the xml_catalog table encoded in xml
1842
	 * The xml format is:
1843
	 * <!ELEMENT xml_catalog (row*)>
1844
	 * <!ELEMENT row (entry_type, source_doctype, target_doctype, public_id,
1845
	 *                system_id)>
1846
	 * All of the sub elements of row are #PCDATA
1847 2286 tao
1848 5014 daigle
	 * If printFlag == false then do not print to out.
1849
	 */
1850 5755 leinfelder
	protected static String handleGetCatalogRequest(
1851 5014 daigle
			Hashtable<String, String[]> params, HttpServletResponse response,
1852
			boolean printFlag) {
1853
		DBConnection dbConn = null;
1854
		int serialNumber = -1;
1855
		PreparedStatement pstmt = null;
1856 5755 leinfelder
		Writer out = null;
1857 5014 daigle
		try {
1858 5755 leinfelder
			// get writer, TODO: encoding?
1859 5944 berkley
		    if(printFlag)
1860
		    {
1861
		        response.setContentType("text/xml");
1862
		        out = response.getWriter();
1863
		    }
1864 5014 daigle
			/*conn = MetacatReplication.getDBConnection("MetacatReplication." +
1865
			                                          "handleGetCatalogRequest");*/
1866
			dbConn = DBConnectionPool
1867
					.getDBConnection("MetacatReplication.handleGetCatalogRequest");
1868
			serialNumber = dbConn.getCheckOutSerialNumber();
1869
			pstmt = dbConn.prepareStatement("select entry_type, "
1870
					+ "source_doctype, target_doctype, public_id, "
1871
					+ "system_id from xml_catalog");
1872
			pstmt.execute();
1873
			ResultSet rs = pstmt.getResultSet();
1874
			boolean tablehasrows = rs.next();
1875
			StringBuffer sb = new StringBuffer();
1876
			sb.append("<?xml version=\"1.0\"?><xml_catalog>");
1877
			while (tablehasrows) {
1878
				sb.append("<row><entry_type>").append(rs.getString(1));
1879
				sb.append("</entry_type><source_doctype>").append(rs.getString(2));
1880
				sb.append("</source_doctype><target_doctype>").append(rs.getString(3));
1881
				sb.append("</target_doctype><public_id>").append(rs.getString(4));
1882
				// system id may not have server url on front.  Add it if not.
1883
				String systemID = rs.getString(5);
1884
				if (!systemID.startsWith("http://")) {
1885
					systemID = SystemUtil.getContextURL() + systemID;
1886
				}
1887
				sb.append("</public_id><system_id>").append(systemID);
1888
				sb.append("</system_id></row>");
1889 2286 tao
1890 5014 daigle
				tablehasrows = rs.next();
1891
			}
1892
			sb.append("</xml_catalog>");
1893
			//conn.close();
1894
			if (printFlag) {
1895
				response.setContentType("text/xml");
1896 5755 leinfelder
				out.write(sb.toString());
1897 5014 daigle
			}
1898
			pstmt.close();
1899
			return sb.toString();
1900
		} catch (Exception e) {
1901
			logMetacat.error("ReplicationService.handleGetCatalogRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);
1902
			logReplication.error("ReplicationService.handleGetCatalogRequest - error in MetacatReplication.handleGetCatalogRequest:"
1903
					+ e.getMessage());
1904
			e.printStackTrace(System.out);
1905
			if (printFlag) {
1906 5755 leinfelder
				try {
1907
					out.write("<error>" + e.getMessage() + "</error>");
1908
				} catch (IOException e1) {
1909
					logMetacat.error(e1.getMessage(), e1);
1910
				}
1911 5014 daigle
			}
1912
		} finally {
1913
			try {
1914
				pstmt.close();
1915
			}//try
1916
			catch (SQLException ee) {
1917
				logMetacat.error("ReplicationService.handleGetCatalogRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);
1918
				logReplication.error("ReplicationService.handleGetCatalogRequest - Error in MetacatReplication.handleGetCatalogRequest: "
1919
						+ ee.getMessage());
1920
			}//catch
1921
			finally {
1922
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1923
			}//finally
1924 5755 leinfelder
			if (out != null) {
1925
				try {
1926
					out.close();
1927
				} catch (IOException e1) {
1928
					logMetacat.error(e1.getMessage(), e1);
1929
				}
1930
			}
1931 5014 daigle
		}//finally
1932 2286 tao
1933 5014 daigle
		return null;
1934
	}
1935 2286 tao
1936 5014 daigle
	/**
1937
	 * Sends the current system date to the remote server.  Using this action
1938
	 * for replication gets rid of any problems with syncronizing clocks
1939
	 * because a time specific to a document is always kept on its home server.
1940
	 */
1941 5755 leinfelder
	protected static void handleGetTimeRequest(
1942 5014 daigle
			Hashtable<String, String[]> params, HttpServletResponse response) {
1943 5755 leinfelder
1944 6614 leinfelder
		// use standard format -- the receiving end wants this too
1945
		String dateString = DateTimeMarshaller.serializeDateToUTC(Calendar.getInstance().getTime());
1946 6595 leinfelder
1947 5755 leinfelder
		// get a writer for sending back to response
1948 5014 daigle
		response.setContentType("text/xml");
1949 5755 leinfelder
		Writer out = null;
1950
		try {
1951
			out = response.getWriter();
1952
			out.write("<timestamp>" + dateString + "</timestamp>");
1953
			out.close();
1954
		} catch (IOException e) {
1955
			logMetacat.error(e.getMessage(), e);
1956
		}
1957
1958 5014 daigle
	}
1959 2286 tao
1960 5014 daigle
	/**
1961
	 * this method handles the timeout for a file lock.  when a lock is
1962
	 * granted it is granted for 30 seconds.  When this thread runs out
1963
	 * it deletes the docid from the queue, thus eliminating the lock.
1964
	 */
1965
	public void run() {
1966
		try {
1967
			logReplication.info("ReplicationService.run - thread started for docid: "
1968
					+ (String) fileLocks.elementAt(0));
1969 2286 tao
1970 5014 daigle
			Thread.sleep(30000); //the lock will expire in 30 seconds
1971
			logReplication.info("thread for docid: "
1972
					+ (String) fileLocks.elementAt(fileLocks.size() - 1) + " exiting.");
1973 2286 tao
1974 5014 daigle
			fileLocks.remove(fileLocks.size() - 1);
1975
			//fileLocks is treated as a FIFO queue.  If there are more than one lock
1976
			//in the vector, the first one inserted will be removed.
1977
		} catch (Exception e) {
1978
			logMetacat.error("ReplicationService.run - " + ReplicationService.METACAT_REPL_ERROR_MSG);
1979
			logReplication.error("ReplicationService.run - error in file lock thread from "
1980
					+ "MetacatReplication.run: " + e.getMessage());
1981
		}
1982
	}
1983 2286 tao
1984 5014 daigle
	/**
1985
	 * Returns the name of a server given a serverCode
1986
	 * @param serverCode the serverid of the server
1987
	 * @return the servername or null if the specified serverCode does not
1988
	 *         exist.
1989
	 */
1990
	public static String getServerNameForServerCode(int serverCode) {
1991
		//System.out.println("serverid: " + serverCode);
1992
		DBConnection dbConn = null;
1993
		int serialNumber = -1;
1994
		PreparedStatement pstmt = null;
1995
		try {
1996
			dbConn = DBConnectionPool.getDBConnection("MetacatReplication.getServer");
1997
			serialNumber = dbConn.getCheckOutSerialNumber();
1998
			String sql = new String("select server from "
1999 6595 leinfelder
					+ "xml_replication where serverid = ?");
2000 5014 daigle
			pstmt = dbConn.prepareStatement(sql);
2001 6595 leinfelder
			pstmt.setInt(1, serverCode);
2002 5014 daigle
			//System.out.println("getserver sql: " + sql);
2003
			pstmt.execute();
2004
			ResultSet rs = pstmt.getResultSet();
2005
			boolean tablehasrows = rs.next();
2006
			if (tablehasrows) {
2007
				//System.out.println("server: " + rs.getString(1));
2008
				return rs.getString(1);
2009
			}
2010 2286 tao
2011 5014 daigle
			//conn.close();
2012
		} catch (Exception e) {
2013
			logMetacat.error("ReplicationService.getServerNameForServerCode - " + ReplicationService.METACAT_REPL_ERROR_MSG);
2014
			logReplication.error("ReplicationService.getServerNameForServerCode - Error in MetacatReplication.getServer: " + e.getMessage());
2015
		} finally {
2016
			try {
2017
				pstmt.close();
2018
			}//try
2019
			catch (SQLException ee) {
2020
				logMetacat.error("ReplicationService.getServerNameForServerCode - " + ReplicationService.METACAT_REPL_ERROR_MSG);
2021
				logReplication.error("ReplicationService.getServerNameForServerCode - Error in MetacactReplication.getserver: "
2022
						+ ee.getMessage());
2023
			}//catch
2024
			finally {
2025
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
2026
			}//fianlly
2027
		}//finally
2028 2286 tao
2029 5014 daigle
		return null;
2030
		//return null if the server does not exist
2031
	}
2032 2286 tao
2033 5014 daigle
	/**
2034
	 * Returns a server code given a server name
2035
	 * @param server the name of the server
2036
	 * @return integer > 0 representing the code of the server, 0 if the server
2037
	 *  does not exist.
2038
	 */
2039
	public static int getServerCodeForServerName(String server) throws ServiceException {
2040
		DBConnection dbConn = null;
2041
		int serialNumber = -1;
2042
		PreparedStatement pstmt = null;
2043
		int serverCode = 0;
2044 2286 tao
2045 5014 daigle
		try {
2046 837 bojilova
2047 5014 daigle
			//conn = util.openDBConnection();
2048
			dbConn = DBConnectionPool.getDBConnection("MetacatReplication.getServerCode");
2049
			serialNumber = dbConn.getCheckOutSerialNumber();
2050
			pstmt = dbConn.prepareStatement("SELECT serverid FROM xml_replication "
2051 6595 leinfelder
					+ "WHERE server LIKE ?");
2052
			pstmt.setString(1, server);
2053 5014 daigle
			pstmt.execute();
2054
			ResultSet rs = pstmt.getResultSet();
2055
			boolean tablehasrows = rs.next();
2056
			if (tablehasrows) {
2057
				serverCode = rs.getInt(1);
2058
				pstmt.close();
2059
				//conn.close();
2060
				return serverCode;
2061
			}
2062 837 bojilova
2063 5014 daigle
		} catch (SQLException sqle) {
2064
			throw new ServiceException("ReplicationService.getServerCodeForServerName - "
2065
					+ "SQL error when getting server code: " + sqle.getMessage());
2066 2286 tao
2067 5014 daigle
		} finally {
2068
			try {
2069
				pstmt.close();
2070
				//conn.close();
2071
			}//try
2072
			catch (Exception ee) {
2073
				logMetacat.error("ReplicationService.getServerCodeForServerName - " + ReplicationService.METACAT_REPL_ERROR_MSG);
2074
				logReplication.error("ReplicationService.getServerNameForServerCode - Error in MetacatReplicatio.getServerCode: "
2075
						+ ee.getMessage());
2076 837 bojilova
2077 5014 daigle
			}//catch
2078
			finally {
2079
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
2080
			}//finally
2081
		}//finally
2082 2286 tao
2083 5014 daigle
		return serverCode;
2084
	}
2085 8689 leinfelder
2086
	/**
2087
	 * Returns a Map of serverCode=serverName
2088
	 * @return Map of server codes to names (URIs)
2089
	 */
2090
	public static Map<Integer, String> getServerCodes() throws ServiceException {
2091
		DBConnection dbConn = null;
2092
		int serialNumber = -1;
2093
		PreparedStatement pstmt = null;
2094
2095
		Map<Integer, String> codes = new HashMap<Integer, String>();
2096 2286 tao
2097 8689 leinfelder
		try {
2098
2099
			dbConn = DBConnectionPool.getDBConnection("MetacatReplication.getServerCodes");
2100
			serialNumber = dbConn.getCheckOutSerialNumber();
2101
			pstmt = dbConn.prepareStatement("SELECT serverid, server FROM xml_replication ");
2102
			pstmt.execute();
2103
			ResultSet rs = pstmt.getResultSet();
2104
			while (rs.next()) {
2105
				int serverCode = rs.getInt(1);
2106
				String server = rs.getString(2);
2107
				codes.put(serverCode, server);
2108
			}
2109
			pstmt.close();
2110
2111
		} catch (SQLException sqle) {
2112
			throw new ServiceException("ReplicationService.getServerCodes - "
2113
					+ "SQL error when getting server map: " + sqle.getMessage());
2114
2115
		} finally {
2116
			try {
2117
				pstmt.close();
2118
			}//try
2119
			catch (Exception ee) {
2120
				logMetacat.error("ReplicationService.getServerCodes - " + ReplicationService.METACAT_REPL_ERROR_MSG);
2121
				logReplication.error("ReplicationService.getServerCodes - Error in MetacatReplicatio.getServerCodes: "
2122
						+ ee.getMessage());
2123
2124
			}//catch
2125
			finally {
2126
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
2127
			}//finally
2128
		}//finally
2129
2130
		return codes;
2131
	}
2132
2133 5014 daigle
	/**
2134
	 * Method to get a host server information for given docid
2135
	 * @param conn a connection to the database
2136
	 */
2137
	public static Hashtable<String, String> getHomeServerInfoForDocId(String docId) {
2138
		Hashtable<String, String> sl = new Hashtable<String, String>();
2139
		DBConnection dbConn = null;
2140
		int serialNumber = -1;
2141 5027 daigle
		docId = DocumentUtil.getDocIdFromString(docId);
2142 5014 daigle
		PreparedStatement pstmt = null;
2143
		int serverLocation;
2144
		try {
2145
			//get conection
2146
			dbConn = DBConnectionPool.getDBConnection("ReplicationHandler.getHomeServer");
2147
			serialNumber = dbConn.getCheckOutSerialNumber();
2148
			//get a server location from xml_document table
2149
			pstmt = dbConn.prepareStatement("select server_location from xml_documents "
2150
					+ "where docid = ?");
2151
			pstmt.setString(1, docId);
2152
			pstmt.execute();
2153
			ResultSet serverName = pstmt.getResultSet();
2154
			//get a server location
2155
			if (serverName.next()) {
2156
				serverLocation = serverName.getInt(1);
2157
				pstmt.close();
2158
			} else {
2159
				pstmt.close();
2160
				//ut.returnConnection(conn);
2161
				return null;
2162
			}
2163
			pstmt = dbConn.prepareStatement("select server, last_checked, replicate "
2164
					+ "from xml_replication where serverid = ?");
2165
			//increase usage count
2166
			dbConn.increaseUsageCount(1);
2167
			pstmt.setInt(1, serverLocation);
2168
			pstmt.execute();
2169
			ResultSet rs = pstmt.getResultSet();
2170
			boolean tableHasRows = rs.next();
2171
			if (tableHasRows) {
2172 2286 tao
2173 5014 daigle
				String server = rs.getString(1);
2174
				String last_checked = rs.getString(2);
2175
				if (!server.equals("localhost")) {
2176
					sl.put(server, last_checked);
2177
				}
2178 2286 tao
2179 5014 daigle
			} else {
2180
				pstmt.close();
2181
				//ut.returnConnection(conn);
2182
				return null;
2183
			}
2184
			pstmt.close();
2185
		} catch (Exception e) {
2186
			logMetacat.error("ReplicationService.getHomeServerInfoForDocId - " + ReplicationService.METACAT_REPL_ERROR_MSG);
2187
			logReplication.error("ReplicationService.getHomeServerInfoForDocId - error in replicationHandler.getHomeServer(): "
2188
					+ e.getMessage());
2189
		} finally {
2190
			try {
2191
				pstmt.close();
2192
				//ut.returnConnection(conn);
2193
			} catch (Exception ee) {
2194
				logMetacat.error("ReplicationService.getHomeServerInfoForDocId - " + ReplicationService.METACAT_REPL_ERROR_MSG);
2195
				logReplication.error("ReplicationService.getHomeServerInfoForDocId - Eror irn rplicationHandler.getHomeServer() "
2196
						+ "to close pstmt: " + ee.getMessage());
2197
			} finally {
2198
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
2199
			}
2200 2286 tao
2201 5014 daigle
		}//finally
2202
		return sl;
2203
	}
2204 2286 tao
2205 5014 daigle
	/**
2206
	 * Returns a home server location  given a accnum
2207
	 * @param accNum , given accNum for a document
2208
	 *
2209
	 */
2210
	public static int getHomeServerCodeForDocId(String accNum) throws ServiceException {
2211
		DBConnection dbConn = null;
2212
		int serialNumber = -1;
2213
		PreparedStatement pstmt = null;
2214
		int serverCode = 1;
2215 5027 daigle
		String docId = DocumentUtil.getDocIdFromString(accNum);
2216 2286 tao
2217 5014 daigle
		try {
2218 1292 tao
2219 5014 daigle
			// Get DBConnection
2220
			dbConn = DBConnectionPool
2221
					.getDBConnection("ReplicationHandler.getServerLocation");
2222
			serialNumber = dbConn.getCheckOutSerialNumber();
2223
			pstmt = dbConn.prepareStatement("SELECT server_location FROM xml_documents "
2224 6595 leinfelder
					+ "WHERE docid LIKE ? ");
2225
			pstmt.setString(1, docId);
2226 5014 daigle
			pstmt.execute();
2227
			ResultSet rs = pstmt.getResultSet();
2228
			boolean tablehasrows = rs.next();
2229
			//If a document is find, return the server location for it
2230
			if (tablehasrows) {
2231
				serverCode = rs.getInt(1);
2232
				pstmt.close();
2233
				//conn.close();
2234
				return serverCode;
2235
			}
2236
			//if couldn't find in xml_documents table, we think server code is 1
2237
			//(this is new document)
2238
			else {
2239
				pstmt.close();
2240
				//conn.close();
2241
				return serverCode;
2242
			}
2243 1292 tao
2244 5014 daigle
		} catch (SQLException sqle) {
2245
			throw new ServiceException("ReplicationService.getHomeServerCodeForDocId - "
2246
					+ "SQL error when getting home server code for docid: " + docId + " : "
2247
					+ sqle.getMessage());
2248 2286 tao
2249 5014 daigle
		} finally {
2250
			try {
2251
				pstmt.close();
2252
				//conn.close();
2253 2286 tao
2254 5014 daigle
			} catch (SQLException sqle) {
2255
				logMetacat.error("ReplicationService.getHomeServerCodeForDocId - " + ReplicationService.METACAT_REPL_ERROR_MSG);
2256
				logReplication.error("ReplicationService.getHomeServerCodeForDocId - ReplicationService.getHomeServerCodeForDocId - "
2257
						+ "SQL error when getting home server code for docid: " + docId + " : "
2258
						+ sqle.getMessage());
2259
			} finally {
2260
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
2261
			}//finally
2262
		}//finally
2263
		//return serverCode;
2264
	}
2265 1292 tao
2266 5014 daigle
	/**
2267
	 * This method returns the content of a url
2268
	 * @param u the url to return the content from
2269
	 * @return a string representing the content of the url
2270
	 * @throws java.io.IOException
2271
	 */
2272 8810 leinfelder
	public static String getURLContent(URL u) throws Exception {
2273 5014 daigle
		char istreamChar;
2274
		int istreamInt;
2275 6582 leinfelder
		// get the response content
2276 6611 leinfelder
		InputStream input = getURLStream(u);
2277 6582 leinfelder
		logReplication.info("ReplicationService.getURLContent - After getting response from: " + u.toString());
2278 5014 daigle
		InputStreamReader istream = new InputStreamReader(input);
2279
		StringBuffer serverResponse = new StringBuffer();
2280
		while ((istreamInt = istream.read()) != -1) {
2281
			istreamChar = (char) istreamInt;
2282
			serverResponse.append(istreamChar);
2283
		}
2284
		istream.close();
2285
		input.close();
2286 2286 tao
2287 5014 daigle
		return serverResponse.toString();
2288
	}
2289 6582 leinfelder
2290
	/**
2291 6611 leinfelder
	 * This method returns the InputStream after opening a url
2292
	 * @param u the url to return the content from
2293
	 * @return a InputStream representing the content of the url
2294
	 * @throws java.io.IOException
2295
	 */
2296 8810 leinfelder
	public static InputStream getURLStream(URL u) throws Exception {
2297 6611 leinfelder
	    logReplication.info("Getting url stream from " + u.toString());
2298
		logReplication.info("ReplicationService.getURLStream - Before sending request to: " + u.toString());
2299
		// use httpclient to set up SSL
2300 8810 leinfelder
		DefaultHttpMultipartRestClient client = getSSLClient();
2301 6611 leinfelder
		// get the response content
2302 8810 leinfelder
		InputStream input = client.doGetRequest(u.toString(), CLIENTTIMEOUT);
2303 6611 leinfelder
		logReplication.info("ReplicationService.getURLStream - After getting response from: " + u.toString());
2304
2305
		return input;
2306
	}
2307
2308
	/**
2309 6582 leinfelder
	 * Sets up an HttpClient with SSL connection.
2310
	 * Sends client certificate to the server when doing the request.
2311
	 * @return
2312
	 */
2313 8810 leinfelder
	private static DefaultHttpMultipartRestClient getSSLClient() {
2314
		DefaultHttpMultipartRestClient client = new DefaultHttpMultipartRestClient();
2315 6582 leinfelder
2316
		// set up this server's client identity
2317
		String subject = null;
2318
		try {
2319 6616 leinfelder
			// TODO: should there be alternative ways to get the key and certificate?
2320 6620 leinfelder
			String certificateFile = PropertyService.getProperty("replication.certificate.file");
2321
	    	String keyFile = PropertyService.getProperty("replication.privatekey.file");
2322
			String keyPassword = PropertyService.getProperty("replication.privatekey.password");
2323
			X509Certificate certificate = CertificateManager.getInstance().loadCertificateFromFile(certificateFile);
2324
			PrivateKey privateKey = CertificateManager.getInstance().loadPrivateKeyFromFile(keyFile, keyPassword);
2325 6582 leinfelder
			subject = CertificateManager.getInstance().getSubjectDN(certificate);
2326 6620 leinfelder
			CertificateManager.getInstance().registerCertificate(subject, certificate, privateKey);
2327 6582 leinfelder
		} catch (Exception e) {
2328
			// this is pretty much required for replication communication
2329 6616 leinfelder
			logReplication.warn("Could not find server's client certificate/private key: " + e.getMessage());
2330 6582 leinfelder
		}
2331 7317 leinfelder
2332
		// set the configured timeout
2333 8810 leinfelder
		//client.setTimeouts(CLIENTTIMEOUT);
2334 7313 leinfelder
2335 6582 leinfelder
		SSLSocketFactory socketFactory = null;
2336
		try {
2337
			socketFactory = CertificateManager.getInstance().getSSLSocketFactory(subject);
2338
		} catch (FileNotFoundException e) {
2339
			// these are somewhat expected for anonymous client use
2340
			logReplication.warn("Could not set up SSL connection for client - likely because the certificate could not be located: " + e.getMessage());
2341
		} catch (Exception e) {
2342
			// this is likely more severe
2343
			logReplication.warn("Funky SSL going on: " + e.getClass() + ":: " + e.getMessage());
2344
		}
2345
		try {
2346
			//443 is the default port, this value is overridden if explicitly set in the URL
2347
			Scheme sch = new Scheme("https", 443, socketFactory);
2348
			client.getHttpClient().getConnectionManager().getSchemeRegistry().register(sch);
2349
		} catch (Exception e) {
2350
			// this is likely more severe
2351
			logReplication.error("Failed to set up SSL connection for client. Continuing. " + e.getClass() + ":: " + e.getMessage(), e);
2352
		}
2353
		return client;
2354
	}
2355
2356 2286 tao
2357 5014 daigle
//	/**
2358
//	 * Method for writing replication messages to a log file specified in
2359
//	 * metacat.properties
2360
//	 */
2361
//	public static void replLog(String message) {
2362
//		try {
2363
//			FileOutputStream fos = new FileOutputStream(PropertyService
2364
//					.getProperty("replication.logdir")
2365
//					+ "/metacatreplication.log", true);
2366
//			PrintWriter pw = new PrintWriter(fos);
2367
//			SimpleDateFormat formatter = new SimpleDateFormat("yy-MM-dd HH:mm:ss");
2368
//			java.util.Date localtime = new java.util.Date();
2369
//			String dateString = formatter.format(localtime);
2370
//			dateString += " :: " + message;
2371
//			// time stamp each entry
2372
//			pw.println(dateString);
2373
//			pw.flush();
2374
//		} catch (Exception e) {
2375
//			logReplication.error("error writing to replication log from "
2376
//					+ "MetacatReplication.replLog: " + e.getMessage());
2377
//			// e.printStackTrace(System.out);
2378
//		}
2379
//	}
2380 2286 tao
2381 5014 daigle
//	/**
2382
//	 * Method for writing replication messages to a log file specified in
2383
//	 * metacat.properties
2384
//	 */
2385
//	public static void replErrorLog(String message) {
2386
//		try {
2387
//			FileOutputStream fos = new FileOutputStream(PropertyService
2388
//					.getProperty("replication.logdir")
2389
//					+ "/metacatreplicationerror.log", true);
2390
//			PrintWriter pw = new PrintWriter(fos);
2391
//			SimpleDateFormat formatter = new SimpleDateFormat("yy-MM-dd HH:mm:ss");
2392
//			java.util.Date localtime = new java.util.Date();
2393
//			String dateString = formatter.format(localtime);
2394
//			dateString += " :: " + message;
2395
//			//time stamp each entry
2396
//			pw.println(dateString);
2397
//			pw.flush();
2398
//		} catch (Exception e) {
2399
//			logReplication.error("error writing to replication error log from "
2400
//					+ "MetacatReplication.replErrorLog: " + e.getMessage());
2401
//			//e.printStackTrace(System.out);
2402
//		}
2403
//	}
2404 2286 tao
2405 5014 daigle
	/**
2406
	 * Returns true if the replicate field for server in xml_replication is 1.
2407
	 * Returns false otherwise
2408 4080 daigle
	 */
2409 5014 daigle
	public static boolean replToServer(String server) {
2410
		DBConnection dbConn = null;
2411
		int serialNumber = -1;
2412
		PreparedStatement pstmt = null;
2413 4080 daigle
		try {
2414 5014 daigle
			dbConn = DBConnectionPool.getDBConnection("MetacatReplication.repltoServer");
2415
			serialNumber = dbConn.getCheckOutSerialNumber();
2416
			pstmt = dbConn.prepareStatement("select replicate from "
2417 6595 leinfelder
					+ "xml_replication where server like ? ");
2418
			pstmt.setString(1, server);
2419 5014 daigle
			pstmt.execute();
2420
			ResultSet rs = pstmt.getResultSet();
2421
			boolean tablehasrows = rs.next();
2422
			if (tablehasrows) {
2423
				int i = rs.getInt(1);
2424
				if (i == 1) {
2425
					pstmt.close();
2426
					//conn.close();
2427
					return true;
2428
				} else {
2429
					pstmt.close();
2430
					//conn.close();
2431
					return false;
2432
				}
2433
			}
2434
		} catch (SQLException sqle) {
2435
			logMetacat.error("ReplicationService.replToServer - " + ReplicationService.METACAT_REPL_ERROR_MSG);
2436
			logReplication.error("ReplicationService.replToServer - SQL error in MetacatReplication.replToServer: "
2437
					+ sqle.getMessage());
2438
		} finally {
2439
			try {
2440
				pstmt.close();
2441
				//conn.close();
2442
			}//try
2443
			catch (Exception ee) {
2444
				logMetacat.error("ReplicationService.replToServer - " + ReplicationService.METACAT_REPL_ERROR_MSG);
2445
				logReplication.error("ReplicationService.replToServer - Error in MetacatReplication.replToServer: "
2446
						+ ee.getMessage());
2447
			}//catch
2448
			finally {
2449
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
2450
			}//finally
2451
		}//finally
2452
		return false;
2453
		//the default if this server does not exist is to not replicate to it.
2454 4080 daigle
	}
2455 2286 tao
2456 522 berkley
}