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-12-21 13:00:40 -0800 (Wed, 21 Dec 2011) $'
10
 * '$Revision: 6814 $'
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.jibx.runtime.JiBXException;
69
import org.xml.sax.InputSource;
70
import org.xml.sax.SAXException;
71
import org.xml.sax.XMLReader;
72

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

    
101
public class ReplicationService extends BaseService {
102

    
103
	private static ReplicationService replicationService = null;
104

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
284
	/**
285
	 * This method can add, delete and list the servers currently included in
286
	 * xml_replication.
287
	 * action           subaction            other needed params
288
	 * ---------------------------------------------------------
289
	 * servercontrol    add                  server
290
	 * servercontrol    delete               server
291
	 * servercontrol    list
292
	 */
293
	public static void handleServerControlRequest(
294
			Hashtable<String, String[]> params, HttpServletResponse response) {
295
		String subaction = ((String[]) params.get("subaction"))[0];
296
		DBConnection dbConn = null;
297
		int serialNumber = -1;
298
		PreparedStatement pstmt = null;
299
		String replicate = null;
300
		String server = null;
301
		String dataReplicate = null;
302
		String hub = null;
303
		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
				
321
				//Get hub value
322
				hub = ((String[]) params.get("hub"))[0];
323

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

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

    
369
					tablehasrows = rs.next();
370
				}
371
				out.write("</table></body></html>");
372

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

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

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

    
427
					tablehasrows = rs.next();
428
				}
429
				out.write("</table></body></html>");
430
			} else {
431

    
432
				out.write("<error>Unkonwn subaction</error>");
433

    
434
			}
435
			pstmt.close();
436
			//conn.close();
437

    
438
		} catch (Exception e) {
439
			logMetacat.error("ReplicationService.handleServerControlRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
440
			logReplication.error("ReplicationService.handleServerControlRequest - Error in "
441
					+ "MetacatReplication.handleServerControlRequest " + e.getMessage());
442
			e.printStackTrace(System.out);
443
		} finally {
444
			try {
445
				pstmt.close();
446
			}//try
447
			catch (SQLException ee) {
448
				logMetacat.error("ReplicationService.handleServerControlRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
449
				logReplication.error("ReplicationService.handleServerControlRequest - Error in MetacatReplication.handleServerControlRequest to close pstmt "
450
						+ ee.getMessage());
451
			}//catch
452
			finally {
453
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
454
			}//finally
455
			if (out != null) {
456
				try {
457
					out.close();
458
				} catch (IOException e) {
459
					logMetacat.error(e.getMessage(), e);
460
				}
461
			}
462
		}//finally
463

    
464
	}
465

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

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

    
499
			// get the document info from server
500
			URL docinfourl = new URL("https://" + server + "?server="
501
					+ MetacatUtil.getLocalReplicationServerName()
502
					+ "&action=getdocumentinfo&docid=" + docid);
503
			
504

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

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

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

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

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

    
681
		}//catch
682

    
683
	}
684

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

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

    
708
		// Overide or not
709
		//    boolean override = false;
710
		// dbaction - update or insert
711
		String dbaction = null;
712

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

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

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

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

    
747
			String docType = (String) docinfoHash.get("doctype");
748

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

    
759
			// in case we have a write exception, we still want to track access and sysmeta
760
			Exception writeException = null;
761

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

    
772
				InputStream inputStream = getURLStream(url);
773
				
774
				//register data file into xml_documents table and write 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
			}
786
			
787
			// process the real owner and updater
788
			DBConnection dbConn = DBConnectionPool.getDBConnection("ReplicationService.handleForceDataFileRequest");
789
	        int serialNumber = dbConn.getCheckOutSerialNumber();
790
	        dbConn.setAutoCommit(false);
791
			String user = (String) docinfoHash.get("user_owner");
792
			String updated = (String) docinfoHash.get("user_updated");
793
	        updateUserOwner(dbConn, docid, user, updated);
794
	        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
795
	        
796
			// process system metadata
797
	        if (systemMetadataXML != null) {
798
	      	  SystemMetadata sysMeta = 
799
	      		TypeMarshaller.unmarshalTypeFromStream(
800
	      				  SystemMetadata.class, 
801
	      				  new ByteArrayInputStream(systemMetadataXML.getBytes("UTF-8")));
802
	      	  
803
	      	  // need the guid-to-docid mapping
804
	      	  boolean mappingExists = true;
805
	      	  mappingExists = IdentifierManager.getInstance().identifierExists(sysMeta.getIdentifier().getValue());
806
	      	  if (!mappingExists) {
807
	      		  IdentifierManager.getInstance().createMapping(sysMeta.getIdentifier().getValue(), docid);
808
	      	  }
809
	      	  // save the system metadata
810
	      	  HazelcastService.getInstance().getSystemMetadataMap().put(sysMeta.getIdentifier(), sysMeta);
811
	        }
812
	        
813
	        // process the access control
814
	        Vector<XMLAccessDAO> accessControlList = dih.getAccessControlList();
815
	        if (accessControlList != null) {
816
	        	AccessControlForSingleFile acfsf = new AccessControlForSingleFile(docid);
817
	        	for (XMLAccessDAO xmlAccessDAO : accessControlList) {
818
	        		if (!acfsf.accessControlExists(xmlAccessDAO)) {
819
	        			acfsf.insertPermissions(xmlAccessDAO);
820
						logReplication.info("ReplicationService.handleForceReplicateRequest - document " + docid
821
								+ " permissions added to DB");
822
	        		}
823
	            }
824
	        }
825
	        
826
	        // throw the write exception now -- this happens when access changes on an object
827
			if (writeException != null) {
828
				throw writeException;
829
			}
830

    
831
			logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - datafile " + docid + " added to DB with "
832
					+ "action " + dbaction);
833
			EventLog.getInstance().log(request.getRemoteAddr(), request.getHeader("User-Agent"), REPLICATIONUSER,
834
					docid, dbaction);
835

    
836
		} catch (Exception e) {
837
			e.printStackTrace();
838
			logMetacat.error("ReplicationService.handleForceReplicateDataFileRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG, e);                         
839
			logReplication.error("ReplicationService.handleForceReplicateDataFileRequest - Datafile " + docid
840
					+ " failed to added to DB with " + "action " + dbaction + " because "
841
					+ e.getMessage());
842
			logReplication.error("ReplicationService.handleForceReplicateDataFileRequest - ERROR in MetacatReplication.handleForceDataFileReplicate"
843
					+ "Request(): " + e.getMessage());
844
		}
845
	}
846

    
847
	/**
848
	 * Grants or denies a lock to a requesting host.
849
	 * The servlet parameters of interrest are:
850
	 * docid: the docid of the file the lock is being requested for
851
	 * currentdate: the timestamp of the document on the remote server
852
	 *
853
	 */
