Project

General

Profile

1
/**
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: leinfelder $'
9
 *     '$Date: 2011-11-17 14:47:00 -0800 (Thu, 17 Nov 2011) $'
10
 * '$Revision: 6672 $'
11
 *
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
 */
26

    
27
package edu.ucsb.nceas.metacat.replication;
28

    
29
import java.io.ByteArrayInputStream;
30
import java.io.ByteArrayOutputStream;
31
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
import java.security.PrivateKey;
44
import java.security.cert.X509Certificate;
45
import java.sql.PreparedStatement;
46
import java.sql.ResultSet;
47
import java.sql.SQLException;
48
import java.sql.Timestamp;
49
import java.util.Calendar;
50
import java.util.Date;
51
import java.util.Hashtable;
52
import java.util.List;
53
import java.util.Timer;
54
import java.util.Vector;
55

    
56
import javax.servlet.http.HttpServletRequest;
57
import javax.servlet.http.HttpServletResponse;
58

    
59
import org.apache.http.HttpResponse;
60
import org.apache.http.conn.scheme.Scheme;
61
import org.apache.http.conn.ssl.SSLSocketFactory;
62
import org.apache.log4j.Logger;
63
import org.dataone.client.RestClient;
64
import org.dataone.client.auth.CertificateManager;
65
import org.dataone.service.types.v1.SystemMetadata;
66
import org.dataone.service.util.DateTimeMarshaller;
67
import org.dataone.service.util.TypeMarshaller;
68
import org.xml.sax.InputSource;
69
import org.xml.sax.SAXException;
70
import org.xml.sax.XMLReader;
71

    
72
import edu.ucsb.nceas.metacat.DocInfoHandler;
73
import edu.ucsb.nceas.metacat.DocumentImpl;
74
import edu.ucsb.nceas.metacat.DocumentImplWrapper;
75
import edu.ucsb.nceas.metacat.EventLog;
76
import edu.ucsb.nceas.metacat.IdentifierManager;
77
import edu.ucsb.nceas.metacat.McdbDocNotFoundException;
78
import edu.ucsb.nceas.metacat.McdbException;
79
import edu.ucsb.nceas.metacat.accesscontrol.AccessControlException;
80
import edu.ucsb.nceas.metacat.accesscontrol.AccessControlForSingleFile;
81
import edu.ucsb.nceas.metacat.accesscontrol.PermOrderException;
82
import edu.ucsb.nceas.metacat.accesscontrol.XMLAccessDAO;
83
import edu.ucsb.nceas.metacat.client.InsufficientKarmaException;
84
import edu.ucsb.nceas.metacat.database.DBConnection;
85
import edu.ucsb.nceas.metacat.database.DBConnectionPool;
86
import edu.ucsb.nceas.metacat.database.DatabaseService;
87
import edu.ucsb.nceas.metacat.dataone.hazelcast.HazelcastService;
88
import edu.ucsb.nceas.metacat.properties.PropertyService;
89
import edu.ucsb.nceas.metacat.shared.BaseService;
90
import edu.ucsb.nceas.metacat.shared.HandlerException;
91
import edu.ucsb.nceas.metacat.shared.ServiceException;
92
import edu.ucsb.nceas.metacat.util.DocumentUtil;
93
import edu.ucsb.nceas.metacat.util.MetacatUtil;
94
import edu.ucsb.nceas.metacat.util.ReplicationUtil;
95
import edu.ucsb.nceas.metacat.util.SystemUtil;
96
import edu.ucsb.nceas.utilities.FileUtil;
97
import edu.ucsb.nceas.utilities.GeneralPropertyException;
98
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
99

    
100
public class ReplicationService extends BaseService {
101

    
102
	private static ReplicationService replicationService = null;
103

    
104
	private long timeInterval;
105
	private Date firstTime;
106
	private boolean timedReplicationIsOn = false;
107
	Timer replicationDaemon;
108
	private static Vector<String> fileLocks = new Vector<String>();
109
//	private Thread lockThread = null;
110
	public static final String FORCEREPLICATEDELETE = "forcereplicatedelete";
111
	private static String TIMEREPLICATION = "replication.timedreplication";
112
	private static String TIMEREPLICATIONINTERVAl ="replication.timedreplicationinterval";
113
	private static String FIRSTTIME = "replication.firsttimedreplication";
114
	private static final int TIMEINTERVALLIMIT = 7200000;
115
	public static final String REPLICATIONUSER = "replication";
116

    
117
	public static final String REPLICATION_LOG_FILE_NAME = "metacatreplication.log";
118
	public static String METACAT_REPL_ERROR_MSG = null;
119
	private static Logger logReplication = Logger.getLogger("ReplicationLogging");
120
	private static Logger logMetacat = Logger.getLogger(ReplicationService.class);
121

    
122
	private ReplicationService() throws ServiceException {
123
		_serviceName = "ReplicationService";
124
		
125
		initialize();
126
	}
127
	
128
	private void initialize() throws ServiceException {
129
				
130
		// initialize db connections to handle any update requests
131
		// deltaT = util.getProperty("replication.deltaT");
132
		// the default deltaT can be set from metacat.properties
133
		// create a thread to do the delta-T check but don't execute it yet
134
		replicationDaemon = new Timer(true);
135
		try {
136
			String replLogFile = PropertyService.getProperty("replication.logdir")
137
				+ FileUtil.getFS() + REPLICATION_LOG_FILE_NAME;
138
			METACAT_REPL_ERROR_MSG = "An error occurred in replication.  Please see the " +
139
				"replication log at: " + replLogFile;
140
			
141
			String timedRepIsOnStr = 
142
				PropertyService.getProperty("replication.timedreplication");
143
			timedReplicationIsOn = (new Boolean(timedRepIsOnStr)).booleanValue();
144
			logReplication.info("ReplicationService.initialize - The timed replication on is" + timedReplicationIsOn);
145

    
146
			String timeIntervalStr = 
147
				PropertyService.getProperty("replication.timedreplicationinterval");
148
			timeInterval = (new Long(timeIntervalStr)).longValue();
149
			logReplication.info("ReplicationService.initialize - The timed replication time Interval is " + timeInterval);
150

    
151
			String firstTimeStr = 
152
				PropertyService.getProperty("replication.firsttimedreplication");
153
			logReplication.info("ReplicationService.initialize - first replication time form property is " + firstTimeStr);
154
			firstTime = ReplicationHandler.combinateCurrentDateAndGivenTime(firstTimeStr);
155

    
156
			logReplication.info("ReplicationService.initialize - After combine current time, the real first time is "
157
					+ firstTime.toString() + " minisec");
158

    
159
			// set up time replication if it is on
160
			if (timedReplicationIsOn) {
161
				replicationDaemon.scheduleAtFixedRate(new ReplicationHandler(),
162
						firstTime, timeInterval);
163
				logReplication.info("ReplicationService.initialize - deltaT handler started with rate="
164
						+ timeInterval + " mini seconds at " + firstTime.toString());
165
			}
166

    
167
		} catch (PropertyNotFoundException pnfe) {
168
			throw new ServiceException(
169
					"ReplicationService.initialize - Property error while instantiating "
170
							+ "replication service: " + pnfe.getMessage());
171
		} catch (HandlerException he) {
172
			throw new ServiceException(
173
					"ReplicationService.initialize - Handler error while instantiating "
174
							+ "replication service" + he.getMessage());
175
		} 
176
	}
177

    
178
	/**
179
	 * Get the single instance of SessionService.
180
	 * 
181
	 * @return the single instance of SessionService
182
	 */
183
	public static ReplicationService getInstance() throws ServiceException {
184
		if (replicationService == null) {
185
			replicationService = new ReplicationService();
186
		}
187
		return replicationService;
188
	}
189

    
190
	public boolean refreshable() {
191
		return true;
192
	}
193

    
194
	protected void doRefresh() throws ServiceException {
195
		return;
196
	}
197
	
198
	public void stop() throws ServiceException{
199
		
200
	}
201

    
202
	public void stopReplication() throws ServiceException {
203
	      //stop the replication server
204
	      replicationDaemon.cancel();
205
	      replicationDaemon = new Timer(true);
206
	      timedReplicationIsOn = false;
207
	      try {
208
	    	  PropertyService.setProperty("replication.timedreplication", (new Boolean(timedReplicationIsOn)).toString());
209
	      } catch (GeneralPropertyException gpe) {
210
	    	  logReplication.warn("ReplicationService.stopReplication - Could not set replication.timedreplication property: " + gpe.getMessage());
211
	      }
212

    
213
	      logReplication.info("ReplicationService.stopReplication - deltaT handler stopped");
214
		return;
215
	}
216
	
217
	public void startReplication(Hashtable<String, String[]> params) throws ServiceException {
218

    
219
	       String firstTimeStr = "";
220
	      //start the replication server
221
	       if ( params.containsKey("rate") ) {
222
	        timeInterval = new Long(
223
	               new String(((String[])params.get("rate"))[0])).longValue();
224
	        if(timeInterval < TIMEINTERVALLIMIT) {
225
	            //deltaT<30 is a timing mess!
226
	            timeInterval = TIMEINTERVALLIMIT;
227
	            throw new ServiceException("Replication deltaT rate cannot be less than "+
228
	                    TIMEINTERVALLIMIT + " millisecs and system automatically setup the rate to "+TIMEINTERVALLIMIT);
229
	        }
230
	      } else {
231
	        timeInterval = TIMEINTERVALLIMIT ;
232
	      }
233
	      logReplication.info("ReplicationService.startReplication - New rate is: " + timeInterval + " mini seconds.");
234
	      if ( params.containsKey("firsttime"))
235
	      {
236
	         firstTimeStr = ((String[])params.get("firsttime"))[0];
237
	         try
238
	         {
239
	           firstTime = ReplicationHandler.combinateCurrentDateAndGivenTime(firstTimeStr);
240
	           logReplication.info("ReplicationService.startReplication - The first time setting is "+firstTime.toString());
241
	         }
242
	         catch (HandlerException e)
243
	         {
244
	            throw new ServiceException(e.getMessage());
245
	         }
246
	         logReplication.warn("After combine current time, the real first time is "
247
	                                  +firstTime.toString()+" minisec");
248
	      }
249
	      else
250
	      {
251
	    	  logMetacat.error("ReplicationService.startReplication - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
252
	          logReplication.error("ReplicationService.startReplication - You should specify the first time " +
253
	                                  "to start a time replication");
254
	          return;
255
	      }
256
	      
257
	      timedReplicationIsOn = true;
258
	      try {
259
	      // save settings to property file
260
	      PropertyService.setProperty(TIMEREPLICATION, (new Boolean(timedReplicationIsOn)).toString());
261
	      // note we couldn't use firstTime object because it has date info
262
	      // we only need time info such as 10:00 PM
263
	      PropertyService.setProperty(FIRSTTIME, firstTimeStr);
264
	      PropertyService.setProperty(TIMEREPLICATIONINTERVAl, (new Long(timeInterval)).toString());
265
	      } catch (GeneralPropertyException gpe) {
266
	    	  logReplication.warn("ReplicationService.startReplication - Could not set property: " + gpe.getMessage());
267
	      }
268
	      replicationDaemon.cancel();
269
	      replicationDaemon = new Timer(true);
270
	      replicationDaemon.scheduleAtFixedRate(new ReplicationHandler(), firstTime,
271
	                                            timeInterval);
272
	      
273
	      logReplication.info("ReplicationService.startReplication - deltaT handler started with rate=" +
274
	                                    timeInterval + " milliseconds at " +firstTime.toString());
275

    
276
	}
277
	
278
	public void runOnce() throws ServiceException {
279
	      //updates this server exactly once
280
	      replicationDaemon.schedule(new ReplicationHandler(), 0);
281
	}
282

    
283
	/**
284
	 * This method can add, delete and list the servers currently included in
285
	 * xml_replication.
286
	 * action           subaction            other needed params
287
	 * ---------------------------------------------------------
288
	 * servercontrol    add                  server
289
	 * servercontrol    delete               server
290
	 * servercontrol    list
291
	 */
292
	public static void handleServerControlRequest(
293
			Hashtable<String, String[]> params, HttpServletResponse response) {
294
		String subaction = ((String[]) params.get("subaction"))[0];
295
		DBConnection dbConn = null;
296
		int serialNumber = -1;
297
		PreparedStatement pstmt = null;
298
		String replicate = null;
299
		String server = null;
300
		String dataReplicate = null;
301
		String systemMetadataReplicate = null;
302
		String hub = null;
303
		Writer out = null;
304
		try {
305
			response.setContentType("text/xml");
306
			out = response.getWriter();
307
			
308
			//conn = util.openDBConnection();
309
			dbConn = DBConnectionPool
310
					.getDBConnection("MetacatReplication.handleServerControlRequest");
311
			serialNumber = dbConn.getCheckOutSerialNumber();
312

    
313
			// add server to server list
314
			if (subaction.equals("add")) {
315
				replicate = ((String[]) params.get("replicate"))[0];
316
				server = ((String[]) params.get("server"))[0];
317

    
318
				//Get data replication value
319
				dataReplicate = ((String[]) params.get("datareplicate"))[0];
320
				//Get system metadata replication value
321
				systemMetadataReplicate = ((String[]) params.get("systemmetadatareplicate"))[0];
322
				//Get hub value
323
				hub = ((String[]) params.get("hub"))[0];
324

    
325
				Calendar cal = Calendar.getInstance();
326
                cal.set(1980, 1, 1);
327
				String sql = "INSERT INTO xml_replication "
328
						+ "(server, last_checked, replicate, datareplicate, systemmetadatareplicate, hub) "
329
						+ "VALUES (?,?,?,?,?,?)";
330
				
331
				pstmt = dbConn.prepareStatement(sql);
332
						
333
				pstmt.setString(1, server);
334
				pstmt.setTimestamp(2, new Timestamp(cal.getTimeInMillis()));
335
				pstmt.setInt(3, Integer.parseInt(replicate));
336
				pstmt.setInt(4, Integer.parseInt(dataReplicate));
337
				pstmt.setInt(5, Integer.parseInt(systemMetadataReplicate));
338
				pstmt.setInt(6, Integer.parseInt(hub));
339
				
340
				String sqlReport = "XMLAccessAccess.getXMLAccessForDoc - SQL: " + sql;
341
				sqlReport += " [" + server + "," + replicate + 
342
					"," + dataReplicate + "," + hub + "]";
343
				
344
				logMetacat.info(sqlReport);
345
				
346
				pstmt.execute();
347
				pstmt.close();
348
				dbConn.commit();
349
				out.write("Server " + server + " added");
350
				response.setContentType("text/html");
351
				out.write("<html><body><table border=\"1\">");
352
				out.write("<tr><td><b>server</b></td>");
353
				out.write("<td><b>last_checked</b></td>");
354
				out.write("<td><b>replicate</b></td>");
355
				out.write("<td><b>datareplicate</b></td>");
356
				out.write("<td><b>systemmetadatareplicate</b></td>");
357
				out.write("<td><b>hub</b></td></tr>");
358
				pstmt = dbConn.prepareStatement("SELECT serverid, server, last_checked, replicate, datareplicate, systemmetadatareplicate, hub FROM xml_replication");
359
				//increase dbconnection usage
360
				dbConn.increaseUsageCount(1);
361

    
362
				pstmt.execute();
363
				ResultSet rs = pstmt.getResultSet();
364
				boolean tablehasrows = rs.next();
365
				while (tablehasrows) {
366
					out.write("<tr><td>" + rs.getString(2) + "</td><td>");
367
					out.write(rs.getString(3) + "</td><td>");
368
					out.write(rs.getString(4) + "</td><td>");
369
					out.write(rs.getString(5) + "</td><td>");
370
					out.write(rs.getString(6) + "</td><td>");
371
					out.write(rs.getString(7) + "</td></tr>");
372

    
373
					tablehasrows = rs.next();
374
				}
375
				out.write("</table></body></html>");
376

    
377
				// delete server from server list
378
			} else if (subaction.equals("delete")) {
379
				server = ((String[]) params.get("server"))[0];
380
				pstmt = dbConn.prepareStatement("DELETE FROM xml_replication "
381
						+ "WHERE server LIKE ?");
382
				pstmt.setString(1, server);
383
				pstmt.execute();
384
				pstmt.close();
385
				dbConn.commit();
386
				out.write("Server " + server + " deleted");
387
				response.setContentType("text/html");
388
				out.write("<html><body><table border=\"1\">");
389
				out.write("<tr><td><b>server</b></td>");
390
				out.write("<td><b>last_checked</b></td>");
391
				out.write("<td><b>replicate</b></td>");
392
				out.write("<td><b>datareplicate</b></td>");
393
				out.write("<td><b>systemmetadatareplicate</b></td>");
394
				out.write("<td><b>hub</b></td></tr>");
395

    
396
				pstmt = dbConn.prepareStatement("SELECT serverid, server, last_checked, replicate, datareplicate, systemmetadatareplicate, hub FROM xml_replication");
397
				//increase dbconnection usage
398
				dbConn.increaseUsageCount(1);
399
				pstmt.execute();
400
				ResultSet rs = pstmt.getResultSet();
401
				boolean tablehasrows = rs.next();
402
				while (tablehasrows) {
403
					out.write("<tr><td>" + rs.getString(2) + "</td><td>");
404
					out.write(rs.getString(3) + "</td><td>");
405
					out.write(rs.getString(4) + "</td><td>");
406
					out.write(rs.getString(5) + "</td><td>");
407
					out.write(rs.getString(6) + "</td><td>");
408
					out.write(rs.getString(7) + "</td></tr>");
409
					tablehasrows = rs.next();
410
				}
411
				out.write("</table></body></html>");
412

    
413
				// list servers in server list
414
			} else if (subaction.equals("list")) {
415
				response.setContentType("text/html");
416
				out.write("<html><body><table border=\"1\">");
417
				out.write("<tr><td><b>server</b></td>");
418
				out.write("<td><b>last_checked</b></td>");
419
				out.write("<td><b>replicate</b></td>");
420
				out.write("<td><b>datareplicate</b></td>");
421
				out.write("<td><b>systemmetadatareplicate</b></td>");
422
				out.write("<td><b>hub</b></td></tr>");
423
				pstmt = dbConn.prepareStatement("SELECT serverid, server, last_checked, replicate, datareplicate, systemmetadatareplicate, hub FROM xml_replication");
424
				pstmt.execute();
425
				ResultSet rs = pstmt.getResultSet();
426
				boolean tablehasrows = rs.next();
427
				while (tablehasrows) {
428
					out.write("<tr><td>" + rs.getString(2) + "</td><td>");
429
					out.write(rs.getString(3) + "</td><td>");
430
					out.write(rs.getString(4) + "</td><td>");
431
					out.write(rs.getString(5) + "</td><td>");
432
					out.write(rs.getString(6) + "</td><td>");
433
					out.write(rs.getString(7) + "</td></tr>");
434

    
435
					tablehasrows = rs.next();
436
				}
437
				out.write("</table></body></html>");
438
			} else {
439

    
440
				out.write("<error>Unkonwn subaction</error>");
441

    
442
			}
443
			pstmt.close();
444
			//conn.close();
445

    
446
		} catch (Exception e) {
447
			logMetacat.error("ReplicationService.handleServerControlRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
448
			logReplication.error("ReplicationService.handleServerControlRequest - Error in "
449
					+ "MetacatReplication.handleServerControlRequest " + e.getMessage());
450
			e.printStackTrace(System.out);
451
		} finally {
452
			try {
453
				pstmt.close();
454
			}//try
455
			catch (SQLException ee) {
456
				logMetacat.error("ReplicationService.handleServerControlRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
457
				logReplication.error("ReplicationService.handleServerControlRequest - Error in MetacatReplication.handleServerControlRequest to close pstmt "
458
						+ ee.getMessage());
459
			}//catch
460
			finally {
461
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
462
			}//finally
463
			if (out != null) {
464
				try {
465
					out.close();
466
				} catch (IOException e) {
467
					logMetacat.error(e.getMessage(), e);
468
				}
469
			}
470
		}//finally
471

    
472
	}
473

    
474
	/**
475
	 * when a forcereplication request comes in, local host sends a read request
476
	 * to the requesting server (remote server) for the specified docid. Then
477
	 * store it in local database.
478
	 */
479
	protected static void handleForceReplicateRequest(
480
			Hashtable<String, String[]> params, HttpServletResponse response,
481
			HttpServletRequest request) {
482
		String server = ((String[]) params.get("server"))[0]; // the server that
483
		String docid = ((String[]) params.get("docid"))[0]; // sent the document
484
		String dbaction = "UPDATE"; // the default action is UPDATE
485
		//    boolean override = false;
486
		//    int serverCode = 1;
487
		DBConnection dbConn = null;
488
		int serialNumber = -1;
489
		String docName = null;
490

    
491
		try {
492
			//if the url contains a dbaction then the default action is overridden
493
			if (params.containsKey("dbaction")) {
494
				dbaction = ((String[]) params.get("dbaction"))[0];
495
				//serverCode = MetacatReplication.getServerCode(server);
496
				//override = true; //we are now overriding the default action
497
			}
498
			logReplication.info("ReplicationService.handleForceReplicateRequest - Force replication request from: " + server);
499
			logReplication.info("ReplicationService.handleForceReplicateRequest - Force replication docid: " + docid);
500
			logReplication.info("ReplicationService.handleForceReplicateRequest - Force replication action: " + dbaction);
501
			// sending back read request to remote server
502
			URL u = new URL("https://" + server + "?server="
503
					+ MetacatUtil.getLocalReplicationServerName() + "&action=read&docid="
504
					+ docid);
505
			String xmldoc = ReplicationService.getURLContent(u);
506

    
507
			// get the document info from server
508
			URL docinfourl = new URL("https://" + server + "?server="
509
					+ MetacatUtil.getLocalReplicationServerName()
510
					+ "&action=getdocumentinfo&docid=" + docid);
511
			
512

    
513
			String docInfoStr = ReplicationService.getURLContent(docinfourl);
514
			// strip out the system metadata portion
515
			String systemMetadataXML = ReplicationUtil.getSystemMetadataContent(docInfoStr);
516
			docInfoStr = ReplicationUtil.getContentWithoutSystemMetadata(docInfoStr);
517
		   	  
518
			//dih is the parser for the docinfo xml format
519
			DocInfoHandler dih = new DocInfoHandler();
520
			XMLReader docinfoParser = ReplicationHandler.initParser(dih);
521
			docinfoParser.parse(new InputSource(new StringReader(docInfoStr)));
522
			//      Hashtable<String,Vector<AccessControlForSingleFile>> docinfoHash = dih.getDocInfo();
523
			Hashtable<String, String> docinfoHash = dih.getDocInfo();
524
			
525
			// Get home server of this docid
526
			String homeServer = (String) docinfoHash.get("home_server");
527
			
528
			// process system metadata
529
			if (systemMetadataXML != null) {
530
				SystemMetadata sysMeta = 
531
					TypeMarshaller.unmarshalTypeFromStream(
532
							SystemMetadata.class,
533
							new ByteArrayInputStream(systemMetadataXML.getBytes("UTF-8")));
534
				// need the guid-to-docid mapping
535
				IdentifierManager.getInstance().createMapping(sysMeta.getIdentifier().getValue(), docid);
536
				// save the system metadata
537
				HazelcastService.getInstance().getSystemMetadataMap().put(sysMeta.getIdentifier(), sysMeta);
538
			}
539
      
540
			// dates
541
			String createdDateString = docinfoHash.get("date_created");
542
			String updatedDateString = docinfoHash.get("date_updated");
543
			Date createdDate = DateTimeMarshaller.deserializeDateToUTC(createdDateString);
544
			Date updatedDate = DateTimeMarshaller.deserializeDateToUTC(updatedDateString);
545
		      
546
			logReplication.info("ReplicationService.handleForceReplicateRequest - homeServer: " + homeServer);
547
			// Get Document type
548
			String docType = (String) docinfoHash.get("doctype");
549
			logReplication.info("ReplicationService.handleForceReplicateRequest - docType: " + docType);
550
			String parserBase = null;
551
			// this for eml2 and we need user eml2 parser
552
			if (docType != null
553
					&& (docType.trim()).equals(DocumentImpl.EML2_0_0NAMESPACE)) {
554
				logReplication.warn("ReplicationService.handleForceReplicateRequest - This is an eml200 document!");
555
				parserBase = DocumentImpl.EML200;
556
			} else if (docType != null
557
					&& (docType.trim()).equals(DocumentImpl.EML2_0_1NAMESPACE)) {
558
				logReplication.warn("ReplicationService.handleForceReplicateRequest - This is an eml2.0.1 document!");
559
				parserBase = DocumentImpl.EML200;
560
			} else if (docType != null
561
					&& (docType.trim()).equals(DocumentImpl.EML2_1_0NAMESPACE)) {
562
				logReplication.warn("ReplicationService.handleForceReplicateRequest - This is an eml2.1.0 document!");
563
				parserBase = DocumentImpl.EML210;
564
			} else if (docType != null
565
					&& (docType.trim()).equals(DocumentImpl.EML2_1_1NAMESPACE)) {
566
				logReplication.warn("ReplicationService.handleForceReplicateRequest - This is an eml2.1.1 document!");
567
				parserBase = DocumentImpl.EML210;
568
			}
569
			logReplication.warn("ReplicationService.handleForceReplicateRequest - The parserBase is: " + parserBase);
570

    
571
			// Get DBConnection from pool
572
			dbConn = DBConnectionPool
573
					.getDBConnection("MetacatReplication.handleForceReplicateRequest");
574
			serialNumber = dbConn.getCheckOutSerialNumber();
575
			// write the document to local database
576
			DocumentImplWrapper wrapper = new DocumentImplWrapper(parserBase, false);
577
			//try this independently so we can set access even if the update action is invalid (i.e docid has not changed)
578
			try {
579
				wrapper.writeReplication(dbConn, xmldoc, null, null,
580
						dbaction, docid, null, null, homeServer, server, createdDate,
581
						updatedDate);
582
			} finally {
583

    
584
				//process extra access rules before dealing with the write exception (doc exist already)			
585
		        Vector<XMLAccessDAO> accessControlList = dih.getAccessControlList();
586
		        if (accessControlList != null) {
587
		        	AccessControlForSingleFile acfsf = new AccessControlForSingleFile(docid);
588
		        	for (XMLAccessDAO xmlAccessDAO : accessControlList) {
589
		        		if (!acfsf.accessControlExists(xmlAccessDAO)) {
590
		        			acfsf.insertPermissions(xmlAccessDAO);
591
							logReplication.info("ReplicationService.handleForceReplicateRequest - document " + docid
592
									+ " permissions added to DB");
593
		        		}
594
		            }
595
		        }
596
		        
597
		        // process the real owner and updater
598
				String user = (String) docinfoHash.get("user_owner");
599
				String updated = (String) docinfoHash.get("user_updated");
600
		        updateUserOwner(dbConn, docid, user, updated);
601

    
602
				logReplication.info("ReplicationService.handleForceReplicateRequest - document " + docid + " added to DB with "
603
						+ "action " + dbaction);
604
				
605
				EventLog.getInstance().log(request.getRemoteAddr(), request.getHeader("User-Agent"), REPLICATIONUSER, docid, dbaction);
606
			}
607
		} catch (SQLException sqle) {
608
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
609
			logReplication.error("ReplicationService.handleForceReplicateRequest - SQL error when adding doc " + docid + 
610
					" to DB with action " + dbaction + ": " + sqle.getMessage());
611
		} catch (MalformedURLException mue) {
612
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
613
			logReplication.error("ReplicationService.handleForceReplicateRequest - URL error when adding doc " + docid + 
614
					" to DB with action " + dbaction + ": " + mue.getMessage());
615
		} catch (SAXException se) {
616
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
617
			logReplication.error("ReplicationService.handleForceReplicateRequest - SAX parsing error when adding doc " + docid + 
618
					" to DB with action " + dbaction + ": " + se.getMessage());
619
		} catch (HandlerException he) {
620
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
621
			logReplication.error("ReplicationService.handleForceReplicateRequest - Handler error when adding doc " + docid + 
622
					" to DB with action " + dbaction + ": " + he.getMessage());
623
		} catch (IOException ioe) {
624
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
625
			logReplication.error("ReplicationService.handleForceReplicateRequest - I/O error when adding doc " + docid + 
626
					" to DB with action " + dbaction + ": " + ioe.getMessage());
627
		} catch (PermOrderException poe) {
628
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
629
			logReplication.error("ReplicationService.handleForceReplicateRequest - Permissions order error when adding doc " + docid + 
630
					" to DB with action " + dbaction + ": " + poe.getMessage());
631
		} catch (AccessControlException ace) {
632
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
633
			logReplication.error("ReplicationService.handleForceReplicateRequest - Permissions order error when adding doc " + docid + 
634
					" to DB with action " + dbaction + ": " + ace.getMessage());
635
		} catch (Exception e) {
636
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
637
			logReplication.error("ReplicationService.handleForceReplicateRequest - General error when adding doc " + docid + 
638
					" to DB with action " + dbaction + ": " + e.getMessage());
639
		} finally {
640
			// Return the checked out DBConnection
641
			DBConnectionPool.returnDBConnection(dbConn, serialNumber);
642
		}//finally
643
	}
644

    
645
	/*
646
	 * when a forcereplication delete request comes in, local host will delete this
647
	 * document
648
	 */
649
	protected static void handleForceReplicateDeleteRequest(
650
			Hashtable<String, String[]> params, HttpServletResponse response,
651
			HttpServletRequest request) {
652
		String server = ((String[]) params.get("server"))[0]; // the server that
653
		String docid = ((String[]) params.get("docid"))[0]; // sent the document
654
		try {
655
			logReplication.info("ReplicationService.handleForceReplicateDeleteRequest - force replication delete request from " + server);
656
			logReplication.info("ReplicationService.handleForceReplicateDeleteRequest - force replication delete docid " + docid);
657
			logReplication.info("ReplicationService.handleForceReplicateDeleteRequest - Force replication delete request from: " + server);
658
			logReplication.info("ReplicationService.handleForceReplicateDeleteRequest - Force replication delete docid: " + docid);
659
			DocumentImpl.delete(docid, null, null, server);
660
			logReplication.info("ReplicationService.handleForceReplicateDeleteRequest - document " + docid + " was successfully deleted ");
661
			EventLog.getInstance().log(request.getRemoteAddr(), request.getHeader("User-Agent"), REPLICATIONUSER, docid,
662
					"delete");
663
			logReplication.info("ReplicationService.handleForceReplicateDeleteRequest - document " + docid + " was successfully deleted ");
664
		} catch (McdbDocNotFoundException e) {
665
			logMetacat.error("ReplicationService.handleForceReplicateDeleteRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
666
			logReplication.error("document " + docid
667
					+ " failed to delete because " + e.getMessage());
668
			logReplication.error("ReplicationService.handleForceReplicateDeleteRequest - error: " + e.getMessage());
669
		} catch (InsufficientKarmaException e) {
670
			logMetacat.error("ReplicationService.handleForceReplicateDeleteRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
671
			logReplication.error("document " + docid
672
					+ " failed to delete because " + e.getMessage());
673
			logReplication.error("ReplicationService.handleForceReplicateDeleteRequest - error: " + e.getMessage());
674
		} catch (SQLException e) {
675
			logMetacat.error("ReplicationService.handleForceReplicateDeleteRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
676
			logReplication.error("document " + docid
677
					+ " failed to delete because " + e.getMessage());
678
			logReplication.error("ReplicationService.handleForceReplicateDeleteRequest - error: " + e.getMessage());
679
		} catch (Exception e) {
680
			logMetacat.error("ReplicationService.handleForceReplicateDeleteRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
681
			logReplication.error("document " + docid
682
					+ " failed to delete because " + e.getMessage());
683
			logReplication.error("ReplicationService.handleForceReplicateDeleteRequest - error: " + e.getMessage());
684

    
685
		}//catch
686

    
687
	}
688

    
689
	/**
690
	 * when a forcereplication data file request comes in, local host sends a
691
	 * readdata request to the requesting server (remote server) for the specified
692
	 * docid. Then store it in local database and file system
693
	 */
694
	protected static void handleForceReplicateDataFileRequest(Hashtable<String, String[]> params,
695
			HttpServletRequest request) {
696

    
697
		//make sure there is some parameters
698
		if (params.isEmpty()) {
699
			return;
700
		}
701
		// Get remote server
702
		String server = ((String[]) params.get("server"))[0];
703
		// the docid should include rev number
704
		String docid = ((String[]) params.get("docid"))[0];
705
		// Make sure there is a docid and server
706
		if (docid == null || server == null || server.equals("")) {
707
			logMetacat.error("ReplicationService.handleForceReplicateDataFileRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
708
			logReplication.error("ReplicationService.handleForceReplicateDataFileRequest - Didn't specify docid or server for replication");
709
			return;
710
		}
711

    
712
		// Overide or not
713
		//    boolean override = false;
714
		// dbaction - update or insert
715
		String dbaction = null;
716

    
717
		try {
718
			//docid was switch to two parts uinque code and rev
719
			//String uniqueCode=MetacatUtil.getDocIdFromString(docid);
720
			//int rev=MetacatUtil.getVersionFromString(docid);
721
			if (params.containsKey("dbaction")) {
722
				dbaction = ((String[]) params.get("dbaction"))[0];
723
			} else//default value is update
724
			{
725
				dbaction = "update";
726
			}
727

    
728
			logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - Force replication request from: " + server);
729
			logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - Force replication docid: " + docid);
730
			logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - Force replication action: " + dbaction);
731
			// get the document info from server
732
			URL docinfourl = new URL("https://" + server + "?server="
733
					+ MetacatUtil.getLocalReplicationServerName()
734
					+ "&action=getdocumentinfo&docid=" + docid);
735

    
736
			String docInfoStr = ReplicationService.getURLContent(docinfourl);
737
			
738
			// strip out the system metadata portion
739
		    String systemMetadataXML = ReplicationUtil.getSystemMetadataContent(docInfoStr);
740
		   	docInfoStr = ReplicationUtil.getContentWithoutSystemMetadata(docInfoStr);
741

    
742
			//dih is the parser for the docinfo xml format
743
			DocInfoHandler dih = new DocInfoHandler();
744
			XMLReader docinfoParser = ReplicationHandler.initParser(dih);
745
			docinfoParser.parse(new InputSource(new StringReader(docInfoStr)));
746
			Hashtable<String, String> docinfoHash = dih.getDocInfo();
747
			
748
			String docName = (String) docinfoHash.get("docname");
749

    
750
			String docType = (String) docinfoHash.get("doctype");
751

    
752
			String docHomeServer = (String) docinfoHash.get("home_server");
753
			
754
			String createdDateString = docinfoHash.get("date_created");
755
			String updatedDateString = docinfoHash.get("date_updated");
756
			
757
			Date createdDate = DateTimeMarshaller.deserializeDateToUTC(createdDateString);
758
			Date updatedDate = DateTimeMarshaller.deserializeDateToUTC(updatedDateString);
759
			
760
			logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - docHomeServer of datafile: " + docHomeServer);
761

    
762
			if (dbaction.equals("insert") || dbaction.equals("update")) {
763
				//Get data file and store it into local file system.
764
				// sending back readdata request to server
765
				URL url = new URL("https://" + server + "?server="
766
						+ MetacatUtil.getLocalReplicationServerName()
767
						+ "&action=readdata&docid=" + docid);
768
				String datafilePath = PropertyService
769
						.getProperty("application.datafilepath");
770

    
771
				InputStream inputStream = getURLStream(url);
772
				
773
				Exception writeException = null;
774
				//register data file into xml_documents table and wite data file
775
				//into file system
776
				try {
777
					DocumentImpl.writeDataFileInReplication(inputStream,
778
							datafilePath, docName, docType, docid, null, docHomeServer,
779
							server, DocumentImpl.DOCUMENTTABLE, false, createdDate,
780
							updatedDate);
781
				} catch (Exception e) {
782
					writeException = e;
783
				}
784
				
785
				// process the real owner and updater
786
				DBConnection dbConn = DBConnectionPool.getDBConnection("ReplicationService.handleForceDataFileRequest");
787
		        int serialNumber = dbConn.getCheckOutSerialNumber();
788
		        dbConn.setAutoCommit(false);
789
				String user = (String) docinfoHash.get("user_owner");
790
				String updated = (String) docinfoHash.get("user_updated");
791
		        updateUserOwner(dbConn, docid, user, updated);
792
		        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
793
		        
794
		        Vector<XMLAccessDAO> accessControlList = dih.getAccessControlList();
795
		        if (accessControlList != null) {
796
		        	AccessControlForSingleFile acfsf = new AccessControlForSingleFile(docid);
797
		        	for (XMLAccessDAO xmlAccessDAO : accessControlList) {
798
		        		if (!acfsf.accessControlExists(xmlAccessDAO)) {
799
		        			acfsf.insertPermissions(xmlAccessDAO);
800
							logReplication.info("ReplicationService.handleForceReplicateRequest - document " + docid
801
									+ " permissions added to DB");
802
		        		}
803
		            }
804
		        }
805
		        
806
		        // process system metadata
807
		        if (systemMetadataXML != null) {
808
		      	  SystemMetadata sysMeta = 
809
		      		TypeMarshaller.unmarshalTypeFromStream(
810
		      				  SystemMetadata.class, 
811
		      				  new ByteArrayInputStream(systemMetadataXML.getBytes("UTF-8")));
812
		      	  // need the guid-to-docid mapping
813
		      	  IdentifierManager.getInstance().createMapping(sysMeta.getIdentifier().getValue(), docid);
814
		      	  // save the system metadata
815
		      	  HazelcastService.getInstance().getSystemMetadataMap().put(sysMeta.getIdentifier(), sysMeta);
816
		        }
817

    
818
				if (writeException != null) {
819
					throw writeException;
820
				}
821

    
822
				logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - datafile " + docid + " added to DB with "
823
						+ "action " + dbaction);
824
				EventLog.getInstance().log(request.getRemoteAddr(), request.getHeader("User-Agent"), REPLICATIONUSER,
825
						docid, dbaction);
826
			}
827

    
828
		} catch (Exception e) {
829
			e.printStackTrace();
830
			logMetacat.error("ReplicationService.handleForceReplicateDataFileRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG, e);                         
831
			logReplication.error("ReplicationService.handleForceReplicateDataFileRequest - Datafile " + docid
832
					+ " failed to added to DB with " + "action " + dbaction + " because "
833
					+ e.getMessage());
834
			logReplication.error("ReplicationService.handleForceReplicateDataFileRequest - ERROR in MetacatReplication.handleForceDataFileReplicate"
835
					+ "Request(): " + e.getMessage());
836
		}
837
	}
838

    
839
	/**
840
	 * Grants or denies a lock to a requesting host.
841
	 * The servlet parameters of interrest are:
842
	 * docid: the docid of the file the lock is being requested for
843
	 * currentdate: the timestamp of the document on the remote server
844
	 *
845
	 */
846
	protected static void handleGetLockRequest(
847
			Hashtable<String, String[]> params, HttpServletResponse response) {
848

    
849
		try {
850

    
851
			String docid = ((String[]) params.get("docid"))[0];
852
			String remoteRev = ((String[]) params.get("updaterev"))[0];
853
			DocumentImpl requestDoc = new DocumentImpl(docid);
854
			logReplication.info("ReplicationService.handleGetLockRequest - lock request for " + docid);
855
			int localRevInt = requestDoc.getRev();
856
			int remoteRevInt = Integer.parseInt(remoteRev);
857

    
858
			// get a writer for sending back to response
859
			response.setContentType("text/xml");
860
			Writer out = response.getWriter();
861
			
862
			if (remoteRevInt >= localRevInt) {
863
				if (!fileLocks.contains(docid)) { //grant the lock if it is not already locked
864
					fileLocks.add(0, docid); //insert at the beginning of the queue Vector
865
					//send a message back to the the remote host authorizing the insert
866
					out.write("<lockgranted><docid>" + docid
867
									+ "</docid></lockgranted>");
868
					//          lockThread = new Thread(this);
869
					//          lockThread.setPriority(Thread.MIN_PRIORITY);
870
					//          lockThread.start();
871
					logReplication.info("ReplicationService.handleGetLockRequest - lock granted for " + docid);
872
				} else { //deny the lock
873
					out.write("<filelocked><docid>" + docid + "</docid></filelocked>");
874
					logReplication.info("ReplicationService.handleGetLockRequest - lock denied for " + docid
875
							+ "reason: file already locked");
876
				}
877
			} else {//deny the lock.
878
				out.write("<outdatedfile><docid>" + docid + "</docid></filelocked>");
879
				logReplication.info("ReplicationService.handleGetLockRequest - lock denied for " + docid
880
						+ "reason: client has outdated file");
881
			}
882
			out.close();
883
			//conn.close();
884
		} catch (Exception e) {
885
			logMetacat.error("ReplicationService.handleGetLockRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
886
			logReplication.error("ReplicationService.handleGetLockRequest - error requesting file lock from MetacatReplication."
887
					+ "handleGetLockRequest: " + e.getMessage());
888
			e.printStackTrace(System.out);
889
		}
890
	}
891

    
892
	/**
893
	 * Sends all of the xml_documents information encoded in xml to a requestor
894
	 * the format is:
895
	 * <!ELEMENT documentinfo (docid, docname, doctype, doctitle, user_owner,
896
	 *                  user_updated, home_server, public_access, rev)/>
897
	 * all of the subelements of document info are #PCDATA
898
	 */
899
	protected static void handleGetDocumentInfoRequest(
900
			Hashtable<String, String[]> params, HttpServletResponse response) {
901
		String docid = ((String[]) (params.get("docid")))[0];
902
		StringBuffer sb = new StringBuffer();
903

    
904
		try {
905
			DocumentImpl doc = new DocumentImpl(docid);
906
			sb.append("<documentinfo><docid>").append(docid);
907
			sb.append("</docid>");
908
			
909
			try {
910
				// serialize the System Metadata as XML for docinfo
911
				String guid = IdentifierManager.getInstance().getGUID(doc.getDocID(), doc.getRev());
912
				SystemMetadata systemMetadata = IdentifierManager.getInstance().getSystemMetadata(guid);
913
				ByteArrayOutputStream baos = new ByteArrayOutputStream();
914
				TypeMarshaller.marshalTypeToOutputStream(systemMetadata, baos);
915
				String systemMetadataXML = baos.toString("UTF-8");
916
				sb.append("<systemMetadata>");
917
				sb.append(systemMetadataXML);
918
				sb.append("</systemMetadata>");
919
			} catch(McdbDocNotFoundException e) {
920
			  logMetacat.warn("No SystemMetadata found for: " + docid);
921
			}
922
			
923
			Calendar created = Calendar.getInstance();
924
			created.setTime(doc.getCreateDate());
925
			Calendar updated = Calendar.getInstance();
926
			updated.setTime(doc.getUpdateDate());
927
			
928
			sb.append("<docname>").append(doc.getDocname());
929
			sb.append("</docname><doctype>").append(doc.getDoctype());
930
			sb.append("</doctype>");
931
			sb.append("<user_owner>").append(doc.getUserowner());
932
			sb.append("</user_owner><user_updated>").append(doc.getUserupdated());
933
			sb.append("</user_updated>");
934
			sb.append("<date_created>");
935
			sb.append(DateTimeMarshaller.serializeDateToUTC(doc.getCreateDate()));
936
			sb.append("</date_created>");
937
			sb.append("<date_updated>");
938
			sb.append(DateTimeMarshaller.serializeDateToUTC(doc.getUpdateDate()));
939
			sb.append("</date_updated>");
940
			sb.append("<home_server>");
941
			sb.append(doc.getDocHomeServer());
942
			sb.append("</home_server>");
943
			sb.append("<public_access>").append(doc.getPublicaccess());
944
			sb.append("</public_access><rev>").append(doc.getRev());
945
			sb.append("</rev>");
946

    
947
			sb.append("<accessControl>");
948

    
949
			AccessControlForSingleFile acfsf = new AccessControlForSingleFile(docid); 
950
			sb.append(acfsf.getAccessString());
951
			
952
			sb.append("</accessControl>");
953

    
954
			sb.append("</documentinfo>");
955
			// get a writer for sending back to response
956
			response.setContentType("text/xml");
957
			Writer out = response.getWriter();
958
			out.write(sb.toString());
959
			out.close();
960

    
961
		} catch (Exception e) {
962
			logMetacat.error("ReplicationService.handleGetDocumentInfoRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
963
			logReplication.error("ReplicationService.handleGetDocumentInfoRequest - error in metacatReplication.handlegetdocumentinforequest "
964
					+ "for doc: " + docid + " : " + e.getMessage());
965
		}
966

    
967
	}
968
	
969
	/**
970
	 * Sends System Metadata as XML
971
	 */
972
	protected static void handleGetSystemMetadataRequest(
973
			Hashtable<String, String[]> params, HttpServletResponse response) {
974
		String guid = ((String[]) (params.get("guid")))[0];
975
		String systemMetadataXML = null;
976
		try {
977
			
978
			// serialize the System Metadata as XML 
979
			SystemMetadata systemMetadata = IdentifierManager.getInstance().getSystemMetadata(guid);
980
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
981
			TypeMarshaller.marshalTypeToOutputStream(systemMetadata, baos);
982
			systemMetadataXML = baos.toString("UTF-8");
983
				
984
			// get a writer for sending back to response
985
			response.setContentType("text/xml");
986
			Writer out = response.getWriter();
987
			out.write(systemMetadataXML);
988
			out.close();
989

    
990
		} catch (Exception e) {
991
			String msg = "ReplicationService.handleGetSystemMetadataRequest for guid: " + guid + " : " + e.getMessage();
992
			logMetacat.error(msg);                         
993
			logReplication.error(msg);
994
		}
995

    
996
	}
997
	
998
	/**
999
	 * when a forcereplication request comes in, local host sends a read request
1000
	 * to the requesting server (remote server) for the specified docid. Then
1001
	 * store it in local database.
1002
	 */
1003
	protected static void handleForceReplicateSystemMetadataRequest(
1004
			Hashtable<String, String[]> params, HttpServletResponse response,
1005
			HttpServletRequest request) {
1006
		String server = ((String[]) params.get("server"))[0]; // the server that
1007
		String guid = ((String[]) params.get("guid"))[0]; // sent the document
1008
		
1009
		try {
1010
			logReplication.info("ReplicationService.handleForceReplicateSystemMetadataRequest - Force replication system metadata request from: " + server);
1011
			// get the system metadata from server
1012
			URL docinfourl = new URL("https://" + server + "?server="
1013
					+ MetacatUtil.getLocalReplicationServerName()
1014
					+ "&action=getsystemmetadata&guid=" + guid);
1015
			
1016
			String systemMetadataXML = ReplicationService.getURLContent(docinfourl);
1017
						
1018
			// process system metadata
1019
			if (systemMetadataXML != null) {
1020
				SystemMetadata sysMeta = 
1021
					TypeMarshaller.unmarshalTypeFromStream(
1022
							SystemMetadata.class,
1023
							new ByteArrayInputStream(systemMetadataXML.getBytes("UTF-8")));
1024
				HazelcastService.getInstance().getSystemMetadataMap().put(sysMeta.getIdentifier(), sysMeta);
1025
			}
1026
      
1027
			logReplication.info("ReplicationService.handleForceReplicateSystemMetadataRequest - processed guid: " + guid);
1028
			EventLog.getInstance().log(request.getRemoteAddr(), request.getHeader("User-Agent"), REPLICATIONUSER, guid, "systemMetadata");
1029

    
1030
		} catch (Exception e) {
1031
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG, e);                         
1032
			logReplication.error("ReplicationService.handleForceReplicateRequest - General error when processing guid: " + guid, e);
1033
		}
1034
	}
1035

    
1036
	/**
1037
	 * Sends a datafile to a remote host
1038
	 */
1039
	protected static void handleGetDataFileRequest(OutputStream outPut,
1040
			Hashtable<String, String[]> params, HttpServletResponse response)
1041

    
1042
	{
1043
		// File path for data file
1044
		String filepath;
1045
		// Request docid
1046
		String docId = ((String[]) (params.get("docid")))[0];
1047
		//check if the doicd is null
1048
		if (docId == null) {
1049
			logMetacat.error("ReplicationService.handleGetDataFileRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1050
			logReplication.error("ReplicationService.handleGetDataFileRequest - Didn't specify docid for replication");
1051
			return;
1052
		}
1053

    
1054
		//try to open a https stream to test if the request server's public key
1055
		//in the key store, this is security issue
1056
		try {
1057
			filepath = PropertyService.getProperty("application.datafilepath");
1058
			String server = params.get("server")[0];
1059
			URL u = new URL("https://" + server + "?server="
1060
					+ MetacatUtil.getLocalReplicationServerName() + "&action=test");
1061
			String test = ReplicationService.getURLContent(u);
1062
			//couldn't pass the test
1063
			if (test.indexOf("successfully") == -1) {
1064
				//response.setContentType("text/xml");
1065
				//outPut.println("<error>Couldn't pass the trust test</error>");
1066
				logMetacat.error("ReplicationService.handleGetDataFileRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1067
				logReplication.error("ReplicationService.handleGetDataFileRequest - Couldn't pass the trust test");
1068
				return;
1069
			}
1070
		}//try
1071
		catch (Exception ee) {
1072
			return;
1073
		}//catch
1074

    
1075
		if (!filepath.endsWith("/")) {
1076
			filepath += "/";
1077
		}
1078
		// Get file aboslute file name
1079
		String filename = filepath + docId;
1080

    
1081
		//MIME type
1082
		String contentType = null;
1083
		if (filename.endsWith(".xml")) {
1084
			contentType = "text/xml";
1085
		} else if (filename.endsWith(".css")) {
1086
			contentType = "text/css";
1087
		} else if (filename.endsWith(".dtd")) {
1088
			contentType = "text/plain";
1089
		} else if (filename.endsWith(".xsd")) {
1090
			contentType = "text/xml";
1091
		} else if (filename.endsWith("/")) {
1092
			contentType = "text/html";
1093
		} else {
1094
			File f = new File(filename);
1095
			if (f.isDirectory()) {
1096
				contentType = "text/html";
1097
			} else {
1098
				contentType = "application/octet-stream";
1099
			}
1100
		}
1101

    
1102
		// Set the mime type
1103
		response.setContentType(contentType);
1104

    
1105
		// Get the content of the file
1106
		FileInputStream fin = null;
1107
		try {
1108
			// FileInputStream to metacat
1109
			fin = new FileInputStream(filename);
1110
			// 4K buffer
1111
			byte[] buf = new byte[4 * 1024];
1112
			// Read data from file input stream to byte array
1113
			int b = fin.read(buf);
1114
			// Write to outStream from byte array
1115
			while (b != -1) {
1116
				outPut.write(buf, 0, b);
1117
				b = fin.read(buf);
1118
			}
1119
			// close file input stream
1120
			fin.close();
1121

    
1122
		}//try
1123
		catch (Exception e) {
1124
			logMetacat.error("ReplicationService.handleGetDataFileRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1125
			logReplication.error("ReplicationService.handleGetDataFileRequest - error getting data file from MetacatReplication."
1126
					+ "handlGetDataFileRequest " + e.getMessage());
1127
			e.printStackTrace(System.out);
1128
		}//catch
1129

    
1130
	}
1131

    
1132
	/**
1133
	 * Sends a document to a remote host
1134
	 */
1135
	protected static void handleGetDocumentRequest(
1136
			Hashtable<String, String[]> params, HttpServletResponse response) {
1137

    
1138
		String urlString = null;
1139
		String documentPath = null;
1140
		String errorMsg = null;
1141
		try {
1142
			// try to open a https stream to test if the request server's public
1143
			// key
1144
			// in the key store, this is security issue
1145
			String server = params.get("server")[0];
1146
			urlString = "https://" + server + "?server="
1147
					+ MetacatUtil.getLocalReplicationServerName() + "&action=test";
1148
			URL u = new URL(urlString);
1149
			String test = ReplicationService.getURLContent(u);
1150
			// couldn't pass the test
1151
			if (test.indexOf("successfully") == -1) {
1152
				response.setContentType("text/xml");
1153
				Writer out = response.getWriter();
1154
				out.write("<error>Couldn't pass the trust test " + test + " </error>");
1155
				out.close();
1156
				return;
1157
			}
1158

    
1159
			String docid = params.get("docid")[0];
1160
			logReplication.debug("ReplicationService.handleGetDocumentRequest - MetacatReplication.handleGetDocumentRequest for docid: "
1161
					+ docid);
1162
			DocumentImpl di = new DocumentImpl(docid);
1163

    
1164
			String documentDir = PropertyService
1165
					.getProperty("application.documentfilepath");
1166
			documentPath = documentDir + FileUtil.getFS() + docid;
1167

    
1168
			// if the document does not exist on disk, read it from db and write
1169
			// it to disk.
1170
			if (FileUtil.getFileStatus(documentPath) == FileUtil.DOES_NOT_EXIST
1171
					|| FileUtil.getFileSize(documentPath) == 0) {
1172
				FileOutputStream fos = new FileOutputStream(documentPath);
1173
				di.toXml(fos, null, null, true);
1174
			}
1175

    
1176
			// read the file from disk and send it to outputstream
1177
			OutputStream outputStream = response.getOutputStream();
1178
			di.readFromFileSystem(outputStream, null, null, documentPath);
1179

    
1180
			logReplication.info("ReplicationService.handleGetDocumentRequest - document " + docid + " sent");
1181

    
1182
			// return to avoid continuing to the error reporting section at the end
1183
			return;
1184
			
1185
		} catch (MalformedURLException mue) {
1186
			logMetacat.error("ReplicationService.handleGetDocumentRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1187
			logReplication.error("ReplicationService.handleGetDocumentRequest - Url error when getting document from MetacatReplication."
1188
					+ "handlGetDocumentRequest for url: " + urlString + " : "
1189
					+ mue.getMessage());
1190
			// e.printStackTrace(System.out);
1191
			
1192
		} catch (IOException ioe) {
1193
			logMetacat.error("ReplicationService.handleGetDocumentRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1194
			logReplication.error("ReplicationService.handleGetDocumentRequest - I/O error when getting document from MetacatReplication."
1195
					+ "handlGetDocumentRequest for file: " + documentPath + " : "
1196
					+ ioe.getMessage());
1197
			errorMsg = ioe.getMessage();
1198
		} catch (PropertyNotFoundException pnfe) {
1199
			logMetacat.error("ReplicationService.handleGetDocumentRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1200
			logReplication
1201
					.error("ReplicationService.handleGetDocumentRequest - Error getting property when getting document from MetacatReplication."
1202
							+ "handlGetDocumentRequest for file: "
1203
							+ documentPath
1204
							+ " : "
1205
							+ pnfe.getMessage());
1206
			// e.printStackTrace(System.out);
1207
			errorMsg = pnfe.getMessage();
1208
		} catch (McdbException me) {
1209
			logReplication
1210
					.error("ReplicationService.handleGetDocumentRequest - Document implementation error  getting property when getting document from MetacatReplication."
1211
							+ "handlGetDocumentRequest for file: "
1212
							+ documentPath
1213
							+ " : "
1214
							+ me.getMessage());
1215
			// e.printStackTrace(System.out);
1216
			errorMsg = me.getMessage();
1217
		}
1218
		
1219
		// report any errors if we got here
1220
		response.setContentType("text/xml");
1221
		Writer out = null;
1222
		try {
1223
			response.getWriter();
1224
			out = response.getWriter();
1225
			out.write("<error>" + errorMsg + "</error>");
1226
		} catch (Exception e) {
1227
			logMetacat.error(e.getMessage(), e);
1228
		} finally {
1229
			try {
1230
				out.close();
1231
			} catch (IOException e) {
1232
				logMetacat.error(e.getMessage(), e);
1233
			}
1234
		}
1235
		
1236

    
1237
	}
1238

    
1239
	/**
1240
	 * Sends a list of all of the documents on this sever along with their
1241
	 * revision numbers. The format is: <!ELEMENT replication (server, updates)>
1242
	 * <!ELEMENT server (#PCDATA)> <!ELEMENT updates ((updatedDocument |
1243
	 * deleteDocument | revisionDocument)*)> <!ELEMENT updatedDocument (docid,
1244
	 * rev, datafile*)> <!ELEMENT deletedDocument (docid, rev)> <!ELEMENT
1245
	 * revisionDocument (docid, rev, datafile*)> <!ELEMENT docid (#PCDATA)>
1246
	 * <!ELEMENT rev (#PCDATA)> <!ELEMENT datafile (#PCDATA)> note that the rev
1247
	 * in deletedDocument is always empty. I just left it in there to make the
1248
	 * parser implementation easier.
1249
	 */
1250
	protected static void handleUpdateRequest(Hashtable<String, String[]> params,
1251
			HttpServletResponse response) {
1252
		// Checked out DBConnection
1253
		DBConnection dbConn = null;
1254
		// DBConenction serial number when checked it out
1255
		int serialNumber = -1;
1256
		PreparedStatement pstmt = null;
1257
		// Server list to store server info of xml_replication table
1258
		ReplicationServerList serverList = null;
1259
		
1260
		// a writer for response
1261
		Writer out = null;
1262

    
1263
		try {
1264
			// get writer, TODO: encoding?
1265
			response.setContentType("text/xml");
1266
			out = response.getWriter();
1267
			
1268
			// Check out a DBConnection from pool
1269
			dbConn = DBConnectionPool
1270
					.getDBConnection("MetacatReplication.handleUpdateRequest");
1271
			serialNumber = dbConn.getCheckOutSerialNumber();
1272
			// Create a server list from xml_replication table
1273
			serverList = new ReplicationServerList();
1274

    
1275
			// Get remote server name from param
1276
			String server = ((String[]) params.get("server"))[0];
1277
			// If no servr name in param, return a error
1278
			if (server == null || server.equals("")) {
1279
				out.write("<error>Request didn't specify server name</error>");
1280
				out.close();
1281
				return;
1282
			}//if
1283

    
1284
			//try to open a https stream to test if the request server's public key
1285
			//in the key store, this is security issue
1286
			String testUrl = "https://" + server + "?server="
1287
            + MetacatUtil.getLocalReplicationServerName() + "&action=test";
1288
			logReplication.info("Running trust test: " + testUrl);
1289
			URL u = new URL(testUrl);
1290
			String test = ReplicationService.getURLContent(u);
1291
			logReplication.info("Ouput from test is '" + test + "'");
1292
			//couldn't pass the test
1293
			if (test.indexOf("successfully") == -1) {
1294
			    logReplication.error("Trust test failed.");
1295
				out.write("<error>Couldn't pass the trust test</error>");
1296
				out.close();
1297
				return;
1298
			}
1299
			logReplication.info("Trust test succeeded.");
1300

    
1301
			// Check if local host configure to replicate xml documents to remote
1302
			// server. If not send back a error message
1303
			if (!serverList.getReplicationValue(server)) {
1304
				out.write("<error>Configuration not allow to replicate document to you</error>");
1305
				out.close();
1306
				return;
1307
			}//if
1308

    
1309
			// Store the sql command
1310
			StringBuffer docsql = new StringBuffer();
1311
			StringBuffer revisionSql = new StringBuffer();
1312
			// Stroe the docid list
1313
			StringBuffer doclist = new StringBuffer();
1314
			// Store the deleted docid list
1315
			StringBuffer delsql = new StringBuffer();
1316
			// Store the data set file
1317
			Vector<Vector<String>> packageFiles = new Vector<Vector<String>>();
1318

    
1319
			// Append local server's name and replication servlet to doclist
1320
			doclist.append("<?xml version=\"1.0\"?><replication>");
1321
			doclist.append("<server>")
1322
					.append(MetacatUtil.getLocalReplicationServerName());
1323
			//doclist.append(util.getProperty("replicationpath"));
1324
			doclist.append("</server><updates>");
1325

    
1326
			// Get correct docid that reside on this server according the requesting
1327
			// server's replicate and data replicate value in xml_replication table
1328
			docsql.append(DatabaseService.getInstance().getDBAdapter().getReplicationDocumentListSQL());
1329
			//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)) ");
1330
			revisionSql.append("select docid, rev, doctype from xml_revisions ");
1331
			// If the localhost is not a hub to the remote server, only replicate
1332
			// the docid' which home server is local host (server_location =1)
1333
			if (!serverList.getHubValue(server)) {
1334
				String serverLocationDoc = " and a.server_location = 1";
1335
				String serverLocationRev = "where server_location = 1";
1336
				docsql.append(serverLocationDoc);
1337
				revisionSql.append(serverLocationRev);
1338
			}
1339
			logReplication.info("ReplicationService.handleUpdateRequest - Doc sql: " + docsql.toString());
1340

    
1341
			// Get any deleted documents
1342
			delsql.append("select distinct docid from ");
1343
			delsql.append("xml_revisions where docid not in (select docid from ");
1344
			delsql.append("xml_documents) ");
1345
			// If the localhost is not a hub to the remote server, only replicate
1346
			// the docid' which home server is local host (server_location =1)
1347
			if (!serverList.getHubValue(server)) {
1348
				delsql.append("and server_location = 1");
1349
			}
1350
			logReplication.info("ReplicationService.handleUpdateRequest - Deleted sql: " + delsql.toString());
1351

    
1352
			// Get docid list of local host
1353
			pstmt = dbConn.prepareStatement(docsql.toString());
1354
			pstmt.execute();
1355
			ResultSet rs = pstmt.getResultSet();
1356
			boolean tablehasrows = rs.next();
1357
			//If metacat configed to replicate data file
1358
			//if ((util.getProperty("replicationsenddata")).equals("on"))
1359
			boolean replicateData = serverList.getDataReplicationValue(server);
1360
			if (replicateData) {
1361
				while (tablehasrows) {
1362
					String recordDoctype = rs.getString(3);
1363
					Vector<String> packagedoctypes = MetacatUtil
1364
							.getOptionList(PropertyService
1365
									.getProperty("xml.packagedoctype"));
1366
					//if this is a package file, put it at the end
1367
					//because if a package file is read before all of the files it
1368
					//refers to are loaded then there is an error
1369
					if (recordDoctype != null && !packagedoctypes.contains(recordDoctype)) {
1370
						//If this is not data file
1371
						if (!recordDoctype.equals("BIN")) {
1372
							//for non-data file document
1373
							doclist.append("<updatedDocument>");
1374
							doclist.append("<docid>").append(rs.getString(1));
1375
							doclist.append("</docid><rev>").append(rs.getInt(2));
1376
							doclist.append("</rev>");
1377
							doclist.append("</updatedDocument>");
1378
						}//if
1379
						else {
1380
							//for data file document, in datafile attributes
1381
							//we put "datafile" value there
1382
							doclist.append("<updatedDocument>");
1383
							doclist.append("<docid>").append(rs.getString(1));
1384
							doclist.append("</docid><rev>").append(rs.getInt(2));
1385
							doclist.append("</rev>");
1386
							doclist.append("<datafile>");
1387
							doclist.append(PropertyService
1388
									.getProperty("replication.datafileflag"));
1389
							doclist.append("</datafile>");
1390
							doclist.append("</updatedDocument>");
1391
						}//else
1392
					}//if packagedoctpes
1393
					else { //the package files are saved to be put into the xml later.
1394
						Vector<String> v = new Vector<String>();
1395
						v.add(rs.getString(1));
1396
						v.add(String.valueOf(rs.getInt(2)));
1397
						packageFiles.add(v);
1398
					}//esle
1399
					tablehasrows = rs.next();
1400
				}//while
1401
			}//if
1402
			else //metacat was configured not to send data file
1403
			{
1404
				while (tablehasrows) {
1405
					String recordDoctype = rs.getString(3);
1406
					if (!recordDoctype.equals("BIN")) { //don't replicate data files
1407
						Vector<String> packagedoctypes = MetacatUtil
1408
								.getOptionList(PropertyService
1409
										.getProperty("xml.packagedoctype"));
1410
						if (recordDoctype != null
1411
								&& !packagedoctypes.contains(recordDoctype)) { //if this is a package file, put it at the end
1412
							//because if a package file is read before all of the files it
1413
							//refers to are loaded then there is an error
1414
							doclist.append("<updatedDocument>");
1415
							doclist.append("<docid>").append(rs.getString(1));
1416
							doclist.append("</docid><rev>").append(rs.getInt(2));
1417
							doclist.append("</rev>");
1418
							doclist.append("</updatedDocument>");
1419
						} else { //the package files are saved to be put into the xml later.
1420
							Vector<String> v = new Vector<String>();
1421
							v.add(rs.getString(1));
1422
							v.add(String.valueOf(rs.getInt(2)));
1423
							packageFiles.add(v);
1424
						}
1425
					}//if
1426
					tablehasrows = rs.next();
1427
				}//while
1428
			}//else
1429

    
1430
			pstmt = dbConn.prepareStatement(delsql.toString());
1431
			//usage count should increas 1
1432
			dbConn.increaseUsageCount(1);
1433

    
1434
			pstmt.execute();
1435
			rs = pstmt.getResultSet();
1436
			tablehasrows = rs.next();
1437
			while (tablehasrows) { //handle the deleted documents
1438
				doclist.append("<deletedDocument><docid>").append(rs.getString(1));
1439
				doclist.append("</docid><rev></rev></deletedDocument>");
1440
				//note that rev is always empty for deleted docs
1441
				tablehasrows = rs.next();
1442
			}
1443

    
1444
			//now we can put the package files into the xml results
1445
			for (int i = 0; i < packageFiles.size(); i++) {
1446
				Vector<String> v = packageFiles.elementAt(i);
1447
				doclist.append("<updatedDocument>");
1448
				doclist.append("<docid>").append(v.elementAt(0));
1449
				doclist.append("</docid><rev>");
1450
				doclist.append(v.elementAt(1));
1451
				doclist.append("</rev>");
1452
				doclist.append("</updatedDocument>");
1453
			}
1454
			// add revision doc list  
1455
			doclist.append(prepareRevisionDoc(dbConn, revisionSql.toString(),
1456
					replicateData));
1457
			
1458
			// add the system metadata entries if configured to replicate them
1459
			boolean replicateSystemMetadata = serverList.getSystemMetadataReplicationValue(server);
1460
			if (replicateSystemMetadata) {
1461
				Date since = new Date(System.currentTimeMillis());
1462
				since = serverList.getLastCheckedDate(server);
1463
				List<String> systemMetadataEntries = 
1464
					IdentifierManager.getInstance().getUpdatedSystemMetadataIds(since);
1465
				for (int i = 0; i < systemMetadataEntries.size(); i++) {
1466
					String guid = systemMetadataEntries.get(i);
1467
					doclist.append("<updatedSystemMetadata>");
1468
					doclist.append("<guid>");
1469
					doclist.append(guid);
1470
					doclist.append("</guid>");
1471
					doclist.append("</updatedSystemMetadata>");
1472
				}
1473
			}
1474

    
1475
			doclist.append("</updates></replication>");
1476
			logReplication.info("ReplicationService.handleUpdateRequest - doclist: " + doclist.toString());
1477
			pstmt.close();
1478
			//conn.close();
1479
			out.write(doclist.toString());
1480

    
1481
		} catch (Exception e) {
1482
			logMetacat.error("ReplicationService.handleUpdateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1483
			logReplication.error("ReplicationService.handleUpdateRequest - error in MetacatReplication." + "handleupdaterequest: "
1484
					+ e.getMessage());
1485
			//e.printStackTrace(System.out);
1486
			try {
1487
				out.write("<error>" + e.getMessage() + "</error>");
1488
			} catch (IOException e1) {
1489
				logMetacat.error(e1.getMessage(), e1);
1490
			}
1491
		} finally {
1492
			try {
1493
				pstmt.close();
1494
			}//try
1495
			catch (SQLException ee) {
1496
				logMetacat.error("ReplicationService.handleUpdateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1497
				logReplication.error("ReplicationService.handleUpdateRequest - Error in MetacatReplication."
1498
						+ "handleUpdaterequest to close pstmt: " + ee.getMessage());
1499
			}//catch
1500
			finally {
1501
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1502
			}//finally
1503
			try {
1504
				out.close();
1505
			} catch (IOException e) {
1506
				logMetacat.error(e.getMessage(), e);
1507
			}
1508
		}//finally
1509

    
1510
	}//handlUpdateRequest
1511

    
1512
	/**
1513
	 * 
1514
	 * @param dbConn connection for doing the update
1515
	 * @param docid the document id to update
1516
	 * @param owner the user_owner
1517
	 * @param updater the user_updated
1518
	 * @throws SQLException
1519
	 */
1520
	public static void updateUserOwner(DBConnection dbConn, String docid, String owner, String updater) throws SQLException {
1521
	
1522
		String sql = 
1523
			"UPDATE xml_documents " +
1524
			"SET user_owner = ?, " +
1525
			"user_updated = ? " +
1526
			"WHERE docid = ?;";
1527
		PreparedStatement pstmt = dbConn.prepareStatement(sql);
1528
		//usage count should increas 1
1529
		dbConn.increaseUsageCount(1);
1530

    
1531
		docid = DocumentUtil.getSmartDocId(docid);
1532
		pstmt.setString(1, owner);
1533
		pstmt.setString(2, updater);
1534
		pstmt.setString(3, docid);
1535
		pstmt.execute();
1536
		pstmt.close();
1537
		
1538
		dbConn.commit();
1539
	}
1540
	
1541
	/*
1542
	 * This method will get the xml string for document in xml_revision
1543
	 * The schema look like <!ELEMENT revisionDocument (docid, rev, datafile*)>
1544
	 */
1545
	private static String prepareRevisionDoc(DBConnection dbConn, String revSql,
1546
			boolean replicateData) throws Exception {
1547
		logReplication.warn("ReplicationService.prepareRevisionDoc - The revision document sql is " + revSql);
1548
		StringBuffer revDocList = new StringBuffer();
1549
		PreparedStatement pstmt = dbConn.prepareStatement(revSql);
1550
		//usage count should increas 1
1551
		dbConn.increaseUsageCount(1);
1552

    
1553
		pstmt.execute();
1554
		ResultSet rs = pstmt.getResultSet();
1555
		boolean tablehasrows = rs.next();
1556
		while (tablehasrows) {
1557
			String recordDoctype = rs.getString(3);
1558

    
1559
			//If this is data file and it isn't configured to replicate data
1560
			if (recordDoctype.equals("BIN") && !replicateData) {
1561
				// do nothing
1562
				continue;
1563
			} else {
1564

    
1565
				revDocList.append("<revisionDocument>");
1566
				revDocList.append("<docid>").append(rs.getString(1));
1567
				revDocList.append("</docid><rev>").append(rs.getInt(2));
1568
				revDocList.append("</rev>");
1569
				// data file
1570
				if (recordDoctype.equals("BIN")) {
1571
					revDocList.append("<datafile>");
1572
					revDocList.append(PropertyService
1573
							.getProperty("replication.datafileflag"));
1574
					revDocList.append("</datafile>");
1575
				}
1576
				revDocList.append("</revisionDocument>");
1577

    
1578
			}//else
1579
			tablehasrows = rs.next();
1580
		}
1581
		//System.out.println("The revision list is"+ revDocList.toString());
1582
		return revDocList.toString();
1583
	}
1584

    
1585
	/**
1586
	 * Returns the xml_catalog table encoded in xml
1587
	 */
1588
	public static String getCatalogXML() {
1589
		return handleGetCatalogRequest(null, null, false);
1590
	}
1591

    
1592
	/**
1593
	 * Sends the contents of the xml_catalog table encoded in xml
1594
	 * The xml format is:
1595
	 * <!ELEMENT xml_catalog (row*)>
1596
	 * <!ELEMENT row (entry_type, source_doctype, target_doctype, public_id,
1597
	 *                system_id)>
1598
	 * All of the sub elements of row are #PCDATA
1599

    
1600
	 * If printFlag == false then do not print to out.
1601
	 */
1602
	protected static String handleGetCatalogRequest(
1603
			Hashtable<String, String[]> params, HttpServletResponse response,
1604
			boolean printFlag) {
1605
		DBConnection dbConn = null;
1606
		int serialNumber = -1;
1607
		PreparedStatement pstmt = null;
1608
		Writer out = null;
1609
		try {
1610
			// get writer, TODO: encoding?
1611
		    if(printFlag)
1612
		    {
1613
		        response.setContentType("text/xml");
1614
		        out = response.getWriter();
1615
		    }
1616
			/*conn = MetacatReplication.getDBConnection("MetacatReplication." +
1617
			                                          "handleGetCatalogRequest");*/
1618
			dbConn = DBConnectionPool
1619
					.getDBConnection("MetacatReplication.handleGetCatalogRequest");
1620
			serialNumber = dbConn.getCheckOutSerialNumber();
1621
			pstmt = dbConn.prepareStatement("select entry_type, "
1622
					+ "source_doctype, target_doctype, public_id, "
1623
					+ "system_id from xml_catalog");
1624
			pstmt.execute();
1625
			ResultSet rs = pstmt.getResultSet();
1626
			boolean tablehasrows = rs.next();
1627
			StringBuffer sb = new StringBuffer();
1628
			sb.append("<?xml version=\"1.0\"?><xml_catalog>");
1629
			while (tablehasrows) {
1630
				sb.append("<row><entry_type>").append(rs.getString(1));
1631
				sb.append("</entry_type><source_doctype>").append(rs.getString(2));
1632
				sb.append("</source_doctype><target_doctype>").append(rs.getString(3));
1633
				sb.append("</target_doctype><public_id>").append(rs.getString(4));
1634
				// system id may not have server url on front.  Add it if not.
1635
				String systemID = rs.getString(5);
1636
				if (!systemID.startsWith("http://")) {
1637
					systemID = SystemUtil.getContextURL() + systemID;
1638
				}
1639
				sb.append("</public_id><system_id>").append(systemID);
1640
				sb.append("</system_id></row>");
1641

    
1642
				tablehasrows = rs.next();
1643
			}
1644
			sb.append("</xml_catalog>");
1645
			//conn.close();
1646
			if (printFlag) {
1647
				response.setContentType("text/xml");
1648
				out.write(sb.toString());
1649
			}
1650
			pstmt.close();
1651
			return sb.toString();
1652
		} catch (Exception e) {
1653
			logMetacat.error("ReplicationService.handleGetCatalogRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1654
			logReplication.error("ReplicationService.handleGetCatalogRequest - error in MetacatReplication.handleGetCatalogRequest:"
1655
					+ e.getMessage());
1656
			e.printStackTrace(System.out);
1657
			if (printFlag) {
1658
				try {
1659
					out.write("<error>" + e.getMessage() + "</error>");
1660
				} catch (IOException e1) {
1661
					logMetacat.error(e1.getMessage(), e1);
1662
				}
1663
			}
1664
		} finally {
1665
			try {
1666
				pstmt.close();
1667
			}//try
1668
			catch (SQLException ee) {
1669
				logMetacat.error("ReplicationService.handleGetCatalogRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1670
				logReplication.error("ReplicationService.handleGetCatalogRequest - Error in MetacatReplication.handleGetCatalogRequest: "
1671
						+ ee.getMessage());
1672
			}//catch
1673
			finally {
1674
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1675
			}//finally
1676
			if (out != null) {
1677
				try {
1678
					out.close();
1679
				} catch (IOException e1) {
1680
					logMetacat.error(e1.getMessage(), e1);
1681
				}
1682
			}
1683
		}//finally
1684

    
1685
		return null;
1686
	}
1687

    
1688
	/**
1689
	 * Sends the current system date to the remote server.  Using this action
1690
	 * for replication gets rid of any problems with syncronizing clocks
1691
	 * because a time specific to a document is always kept on its home server.
1692
	 */
1693
	protected static void handleGetTimeRequest(
1694
			Hashtable<String, String[]> params, HttpServletResponse response) {
1695
		
1696
		// use standard format -- the receiving end wants this too
1697
		String dateString = DateTimeMarshaller.serializeDateToUTC(Calendar.getInstance().getTime());
1698
		
1699
		// get a writer for sending back to response
1700
		response.setContentType("text/xml");
1701
		Writer out = null;
1702
		try {
1703
			out = response.getWriter();
1704
			out.write("<timestamp>" + dateString + "</timestamp>");
1705
			out.close();
1706
		} catch (IOException e) {
1707
			logMetacat.error(e.getMessage(), e);
1708
		}
1709
		
1710
	}
1711

    
1712
	/**
1713
	 * this method handles the timeout for a file lock.  when a lock is
1714
	 * granted it is granted for 30 seconds.  When this thread runs out
1715
	 * it deletes the docid from the queue, thus eliminating the lock.
1716
	 */
1717
	public void run() {
1718
		try {
1719
			logReplication.info("ReplicationService.run - thread started for docid: "
1720
					+ (String) fileLocks.elementAt(0));
1721

    
1722
			Thread.sleep(30000); //the lock will expire in 30 seconds
1723
			logReplication.info("thread for docid: "
1724
					+ (String) fileLocks.elementAt(fileLocks.size() - 1) + " exiting.");
1725

    
1726
			fileLocks.remove(fileLocks.size() - 1);
1727
			//fileLocks is treated as a FIFO queue.  If there are more than one lock
1728
			//in the vector, the first one inserted will be removed.
1729
		} catch (Exception e) {
1730
			logMetacat.error("ReplicationService.run - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1731
			logReplication.error("ReplicationService.run - error in file lock thread from "
1732
					+ "MetacatReplication.run: " + e.getMessage());
1733
		}
1734
	}
1735

    
1736
	/**
1737
	 * Returns the name of a server given a serverCode
1738
	 * @param serverCode the serverid of the server
1739
	 * @return the servername or null if the specified serverCode does not
1740
	 *         exist.
1741
	 */
1742
	public static String getServerNameForServerCode(int serverCode) {
1743
		//System.out.println("serverid: " + serverCode);
1744
		DBConnection dbConn = null;
1745
		int serialNumber = -1;
1746
		PreparedStatement pstmt = null;
1747
		try {
1748
			dbConn = DBConnectionPool.getDBConnection("MetacatReplication.getServer");
1749
			serialNumber = dbConn.getCheckOutSerialNumber();
1750
			String sql = new String("select server from "
1751
					+ "xml_replication where serverid = ?");
1752
			pstmt = dbConn.prepareStatement(sql);
1753
			pstmt.setInt(1, serverCode);
1754
			//System.out.println("getserver sql: " + sql);
1755
			pstmt.execute();
1756
			ResultSet rs = pstmt.getResultSet();
1757
			boolean tablehasrows = rs.next();
1758
			if (tablehasrows) {
1759
				//System.out.println("server: " + rs.getString(1));
1760
				return rs.getString(1);
1761
			}
1762

    
1763
			//conn.close();
1764
		} catch (Exception e) {
1765
			logMetacat.error("ReplicationService.getServerNameForServerCode - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1766
			logReplication.error("ReplicationService.getServerNameForServerCode - Error in MetacatReplication.getServer: " + e.getMessage());
1767
		} finally {
1768
			try {
1769
				pstmt.close();
1770
			}//try
1771
			catch (SQLException ee) {
1772
				logMetacat.error("ReplicationService.getServerNameForServerCode - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1773
				logReplication.error("ReplicationService.getServerNameForServerCode - Error in MetacactReplication.getserver: "
1774
						+ ee.getMessage());
1775
			}//catch
1776
			finally {
1777
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1778
			}//fianlly
1779
		}//finally
1780

    
1781
		return null;
1782
		//return null if the server does not exist
1783
	}
1784

    
1785
	/**
1786
	 * Returns a server code given a server name
1787
	 * @param server the name of the server
1788
	 * @return integer > 0 representing the code of the server, 0 if the server
1789
	 *  does not exist.
1790
	 */
1791
	public static int getServerCodeForServerName(String server) throws ServiceException {
1792
		DBConnection dbConn = null;
1793
		int serialNumber = -1;
1794
		PreparedStatement pstmt = null;
1795
		int serverCode = 0;
1796

    
1797
		try {
1798

    
1799
			//conn = util.openDBConnection();
1800
			dbConn = DBConnectionPool.getDBConnection("MetacatReplication.getServerCode");
1801
			serialNumber = dbConn.getCheckOutSerialNumber();
1802
			pstmt = dbConn.prepareStatement("SELECT serverid FROM xml_replication "
1803
					+ "WHERE server LIKE ?");
1804
			pstmt.setString(1, server);
1805
			pstmt.execute();
1806
			ResultSet rs = pstmt.getResultSet();
1807
			boolean tablehasrows = rs.next();
1808
			if (tablehasrows) {
1809
				serverCode = rs.getInt(1);
1810
				pstmt.close();
1811
				//conn.close();
1812
				return serverCode;
1813
			}
1814

    
1815
		} catch (SQLException sqle) {
1816
			throw new ServiceException("ReplicationService.getServerCodeForServerName - " 
1817
					+ "SQL error when getting server code: " + sqle.getMessage());
1818

    
1819
		} finally {
1820
			try {
1821
				pstmt.close();
1822
				//conn.close();
1823
			}//try
1824
			catch (Exception ee) {
1825
				logMetacat.error("ReplicationService.getServerCodeForServerName - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1826
				logReplication.error("ReplicationService.getServerNameForServerCode - Error in MetacatReplicatio.getServerCode: "
1827
						+ ee.getMessage());
1828

    
1829
			}//catch
1830
			finally {
1831
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1832
			}//finally
1833
		}//finally
1834

    
1835
		return serverCode;
1836
	}
1837

    
1838
	/**
1839
	 * Method to get a host server information for given docid
1840
	 * @param conn a connection to the database
1841
	 */
1842
	public static Hashtable<String, String> getHomeServerInfoForDocId(String docId) {
1843
		Hashtable<String, String> sl = new Hashtable<String, String>();
1844
		DBConnection dbConn = null;
1845
		int serialNumber = -1;
1846
		docId = DocumentUtil.getDocIdFromString(docId);
1847
		PreparedStatement pstmt = null;
1848
		int serverLocation;
1849
		try {
1850
			//get conection
1851
			dbConn = DBConnectionPool.getDBConnection("ReplicationHandler.getHomeServer");
1852
			serialNumber = dbConn.getCheckOutSerialNumber();
1853
			//get a server location from xml_document table
1854
			pstmt = dbConn.prepareStatement("select server_location from xml_documents "
1855
					+ "where docid = ?");
1856
			pstmt.setString(1, docId);
1857
			pstmt.execute();
1858
			ResultSet serverName = pstmt.getResultSet();
1859
			//get a server location
1860
			if (serverName.next()) {
1861
				serverLocation = serverName.getInt(1);
1862
				pstmt.close();
1863
			} else {
1864
				pstmt.close();
1865
				//ut.returnConnection(conn);
1866
				return null;
1867
			}
1868
			pstmt = dbConn.prepareStatement("select server, last_checked, replicate "
1869
					+ "from xml_replication where serverid = ?");
1870
			//increase usage count
1871
			dbConn.increaseUsageCount(1);
1872
			pstmt.setInt(1, serverLocation);
1873
			pstmt.execute();
1874
			ResultSet rs = pstmt.getResultSet();
1875
			boolean tableHasRows = rs.next();
1876
			if (tableHasRows) {
1877

    
1878
				String server = rs.getString(1);
1879
				String last_checked = rs.getString(2);
1880
				if (!server.equals("localhost")) {
1881
					sl.put(server, last_checked);
1882
				}
1883

    
1884
			} else {
1885
				pstmt.close();
1886
				//ut.returnConnection(conn);
1887
				return null;
1888
			}
1889
			pstmt.close();
1890
		} catch (Exception e) {
1891
			logMetacat.error("ReplicationService.getHomeServerInfoForDocId - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1892
			logReplication.error("ReplicationService.getHomeServerInfoForDocId - error in replicationHandler.getHomeServer(): "
1893
					+ e.getMessage());
1894
		} finally {
1895
			try {
1896
				pstmt.close();
1897
				//ut.returnConnection(conn);
1898
			} catch (Exception ee) {
1899
				logMetacat.error("ReplicationService.getHomeServerInfoForDocId - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1900
				logReplication.error("ReplicationService.getHomeServerInfoForDocId - Eror irn rplicationHandler.getHomeServer() "
1901
						+ "to close pstmt: " + ee.getMessage());
1902
			} finally {
1903
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1904
			}
1905

    
1906
		}//finally
1907
		return sl;
1908
	}
1909

    
1910
	/**
1911
	 * Returns a home server location  given a accnum
1912
	 * @param accNum , given accNum for a document
1913
	 *
1914
	 */
1915
	public static int getHomeServerCodeForDocId(String accNum) throws ServiceException {
1916
		DBConnection dbConn = null;
1917
		int serialNumber = -1;
1918
		PreparedStatement pstmt = null;
1919
		int serverCode = 1;
1920
		String docId = DocumentUtil.getDocIdFromString(accNum);
1921

    
1922
		try {
1923

    
1924
			// Get DBConnection
1925
			dbConn = DBConnectionPool
1926
					.getDBConnection("ReplicationHandler.getServerLocation");
1927
			serialNumber = dbConn.getCheckOutSerialNumber();
1928
			pstmt = dbConn.prepareStatement("SELECT server_location FROM xml_documents "
1929
					+ "WHERE docid LIKE ? ");
1930
			pstmt.setString(1, docId);
1931
			pstmt.execute();
1932
			ResultSet rs = pstmt.getResultSet();
1933
			boolean tablehasrows = rs.next();
1934
			//If a document is find, return the server location for it
1935
			if (tablehasrows) {
1936
				serverCode = rs.getInt(1);
1937
				pstmt.close();
1938
				//conn.close();
1939
				return serverCode;
1940
			}
1941
			//if couldn't find in xml_documents table, we think server code is 1
1942
			//(this is new document)
1943
			else {
1944
				pstmt.close();
1945
				//conn.close();
1946
				return serverCode;
1947
			}
1948

    
1949
		} catch (SQLException sqle) {
1950
			throw new ServiceException("ReplicationService.getHomeServerCodeForDocId - " 
1951
					+ "SQL error when getting home server code for docid: " + docId + " : " 
1952
					+ sqle.getMessage());
1953

    
1954
		} finally {
1955
			try {
1956
				pstmt.close();
1957
				//conn.close();
1958

    
1959
			} catch (SQLException sqle) {
1960
				logMetacat.error("ReplicationService.getHomeServerCodeForDocId - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1961
				logReplication.error("ReplicationService.getHomeServerCodeForDocId - ReplicationService.getHomeServerCodeForDocId - " 
1962
						+ "SQL error when getting home server code for docid: " + docId + " : " 
1963
						+ sqle.getMessage());
1964
			} finally {
1965
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1966
			}//finally
1967
		}//finally
1968
		//return serverCode;
1969
	}
1970

    
1971
	/**
1972
	 * This method returns the content of a url
1973
	 * @param u the url to return the content from
1974
	 * @return a string representing the content of the url
1975
	 * @throws java.io.IOException
1976
	 */
1977
	public static String getURLContent(URL u) throws java.io.IOException {
1978
		char istreamChar;
1979
		int istreamInt;
1980
		// get the response content
1981
		InputStream input = getURLStream(u);
1982
		logReplication.info("ReplicationService.getURLContent - After getting response from: " + u.toString());
1983
		InputStreamReader istream = new InputStreamReader(input);
1984
		StringBuffer serverResponse = new StringBuffer();
1985
		while ((istreamInt = istream.read()) != -1) {
1986
			istreamChar = (char) istreamInt;
1987
			serverResponse.append(istreamChar);
1988
		}
1989
		istream.close();
1990
		input.close();
1991

    
1992
		return serverResponse.toString();
1993
	}
1994
	
1995
	/**
1996
	 * This method returns the InputStream after opening a url
1997
	 * @param u the url to return the content from
1998
	 * @return a InputStream representing the content of the url
1999
	 * @throws java.io.IOException
2000
	 */
2001
	public static InputStream getURLStream(URL u) throws java.io.IOException {
2002
	    logReplication.info("Getting url stream from " + u.toString());
2003
		logReplication.info("ReplicationService.getURLStream - Before sending request to: " + u.toString());
2004
		// use httpclient to set up SSL
2005
		RestClient client = getSSLClient();
2006
		HttpResponse response = client.doGetRequest(u.toString());
2007
		// get the response content
2008
		InputStream input = response.getEntity().getContent();
2009
		logReplication.info("ReplicationService.getURLStream - After getting response from: " + u.toString());
2010
		
2011
		return input;		
2012
	}
2013
	
2014
	/**
2015
	 * Sets up an HttpClient with SSL connection.
2016
	 * Sends client certificate to the server when doing the request.
2017
	 * @return
2018
	 */
2019
	private static RestClient getSSLClient() {
2020
		RestClient client = new RestClient();
2021
		
2022
		// set up this server's client identity
2023
		String subject = null;
2024
		try {
2025
			// TODO: should there be alternative ways to get the key and certificate?
2026
			String certificateFile = PropertyService.getProperty("replication.certificate.file");
2027
	    	String keyFile = PropertyService.getProperty("replication.privatekey.file");
2028
			String keyPassword = PropertyService.getProperty("replication.privatekey.password");
2029
			X509Certificate certificate = CertificateManager.getInstance().loadCertificateFromFile(certificateFile);
2030
			PrivateKey privateKey = CertificateManager.getInstance().loadPrivateKeyFromFile(keyFile, keyPassword);
2031
			subject = CertificateManager.getInstance().getSubjectDN(certificate);
2032
			CertificateManager.getInstance().registerCertificate(subject, certificate, privateKey);
2033
		} catch (Exception e) {
2034
			// this is pretty much required for replication communication
2035
			logReplication.warn("Could not find server's client certificate/private key: " + e.getMessage());
2036
		}
2037
		SSLSocketFactory socketFactory = null;
2038
		try {
2039
			socketFactory = CertificateManager.getInstance().getSSLSocketFactory(subject);
2040
		} catch (FileNotFoundException e) {
2041
			// these are somewhat expected for anonymous client use
2042
			logReplication.warn("Could not set up SSL connection for client - likely because the certificate could not be located: " + e.getMessage());
2043
		} catch (Exception e) {
2044
			// this is likely more severe
2045
			logReplication.warn("Funky SSL going on: " + e.getClass() + ":: " + e.getMessage());
2046
		}
2047
		try {
2048
			//443 is the default port, this value is overridden if explicitly set in the URL
2049
			Scheme sch = new Scheme("https", 443, socketFactory);
2050
			client.getHttpClient().getConnectionManager().getSchemeRegistry().register(sch);
2051
		} catch (Exception e) {
2052
			// this is likely more severe
2053
			logReplication.error("Failed to set up SSL connection for client. Continuing. " + e.getClass() + ":: " + e.getMessage(), e);
2054
		}
2055
		return client;
2056
	}
2057
	
2058

    
2059
//	/**
2060
//	 * Method for writing replication messages to a log file specified in
2061
//	 * metacat.properties
2062
//	 */
2063
//	public static void replLog(String message) {
2064
//		try {
2065
//			FileOutputStream fos = new FileOutputStream(PropertyService
2066
//					.getProperty("replication.logdir")
2067
//					+ "/metacatreplication.log", true);
2068
//			PrintWriter pw = new PrintWriter(fos);
2069
//			SimpleDateFormat formatter = new SimpleDateFormat("yy-MM-dd HH:mm:ss");
2070
//			java.util.Date localtime = new java.util.Date();
2071
//			String dateString = formatter.format(localtime);
2072
//			dateString += " :: " + message;
2073
//			// time stamp each entry
2074
//			pw.println(dateString);
2075
//			pw.flush();
2076
//		} catch (Exception e) {
2077
//			logReplication.error("error writing to replication log from "
2078
//					+ "MetacatReplication.replLog: " + e.getMessage());
2079
//			// e.printStackTrace(System.out);
2080
//		}
2081
//	}
2082

    
2083
//	/**
2084
//	 * Method for writing replication messages to a log file specified in
2085
//	 * metacat.properties
2086
//	 */
2087
//	public static void replErrorLog(String message) {
2088
//		try {
2089
//			FileOutputStream fos = new FileOutputStream(PropertyService
2090
//					.getProperty("replication.logdir")
2091
//					+ "/metacatreplicationerror.log", true);
2092
//			PrintWriter pw = new PrintWriter(fos);
2093
//			SimpleDateFormat formatter = new SimpleDateFormat("yy-MM-dd HH:mm:ss");
2094
//			java.util.Date localtime = new java.util.Date();
2095
//			String dateString = formatter.format(localtime);
2096
//			dateString += " :: " + message;
2097
//			//time stamp each entry
2098
//			pw.println(dateString);
2099
//			pw.flush();
2100
//		} catch (Exception e) {
2101
//			logReplication.error("error writing to replication error log from "
2102
//					+ "MetacatReplication.replErrorLog: " + e.getMessage());
2103
//			//e.printStackTrace(System.out);
2104
//		}
2105
//	}
2106

    
2107
	/**
2108
	 * Returns true if the replicate field for server in xml_replication is 1.
2109
	 * Returns false otherwise
2110
	 */
2111
	public static boolean replToServer(String server) {
2112
		DBConnection dbConn = null;
2113
		int serialNumber = -1;
2114
		PreparedStatement pstmt = null;
2115
		try {
2116
			dbConn = DBConnectionPool.getDBConnection("MetacatReplication.repltoServer");
2117
			serialNumber = dbConn.getCheckOutSerialNumber();
2118
			pstmt = dbConn.prepareStatement("select replicate from "
2119
					+ "xml_replication where server like ? ");
2120
			pstmt.setString(1, server);
2121
			pstmt.execute();
2122
			ResultSet rs = pstmt.getResultSet();
2123
			boolean tablehasrows = rs.next();
2124
			if (tablehasrows) {
2125
				int i = rs.getInt(1);
2126
				if (i == 1) {
2127
					pstmt.close();
2128
					//conn.close();
2129
					return true;
2130
				} else {
2131
					pstmt.close();
2132
					//conn.close();
2133
					return false;
2134
				}
2135
			}
2136
		} catch (SQLException sqle) {
2137
			logMetacat.error("ReplicationService.replToServer - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
2138
			logReplication.error("ReplicationService.replToServer - SQL error in MetacatReplication.replToServer: "
2139
					+ sqle.getMessage());
2140
		} finally {
2141
			try {
2142
				pstmt.close();
2143
				//conn.close();
2144
			}//try
2145
			catch (Exception ee) {
2146
				logMetacat.error("ReplicationService.replToServer - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
2147
				logReplication.error("ReplicationService.replToServer - Error in MetacatReplication.replToServer: "
2148
						+ ee.getMessage());
2149
			}//catch
2150
			finally {
2151
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
2152
			}//finally
2153
		}//finally
2154
		return false;
2155
		//the default if this server does not exist is to not replicate to it.
2156
	}
2157

    
2158
}
(7-7/8)