854
	protected static void handleGetLockRequest(
855
			Hashtable<String, String[]> params, HttpServletResponse response) {
856

    
857
		try {
858

    
859
			String docid = ((String[]) params.get("docid"))[0];
860
			String remoteRev = ((String[]) params.get("updaterev"))[0];
861
			DocumentImpl requestDoc = new DocumentImpl(docid);
862
			logReplication.info("ReplicationService.handleGetLockRequest - lock request for " + docid);
863
			int localRevInt = requestDoc.getRev();
864
			int remoteRevInt = Integer.parseInt(remoteRev);
865

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

    
900
	/**
901
	 * Sends all of the xml_documents information encoded in xml to a requestor
902
	 * the format is:
903
	 * <!ELEMENT documentinfo (docid, docname, doctype, doctitle, user_owner,
904
	 *                  user_updated, home_server, public_access, rev)/>
905
	 * all of the subelements of document info are #PCDATA
906
	 */
907
	protected static void handleGetDocumentInfoRequest(
908
			Hashtable<String, String[]> params, HttpServletResponse response) {
909
		String docid = ((String[]) (params.get("docid")))[0];
910

    
911
		try {
912
			// get docinfo as XML string
913
			String docinfoXML = getDocumentInfo(docid);
914
			
915
			// get a writer for sending back to response
916
			response.setContentType("text/xml");
917
			Writer out = response.getWriter();
918
			out.write(docinfoXML);
919
			out.close();
920

    
921
		} catch (Exception e) {
922
			logMetacat.error("ReplicationService.handleGetDocumentInfoRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
923
			logReplication.error("ReplicationService.handleGetDocumentInfoRequest - error in metacatReplication.handlegetdocumentinforequest "
924
					+ "for doc: " + docid + " : " + e.getMessage());
925
		}
926

    
927
	}
928
	
929
	public static Hashtable<String, String> getDocumentInfoMap(String docid)
930
			throws HandlerException, AccessControlException, JiBXException,
931
			IOException, McdbException, SAXException {
932
		
933
		// Try get docid info from remote server
934
		DocInfoHandler dih = new DocInfoHandler();
935
		XMLReader docinfoParser = ReplicationHandler.initParser(dih);
936

    
937
		String docInfoStr = getDocumentInfo(docid);
938

    
939
		// strip out the system metadata portion
940
		String systemMetadataXML = ReplicationUtil.getSystemMetadataContent(docInfoStr);
941
		docInfoStr = ReplicationUtil.getContentWithoutSystemMetadata(docInfoStr);
942

    
943
		docinfoParser.parse(new InputSource(new StringReader(docInfoStr)));
944
		Hashtable<String, String> docinfoHash = dih.getDocInfo();
945

    
946
		return docinfoHash;
947
	}
948
	
949
	/**
950
	 * Gets a docInfo XML snippet for the replication API
951
	 * @param docid
952
	 * @return
953
	 * @throws AccessControlException
954
	 * @throws JiBXException
955
	 * @throws IOException
956
	 * @throws McdbException
957
	 */
958
	public static String getDocumentInfo(String docid) throws AccessControlException, JiBXException, IOException, McdbException {
959
		StringBuffer sb = new StringBuffer();
960

    
961
		DocumentImpl doc = new DocumentImpl(docid);
962
		sb.append("<documentinfo><docid>").append(docid);
963
		sb.append("</docid>");
964
		
965
		try {
966
			// serialize the System Metadata as XML for docinfo
967
			String guid = IdentifierManager.getInstance().getGUID(doc.getDocID(), doc.getRev());
968
			SystemMetadata systemMetadata = IdentifierManager.getInstance().getSystemMetadata(guid);
969
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
970
			TypeMarshaller.marshalTypeToOutputStream(systemMetadata, baos);
971
			String systemMetadataXML = baos.toString("UTF-8");
972
			sb.append("<systemMetadata>");
973
			sb.append(systemMetadataXML);
974
			sb.append("</systemMetadata>");
975
		} catch(McdbDocNotFoundException e) {
976
		  logMetacat.warn("No SystemMetadata found for: " + docid);
977
		}
978
		
979
		Calendar created = Calendar.getInstance();
980
		created.setTime(doc.getCreateDate());
981
		Calendar updated = Calendar.getInstance();
982
		updated.setTime(doc.getUpdateDate());
983
		
984
		sb.append("<docname>").append(doc.getDocname());
985
		sb.append("</docname><doctype>").append(doc.getDoctype());
986
		sb.append("</doctype>");
987
		sb.append("<user_owner>").append(doc.getUserowner());
988
		sb.append("</user_owner><user_updated>").append(doc.getUserupdated());
989
		sb.append("</user_updated>");
990
		sb.append("<date_created>");
991
		sb.append(DateTimeMarshaller.serializeDateToUTC(doc.getCreateDate()));
992
		sb.append("</date_created>");
993
		sb.append("<date_updated>");
994
		sb.append(DateTimeMarshaller.serializeDateToUTC(doc.getUpdateDate()));
995
		sb.append("</date_updated>");
996
		sb.append("<home_server>");
997
		sb.append(doc.getDocHomeServer());
998
		sb.append("</home_server>");
999
		sb.append("<public_access>").append(doc.getPublicaccess());
1000
		sb.append("</public_access><rev>").append(doc.getRev());
1001
		sb.append("</rev>");
1002

    
1003
		sb.append("<accessControl>");
1004

    
1005
		AccessControlForSingleFile acfsf = new AccessControlForSingleFile(docid); 
1006
		sb.append(acfsf.getAccessString());
1007
		
1008
		sb.append("</accessControl>");
1009

    
1010
		sb.append("</documentinfo>");
1011
			
1012
		return sb.toString();
1013
	}
1014
	
1015
	/**
1016
	 * Sends System Metadata as XML
1017
	 */
1018
	protected static void handleGetSystemMetadataRequest(
1019
			Hashtable<String, String[]> params, HttpServletResponse response) {
1020
		String guid = ((String[]) (params.get("guid")))[0];
1021
		String systemMetadataXML = null;
1022
		try {
1023
			
1024
			// serialize the System Metadata as XML 
1025
			SystemMetadata systemMetadata = IdentifierManager.getInstance().getSystemMetadata(guid);
1026
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
1027
			TypeMarshaller.marshalTypeToOutputStream(systemMetadata, baos);
1028
			systemMetadataXML = baos.toString("UTF-8");
1029
				
1030
			// get a writer for sending back to response
1031
			response.setContentType("text/xml");
1032
			Writer out = response.getWriter();
1033
			out.write(systemMetadataXML);
1034
			out.close();
1035

    
1036
		} catch (Exception e) {
1037
			String msg = "ReplicationService.handleGetSystemMetadataRequest for guid: " + guid + " : " + e.getMessage();
1038
			logMetacat.error(msg);                         
1039
			logReplication.error(msg);
1040
		}
1041

    
1042
	}
1043
	
1044
	/**
1045
	 * when a forcereplication request comes in, local host sends a read request
1046
	 * to the requesting server (remote server) for the specified docid. Then
1047
	 * store it in local database.
1048
	 */
1049
	protected static void handleForceReplicateSystemMetadataRequest(
1050
			Hashtable<String, String[]> params, HttpServletResponse response,
1051
			HttpServletRequest request) {
1052
		String server = ((String[]) params.get("server"))[0]; // the server that
1053
		String guid = ((String[]) params.get("guid"))[0]; // sent the document
1054
		
1055
		try {
1056
			logReplication.info("ReplicationService.handleForceReplicateSystemMetadataRequest - Force replication system metadata request from: " + server);
1057
			// get the system metadata from server
1058
			URL docinfourl = new URL("https://" + server + "?server="
1059
					+ MetacatUtil.getLocalReplicationServerName()
1060
					+ "&action=getsystemmetadata&guid=" + guid);
1061
			
1062
			String systemMetadataXML = ReplicationService.getURLContent(docinfourl);
1063
						
1064
			// process system metadata
1065
			if (systemMetadataXML != null) {
1066
				SystemMetadata sysMeta = 
1067
					TypeMarshaller.unmarshalTypeFromStream(
1068
							SystemMetadata.class,
1069
							new ByteArrayInputStream(systemMetadataXML.getBytes("UTF-8")));
1070
				HazelcastService.getInstance().getSystemMetadataMap().put(sysMeta.getIdentifier(), sysMeta);
1071
			}
1072
      
1073
			logReplication.info("ReplicationService.handleForceReplicateSystemMetadataRequest - processed guid: " + guid);
1074
			EventLog.getInstance().log(request.getRemoteAddr(), request.getHeader("User-Agent"), REPLICATIONUSER, guid, "systemMetadata");
1075

    
1076
		} catch (Exception e) {
1077
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG, e);                         
1078
			logReplication.error("ReplicationService.handleForceReplicateRequest - General error when processing guid: " + guid, e);
1079
		}
1080
	}
1081

    
1082
	/**
1083
	 * Sends a datafile to a remote host
1084
	 */
1085
	protected static void handleGetDataFileRequest(OutputStream outPut,
1086
			Hashtable<String, String[]> params, HttpServletResponse response)
1087

    
1088
	{
1089
		// File path for data file
1090
		String filepath;
1091
		// Request docid
1092
		String docId = ((String[]) (params.get("docid")))[0];
1093
		//check if the doicd is null
1094
		if (docId == null) {
1095
			logMetacat.error("ReplicationService.handleGetDataFileRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1096
			logReplication.error("ReplicationService.handleGetDataFileRequest - Didn't specify docid for replication");
1097
			return;
1098
		}
1099

    
1100
		//try to open a https stream to test if the request server's public key
1101
		//in the key store, this is security issue
1102
		try {
1103
			filepath = PropertyService.getProperty("application.datafilepath");
1104
			String server = params.get("server")[0];
1105
			URL u = new URL("https://" + server + "?server="
1106
					+ MetacatUtil.getLocalReplicationServerName() + "&action=test");
1107
			String test = ReplicationService.getURLContent(u);
1108
			//couldn't pass the test
1109
			if (test.indexOf("successfully") == -1) {
1110
				//response.setContentType("text/xml");
1111
				//outPut.println("<error>Couldn't pass the trust test</error>");
1112
				logMetacat.error("ReplicationService.handleGetDataFileRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1113
				logReplication.error("ReplicationService.handleGetDataFileRequest - Couldn't pass the trust test");
1114
				return;
1115
			}
1116
		}//try
1117
		catch (Exception ee) {
1118
			return;
1119
		}//catch
1120

    
1121
		if (!filepath.endsWith("/")) {
1122
			filepath += "/";
1123
		}
1124
		// Get file aboslute file name
1125
		String filename = filepath + docId;
1126

    
1127
		//MIME type
1128
		String contentType = null;
1129
		if (filename.endsWith(".xml")) {
1130
			contentType = "text/xml";
1131
		} else if (filename.endsWith(".css")) {
1132
			contentType = "text/css";
1133
		} else if (filename.endsWith(".dtd")) {
1134
			contentType = "text/plain";
1135
		} else if (filename.endsWith(".xsd")) {
1136
			contentType = "text/xml";
1137
		} else if (filename.endsWith("/")) {
1138
			contentType = "text/html";
1139
		} else {
1140
			File f = new File(filename);
1141
			if (f.isDirectory()) {
1142
				contentType = "text/html";
1143
			} else {
1144
				contentType = "application/octet-stream";
1145
			}
1146
		}
1147

    
1148
		// Set the mime type
1149
		response.setContentType(contentType);
1150

    
1151
		// Get the content of the file
1152
		FileInputStream fin = null;
1153
		try {
1154
			// FileInputStream to metacat
1155
			fin = new FileInputStream(filename);
1156
			// 4K buffer
1157
			byte[] buf = new byte[4 * 1024];
1158
			// Read data from file input stream to byte array
1159
			int b = fin.read(buf);
1160
			// Write to outStream from byte array
1161
			while (b != -1) {
1162
				outPut.write(buf, 0, b);
1163
				b = fin.read(buf);
1164
			}
1165
			// close file input stream
1166
			fin.close();
1167

    
1168
		}//try
1169
		catch (Exception e) {
1170
			logMetacat.error("ReplicationService.handleGetDataFileRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1171
			logReplication.error("ReplicationService.handleGetDataFileRequest - error getting data file from MetacatReplication."
1172
					+ "handlGetDataFileRequest " + e.getMessage());
1173
			e.printStackTrace(System.out);
1174
		}//catch
1175

    
1176
	}
1177

    
1178
	/**
1179
	 * Sends a document to a remote host
1180
	 */
1181
	protected static void handleGetDocumentRequest(
1182
			Hashtable<String, String[]> params, HttpServletResponse response) {
1183

    
1184
		String urlString = null;
1185
		String documentPath = null;
1186
		String errorMsg = null;
1187
		try {
1188
			// try to open a https stream to test if the request server's public
1189
			// key
1190
			// in the key store, this is security issue
1191
			String server = params.get("server")[0];
1192
			urlString = "https://" + server + "?server="
1193
					+ MetacatUtil.getLocalReplicationServerName() + "&action=test";
1194
			URL u = new URL(urlString);
1195
			String test = ReplicationService.getURLContent(u);
1196
			// couldn't pass the test
1197
			if (test.indexOf("successfully") == -1) {
1198
				response.setContentType("text/xml");
1199
				Writer out = response.getWriter();
1200
				out.write("<error>Couldn't pass the trust test " + test + " </error>");
1201
				out.close();
1202
				return;
1203
			}
1204

    
1205
			String docid = params.get("docid")[0];
1206
			logReplication.debug("ReplicationService.handleGetDocumentRequest - MetacatReplication.handleGetDocumentRequest for docid: "
1207
					+ docid);
1208
			DocumentImpl di = new DocumentImpl(docid);
1209

    
1210
			String documentDir = PropertyService
1211
					.getProperty("application.documentfilepath");
1212
			documentPath = documentDir + FileUtil.getFS() + docid;
1213

    
1214
			// if the document does not exist on disk, read it from db and write
1215
			// it to disk.
1216
			if (FileUtil.getFileStatus(documentPath) == FileUtil.DOES_NOT_EXIST
1217
					|| FileUtil.getFileSize(documentPath) == 0) {
1218
				FileOutputStream fos = new FileOutputStream(documentPath);
1219
				di.toXml(fos, null, null, true);
1220
			}
1221

    
1222
			// read the file from disk and send it to outputstream
1223
			OutputStream outputStream = response.getOutputStream();
1224
			di.readFromFileSystem(outputStream, null, null, documentPath);
1225

    
1226
			logReplication.info("ReplicationService.handleGetDocumentRequest - document " + docid + " sent");
1227

    
1228
			// return to avoid continuing to the error reporting section at the end
1229
			return;
1230
			
1231
		} catch (MalformedURLException mue) {
1232
			logMetacat.error("ReplicationService.handleGetDocumentRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1233
			logReplication.error("ReplicationService.handleGetDocumentRequest - Url error when getting document from MetacatReplication."
1234
					+ "handlGetDocumentRequest for url: " + urlString + " : "
1235
					+ mue.getMessage());
1236
			// e.printStackTrace(System.out);
1237
			
1238
		} catch (IOException ioe) {
1239
			logMetacat.error("ReplicationService.handleGetDocumentRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1240
			logReplication.error("ReplicationService.handleGetDocumentRequest - I/O error when getting document from MetacatReplication."
1241
					+ "handlGetDocumentRequest for file: " + documentPath + " : "
1242
					+ ioe.getMessage());
1243
			errorMsg = ioe.getMessage();
1244
		} catch (PropertyNotFoundException pnfe) {
1245
			logMetacat.error("ReplicationService.handleGetDocumentRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1246
			logReplication
1247
					.error("ReplicationService.handleGetDocumentRequest - Error getting property when getting document from MetacatReplication."
1248
							+ "handlGetDocumentRequest for file: "
1249
							+ documentPath
1250
							+ " : "
1251
							+ pnfe.getMessage());
1252
			// e.printStackTrace(System.out);
1253
			errorMsg = pnfe.getMessage();
1254
		} catch (McdbException me) {
1255
			logReplication
1256
					.error("ReplicationService.handleGetDocumentRequest - Document implementation error  getting property when getting document from MetacatReplication."
1257
							+ "handlGetDocumentRequest for file: "
1258
							+ documentPath
1259
							+ " : "
1260
							+ me.getMessage());
1261
			// e.printStackTrace(System.out);
1262
			errorMsg = me.getMessage();
1263
		}
1264
		
1265
		// report any errors if we got here
1266
		response.setContentType("text/xml");
1267
		Writer out = null;
1268
		try {
1269
			response.getWriter();
1270
			out = response.getWriter();
1271
			out.write("<error>" + errorMsg + "</error>");
1272
		} catch (Exception e) {
1273
			logMetacat.error(e.getMessage(), e);
1274
		} finally {
1275
			try {
1276
				out.close();
1277
			} catch (IOException e) {
1278
				logMetacat.error(e.getMessage(), e);
1279
			}
1280
		}
1281
		
1282

    
1283
	}
1284

    
1285
	/**
1286
	 * Sends a list of all of the documents on this sever along with their
1287
	 * revision numbers. The format is: <!ELEMENT replication (server, updates)>
1288
	 * <!ELEMENT server (#PCDATA)> <!ELEMENT updates ((updatedDocument |
1289
	 * deleteDocument | revisionDocument)*)> <!ELEMENT updatedDocument (docid,
1290
	 * rev, datafile*)> <!ELEMENT deletedDocument (docid, rev)> <!ELEMENT
1291
	 * revisionDocument (docid, rev, datafile*)> <!ELEMENT docid (#PCDATA)>
1292
	 * <!ELEMENT rev (#PCDATA)> <!ELEMENT datafile (#PCDATA)> note that the rev
1293
	 * in deletedDocument is always empty. I just left it in there to make the
1294
	 * parser implementation easier.
1295
	 */
1296
	protected static void handleUpdateRequest(Hashtable<String, String[]> params,
1297
			HttpServletResponse response) {
1298
		// Checked out DBConnection
1299
		DBConnection dbConn = null;
1300
		// DBConenction serial number when checked it out
1301
		int serialNumber = -1;
1302
		PreparedStatement pstmt = null;
1303
		// Server list to store server info of xml_replication table
1304
		ReplicationServerList serverList = null;
1305
		
1306
		// a writer for response
1307
		Writer out = null;
1308

    
1309
		try {
1310
			// get writer, TODO: encoding?
1311
			response.setContentType("text/xml");
1312
			out = response.getWriter();
1313
			
1314
			// Check out a DBConnection from pool
1315
			dbConn = DBConnectionPool
1316
					.getDBConnection("MetacatReplication.handleUpdateRequest");
1317
			serialNumber = dbConn.getCheckOutSerialNumber();
1318
			// Create a server list from xml_replication table
1319
			serverList = new ReplicationServerList();
1320

    
1321
			// Get remote server name from param
1322
			String server = ((String[]) params.get("server"))[0];
1323
			// If no servr name in param, return a error
1324
			if (server == null || server.equals("")) {
1325
				out.write("<error>Request didn't specify server name</error>");
1326
				out.close();
1327
				return;
1328
			}//if
1329

    
1330
			//try to open a https stream to test if the request server's public key
1331
			//in the key store, this is security issue
1332
			String testUrl = "https://" + server + "?server="
1333
            + MetacatUtil.getLocalReplicationServerName() + "&action=test";
1334
			logReplication.info("Running trust test: " + testUrl);
1335
			URL u = new URL(testUrl);
1336
			String test = ReplicationService.getURLContent(u);
1337
			logReplication.info("Ouput from test is '" + test + "'");
1338
			//couldn't pass the test
1339
			if (test.indexOf("successfully") == -1) {
1340
			    logReplication.error("Trust test failed.");
1341
				out.write("<error>Couldn't pass the trust test</error>");
1342
				out.close();
1343
				return;
1344
			}
1345
			logReplication.info("Trust test succeeded.");
1346

    
1347
			// Check if local host configure to replicate xml documents to remote
1348
			// server. If not send back a error message
1349
			if (!serverList.getReplicationValue(server)) {
1350
				out.write("<error>Configuration not allow to replicate document to you</error>");
1351
				out.close();
1352
				return;
1353
			}//if
1354

    
1355
			// Store the sql command
1356
			StringBuffer docsql = new StringBuffer();
1357
			StringBuffer revisionSql = new StringBuffer();
1358
			// Stroe the docid list
1359
			StringBuffer doclist = new StringBuffer();
1360
			// Store the deleted docid list
1361
			StringBuffer delsql = new StringBuffer();
1362
			// Store the data set file
1363
			Vector<Vector<String>> packageFiles = new Vector<Vector<String>>();
1364

    
1365
			// Append local server's name and replication servlet to doclist
1366
			doclist.append("<?xml version=\"1.0\"?><replication>");
1367
			doclist.append("<server>")
1368
					.append(MetacatUtil.getLocalReplicationServerName());
1369
			//doclist.append(util.getProperty("replicationpath"));
1370
			doclist.append("</server><updates>");
1371

    
1372
			// Get correct docid that reside on this server according the requesting
1373
			// server's replicate and data replicate value in xml_replication table
1374
			docsql.append(DatabaseService.getInstance().getDBAdapter().getReplicationDocumentListSQL());
1375
			//docsql.append("select docid, rev, doctype from xml_documents where (docid not in (select a.docid from xml_documents a, xml_revisions b where a.docid=b.docid and a.rev<=b.rev)) ");
1376
			revisionSql.append("select docid, rev, doctype from xml_revisions ");
1377
			// If the localhost is not a hub to the remote server, only replicate
1378
			// the docid' which home server is local host (server_location =1)
1379
			if (!serverList.getHubValue(server)) {
1380
				String serverLocationDoc = " and a.server_location = 1";
1381
				String serverLocationRev = "where server_location = 1";
1382
				docsql.append(serverLocationDoc);
1383
				revisionSql.append(serverLocationRev);
1384
			}
1385
			logReplication.info("ReplicationService.handleUpdateRequest - Doc sql: " + docsql.toString());
1386

    
1387
			// Get any deleted documents
1388
			delsql.append("select distinct docid from ");
1389
			delsql.append("xml_revisions where docid not in (select docid from ");
1390
			delsql.append("xml_documents) ");
1391
			// If the localhost is not a hub to the remote server, only replicate
1392
			// the docid' which home server is local host (server_location =1)
1393
			if (!serverList.getHubValue(server)) {
1394
				delsql.append("and server_location = 1");
1395
			}
1396
			logReplication.info("ReplicationService.handleUpdateRequest - Deleted sql: " + delsql.toString());
1397

    
1398
			// Get docid list of local host
1399
			pstmt = dbConn.prepareStatement(docsql.toString());
1400
			pstmt.execute();
1401
			ResultSet rs = pstmt.getResultSet();
1402
			boolean tablehasrows = rs.next();
1403
			//If metacat configed to replicate data file
1404
			//if ((util.getProperty("replicationsenddata")).equals("on"))
1405
			boolean replicateData = serverList.getDataReplicationValue(server);
1406
			if (replicateData) {
1407
				while (tablehasrows) {
1408
					String recordDoctype = rs.getString(3);
1409
					Vector<String> packagedoctypes = MetacatUtil
1410
							.getOptionList(PropertyService
1411
									.getProperty("xml.packagedoctype"));
1412
					//if this is a package file, put it at the end
1413
					//because if a package file is read before all of the files it
1414
					//refers to are loaded then there is an error
1415
					if (recordDoctype != null && !packagedoctypes.contains(recordDoctype)) {
1416
						//If this is not data file
1417
						if (!recordDoctype.equals("BIN")) {
1418
							//for non-data file document
1419
							doclist.append("<updatedDocument>");
1420
							doclist.append("<docid>").append(rs.getString(1));
1421
							doclist.append("</docid><rev>").append(rs.getInt(2));
1422
							doclist.append("</rev>");
1423
							doclist.append("</updatedDocument>");
1424
						}//if
1425
						else {
1426
							//for data file document, in datafile attributes
1427
							//we put "datafile" value there
1428
							doclist.append("<updatedDocument>");
1429
							doclist.append("<docid>").append(rs.getString(1));
1430
							doclist.append("</docid><rev>").append(rs.getInt(2));
1431
							doclist.append("</rev>");
1432
							doclist.append("<datafile>");
1433
							doclist.append(PropertyService
1434
									.getProperty("replication.datafileflag"));
1435
							doclist.append("</datafile>");
1436
							doclist.append("</updatedDocument>");
1437
						}//else
1438
					}//if packagedoctpes
1439
					else { //the package files are saved to be put into the xml later.
1440
						Vector<String> v = new Vector<String>();
1441
						v.add(rs.getString(1));
1442
						v.add(String.valueOf(rs.getInt(2)));
1443
						packageFiles.add(v);
1444
					}//esle
1445
					tablehasrows = rs.next();
1446
				}//while
1447
			}//if
1448
			else //metacat was configured not to send data file
1449
			{
1450
				while (tablehasrows) {
1451
					String recordDoctype = rs.getString(3);
1452
					if (!recordDoctype.equals("BIN")) { //don't replicate data files
1453
						Vector<String> packagedoctypes = MetacatUtil
1454
								.getOptionList(PropertyService
1455
										.getProperty("xml.packagedoctype"));
1456
						if (recordDoctype != null
1457
								&& !packagedoctypes.contains(recordDoctype)) { //if this is a package file, put it at the end
1458
							//because if a package file is read before all of the files it
1459
							//refers to are loaded then there is an error
1460
							doclist.append("<updatedDocument>");
1461
							doclist.append("<docid>").append(rs.getString(1));
1462
							doclist.append("</docid><rev>").append(rs.getInt(2));
1463
							doclist.append("</rev>");
1464
							doclist.append("</updatedDocument>");
1465
						} else { //the package files are saved to be put into the xml later.
1466
							Vector<String> v = new Vector<String>();
1467
							v.add(rs.getString(1));
1468
							v.add(String.valueOf(rs.getInt(2)));
1469
							packageFiles.add(v);
1470
						}
1471
					}//if
1472
					tablehasrows = rs.next();
1473
				}//while
1474
			}//else
1475

    
1476
			pstmt = dbConn.prepareStatement(delsql.toString());
1477
			//usage count should increas 1
1478
			dbConn.increaseUsageCount(1);
1479

    
1480
			pstmt.execute();
1481
			rs = pstmt.getResultSet();
1482
			tablehasrows = rs.next();
1483
			while (tablehasrows) { //handle the deleted documents
1484
				doclist.append("<deletedDocument><docid>").append(rs.getString(1));
1485
				doclist.append("</docid><rev></rev></deletedDocument>");
1486
				//note that rev is always empty for deleted docs
1487
				tablehasrows = rs.next();
1488
			}
1489

    
1490
			//now we can put the package files into the xml results
1491
			for (int i = 0; i < packageFiles.size(); i++) {
1492
				Vector<String> v = packageFiles.elementAt(i);
1493
				doclist.append("<updatedDocument>");
1494
				doclist.append("<docid>").append(v.elementAt(0));
1495
				doclist.append("</docid><rev>");
1496
				doclist.append(v.elementAt(1));
1497
				doclist.append("</rev>");
1498
				doclist.append("</updatedDocument>");
1499
			}
1500
			// add revision doc list  
1501
			doclist.append(prepareRevisionDoc(dbConn, revisionSql.toString(),
1502
					replicateData));
1503

    
1504
			doclist.append("</updates></replication>");
1505
			logReplication.info("ReplicationService.handleUpdateRequest - doclist: " + doclist.toString());
1506
			pstmt.close();
1507
			//conn.close();
1508
			out.write(doclist.toString());
1509

    
1510
		} catch (Exception e) {
1511
			logMetacat.error("ReplicationService.handleUpdateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1512
			logReplication.error("ReplicationService.handleUpdateRequest - error in MetacatReplication." + "handleupdaterequest: "
1513
					+ e.getMessage());
1514
			//e.printStackTrace(System.out);
1515
			try {
1516
				out.write("<error>" + e.getMessage() + "</error>");
1517
			} catch (IOException e1) {
1518
				logMetacat.error(e1.getMessage(), e1);
1519
			}
1520
		} finally {
1521
			try {
1522
				pstmt.close();
1523
			}//try
1524
			catch (SQLException ee) {
1525
				logMetacat.error("ReplicationService.handleUpdateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1526
				logReplication.error("ReplicationService.handleUpdateRequest - Error in MetacatReplication."
1527
						+ "handleUpdaterequest to close pstmt: " + ee.getMessage());
1528
			}//catch
1529
			finally {
1530
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1531
			}//finally
1532
			try {
1533
				out.close();
1534
			} catch (IOException e) {
1535
				logMetacat.error(e.getMessage(), e);
1536
			}
1537
		}//finally
1538

    
1539
	}//handlUpdateRequest
1540

    
1541
	/**
1542
	 * 
1543
	 * @param dbConn connection for doing the update
1544
	 * @param docid the document id to update
1545
	 * @param owner the user_owner
1546
	 * @param updater the user_updated
1547
	 * @throws SQLException
1548
	 */
1549
	public static void updateUserOwner(DBConnection dbConn, String docid, String owner, String updater) throws SQLException {
1550
	
1551
		String sql = 
1552
			"UPDATE xml_documents " +
1553
			"SET user_owner = ?, " +
1554
			"user_updated = ? " +
1555
			"WHERE docid = ?;";
1556
		PreparedStatement pstmt = dbConn.prepareStatement(sql);
1557
		//usage count should increas 1
1558
		dbConn.increaseUsageCount(1);
1559

    
1560
		docid = DocumentUtil.getSmartDocId(docid);
1561
		pstmt.setString(1, owner);
1562
		pstmt.setString(2, updater);
1563
		pstmt.setString(3, docid);
1564
		pstmt.execute();
1565
		pstmt.close();
1566
		
1567
		dbConn.commit();
1568
	}
1569
	
1570
	/*
1571
	 * This method will get the xml string for document in xml_revision
1572
	 * The schema look like <!ELEMENT revisionDocument (docid, rev, datafile*)>
1573
	 */
1574
	private static String prepareRevisionDoc(DBConnection dbConn, String revSql,
1575
			boolean replicateData) throws Exception {
1576
		logReplication.warn("ReplicationService.prepareRevisionDoc - The revision document sql is " + revSql);
1577
		StringBuffer revDocList = new StringBuffer();
1578
		PreparedStatement pstmt = dbConn.prepareStatement(revSql);
1579
		//usage count should increas 1
1580
		dbConn.increaseUsageCount(1);
1581

    
1582
		pstmt.execute();
1583
		ResultSet rs = pstmt.getResultSet();
1584
		boolean tablehasrows = rs.next();
1585
		while (tablehasrows) {
1586
			String recordDoctype = rs.getString(3);
1587

    
1588
			//If this is data file and it isn't configured to replicate data
1589
			if (recordDoctype.equals("BIN") && !replicateData) {
1590
				// do nothing
1591
				continue;
1592
			} else {
1593

    
1594
				revDocList.append("<revisionDocument>");
1595
				revDocList.append("<docid>").append(rs.getString(1));
1596
				revDocList.append("</docid><rev>").append(rs.getInt(2));
1597
				revDocList.append("</rev>");
1598
				// data file
1599
				if (recordDoctype.equals("BIN")) {
1600
					revDocList.append("<datafile>");
1601
					revDocList.append(PropertyService
1602
							.getProperty("replication.datafileflag"));
1603
					revDocList.append("</datafile>");
1604
				}
1605
				revDocList.append("</revisionDocument>");
1606

    
1607
			}//else
1608
			tablehasrows = rs.next();
1609
		}
1610
		//System.out.println("The revision list is"+ revDocList.toString());
1611
		return revDocList.toString();
1612
	}
1613

    
1614
	/**
1615
	 * Returns the xml_catalog table encoded in xml
1616
	 */
1617
	public static String getCatalogXML() {
1618
		return handleGetCatalogRequest(null, null, false);
1619
	}
1620

    
1621
	/**
1622
	 * Sends the contents of the xml_catalog table encoded in xml
1623
	 * The xml format is:
1624
	 * <!ELEMENT xml_catalog (row*)>
1625
	 * <!ELEMENT row (entry_type, source_doctype, target_doctype, public_id,
1626
	 *                system_id)>
1627
	 * All of the sub elements of row are #PCDATA
1628

    
1629
	 * If printFlag == false then do not print to out.
1630
	 */
1631
	protected static String handleGetCatalogRequest(
1632
			Hashtable<String, String[]> params, HttpServletResponse response,
1633
			boolean printFlag) {
1634
		DBConnection dbConn = null;
1635
		int serialNumber = -1;
1636
		PreparedStatement pstmt = null;
1637
		Writer out = null;
1638
		try {
1639
			// get writer, TODO: encoding?
1640
		    if(printFlag)
1641
		    {
1642
		        response.setContentType("text/xml");
1643
		        out = response.getWriter();
1644
		    }
1645
			/*conn = MetacatReplication.getDBConnection("MetacatReplication." +
1646
			                                          "handleGetCatalogRequest");*/
1647
			dbConn = DBConnectionPool
1648
					.getDBConnection("MetacatReplication.handleGetCatalogRequest");
1649
			serialNumber = dbConn.getCheckOutSerialNumber();
1650
			pstmt = dbConn.prepareStatement("select entry_type, "
1651
					+ "source_doctype, target_doctype, public_id, "
1652
					+ "system_id from xml_catalog");
1653
			pstmt.execute();
1654
			ResultSet rs = pstmt.getResultSet();
1655
			boolean tablehasrows = rs.next();
1656
			StringBuffer sb = new StringBuffer();
1657
			sb.append("<?xml version=\"1.0\"?><xml_catalog>");
1658
			while (tablehasrows) {
1659
				sb.append("<row><entry_type>").append(rs.getString(1));
1660
				sb.append("</entry_type><source_doctype>").append(rs.getString(2));
1661
				sb.append("</source_doctype><target_doctype>").append(rs.getString(3));
1662
				sb.append("</target_doctype><public_id>").append(rs.getString(4));
1663
				// system id may not have server url on front.  Add it if not.
1664
				String systemID = rs.getString(5);
1665
				if (!systemID.startsWith("http://")) {
1666
					systemID = SystemUtil.getContextURL() + systemID;
1667
				}
1668
				sb.append("</public_id><system_id>").append(systemID);
1669
				sb.append("</system_id></row>");
1670

    
1671
				tablehasrows = rs.next();
1672
			}
1673
			sb.append("</xml_catalog>");
1674
			//conn.close();
1675
			if (printFlag) {
1676
				response.setContentType("text/xml");
1677
				out.write(sb.toString());
1678
			}
1679
			pstmt.close();
1680
			return sb.toString();
1681
		} catch (Exception e) {
1682
			logMetacat.error("ReplicationService.handleGetCatalogRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1683
			logReplication.error("ReplicationService.handleGetCatalogRequest - error in MetacatReplication.handleGetCatalogRequest:"
1684
					+ e.getMessage());
1685
			e.printStackTrace(System.out);
1686
			if (printFlag) {
1687
				try {
1688
					out.write("<error>" + e.getMessage() + "</error>");
1689
				} catch (IOException e1) {
1690
					logMetacat.error(e1.getMessage(), e1);
1691
				}
1692
			}
1693
		} finally {
1694
			try {
1695
				pstmt.close();
1696
			}//try
1697
			catch (SQLException ee) {
1698
				logMetacat.error("ReplicationService.handleGetCatalogRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1699
				logReplication.error("ReplicationService.handleGetCatalogRequest - Error in MetacatReplication.handleGetCatalogRequest: "
1700
						+ ee.getMessage());
1701
			}//catch
1702
			finally {
1703
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1704
			}//finally
1705
			if (out != null) {
1706
				try {
1707
					out.close();
1708
				} catch (IOException e1) {
1709
					logMetacat.error(e1.getMessage(), e1);
1710
				}
1711
			}
1712
		}//finally
1713

    
1714
		return null;
1715
	}
1716

    
1717
	/**
1718
	 * Sends the current system date to the remote server.  Using this action
1719
	 * for replication gets rid of any problems with syncronizing clocks
1720
	 * because a time specific to a document is always kept on its home server.
1721
	 */
1722
	protected static void handleGetTimeRequest(
1723
			Hashtable<String, String[]> params, HttpServletResponse response) {
1724
		
1725
		// use standard format -- the receiving end wants this too
1726
		String dateString = DateTimeMarshaller.serializeDateToUTC(Calendar.getInstance().getTime());
1727
		
1728
		// get a writer for sending back to response
1729
		response.setContentType("text/xml");
1730
		Writer out = null;
1731
		try {
1732
			out = response.getWriter();
1733
			out.write("<timestamp>" + dateString + "</timestamp>");
1734
			out.close();
1735
		} catch (IOException e) {
1736
			logMetacat.error(e.getMessage(), e);
1737
		}
1738
		
1739
	}
1740

    
1741
	/**
1742
	 * this method handles the timeout for a file lock.  when a lock is
1743
	 * granted it is granted for 30 seconds.  When this thread runs out
1744
	 * it deletes the docid from the queue, thus eliminating the lock.
1745
	 */
1746
	public void run() {
1747
		try {
1748
			logReplication.info("ReplicationService.run - thread started for docid: "
1749
					+ (String) fileLocks.elementAt(0));
1750

    
1751
			Thread.sleep(30000); //the lock will expire in 30 seconds
1752
			logReplication.info("thread for docid: "
1753
					+ (String) fileLocks.elementAt(fileLocks.size() - 1) + " exiting.");
1754

    
1755
			fileLocks.remove(fileLocks.size() - 1);
1756
			//fileLocks is treated as a FIFO queue.  If there are more than one lock
1757
			//in the vector, the first one inserted will be removed.
1758
		} catch (Exception e) {
1759
			logMetacat.error("ReplicationService.run - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1760
			logReplication.error("ReplicationService.run - error in file lock thread from "
1761
					+ "MetacatReplication.run: " + e.getMessage());
1762
		}
1763
	}
1764

    
1765
	/**
1766
	 * Returns the name of a server given a serverCode
1767
	 * @param serverCode the serverid of the server
1768
	 * @return the servername or null if the specified serverCode does not
1769
	 *         exist.
1770
	 */
1771
	public static String getServerNameForServerCode(int serverCode) {
1772
		//System.out.println("serverid: " + serverCode);
1773
		DBConnection dbConn = null;
1774
		int serialNumber = -1;
1775
		PreparedStatement pstmt = null;
1776
		try {
1777
			dbConn = DBConnectionPool.getDBConnection("MetacatReplication.getServer");
1778
			serialNumber = dbConn.getCheckOutSerialNumber();
1779
			String sql = new String("select server from "
1780
					+ "xml_replication where serverid = ?");
1781
			pstmt = dbConn.prepareStatement(sql);
1782
			pstmt.setInt(1, serverCode);
1783
			//System.out.println("getserver sql: " + sql);
1784
			pstmt.execute();
1785
			ResultSet rs = pstmt.getResultSet();
1786
			boolean tablehasrows = rs.next();
1787
			if (tablehasrows) {
1788
				//System.out.println("server: " + rs.getString(1));
1789
				return rs.getString(1);
1790
			}
1791

    
1792
			//conn.close();
1793
		} catch (Exception e) {
1794
			logMetacat.error("ReplicationService.getServerNameForServerCode - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1795
			logReplication.error("ReplicationService.getServerNameForServerCode - Error in MetacatReplication.getServer: " + e.getMessage());
1796
		} finally {
1797
			try {
1798
				pstmt.close();
1799
			}//try
1800
			catch (SQLException ee) {
1801
				logMetacat.error("ReplicationService.getServerNameForServerCode - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1802
				logReplication.error("ReplicationService.getServerNameForServerCode - Error in MetacactReplication.getserver: "
1803
						+ ee.getMessage());
1804
			}//catch
1805
			finally {
1806
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1807
			}//fianlly
1808
		}//finally
1809

    
1810
		return null;
1811
		//return null if the server does not exist
1812
	}
1813

    
1814
	/**
1815
	 * Returns a server code given a server name
1816
	 * @param server the name of the server
1817
	 * @return integer > 0 representing the code of the server, 0 if the server
1818
	 *  does not exist.
1819
	 */
1820
	public static int getServerCodeForServerName(String server) throws ServiceException {
1821
		DBConnection dbConn = null;
1822
		int serialNumber = -1;
1823
		PreparedStatement pstmt = null;
1824
		int serverCode = 0;
1825

    
1826
		try {
1827

    
1828
			//conn = util.openDBConnection();
1829
			dbConn = DBConnectionPool.getDBConnection("MetacatReplication.getServerCode");
1830
			serialNumber = dbConn.getCheckOutSerialNumber();
1831
			pstmt = dbConn.prepareStatement("SELECT serverid FROM xml_replication "
1832
					+ "WHERE server LIKE ?");
1833
			pstmt.setString(1, server);
1834
			pstmt.execute();
1835
			ResultSet rs = pstmt.getResultSet();
1836
			boolean tablehasrows = rs.next();
1837
			if (tablehasrows) {
1838
				serverCode = rs.getInt(1);
1839
				pstmt.close();
1840
				//conn.close();
1841
				return serverCode;
1842
			}
1843

    
1844
		} catch (SQLException sqle) {
1845
			throw new ServiceException("ReplicationService.getServerCodeForServerName - " 
1846
					+ "SQL error when getting server code: " + sqle.getMessage());
1847

    
1848
		} finally {
1849
			try {
1850
				pstmt.close();
1851
				//conn.close();
1852
			}//try
1853
			catch (Exception ee) {
1854
				logMetacat.error("ReplicationService.getServerCodeForServerName - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1855
				logReplication.error("ReplicationService.getServerNameForServerCode - Error in MetacatReplicatio.getServerCode: "
1856
						+ ee.getMessage());
1857

    
1858
			}//catch
1859
			finally {
1860
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1861
			}//finally
1862
		}//finally
1863

    
1864
		return serverCode;
1865
	}
1866

    
1867
	/**
1868
	 * Method to get a host server information for given docid
1869
	 * @param conn a connection to the database
1870
	 */
1871
	public static Hashtable<String, String> getHomeServerInfoForDocId(String docId) {
1872
		Hashtable<String, String> sl = new Hashtable<String, String>();
1873
		DBConnection dbConn = null;
1874
		int serialNumber = -1;
1875
		docId = DocumentUtil.getDocIdFromString(docId);
1876
		PreparedStatement pstmt = null;
1877
		int serverLocation;
1878
		try {
1879
			//get conection
1880
			dbConn = DBConnectionPool.getDBConnection("ReplicationHandler.getHomeServer");
1881
			serialNumber = dbConn.getCheckOutSerialNumber();
1882
			//get a server location from xml_document table
1883
			pstmt = dbConn.prepareStatement("select server_location from xml_documents "
1884
					+ "where docid = ?");
1885
			pstmt.setString(1, docId);
1886
			pstmt.execute();
1887
			ResultSet serverName = pstmt.getResultSet();
1888
			//get a server location
1889
			if (serverName.next()) {
1890
				serverLocation = serverName.getInt(1);
1891
				pstmt.close();
1892
			} else {
1893
				pstmt.close();
1894
				//ut.returnConnection(conn);
1895
				return null;
1896
			}
1897
			pstmt = dbConn.prepareStatement("select server, last_checked, replicate "
1898
					+ "from xml_replication where serverid = ?");
1899
			//increase usage count
1900
			dbConn.increaseUsageCount(1);
1901
			pstmt.setInt(1, serverLocation);
1902
			pstmt.execute();
1903
			ResultSet rs = pstmt.getResultSet();
1904
			boolean tableHasRows = rs.next();
1905
			if (tableHasRows) {
1906

    
1907
				String server = rs.getString(1);
1908
				String last_checked = rs.getString(2);
1909
				if (!server.equals("localhost")) {
1910
					sl.put(server, last_checked);
1911
				}
1912

    
1913
			} else {
1914
				pstmt.close();
1915
				//ut.returnConnection(conn);
1916
				return null;
1917
			}
1918
			pstmt.close();
1919
		} catch (Exception e) {
1920
			logMetacat.error("ReplicationService.getHomeServerInfoForDocId - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1921
			logReplication.error("ReplicationService.getHomeServerInfoForDocId - error in replicationHandler.getHomeServer(): "
1922
					+ e.getMessage());
1923
		} finally {
1924
			try {
1925
				pstmt.close();
1926
				//ut.returnConnection(conn);
1927
			} catch (Exception ee) {
1928
				logMetacat.error("ReplicationService.getHomeServerInfoForDocId - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1929
				logReplication.error("ReplicationService.getHomeServerInfoForDocId - Eror irn rplicationHandler.getHomeServer() "
1930
						+ "to close pstmt: " + ee.getMessage());
1931
			} finally {
1932
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1933
			}
1934

    
1935
		}//finally
1936
		return sl;
1937
	}
1938

    
1939
	/**
1940
	 * Returns a home server location  given a accnum
1941
	 * @param accNum , given accNum for a document
1942
	 *
1943
	 */
1944
	public static int getHomeServerCodeForDocId(String accNum) throws ServiceException {
1945
		DBConnection dbConn = null;
1946
		int serialNumber = -1;
1947
		PreparedStatement pstmt = null;
1948
		int serverCode = 1;
1949
		String docId = DocumentUtil.getDocIdFromString(accNum);
1950

    
1951
		try {
1952

    
1953
			// Get DBConnection
1954
			dbConn = DBConnectionPool
1955
					.getDBConnection("ReplicationHandler.getServerLocation");
1956
			serialNumber = dbConn.getCheckOutSerialNumber();
1957
			pstmt = dbConn.prepareStatement("SELECT server_location FROM xml_documents "
1958
					+ "WHERE docid LIKE ? ");
1959
			pstmt.setString(1, docId);
1960
			pstmt.execute();
1961
			ResultSet rs = pstmt.getResultSet();
1962
			boolean tablehasrows = rs.next();
1963
			//If a document is find, return the server location for it
1964
			if (tablehasrows) {
1965
				serverCode = rs.getInt(1);
1966
				pstmt.close();
1967
				//conn.close();
1968
				return serverCode;
1969
			}
1970
			//if couldn't find in xml_documents table, we think server code is 1
1971
			//(this is new document)
1972
			else {
1973
				pstmt.close();
1974
				//conn.close();
1975
				return serverCode;
1976
			}
1977

    
1978
		} catch (SQLException sqle) {
1979
			throw new ServiceException("ReplicationService.getHomeServerCodeForDocId - " 
1980
					+ "SQL error when getting home server code for docid: " + docId + " : " 
1981
					+ sqle.getMessage());
1982

    
1983
		} finally {
1984
			try {
1985
				pstmt.close();
1986
				//conn.close();
1987

    
1988
			} catch (SQLException sqle) {
1989
				logMetacat.error("ReplicationService.getHomeServerCodeForDocId - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1990
				logReplication.error("ReplicationService.getHomeServerCodeForDocId - ReplicationService.getHomeServerCodeForDocId - " 
1991
						+ "SQL error when getting home server code for docid: " + docId + " : " 
1992
						+ sqle.getMessage());
1993
			} finally {
1994
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1995
			}//finally
1996
		}//finally
1997
		//return serverCode;
1998
	}
1999

    
2000
	/**
2001
	 * This method returns the content of a url
2002
	 * @param u the url to return the content from
2003
	 * @return a string representing the content of the url
2004
	 * @throws java.io.IOException
2005
	 */
2006
	public static String getURLContent(URL u) throws java.io.IOException {
2007
		char istreamChar;
2008
		int istreamInt;
2009
		// get the response content
2010
		InputStream input = getURLStream(u);
2011
		logReplication.info("ReplicationService.getURLContent - After getting response from: " + u.toString());
2012
		InputStreamReader istream = new InputStreamReader(input);
2013
		StringBuffer serverResponse = new StringBuffer();
2014
		while ((istreamInt = istream.read()) != -1) {
2015
			istreamChar = (char) istreamInt;
2016
			serverResponse.append(istreamChar);
2017
		}
2018
		istream.close();
2019
		input.close();
2020

    
2021
		return serverResponse.toString();
2022
	}
2023
	
2024
	/**
2025
	 * This method returns the InputStream after opening a url
2026
	 * @param u the url to return the content from
2027
	 * @return a InputStream representing the content of the url
2028
	 * @throws java.io.IOException
2029
	 */
2030
	public static InputStream getURLStream(URL u) throws java.io.IOException {
2031
	    logReplication.info("Getting url stream from " + u.toString());
2032
		logReplication.info("ReplicationService.getURLStream - Before sending request to: " + u.toString());
2033
		// use httpclient to set up SSL
2034
		RestClient client = getSSLClient();
2035
		HttpResponse response = client.doGetRequest(u.toString());
2036
		// get the response content
2037
		InputStream input = response.getEntity().getContent();
2038
		logReplication.info("ReplicationService.getURLStream - After getting response from: " + u.toString());
2039
		
2040
		return input;		
2041
	}
2042
	
2043
	/**
2044
	 * Sets up an HttpClient with SSL connection.
2045
	 * Sends client certificate to the server when doing the request.
2046
	 * @return
2047
	 */
2048
	private static RestClient getSSLClient() {
2049
		RestClient client = new RestClient();
2050
		
2051
		// set up this server's client identity
2052
		String subject = null;
2053
		try {
2054
			// TODO: should there be alternative ways to get the key and certificate?
2055
			String certificateFile = PropertyService.getProperty("replication.certificate.file");
2056
	    	String keyFile = PropertyService.getProperty("replication.privatekey.file");
2057
			String keyPassword = PropertyService.getProperty("replication.privatekey.password");
2058
			X509Certificate certificate = CertificateManager.getInstance().loadCertificateFromFile(certificateFile);
2059
			PrivateKey privateKey = CertificateManager.getInstance().loadPrivateKeyFromFile(keyFile, keyPassword);
2060
			subject = CertificateManager.getInstance().getSubjectDN(certificate);
2061
			CertificateManager.getInstance().registerCertificate(subject, certificate, privateKey);
2062
		} catch (Exception e) {
2063
			// this is pretty much required for replication communication
2064
			logReplication.warn("Could not find server's client certificate/private key: " + e.getMessage());
2065
		}
2066
		SSLSocketFactory socketFactory = null;
2067
		try {
2068
			socketFactory = CertificateManager.getInstance().getSSLSocketFactory(subject);
2069
		} catch (FileNotFoundException e) {
2070
			// these are somewhat expected for anonymous client use
2071
			logReplication.warn("Could not set up SSL connection for client - likely because the certificate could not be located: " + e.getMessage());
2072
		} catch (Exception e) {
2073
			// this is likely more severe
2074
			logReplication.warn("Funky SSL going on: " + e.getClass() + ":: " + e.getMessage());
2075
		}
2076
		try {
2077
			//443 is the default port, this value is overridden if explicitly set in the URL
2078
			Scheme sch = new Scheme("https", 443, socketFactory);
2079
			client.getHttpClient().getConnectionManager().getSchemeRegistry().register(sch);
2080
		} catch (Exception e) {
2081
			// this is likely more severe
2082
			logReplication.error("Failed to set up SSL connection for client. Continuing. " + e.getClass() + ":: " + e.getMessage(), e);
2083
		}
2084
		return client;
2085
	}
2086
	
2087

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

    
2112
//	/**
2113
//	 * Method for writing replication messages to a log file specified in
2114
//	 * metacat.properties
2115
//	 */
2116
//	public static void replErrorLog(String message) {
2117
//		try {
2118
//			FileOutputStream fos = new FileOutputStream(PropertyService
2119
//					.getProperty("replication.logdir")
2120
//					+ "/metacatreplicationerror.log", true);
2121
//			PrintWriter pw = new PrintWriter(fos);
2122
//			SimpleDateFormat formatter = new SimpleDateFormat("yy-MM-dd HH:mm:ss");
2123
//			java.util.Date localtime = new java.util.Date();
2124
//			String dateString = formatter.format(localtime);
2125
//			dateString += " :: " + message;
2126
//			//time stamp each entry
2127
//			pw.println(dateString);
2128
//			pw.flush();
2129
//		} catch (Exception e) {
2130
//			logReplication.error("error writing to replication error log from "
2131
//					+ "MetacatReplication.replErrorLog: " + e.getMessage());
2132
//			//e.printStackTrace(System.out);
2133
//		}
2134
//	}
2135

    
2136
	/**
2137
	 * Returns true if the replicate field for server in xml_replication is 1.
2138
	 * Returns false otherwise
2139
	 */
2140
	public static boolean replToServer(String server) {
2141
		DBConnection dbConn = null;
2142
		int serialNumber = -1;
2143
		PreparedStatement pstmt = null;
2144
		try {
2145
			dbConn = DBConnectionPool.getDBConnection("MetacatReplication.repltoServer");
2146
			serialNumber = dbConn.getCheckOutSerialNumber();
2147
			pstmt = dbConn.prepareStatement("select replicate from "
2148
					+ "xml_replication where server like ? ");
2149
			pstmt.setString(1, server);
2150
			pstmt.execute();
2151
			ResultSet rs = pstmt.getResultSet();
2152
			boolean tablehasrows = rs.next();
2153
			if (tablehasrows) {
2154
				int i = rs.getInt(1);
2155
				if (i == 1) {
2156
					pstmt.close();
2157
					//conn.close();
2158
					return true;
2159
				} else {
2160
					pstmt.close();
2161
					//conn.close();
2162
					return false;
2163
				}
2164
			}
2165
		} catch (SQLException sqle) {
2166
			logMetacat.error("ReplicationService.replToServer - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
2167
			logReplication.error("ReplicationService.replToServer - SQL error in MetacatReplication.replToServer: "
2168
					+ sqle.getMessage());
2169
		} finally {
2170
			try {
2171
				pstmt.close();
2172
				//conn.close();
2173
			}//try
2174
			catch (Exception ee) {
2175
				logMetacat.error("ReplicationService.replToServer - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
2176
				logReplication.error("ReplicationService.replToServer - Error in MetacatReplication.replToServer: "
2177
						+ ee.getMessage());
2178
			}//catch
2179
			finally {
2180
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
2181
			}//finally
2182
		}//finally
2183
		return false;
2184
		//the default if this server does not exist is to not replicate to it.
2185
	}
2186

    
2187
}
(6-6/7)