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: 2012-05-18 12:09:33 -0700 (Fri, 18 May 2012) $'
10
 * '$Revision: 7175 $'
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.Timer;
53
import java.util.Vector;
54

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

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

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

    
102
public class ReplicationService extends BaseService {
103

    
104
	private static ReplicationService replicationService = null;
105

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
320
				//Get data replication value
321
				dataReplicate = ((String[]) params.get("datareplicate"))[0];
322
				
323
				//Get hub value
324
				hub = ((String[]) params.get("hub"))[0];
325

    
326
				Calendar cal = Calendar.getInstance();
327
                cal.set(1980, 1, 1);
328
				String sql = "INSERT INTO xml_replication "
329
						+ "(server, last_checked, replicate, datareplicate, hub) "
330
						+ "VALUES (?,?,?,?,?)";
331
				
332
				pstmt = dbConn.prepareStatement(sql);
333
						
334
				pstmt.setString(1, server);
335
				pstmt.setTimestamp(2, new Timestamp(cal.getTimeInMillis()));
336
				pstmt.setInt(3, Integer.parseInt(replicate));
337
				pstmt.setInt(4, Integer.parseInt(dataReplicate));
338
				pstmt.setInt(5, Integer.parseInt(hub));
339
				
340
				String sqlReport = "XMLAccessAccess.getXMLAccessForDoc - SQL: " + sql;
341
				sqlReport += " [" + server + "," + replicate + 
342
					"," + dataReplicate + "," + hub + "]";
343
				
344
				logMetacat.info(sqlReport);
345
				
346
				pstmt.execute();
347
				pstmt.close();
348
				dbConn.commit();
349
				out.write("Server " + server + " added");
350
				
351
				
352
				// delete server from server list
353
			} else if (subaction.equals("delete")) {
354
				server = ((String[]) params.get("server"))[0];
355
				pstmt = dbConn.prepareStatement("DELETE FROM xml_replication "
356
						+ "WHERE server LIKE ?");
357
				pstmt.setString(1, server);
358
				pstmt.execute();
359
				pstmt.close();
360
				dbConn.commit();
361
				out.write("Server " + server + " deleted");
362
			} else if (subaction.equals("list")) {
363
				// nothing special - it's the default behavior
364

    
365
			} else if (subaction.equals("generatesystemmetadata")) {
366
				GenerateSystemMetadata gsm = new GenerateSystemMetadata();
367
				int serverLocation = -1;
368
				String serverid = ((String[]) params.get("serverid"))[0];
369
				serverLocation = Integer.parseInt(serverid);
370
				gsm.setServerLocation(serverLocation );
371
				gsm.multiThreadUpgrade();
372
				out.write("System Metadata generated for server " + serverid);
373
				
374
			} else if (subaction.equals("generateore")) {
375
				GenerateORE gore = new GenerateORE();
376
				int serverLocation = -1;
377
				String serverid = ((String[]) params.get("serverid"))[0];
378
				serverLocation = Integer.parseInt(serverid);
379
				gore.setServerLocation(serverLocation );
380
				gore.upgrade();
381
				out.write("Generated ORE maps for server " + serverid);
382
				
383
			} else {
384
			
385
				out.write("<error>Unkonwn subaction</error>");
386
				return;
387
			}
388
			
389
			// show SM generate button?
390
			String dataoneConfigured = PropertyService.getProperty("configutil.dataoneConfigured");
391
			if (dataoneConfigured != null) {
392
				showGenerateSystemMetadata = Boolean.parseBoolean(dataoneConfigured);
393
			}
394
			
395
			// always list them after processing
396
			response.setContentType("text/html");
397
			out.write("<html><body><table border=\"1\">");
398
			out.write("<tr><td><b>server</b></td>");
399
			out.write("<td><b>last_checked</b></td>");
400
			out.write("<td><b>replicate</b></td>");
401
			out.write("<td><b>datareplicate</b></td>");
402
			out.write("<td><b>hub</b></td>");
403
			if (showGenerateSystemMetadata) {
404
				out.write("<td><b>System Metadata</b></td>");
405
				out.write("<td><b>ORE Maps</b></td>");
406
			}
407
			out.write("</tr>");
408

    
409
			pstmt = dbConn.prepareStatement("SELECT serverid, server, last_checked, replicate, datareplicate, hub FROM xml_replication");
410
			pstmt.execute();
411
			ResultSet rs = pstmt.getResultSet();
412
			boolean tablehasrows = rs.next();
413
			while (tablehasrows) {
414
				out.write("<tr><td>" + rs.getString(2) + "</td><td>");
415
				out.write(rs.getString(3) + "</td><td>");
416
				out.write(rs.getString(4) + "</td><td>");
417
				out.write(rs.getString(5) + "</td><td>");
418
				out.write(rs.getString(6) + "</td>");
419
				if (showGenerateSystemMetadata) {
420
					// for SM
421
					out.write("<td><form action='" + request.getContextPath() + "/admin'>");
422
					out.write("<input name='serverid' type='hidden' value='" + rs.getString(1) + "'/>");
423
					out.write("<input name='configureType' type='hidden' value='replication'/>");
424
					out.write("<input name='action' type='hidden' value='servercontrol'/>");
425
					out.write("<input name='subaction' type='hidden' value='generatesystemmetadata'/>");
426
					out.write("<input type='submit' value='Generate System Metadata'/>");
427
					out.write("</form></td>");
428
					
429
					// for ORE maps
430
					out.write("<td><form action='" + request.getContextPath() + "/admin'>");
431
					out.write("<input name='serverid' type='hidden' value='" + rs.getString(1) + "'/>");
432
					out.write("<input name='configureType' type='hidden' value='replication'/>");
433
					out.write("<input name='action' type='hidden' value='servercontrol'/>");
434
					out.write("<input name='subaction' type='hidden' value='generateore'/>");
435
					out.write("<input type='submit' value='Generate ORE'/>");
436
					out.write("</form></td>");
437
				}
438
				out.write("</tr>");
439

    
440
				tablehasrows = rs.next();
441
			}
442
			out.write("</table></body></html>");
443
			
444
			
445
			pstmt.close();
446
			//conn.close();
447

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

    
474
	}
475

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

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

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

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

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

    
590
				//process extra access rules before dealing with the write exception (doc exist already)			
591
		        Vector<XMLAccessDAO> accessControlList = dih.getAccessControlList();
592
		        if (accessControlList != null) {
593
		        	AccessControlForSingleFile acfsf = new AccessControlForSingleFile(docid);
594
		        	for (XMLAccessDAO xmlAccessDAO : accessControlList) {
595
		        		try {
596
			        		if (!acfsf.accessControlExists(xmlAccessDAO)) {
597
			        			acfsf.insertPermissions(xmlAccessDAO);
598
								logReplication.info("ReplicationService.handleForceReplicateRequest - document " + docid
599
										+ " permissions added to DB");
600
			        		}
601
		        		} catch (PermOrderException poe) {
602
		        			// this is problematic, but should not prevent us from replicating
603
		        			// see https://redmine.dataone.org/issues/2583
604
		        			String msg = "Could not insert access control for: " + docid + " Message: " + poe.getMessage();
605
		        			logMetacat.error(msg, poe);
606
		        			logReplication.error(msg, poe);
607
		        		}
608
		            }
609
		        }
610
		        
611
		        // process the real owner and updater
612
				String user = (String) docinfoHash.get("user_owner");
613
				String updated = (String) docinfoHash.get("user_updated");
614
		        updateUserOwner(dbConn, docid, user, updated);
615

    
616
				logReplication.info("ReplicationService.handleForceReplicateRequest - document " + docid + " added to DB with "
617
						+ "action " + dbaction);
618
				
619
				EventLog.getInstance().log(request.getRemoteAddr(), request.getHeader("User-Agent"), REPLICATIONUSER, docid, dbaction);
620
			}
621
		} catch (SQLException sqle) {
622
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
623
			logReplication.error("ReplicationService.handleForceReplicateRequest - SQL error when adding doc " + docid + 
624
					" to DB with action " + dbaction + ": " + sqle.getMessage());
625
		} catch (MalformedURLException mue) {
626
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
627
			logReplication.error("ReplicationService.handleForceReplicateRequest - URL error when adding doc " + docid + 
628
					" to DB with action " + dbaction + ": " + mue.getMessage());
629
		} catch (SAXException se) {
630
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
631
			logReplication.error("ReplicationService.handleForceReplicateRequest - SAX parsing error when adding doc " + docid + 
632
					" to DB with action " + dbaction + ": " + se.getMessage());
633
		} catch (HandlerException he) {
634
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
635
			logReplication.error("ReplicationService.handleForceReplicateRequest - Handler error when adding doc " + docid + 
636
					" to DB with action " + dbaction + ": " + he.getMessage());
637
		} catch (IOException ioe) {
638
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
639
			logReplication.error("ReplicationService.handleForceReplicateRequest - I/O error when adding doc " + docid + 
640
					" to DB with action " + dbaction + ": " + ioe.getMessage());
641
		} catch (PermOrderException poe) {
642
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
643
			logReplication.error("ReplicationService.handleForceReplicateRequest - Permissions order error when adding doc " + docid + 
644
					" to DB with action " + dbaction + ": " + poe.getMessage());
645
		} catch (AccessControlException ace) {
646
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
647
			logReplication.error("ReplicationService.handleForceReplicateRequest - Permissions order error when adding doc " + docid + 
648
					" to DB with action " + dbaction + ": " + ace.getMessage());
649
		} catch (Exception e) {
650
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
651
			logReplication.error("ReplicationService.handleForceReplicateRequest - General error when adding doc " + docid + 
652
					" to DB with action " + dbaction + ": " + e.getMessage());
653
		} finally {
654
			// Return the checked out DBConnection
655
			DBConnectionPool.returnDBConnection(dbConn, serialNumber);
656
		}//finally
657
	}
658

    
659
	/*
660
	 * when a forcereplication delete request comes in, local host will delete this
661
	 * document
662
	 */
663
	protected static void handleForceReplicateDeleteRequest(
664
			Hashtable<String, String[]> params, HttpServletResponse response,
665
			HttpServletRequest request) {
666
		String server = ((String[]) params.get("server"))[0]; // the server that
667
		String docid = ((String[]) params.get("docid"))[0]; // sent the document
668
		try {
669
			logReplication.info("ReplicationService.handleForceReplicateDeleteRequest - force replication delete request from " + server);
670
			logReplication.info("ReplicationService.handleForceReplicateDeleteRequest - force replication delete docid " + docid);
671
			logReplication.info("ReplicationService.handleForceReplicateDeleteRequest - Force replication delete request from: " + server);
672
			logReplication.info("ReplicationService.handleForceReplicateDeleteRequest - Force replication delete docid: " + docid);
673
			DocumentImpl.delete(docid, null, null, server, false);
674
			logReplication.info("ReplicationService.handleForceReplicateDeleteRequest - document " + docid + " was successfully deleted ");
675
			EventLog.getInstance().log(request.getRemoteAddr(), request.getHeader("User-Agent"), REPLICATIONUSER, docid,
676
					"delete");
677
			logReplication.info("ReplicationService.handleForceReplicateDeleteRequest - document " + docid + " was successfully deleted ");
678
		} catch (McdbDocNotFoundException e) {
679
			logMetacat.error("ReplicationService.handleForceReplicateDeleteRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
680
			logReplication.error("document " + docid
681
					+ " failed to delete because " + e.getMessage());
682
			logReplication.error("ReplicationService.handleForceReplicateDeleteRequest - error: " + e.getMessage());
683
		} catch (InsufficientKarmaException e) {
684
			logMetacat.error("ReplicationService.handleForceReplicateDeleteRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
685
			logReplication.error("document " + docid
686
					+ " failed to delete because " + e.getMessage());
687
			logReplication.error("ReplicationService.handleForceReplicateDeleteRequest - error: " + e.getMessage());
688
		} catch (SQLException e) {
689
			logMetacat.error("ReplicationService.handleForceReplicateDeleteRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
690
			logReplication.error("document " + docid
691
					+ " failed to delete because " + e.getMessage());
692
			logReplication.error("ReplicationService.handleForceReplicateDeleteRequest - error: " + e.getMessage());
693
		} catch (Exception e) {
694
			logMetacat.error("ReplicationService.handleForceReplicateDeleteRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
695
			logReplication.error("document " + docid
696
					+ " failed to delete because " + e.getMessage());
697
			logReplication.error("ReplicationService.handleForceReplicateDeleteRequest - error: " + e.getMessage());
698

    
699
		}//catch
700

    
701
	}
702

    
703
	/**
704
	 * when a forcereplication data file request comes in, local host sends a
705
	 * readdata request to the requesting server (remote server) for the specified
706
	 * docid. Then store it in local database and file system
707
	 */
708
	protected static void handleForceReplicateDataFileRequest(Hashtable<String, String[]> params,
709
			HttpServletRequest request) {
710

    
711
		//make sure there is some parameters
712
		if (params.isEmpty()) {
713
			return;
714
		}
715
		// Get remote server
716
		String server = ((String[]) params.get("server"))[0];
717
		// the docid should include rev number
718
		String docid = ((String[]) params.get("docid"))[0];
719
		// Make sure there is a docid and server
720
		if (docid == null || server == null || server.equals("")) {
721
			logMetacat.error("ReplicationService.handleForceReplicateDataFileRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
722
			logReplication.error("ReplicationService.handleForceReplicateDataFileRequest - Didn't specify docid or server for replication");
723
			return;
724
		}
725

    
726
		// Overide or not
727
		//    boolean override = false;
728
		// dbaction - update or insert
729
		String dbaction = null;
730

    
731
		try {
732
			//docid was switch to two parts uinque code and rev
733
			//String uniqueCode=MetacatUtil.getDocIdFromString(docid);
734
			//int rev=MetacatUtil.getVersionFromString(docid);
735
			if (params.containsKey("dbaction")) {
736
				dbaction = ((String[]) params.get("dbaction"))[0];
737
			} else//default value is update
738
			{
739
//				dbaction = "update";
740
				dbaction = null;
741
			}
742

    
743
			logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - Force replication request from: " + server);
744
			logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - Force replication docid: " + docid);
745
			logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - Force replication action: " + dbaction);
746
			// get the document info from server
747
			URL docinfourl = new URL("https://" + server + "?server="
748
					+ MetacatUtil.getLocalReplicationServerName()
749
					+ "&action=getdocumentinfo&docid=" + docid);
750

    
751
			String docInfoStr = ReplicationService.getURLContent(docinfourl);
752
			
753
			// strip out the system metadata portion
754
		    String systemMetadataXML = ReplicationUtil.getSystemMetadataContent(docInfoStr);
755
		   	docInfoStr = ReplicationUtil.getContentWithoutSystemMetadata(docInfoStr);
756

    
757
			//dih is the parser for the docinfo xml format
758
			DocInfoHandler dih = new DocInfoHandler();
759
			XMLReader docinfoParser = ReplicationHandler.initParser(dih);
760
			docinfoParser.parse(new InputSource(new StringReader(docInfoStr)));
761
			Hashtable<String, String> docinfoHash = dih.getDocInfo();
762
			
763
			String docName = (String) docinfoHash.get("docname");
764

    
765
			String docType = (String) docinfoHash.get("doctype");
766

    
767
			String docHomeServer = (String) docinfoHash.get("home_server");
768
			
769
			String createdDateString = docinfoHash.get("date_created");
770
			String updatedDateString = docinfoHash.get("date_updated");
771
			
772
			Date createdDate = DateTimeMarshaller.deserializeDateToUTC(createdDateString);
773
			Date updatedDate = DateTimeMarshaller.deserializeDateToUTC(updatedDateString);
774
			
775
			logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - docHomeServer of datafile: " + docHomeServer);
776

    
777
			// in case we have a write exception, we still want to track access and sysmeta
778
			Exception writeException = null;
779

    
780
			// do we need the object content?
781
			if (dbaction != null && (dbaction.equals("insert") || dbaction.equals("update"))) {
782
				//Get data file and store it into local file system.
783
				// sending back readdata request to server
784
				URL url = new URL("https://" + server + "?server="
785
						+ MetacatUtil.getLocalReplicationServerName()
786
						+ "&action=readdata&docid=" + docid);
787
				String datafilePath = PropertyService
788
						.getProperty("application.datafilepath");
789

    
790
				InputStream inputStream = getURLStream(url);
791
				
792
				//register data file into xml_documents table and write data file
793
				//into file system
794
				try {
795
					DocumentImpl.writeDataFileInReplication(inputStream,
796
							datafilePath, docName, docType, docid, null, docHomeServer,
797
							server, DocumentImpl.DOCUMENTTABLE, false, createdDate,
798
							updatedDate);
799
				} catch (Exception e) {
800
					writeException = e;
801
				}
802

    
803
			}
804
			
805
			// process the real owner and updater
806
			DBConnection dbConn = DBConnectionPool.getDBConnection("ReplicationService.handleForceDataFileRequest");
807
	        int serialNumber = dbConn.getCheckOutSerialNumber();
808
	        dbConn.setAutoCommit(false);
809
			String user = (String) docinfoHash.get("user_owner");
810
			String updated = (String) docinfoHash.get("user_updated");
811
	        updateUserOwner(dbConn, docid, user, updated);
812
	        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
813
	        
814
			// process system metadata
815
	        if (systemMetadataXML != null) {
816
	      	  SystemMetadata sysMeta = 
817
	      		TypeMarshaller.unmarshalTypeFromStream(
818
	      				  SystemMetadata.class, 
819
	      				  new ByteArrayInputStream(systemMetadataXML.getBytes("UTF-8")));
820
	      	  
821
	      	  // need the guid-to-docid mapping
822
	      	  boolean mappingExists = true;
823
	      	  mappingExists = IdentifierManager.getInstance().mappingExists(sysMeta.getIdentifier().getValue());
824
	      	  if (!mappingExists) {
825
	      		  IdentifierManager.getInstance().createMapping(sysMeta.getIdentifier().getValue(), docid);
826
	      	  }
827
	      	  // save the system metadata
828
	      	  HazelcastService.getInstance().getSystemMetadataMap().put(sysMeta.getIdentifier(), sysMeta);
829
	        }
830
	        
831
	        // process the access control
832
	        Vector<XMLAccessDAO> accessControlList = dih.getAccessControlList();
833
	        if (accessControlList != null) {
834
	        	AccessControlForSingleFile acfsf = new AccessControlForSingleFile(docid);
835
	        	for (XMLAccessDAO xmlAccessDAO : accessControlList) {
836
	        		if (!acfsf.accessControlExists(xmlAccessDAO)) {
837
	        			acfsf.insertPermissions(xmlAccessDAO);
838
						logReplication.info("ReplicationService.handleForceReplicateRequest - document " + docid
839
								+ " permissions added to DB");
840
	        		}
841
	            }
842
	        }
843
	        
844
	        // throw the write exception now -- this happens when access changes on an object
845
			if (writeException != null) {
846
				throw writeException;
847
			}
848

    
849
			logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - datafile " + docid + " added to DB with "
850
					+ "action " + dbaction);
851
			EventLog.getInstance().log(request.getRemoteAddr(), request.getHeader("User-Agent"), REPLICATIONUSER,
852
					docid, dbaction);
853

    
854
		} catch (Exception e) {
855
			e.printStackTrace();
856
			logMetacat.error("ReplicationService.handleForceReplicateDataFileRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG, e);                         
857
			logReplication.error("ReplicationService.handleForceReplicateDataFileRequest - Datafile " + docid
858
					+ " failed to added to DB with " + "action " + dbaction + " because "
859
					+ e.getMessage());
860
			logReplication.error("ReplicationService.handleForceReplicateDataFileRequest - ERROR in MetacatReplication.handleForceDataFileReplicate"
861
					+ "Request(): " + e.getMessage());
862
		}
863
	}
864

    
865
	/**
866
	 * Grants or denies a lock to a requesting host.
867
	 * The servlet parameters of interrest are:
868
	 * docid: the docid of the file the lock is being requested for
869
	 * currentdate: the timestamp of the document on the remote server
870
	 *
871
	 */
872
	protected static void handleGetLockRequest(
873
			Hashtable<String, String[]> params, HttpServletResponse response) {
874

    
875
		try {
876

    
877
			String docid = ((String[]) params.get("docid"))[0];
878
			String remoteRev = ((String[]) params.get("updaterev"))[0];
879
			DocumentImpl requestDoc = new DocumentImpl(docid);
880
			logReplication.info("ReplicationService.handleGetLockRequest - lock request for " + docid);
881
			int localRevInt = requestDoc.getRev();
882
			int remoteRevInt = Integer.parseInt(remoteRev);
883

    
884
			// get a writer for sending back to response
885
			response.setContentType("text/xml");
886
			Writer out = response.getWriter();
887
			
888
			if (remoteRevInt >= localRevInt) {
889
				if (!fileLocks.contains(docid)) { //grant the lock if it is not already locked
890
					fileLocks.add(0, docid); //insert at the beginning of the queue Vector
891
					//send a message back to the the remote host authorizing the insert
892
					out.write("<lockgranted><docid>" + docid
893
									+ "</docid></lockgranted>");
894
					//          lockThread = new Thread(this);
895
					//          lockThread.setPriority(Thread.MIN_PRIORITY);
896
					//          lockThread.start();
897
					logReplication.info("ReplicationService.handleGetLockRequest - lock granted for " + docid);
898
				} else { //deny the lock
899
					out.write("<filelocked><docid>" + docid + "</docid></filelocked>");
900
					logReplication.info("ReplicationService.handleGetLockRequest - lock denied for " + docid
901
							+ "reason: file already locked");
902
				}
903
			} else {//deny the lock.
904
				out.write("<outdatedfile><docid>" + docid + "</docid></filelocked>");
905
				logReplication.info("ReplicationService.handleGetLockRequest - lock denied for " + docid
906
						+ "reason: client has outdated file");
907
			}
908
			out.close();
909
			//conn.close();
910
		} catch (Exception e) {
911
			logMetacat.error("ReplicationService.handleGetLockRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
912
			logReplication.error("ReplicationService.handleGetLockRequest - error requesting file lock from MetacatReplication."
913
					+ "handleGetLockRequest: " + e.getMessage());
914
			e.printStackTrace(System.out);
915
		}
916
	}
917

    
918
	/**
919
	 * Sends all of the xml_documents information encoded in xml to a requestor
920
	 * the format is:
921
	 * <!ELEMENT documentinfo (docid, docname, doctype, doctitle, user_owner,
922
	 *                  user_updated, home_server, public_access, rev)/>
923
	 * all of the subelements of document info are #PCDATA
924
	 */
925
	protected static void handleGetDocumentInfoRequest(
926
			Hashtable<String, String[]> params, HttpServletResponse response) {
927
		String docid = ((String[]) (params.get("docid")))[0];
928

    
929
		try {
930
			// get docinfo as XML string
931
			String docinfoXML = getDocumentInfo(docid);
932
			
933
			// get a writer for sending back to response
934
			response.setContentType("text/xml");
935
			Writer out = response.getWriter();
936
			out.write(docinfoXML);
937
			out.close();
938

    
939
		} catch (Exception e) {
940
			logMetacat.error("ReplicationService.handleGetDocumentInfoRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
941
			logReplication.error("ReplicationService.handleGetDocumentInfoRequest - error in metacatReplication.handlegetdocumentinforequest "
942
					+ "for doc: " + docid + " : " + e.getMessage());
943
		}
944

    
945
	}
946
	
947
	public static Hashtable<String, String> getDocumentInfoMap(String docid)
948
			throws HandlerException, AccessControlException, JiBXException,
949
			IOException, McdbException, SAXException {
950
		
951
		// Try get docid info from remote server
952
		DocInfoHandler dih = new DocInfoHandler();
953
		XMLReader docinfoParser = ReplicationHandler.initParser(dih);
954

    
955
		String docInfoStr = getDocumentInfo(docid);
956

    
957
		// strip out the system metadata portion
958
		String systemMetadataXML = ReplicationUtil.getSystemMetadataContent(docInfoStr);
959
		docInfoStr = ReplicationUtil.getContentWithoutSystemMetadata(docInfoStr);
960

    
961
		docinfoParser.parse(new InputSource(new StringReader(docInfoStr)));
962
		Hashtable<String, String> docinfoHash = dih.getDocInfo();
963

    
964
		return docinfoHash;
965
	}
966
	
967
	/**
968
	 * Gets a docInfo XML snippet for the replication API
969
	 * @param docid
970
	 * @return
971
	 * @throws AccessControlException
972
	 * @throws JiBXException
973
	 * @throws IOException
974
	 * @throws McdbException
975
	 */
976
	public static String getDocumentInfo(String docid) throws AccessControlException, JiBXException, IOException, McdbException {
977
		StringBuffer sb = new StringBuffer();
978

    
979
		DocumentImpl doc = new DocumentImpl(docid);
980
		sb.append("<documentinfo><docid>").append(docid);
981
		sb.append("</docid>");
982
		
983
		try {
984
			// serialize the System Metadata as XML for docinfo
985
			String guid = IdentifierManager.getInstance().getGUID(doc.getDocID(), doc.getRev());
986
			SystemMetadata systemMetadata = IdentifierManager.getInstance().getSystemMetadata(guid);
987
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
988
			TypeMarshaller.marshalTypeToOutputStream(systemMetadata, baos);
989
			String systemMetadataXML = baos.toString("UTF-8");
990
			sb.append("<systemMetadata>");
991
			sb.append(systemMetadataXML);
992
			sb.append("</systemMetadata>");
993
		} catch(McdbDocNotFoundException e) {
994
		  logMetacat.warn("No SystemMetadata found for: " + docid);
995
		}
996
		
997
		Calendar created = Calendar.getInstance();
998
		created.setTime(doc.getCreateDate());
999
		Calendar updated = Calendar.getInstance();
1000
		updated.setTime(doc.getUpdateDate());
1001
		
1002
		sb.append("<docname>").append(doc.getDocname());
1003
		sb.append("</docname><doctype>").append(doc.getDoctype());
1004
		sb.append("</doctype>");
1005
		sb.append("<user_owner>").append(doc.getUserowner());
1006
		sb.append("</user_owner><user_updated>").append(doc.getUserupdated());
1007
		sb.append("</user_updated>");
1008
		sb.append("<date_created>");
1009
		sb.append(DateTimeMarshaller.serializeDateToUTC(doc.getCreateDate()));
1010
		sb.append("</date_created>");
1011
		sb.append("<date_updated>");
1012
		sb.append(DateTimeMarshaller.serializeDateToUTC(doc.getUpdateDate()));
1013
		sb.append("</date_updated>");
1014
		sb.append("<home_server>");
1015
		sb.append(doc.getDocHomeServer());
1016
		sb.append("</home_server>");
1017
		sb.append("<public_access>").append(doc.getPublicaccess());
1018
		sb.append("</public_access><rev>").append(doc.getRev());
1019
		sb.append("</rev>");
1020

    
1021
		sb.append("<accessControl>");
1022

    
1023
		AccessControlForSingleFile acfsf = new AccessControlForSingleFile(docid); 
1024
		sb.append(acfsf.getAccessString());
1025
		
1026
		sb.append("</accessControl>");
1027

    
1028
		sb.append("</documentinfo>");
1029
			
1030
		return sb.toString();
1031
	}
1032
	
1033
	/**
1034
	 * Sends System Metadata as XML
1035
	 */
1036
	protected static void handleGetSystemMetadataRequest(
1037
			Hashtable<String, String[]> params, HttpServletResponse response) {
1038
		String guid = ((String[]) (params.get("guid")))[0];
1039
		String systemMetadataXML = null;
1040
		try {
1041
			
1042
			// serialize the System Metadata as XML 
1043
			SystemMetadata systemMetadata = IdentifierManager.getInstance().getSystemMetadata(guid);
1044
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
1045
			TypeMarshaller.marshalTypeToOutputStream(systemMetadata, baos);
1046
			systemMetadataXML = baos.toString("UTF-8");
1047
				
1048
			// get a writer for sending back to response
1049
			response.setContentType("text/xml");
1050
			Writer out = response.getWriter();
1051
			out.write(systemMetadataXML);
1052
			out.close();
1053

    
1054
		} catch (Exception e) {
1055
			String msg = "ReplicationService.handleGetSystemMetadataRequest for guid: " + guid + " : " + e.getMessage();
1056
			logMetacat.error(msg);                         
1057
			logReplication.error(msg);
1058
		}
1059

    
1060
	}
1061
	
1062
	/**
1063
	 * when a forcereplication request comes in, local host sends a read request
1064
	 * to the requesting server (remote server) for the specified docid. Then
1065
	 * store it in local database.
1066
	 */
1067
	protected static void handleForceReplicateSystemMetadataRequest(
1068
			Hashtable<String, String[]> params, HttpServletResponse response,
1069
			HttpServletRequest request) {
1070
		String server = ((String[]) params.get("server"))[0]; // the server that
1071
		String guid = ((String[]) params.get("guid"))[0]; // sent the document
1072
		
1073
		try {
1074
			logReplication.info("ReplicationService.handleForceReplicateSystemMetadataRequest - Force replication system metadata request from: " + server);
1075
			// get the system metadata from server
1076
			URL docinfourl = new URL("https://" + server + "?server="
1077
					+ MetacatUtil.getLocalReplicationServerName()
1078
					+ "&action=getsystemmetadata&guid=" + guid);
1079
			
1080
			String systemMetadataXML = ReplicationService.getURLContent(docinfourl);
1081
						
1082
			// process system metadata
1083
			if (systemMetadataXML != null) {
1084
				SystemMetadata sysMeta = 
1085
					TypeMarshaller.unmarshalTypeFromStream(
1086
							SystemMetadata.class,
1087
							new ByteArrayInputStream(systemMetadataXML.getBytes("UTF-8")));
1088
				HazelcastService.getInstance().getSystemMetadataMap().put(sysMeta.getIdentifier(), sysMeta);
1089
			}
1090
      
1091
			logReplication.info("ReplicationService.handleForceReplicateSystemMetadataRequest - processed guid: " + guid);
1092
			EventLog.getInstance().log(request.getRemoteAddr(), request.getHeader("User-Agent"), REPLICATIONUSER, guid, "systemMetadata");
1093

    
1094
		} catch (Exception e) {
1095
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG, e);                         
1096
			logReplication.error("ReplicationService.handleForceReplicateRequest - General error when processing guid: " + guid, e);
1097
		}
1098
	}
1099

    
1100
	/**
1101
	 * Sends a datafile to a remote host
1102
	 */
1103
	protected static void handleGetDataFileRequest(OutputStream outPut,
1104
			Hashtable<String, String[]> params, HttpServletResponse response)
1105

    
1106
	{
1107
		// File path for data file
1108
		String filepath;
1109
		// Request docid
1110
		String docId = ((String[]) (params.get("docid")))[0];
1111
		//check if the doicd is null
1112
		if (docId == null) {
1113
			logMetacat.error("ReplicationService.handleGetDataFileRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1114
			logReplication.error("ReplicationService.handleGetDataFileRequest - Didn't specify docid for replication");
1115
			return;
1116
		}
1117

    
1118
		//try to open a https stream to test if the request server's public key
1119
		//in the key store, this is security issue
1120
		try {
1121
			filepath = PropertyService.getProperty("application.datafilepath");
1122
			String server = params.get("server")[0];
1123
			URL u = new URL("https://" + server + "?server="
1124
					+ MetacatUtil.getLocalReplicationServerName() + "&action=test");
1125
			String test = ReplicationService.getURLContent(u);
1126
			//couldn't pass the test
1127
			if (test.indexOf("successfully") == -1) {
1128
				//response.setContentType("text/xml");
1129
				//outPut.println("<error>Couldn't pass the trust test</error>");
1130
				logMetacat.error("ReplicationService.handleGetDataFileRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1131
				logReplication.error("ReplicationService.handleGetDataFileRequest - Couldn't pass the trust test");
1132
				return;
1133
			}
1134
		}//try
1135
		catch (Exception ee) {
1136
			return;
1137
		}//catch
1138

    
1139
		if (!filepath.endsWith("/")) {
1140
			filepath += "/";
1141
		}
1142
		// Get file aboslute file name
1143
		String filename = filepath + docId;
1144

    
1145
		//MIME type
1146
		String contentType = null;
1147
		if (filename.endsWith(".xml")) {
1148
			contentType = "text/xml";
1149
		} else if (filename.endsWith(".css")) {
1150
			contentType = "text/css";
1151
		} else if (filename.endsWith(".dtd")) {
1152
			contentType = "text/plain";
1153
		} else if (filename.endsWith(".xsd")) {
1154
			contentType = "text/xml";
1155
		} else if (filename.endsWith("/")) {
1156
			contentType = "text/html";
1157
		} else {
1158
			File f = new File(filename);
1159
			if (f.isDirectory()) {
1160
				contentType = "text/html";
1161
			} else {
1162
				contentType = "application/octet-stream";
1163
			}
1164
		}
1165

    
1166
		// Set the mime type
1167
		response.setContentType(contentType);
1168

    
1169
		// Get the content of the file
1170
		FileInputStream fin = null;
1171
		try {
1172
			// FileInputStream to metacat
1173
			fin = new FileInputStream(filename);
1174
			// 4K buffer
1175
			byte[] buf = new byte[4 * 1024];
1176
			// Read data from file input stream to byte array
1177
			int b = fin.read(buf);
1178
			// Write to outStream from byte array
1179
			while (b != -1) {
1180
				outPut.write(buf, 0, b);
1181
				b = fin.read(buf);
1182
			}
1183
			// close file input stream
1184
			fin.close();
1185

    
1186
		}//try
1187
		catch (Exception e) {
1188
			logMetacat.error("ReplicationService.handleGetDataFileRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1189
			logReplication.error("ReplicationService.handleGetDataFileRequest - error getting data file from MetacatReplication."
1190
					+ "handlGetDataFileRequest " + e.getMessage());
1191
			e.printStackTrace(System.out);
1192
		}//catch
1193

    
1194
	}
1195

    
1196
	/**
1197
	 * Sends a document to a remote host
1198
	 */
1199
	protected static void handleGetDocumentRequest(
1200
			Hashtable<String, String[]> params, HttpServletResponse response) {
1201

    
1202
		String urlString = null;
1203
		String documentPath = null;
1204
		String errorMsg = null;
1205
		try {
1206
			// try to open a https stream to test if the request server's public
1207
			// key
1208
			// in the key store, this is security issue
1209
			String server = params.get("server")[0];
1210
			urlString = "https://" + server + "?server="
1211
					+ MetacatUtil.getLocalReplicationServerName() + "&action=test";
1212
			URL u = new URL(urlString);
1213
			String test = ReplicationService.getURLContent(u);
1214
			// couldn't pass the test
1215
			if (test.indexOf("successfully") == -1) {
1216
				response.setContentType("text/xml");
1217
				Writer out = response.getWriter();
1218
				out.write("<error>Couldn't pass the trust test " + test + " </error>");
1219
				out.close();
1220
				return;
1221
			}
1222

    
1223
			String docid = params.get("docid")[0];
1224
			logReplication.debug("ReplicationService.handleGetDocumentRequest - MetacatReplication.handleGetDocumentRequest for docid: "
1225
					+ docid);
1226
			DocumentImpl di = new DocumentImpl(docid);
1227

    
1228
			String documentDir = PropertyService
1229
					.getProperty("application.documentfilepath");
1230
			documentPath = documentDir + FileUtil.getFS() + docid;
1231

    
1232
			// if the document does not exist on disk, read it from db and write
1233
			// it to disk.
1234
			if (FileUtil.getFileStatus(documentPath) == FileUtil.DOES_NOT_EXIST
1235
					|| FileUtil.getFileSize(documentPath) == 0) {
1236
				FileOutputStream fos = new FileOutputStream(documentPath);
1237
				di.toXml(fos, null, null, true);
1238
			}
1239

    
1240
			// read the file from disk and send it to outputstream
1241
			OutputStream outputStream = response.getOutputStream();
1242
			di.readFromFileSystem(outputStream, null, null, documentPath);
1243

    
1244
			logReplication.info("ReplicationService.handleGetDocumentRequest - document " + docid + " sent");
1245

    
1246
			// return to avoid continuing to the error reporting section at the end
1247
			return;
1248
			
1249
		} catch (MalformedURLException mue) {
1250
			logMetacat.error("ReplicationService.handleGetDocumentRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1251
			logReplication.error("ReplicationService.handleGetDocumentRequest - Url error when getting document from MetacatReplication."
1252
					+ "handlGetDocumentRequest for url: " + urlString + " : "
1253
					+ mue.getMessage());
1254
			// e.printStackTrace(System.out);
1255
			
1256
		} catch (IOException ioe) {
1257
			logMetacat.error("ReplicationService.handleGetDocumentRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1258
			logReplication.error("ReplicationService.handleGetDocumentRequest - I/O error when getting document from MetacatReplication."
1259
					+ "handlGetDocumentRequest for file: " + documentPath + " : "
1260
					+ ioe.getMessage());
1261
			errorMsg = ioe.getMessage();
1262
		} catch (PropertyNotFoundException pnfe) {
1263
			logMetacat.error("ReplicationService.handleGetDocumentRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1264
			logReplication
1265
					.error("ReplicationService.handleGetDocumentRequest - Error getting property when getting document from MetacatReplication."
1266
							+ "handlGetDocumentRequest for file: "
1267
							+ documentPath
1268
							+ " : "
1269
							+ pnfe.getMessage());
1270
			// e.printStackTrace(System.out);
1271
			errorMsg = pnfe.getMessage();
1272
		} catch (McdbException me) {
1273
			logReplication
1274
					.error("ReplicationService.handleGetDocumentRequest - Document implementation error  getting property when getting document from MetacatReplication."
1275
							+ "handlGetDocumentRequest for file: "
1276
							+ documentPath
1277
							+ " : "
1278
							+ me.getMessage());
1279
			// e.printStackTrace(System.out);
1280
			errorMsg = me.getMessage();
1281
		}
1282
		
1283
		// report any errors if we got here
1284
		response.setContentType("text/xml");
1285
		Writer out = null;
1286
		try {
1287
			response.getWriter();
1288
			out = response.getWriter();
1289
			out.write("<error>" + errorMsg + "</error>");
1290
		} catch (Exception e) {
1291
			logMetacat.error(e.getMessage(), e);
1292
		} finally {
1293
			try {
1294
				out.close();
1295
			} catch (IOException e) {
1296
				logMetacat.error(e.getMessage(), e);
1297
			}
1298
		}
1299
		
1300

    
1301
	}
1302

    
1303
	/**
1304
	 * Sends a list of all of the documents on this sever along with their
1305
	 * revision numbers. The format is: <!ELEMENT replication (server, updates)>
1306
	 * <!ELEMENT server (#PCDATA)> <!ELEMENT updates ((updatedDocument |
1307
	 * deleteDocument | revisionDocument)*)> <!ELEMENT updatedDocument (docid,
1308
	 * rev, datafile*)> <!ELEMENT deletedDocument (docid, rev)> <!ELEMENT
1309
	 * revisionDocument (docid, rev, datafile*)> <!ELEMENT docid (#PCDATA)>
1310
	 * <!ELEMENT rev (#PCDATA)> <!ELEMENT datafile (#PCDATA)> note that the rev
1311
	 * in deletedDocument is always empty. I just left it in there to make the
1312
	 * parser implementation easier.
1313
	 */
1314
	protected static void handleUpdateRequest(Hashtable<String, String[]> params,
1315
			HttpServletResponse response) {
1316
		// Checked out DBConnection
1317
		DBConnection dbConn = null;
1318
		// DBConenction serial number when checked it out
1319
		int serialNumber = -1;
1320
		PreparedStatement pstmt = null;
1321
		// Server list to store server info of xml_replication table
1322
		ReplicationServerList serverList = null;
1323
		
1324
		// a writer for response
1325
		Writer out = null;
1326

    
1327
		try {
1328
			// get writer, TODO: encoding?
1329
			response.setContentType("text/xml");
1330
			out = response.getWriter();
1331
			
1332
			// Check out a DBConnection from pool
1333
			dbConn = DBConnectionPool
1334
					.getDBConnection("MetacatReplication.handleUpdateRequest");
1335
			serialNumber = dbConn.getCheckOutSerialNumber();
1336
			// Create a server list from xml_replication table
1337
			serverList = new ReplicationServerList();
1338

    
1339
			// Get remote server name from param
1340
			String server = ((String[]) params.get("server"))[0];
1341
			// If no servr name in param, return a error
1342
			if (server == null || server.equals("")) {
1343
				out.write("<error>Request didn't specify server name</error>");
1344
				out.close();
1345
				return;
1346
			}//if
1347

    
1348
			//try to open a https stream to test if the request server's public key
1349
			//in the key store, this is security issue
1350
			String testUrl = "https://" + server + "?server="
1351
            + MetacatUtil.getLocalReplicationServerName() + "&action=test";
1352
			logReplication.info("Running trust test: " + testUrl);
1353
			URL u = new URL(testUrl);
1354
			String test = ReplicationService.getURLContent(u);
1355
			logReplication.info("Ouput from test is '" + test + "'");
1356
			//couldn't pass the test
1357
			if (test.indexOf("successfully") == -1) {
1358
			    logReplication.error("Trust test failed.");
1359
				out.write("<error>Couldn't pass the trust test</error>");
1360
				out.close();
1361
				return;
1362
			}
1363
			logReplication.info("Trust test succeeded.");
1364

    
1365
			// Check if local host configure to replicate xml documents to remote
1366
			// server. If not send back a error message
1367
			if (!serverList.getReplicationValue(server)) {
1368
				out.write("<error>Configuration not allow to replicate document to you</error>");
1369
				out.close();
1370
				return;
1371
			}//if
1372

    
1373
			// Store the sql command
1374
			StringBuffer docsql = new StringBuffer();
1375
			StringBuffer revisionSql = new StringBuffer();
1376
			// Stroe the docid list
1377
			StringBuffer doclist = new StringBuffer();
1378
			// Store the deleted docid list
1379
			StringBuffer delsql = new StringBuffer();
1380
			// Store the data set file
1381
			Vector<Vector<String>> packageFiles = new Vector<Vector<String>>();
1382

    
1383
			// Append local server's name and replication servlet to doclist
1384
			doclist.append("<?xml version=\"1.0\"?><replication>");
1385
			doclist.append("<server>")
1386
					.append(MetacatUtil.getLocalReplicationServerName());
1387
			//doclist.append(util.getProperty("replicationpath"));
1388
			doclist.append("</server><updates>");
1389

    
1390
			// Get correct docid that reside on this server according the requesting
1391
			// server's replicate and data replicate value in xml_replication table
1392
			docsql.append(DatabaseService.getInstance().getDBAdapter().getReplicationDocumentListSQL());
1393
			//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)) ");
1394
			revisionSql.append("select docid, rev, doctype from xml_revisions ");
1395
			// If the localhost is not a hub to the remote server, only replicate
1396
			// the docid' which home server is local host (server_location =1)
1397
			if (!serverList.getHubValue(server)) {
1398
				String serverLocationDoc = " and a.server_location = 1";
1399
				String serverLocationRev = "where server_location = 1";
1400
				docsql.append(serverLocationDoc);
1401
				revisionSql.append(serverLocationRev);
1402
			}
1403
			logReplication.info("ReplicationService.handleUpdateRequest - Doc sql: " + docsql.toString());
1404

    
1405
			// Get any deleted documents
1406
			delsql.append("select distinct docid from ");
1407
			delsql.append("xml_revisions where docid not in (select docid from ");
1408
			delsql.append("xml_documents) ");
1409
			// If the localhost is not a hub to the remote server, only replicate
1410
			// the docid' which home server is local host (server_location =1)
1411
			if (!serverList.getHubValue(server)) {
1412
				delsql.append("and server_location = 1");
1413
			}
1414
			logReplication.info("ReplicationService.handleUpdateRequest - Deleted sql: " + delsql.toString());
1415

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

    
1494
			pstmt = dbConn.prepareStatement(delsql.toString());
1495
			//usage count should increas 1
1496
			dbConn.increaseUsageCount(1);
1497

    
1498
			pstmt.execute();
1499
			rs = pstmt.getResultSet();
1500
			tablehasrows = rs.next();
1501
			while (tablehasrows) { //handle the deleted documents
1502
				doclist.append("<deletedDocument><docid>").append(rs.getString(1));
1503
				doclist.append("</docid><rev></rev></deletedDocument>");
1504
				//note that rev is always empty for deleted docs
1505
				tablehasrows = rs.next();
1506
			}
1507

    
1508
			//now we can put the package files into the xml results
1509
			for (int i = 0; i < packageFiles.size(); i++) {
1510
				Vector<String> v = packageFiles.elementAt(i);
1511
				doclist.append("<updatedDocument>");
1512
				doclist.append("<docid>").append(v.elementAt(0));
1513
				doclist.append("</docid><rev>");
1514
				doclist.append(v.elementAt(1));
1515
				doclist.append("</rev>");
1516
				doclist.append("</updatedDocument>");
1517
			}
1518
			// add revision doc list  
1519
			doclist.append(prepareRevisionDoc(dbConn, revisionSql.toString(),
1520
					replicateData));
1521

    
1522
			doclist.append("</updates></replication>");
1523
			logReplication.info("ReplicationService.handleUpdateRequest - doclist: " + doclist.toString());
1524
			pstmt.close();
1525
			//conn.close();
1526
			out.write(doclist.toString());
1527

    
1528
		} catch (Exception e) {
1529
			logMetacat.error("ReplicationService.handleUpdateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1530
			logReplication.error("ReplicationService.handleUpdateRequest - error in MetacatReplication." + "handleupdaterequest: "
1531
					+ e.getMessage());
1532
			//e.printStackTrace(System.out);
1533
			try {
1534
				out.write("<error>" + e.getMessage() + "</error>");
1535
			} catch (IOException e1) {
1536
				logMetacat.error(e1.getMessage(), e1);
1537
			}
1538
		} finally {
1539
			try {
1540
				pstmt.close();
1541
			}//try
1542
			catch (SQLException ee) {
1543
				logMetacat.error("ReplicationService.handleUpdateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1544
				logReplication.error("ReplicationService.handleUpdateRequest - Error in MetacatReplication."
1545
						+ "handleUpdaterequest to close pstmt: " + ee.getMessage());
1546
			}//catch
1547
			finally {
1548
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1549
			}//finally
1550
			try {
1551
				out.close();
1552
			} catch (IOException e) {
1553
				logMetacat.error(e.getMessage(), e);
1554
			}
1555
		}//finally
1556

    
1557
	}//handlUpdateRequest
1558

    
1559
	/**
1560
	 * 
1561
	 * @param dbConn connection for doing the update
1562
	 * @param docid the document id to update
1563
	 * @param owner the user_owner
1564
	 * @param updater the user_updated
1565
	 * @throws SQLException
1566
	 */
1567
	public static void updateUserOwner(DBConnection dbConn, String docid, String owner, String updater) throws SQLException {
1568
	
1569
		String sql = 
1570
			"UPDATE xml_documents " +
1571
			"SET user_owner = ?, " +
1572
			"user_updated = ? " +
1573
			"WHERE docid = ?;";
1574
		PreparedStatement pstmt = dbConn.prepareStatement(sql);
1575
		//usage count should increas 1
1576
		dbConn.increaseUsageCount(1);
1577

    
1578
		docid = DocumentUtil.getSmartDocId(docid);
1579
		pstmt.setString(1, owner);
1580
		pstmt.setString(2, updater);
1581
		pstmt.setString(3, docid);
1582
		pstmt.execute();
1583
		pstmt.close();
1584
		
1585
		dbConn.commit();
1586
	}
1587
	
1588
	/*
1589
	 * This method will get the xml string for document in xml_revision
1590
	 * The schema look like <!ELEMENT revisionDocument (docid, rev, datafile*)>
1591
	 */
1592
	private static String prepareRevisionDoc(DBConnection dbConn, String revSql,
1593
			boolean replicateData) throws Exception {
1594
		logReplication.warn("ReplicationService.prepareRevisionDoc - The revision document sql is " + revSql);
1595
		StringBuffer revDocList = new StringBuffer();
1596
		PreparedStatement pstmt = dbConn.prepareStatement(revSql);
1597
		//usage count should increas 1
1598
		dbConn.increaseUsageCount(1);
1599

    
1600
		pstmt.execute();
1601
		ResultSet rs = pstmt.getResultSet();
1602
		boolean tablehasrows = rs.next();
1603
		while (tablehasrows) {
1604
			String recordDoctype = rs.getString(3);
1605

    
1606
			//If this is data file and it isn't configured to replicate data
1607
			if (recordDoctype.equals("BIN") && !replicateData) {
1608
				// do nothing
1609
				continue;
1610
			} else {
1611

    
1612
				revDocList.append("<revisionDocument>");
1613
				revDocList.append("<docid>").append(rs.getString(1));
1614
				revDocList.append("</docid><rev>").append(rs.getInt(2));
1615
				revDocList.append("</rev>");
1616
				// data file
1617
				if (recordDoctype.equals("BIN")) {
1618
					revDocList.append("<datafile>");
1619
					revDocList.append(PropertyService
1620
							.getProperty("replication.datafileflag"));
1621
					revDocList.append("</datafile>");
1622
				}
1623
				revDocList.append("</revisionDocument>");
1624

    
1625
			}//else
1626
			tablehasrows = rs.next();
1627
		}
1628
		//System.out.println("The revision list is"+ revDocList.toString());
1629
		return revDocList.toString();
1630
	}
1631

    
1632
	/**
1633
	 * Returns the xml_catalog table encoded in xml
1634
	 */
1635
	public static String getCatalogXML() {
1636
		return handleGetCatalogRequest(null, null, false);
1637
	}
1638

    
1639
	/**
1640
	 * Sends the contents of the xml_catalog table encoded in xml
1641
	 * The xml format is:
1642
	 * <!ELEMENT xml_catalog (row*)>
1643
	 * <!ELEMENT row (entry_type, source_doctype, target_doctype, public_id,
1644
	 *                system_id)>
1645
	 * All of the sub elements of row are #PCDATA
1646

    
1647
	 * If printFlag == false then do not print to out.
1648
	 */
1649
	protected static String handleGetCatalogRequest(
1650
			Hashtable<String, String[]> params, HttpServletResponse response,
1651
			boolean printFlag) {
1652
		DBConnection dbConn = null;
1653
		int serialNumber = -1;
1654
		PreparedStatement pstmt = null;
1655
		Writer out = null;
1656
		try {
1657
			// get writer, TODO: encoding?
1658
		    if(printFlag)
1659
		    {
1660
		        response.setContentType("text/xml");
1661
		        out = response.getWriter();
1662
		    }
1663
			/*conn = MetacatReplication.getDBConnection("MetacatReplication." +
1664
			                                          "handleGetCatalogRequest");*/
1665
			dbConn = DBConnectionPool
1666
					.getDBConnection("MetacatReplication.handleGetCatalogRequest");
1667
			serialNumber = dbConn.getCheckOutSerialNumber();
1668
			pstmt = dbConn.prepareStatement("select entry_type, "
1669
					+ "source_doctype, target_doctype, public_id, "
1670
					+ "system_id from xml_catalog");
1671
			pstmt.execute();
1672
			ResultSet rs = pstmt.getResultSet();
1673
			boolean tablehasrows = rs.next();
1674
			StringBuffer sb = new StringBuffer();
1675
			sb.append("<?xml version=\"1.0\"?><xml_catalog>");
1676
			while (tablehasrows) {
1677
				sb.append("<row><entry_type>").append(rs.getString(1));
1678
				sb.append("</entry_type><source_doctype>").append(rs.getString(2));
1679
				sb.append("</source_doctype><target_doctype>").append(rs.getString(3));
1680
				sb.append("</target_doctype><public_id>").append(rs.getString(4));
1681
				// system id may not have server url on front.  Add it if not.
1682
				String systemID = rs.getString(5);
1683
				if (!systemID.startsWith("http://")) {
1684
					systemID = SystemUtil.getContextURL() + systemID;
1685
				}
1686
				sb.append("</public_id><system_id>").append(systemID);
1687
				sb.append("</system_id></row>");
1688

    
1689
				tablehasrows = rs.next();
1690
			}
1691
			sb.append("</xml_catalog>");
1692
			//conn.close();
1693
			if (printFlag) {
1694
				response.setContentType("text/xml");
1695
				out.write(sb.toString());
1696
			}
1697
			pstmt.close();
1698
			return sb.toString();
1699
		} catch (Exception e) {
1700
			logMetacat.error("ReplicationService.handleGetCatalogRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1701
			logReplication.error("ReplicationService.handleGetCatalogRequest - error in MetacatReplication.handleGetCatalogRequest:"
1702
					+ e.getMessage());
1703
			e.printStackTrace(System.out);
1704
			if (printFlag) {
1705
				try {
1706
					out.write("<error>" + e.getMessage() + "</error>");
1707
				} catch (IOException e1) {
1708
					logMetacat.error(e1.getMessage(), e1);
1709
				}
1710
			}
1711
		} finally {
1712
			try {
1713
				pstmt.close();
1714
			}//try
1715
			catch (SQLException ee) {
1716
				logMetacat.error("ReplicationService.handleGetCatalogRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1717
				logReplication.error("ReplicationService.handleGetCatalogRequest - Error in MetacatReplication.handleGetCatalogRequest: "
1718
						+ ee.getMessage());
1719
			}//catch
1720
			finally {
1721
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1722
			}//finally
1723
			if (out != null) {
1724
				try {
1725
					out.close();
1726
				} catch (IOException e1) {
1727
					logMetacat.error(e1.getMessage(), e1);
1728
				}
1729
			}
1730
		}//finally
1731

    
1732
		return null;
1733
	}
1734

    
1735
	/**
1736
	 * Sends the current system date to the remote server.  Using this action
1737
	 * for replication gets rid of any problems with syncronizing clocks
1738
	 * because a time specific to a document is always kept on its home server.
1739
	 */
1740
	protected static void handleGetTimeRequest(
1741
			Hashtable<String, String[]> params, HttpServletResponse response) {
1742
		
1743
		// use standard format -- the receiving end wants this too
1744
		String dateString = DateTimeMarshaller.serializeDateToUTC(Calendar.getInstance().getTime());
1745
		
1746
		// get a writer for sending back to response
1747
		response.setContentType("text/xml");
1748
		Writer out = null;
1749
		try {
1750
			out = response.getWriter();
1751
			out.write("<timestamp>" + dateString + "</timestamp>");
1752
			out.close();
1753
		} catch (IOException e) {
1754
			logMetacat.error(e.getMessage(), e);
1755
		}
1756
		
1757
	}
1758

    
1759
	/**
1760
	 * this method handles the timeout for a file lock.  when a lock is
1761
	 * granted it is granted for 30 seconds.  When this thread runs out
1762
	 * it deletes the docid from the queue, thus eliminating the lock.
1763
	 */
1764
	public void run() {
1765
		try {
1766
			logReplication.info("ReplicationService.run - thread started for docid: "
1767
					+ (String) fileLocks.elementAt(0));
1768

    
1769
			Thread.sleep(30000); //the lock will expire in 30 seconds
1770
			logReplication.info("thread for docid: "
1771
					+ (String) fileLocks.elementAt(fileLocks.size() - 1) + " exiting.");
1772

    
1773
			fileLocks.remove(fileLocks.size() - 1);
1774
			//fileLocks is treated as a FIFO queue.  If there are more than one lock
1775
			//in the vector, the first one inserted will be removed.
1776
		} catch (Exception e) {
1777
			logMetacat.error("ReplicationService.run - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1778
			logReplication.error("ReplicationService.run - error in file lock thread from "
1779
					+ "MetacatReplication.run: " + e.getMessage());
1780
		}
1781
	}
1782

    
1783
	/**
1784
	 * Returns the name of a server given a serverCode
1785
	 * @param serverCode the serverid of the server
1786
	 * @return the servername or null if the specified serverCode does not
1787
	 *         exist.
1788
	 */
1789
	public static String getServerNameForServerCode(int serverCode) {
1790
		//System.out.println("serverid: " + serverCode);
1791
		DBConnection dbConn = null;
1792
		int serialNumber = -1;
1793
		PreparedStatement pstmt = null;
1794
		try {
1795
			dbConn = DBConnectionPool.getDBConnection("MetacatReplication.getServer");
1796
			serialNumber = dbConn.getCheckOutSerialNumber();
1797
			String sql = new String("select server from "
1798
					+ "xml_replication where serverid = ?");
1799
			pstmt = dbConn.prepareStatement(sql);
1800
			pstmt.setInt(1, serverCode);
1801
			//System.out.println("getserver sql: " + sql);
1802
			pstmt.execute();
1803
			ResultSet rs = pstmt.getResultSet();
1804
			boolean tablehasrows = rs.next();
1805
			if (tablehasrows) {
1806
				//System.out.println("server: " + rs.getString(1));
1807
				return rs.getString(1);
1808
			}
1809

    
1810
			//conn.close();
1811
		} catch (Exception e) {
1812
			logMetacat.error("ReplicationService.getServerNameForServerCode - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1813
			logReplication.error("ReplicationService.getServerNameForServerCode - Error in MetacatReplication.getServer: " + e.getMessage());
1814
		} finally {
1815
			try {
1816
				pstmt.close();
1817
			}//try
1818
			catch (SQLException ee) {
1819
				logMetacat.error("ReplicationService.getServerNameForServerCode - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1820
				logReplication.error("ReplicationService.getServerNameForServerCode - Error in MetacactReplication.getserver: "
1821
						+ ee.getMessage());
1822
			}//catch
1823
			finally {
1824
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1825
			}//fianlly
1826
		}//finally
1827

    
1828
		return null;
1829
		//return null if the server does not exist
1830
	}
1831

    
1832
	/**
1833
	 * Returns a server code given a server name
1834
	 * @param server the name of the server
1835
	 * @return integer > 0 representing the code of the server, 0 if the server
1836
	 *  does not exist.
1837
	 */
1838
	public static int getServerCodeForServerName(String server) throws ServiceException {
1839
		DBConnection dbConn = null;
1840
		int serialNumber = -1;
1841
		PreparedStatement pstmt = null;
1842
		int serverCode = 0;
1843

    
1844
		try {
1845

    
1846
			//conn = util.openDBConnection();
1847
			dbConn = DBConnectionPool.getDBConnection("MetacatReplication.getServerCode");
1848
			serialNumber = dbConn.getCheckOutSerialNumber();
1849
			pstmt = dbConn.prepareStatement("SELECT serverid FROM xml_replication "
1850
					+ "WHERE server LIKE ?");
1851
			pstmt.setString(1, server);
1852
			pstmt.execute();
1853
			ResultSet rs = pstmt.getResultSet();
1854
			boolean tablehasrows = rs.next();
1855
			if (tablehasrows) {
1856
				serverCode = rs.getInt(1);
1857
				pstmt.close();
1858
				//conn.close();
1859
				return serverCode;
1860
			}
1861

    
1862
		} catch (SQLException sqle) {
1863
			throw new ServiceException("ReplicationService.getServerCodeForServerName - " 
1864
					+ "SQL error when getting server code: " + sqle.getMessage());
1865

    
1866
		} finally {
1867
			try {
1868
				pstmt.close();
1869
				//conn.close();
1870
			}//try
1871
			catch (Exception ee) {
1872
				logMetacat.error("ReplicationService.getServerCodeForServerName - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1873
				logReplication.error("ReplicationService.getServerNameForServerCode - Error in MetacatReplicatio.getServerCode: "
1874
						+ ee.getMessage());
1875

    
1876
			}//catch
1877
			finally {
1878
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1879
			}//finally
1880
		}//finally
1881

    
1882
		return serverCode;
1883
	}
1884

    
1885
	/**
1886
	 * Method to get a host server information for given docid
1887
	 * @param conn a connection to the database
1888
	 */
1889
	public static Hashtable<String, String> getHomeServerInfoForDocId(String docId) {
1890
		Hashtable<String, String> sl = new Hashtable<String, String>();
1891
		DBConnection dbConn = null;
1892
		int serialNumber = -1;
1893
		docId = DocumentUtil.getDocIdFromString(docId);
1894
		PreparedStatement pstmt = null;
1895
		int serverLocation;
1896
		try {
1897
			//get conection
1898
			dbConn = DBConnectionPool.getDBConnection("ReplicationHandler.getHomeServer");
1899
			serialNumber = dbConn.getCheckOutSerialNumber();
1900
			//get a server location from xml_document table
1901
			pstmt = dbConn.prepareStatement("select server_location from xml_documents "
1902
					+ "where docid = ?");
1903
			pstmt.setString(1, docId);
1904
			pstmt.execute();
1905
			ResultSet serverName = pstmt.getResultSet();
1906
			//get a server location
1907
			if (serverName.next()) {
1908
				serverLocation = serverName.getInt(1);
1909
				pstmt.close();
1910
			} else {
1911
				pstmt.close();
1912
				//ut.returnConnection(conn);
1913
				return null;
1914
			}
1915
			pstmt = dbConn.prepareStatement("select server, last_checked, replicate "
1916
					+ "from xml_replication where serverid = ?");
1917
			//increase usage count
1918
			dbConn.increaseUsageCount(1);
1919
			pstmt.setInt(1, serverLocation);
1920
			pstmt.execute();
1921
			ResultSet rs = pstmt.getResultSet();
1922
			boolean tableHasRows = rs.next();
1923
			if (tableHasRows) {
1924

    
1925
				String server = rs.getString(1);
1926
				String last_checked = rs.getString(2);
1927
				if (!server.equals("localhost")) {
1928
					sl.put(server, last_checked);
1929
				}
1930

    
1931
			} else {
1932
				pstmt.close();
1933
				//ut.returnConnection(conn);
1934
				return null;
1935
			}
1936
			pstmt.close();
1937
		} catch (Exception e) {
1938
			logMetacat.error("ReplicationService.getHomeServerInfoForDocId - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1939
			logReplication.error("ReplicationService.getHomeServerInfoForDocId - error in replicationHandler.getHomeServer(): "
1940
					+ e.getMessage());
1941
		} finally {
1942
			try {
1943
				pstmt.close();
1944
				//ut.returnConnection(conn);
1945
			} catch (Exception ee) {
1946
				logMetacat.error("ReplicationService.getHomeServerInfoForDocId - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1947
				logReplication.error("ReplicationService.getHomeServerInfoForDocId - Eror irn rplicationHandler.getHomeServer() "
1948
						+ "to close pstmt: " + ee.getMessage());
1949
			} finally {
1950
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1951
			}
1952

    
1953
		}//finally
1954
		return sl;
1955
	}
1956

    
1957
	/**
1958
	 * Returns a home server location  given a accnum
1959
	 * @param accNum , given accNum for a document
1960
	 *
1961
	 */
1962
	public static int getHomeServerCodeForDocId(String accNum) throws ServiceException {
1963
		DBConnection dbConn = null;
1964
		int serialNumber = -1;
1965
		PreparedStatement pstmt = null;
1966
		int serverCode = 1;
1967
		String docId = DocumentUtil.getDocIdFromString(accNum);
1968

    
1969
		try {
1970

    
1971
			// Get DBConnection
1972
			dbConn = DBConnectionPool
1973
					.getDBConnection("ReplicationHandler.getServerLocation");
1974
			serialNumber = dbConn.getCheckOutSerialNumber();
1975
			pstmt = dbConn.prepareStatement("SELECT server_location FROM xml_documents "
1976
					+ "WHERE docid LIKE ? ");
1977
			pstmt.setString(1, docId);
1978
			pstmt.execute();
1979
			ResultSet rs = pstmt.getResultSet();
1980
			boolean tablehasrows = rs.next();
1981
			//If a document is find, return the server location for it
1982
			if (tablehasrows) {
1983
				serverCode = rs.getInt(1);
1984
				pstmt.close();
1985
				//conn.close();
1986
				return serverCode;
1987
			}
1988
			//if couldn't find in xml_documents table, we think server code is 1
1989
			//(this is new document)
1990
			else {
1991
				pstmt.close();
1992
				//conn.close();
1993
				return serverCode;
1994
			}
1995

    
1996
		} catch (SQLException sqle) {
1997
			throw new ServiceException("ReplicationService.getHomeServerCodeForDocId - " 
1998
					+ "SQL error when getting home server code for docid: " + docId + " : " 
1999
					+ sqle.getMessage());
2000

    
2001
		} finally {
2002
			try {
2003
				pstmt.close();
2004
				//conn.close();
2005

    
2006
			} catch (SQLException sqle) {
2007
				logMetacat.error("ReplicationService.getHomeServerCodeForDocId - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
2008
				logReplication.error("ReplicationService.getHomeServerCodeForDocId - ReplicationService.getHomeServerCodeForDocId - " 
2009
						+ "SQL error when getting home server code for docid: " + docId + " : " 
2010
						+ sqle.getMessage());
2011
			} finally {
2012
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
2013
			}//finally
2014
		}//finally
2015
		//return serverCode;
2016
	}
2017

    
2018
	/**
2019
	 * This method returns the content of a url
2020
	 * @param u the url to return the content from
2021
	 * @return a string representing the content of the url
2022
	 * @throws java.io.IOException
2023
	 */
2024
	public static String getURLContent(URL u) throws java.io.IOException {
2025
		char istreamChar;
2026
		int istreamInt;
2027
		// get the response content
2028
		InputStream input = getURLStream(u);
2029
		logReplication.info("ReplicationService.getURLContent - After getting response from: " + u.toString());
2030
		InputStreamReader istream = new InputStreamReader(input);
2031
		StringBuffer serverResponse = new StringBuffer();
2032
		while ((istreamInt = istream.read()) != -1) {
2033
			istreamChar = (char) istreamInt;
2034
			serverResponse.append(istreamChar);
2035
		}
2036
		istream.close();
2037
		input.close();
2038

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

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

    
2130
//	/**
2131
//	 * Method for writing replication messages to a log file specified in
2132
//	 * metacat.properties
2133
//	 */
2134
//	public static void replErrorLog(String message) {
2135
//		try {
2136
//			FileOutputStream fos = new FileOutputStream(PropertyService
2137
//					.getProperty("replication.logdir")
2138
//					+ "/metacatreplicationerror.log", true);
2139
//			PrintWriter pw = new PrintWriter(fos);
2140
//			SimpleDateFormat formatter = new SimpleDateFormat("yy-MM-dd HH:mm:ss");
2141
//			java.util.Date localtime = new java.util.Date();
2142
//			String dateString = formatter.format(localtime);
2143
//			dateString += " :: " + message;
2144
//			//time stamp each entry
2145
//			pw.println(dateString);
2146
//			pw.flush();
2147
//		} catch (Exception e) {
2148
//			logReplication.error("error writing to replication error log from "
2149
//					+ "MetacatReplication.replErrorLog: " + e.getMessage());
2150
//			//e.printStackTrace(System.out);
2151
//		}
2152
//	}
2153

    
2154
	/**
2155
	 * Returns true if the replicate field for server in xml_replication is 1.
2156
	 * Returns false otherwise
2157
	 */
2158
	public static boolean replToServer(String server) {
2159
		DBConnection dbConn = null;
2160
		int serialNumber = -1;
2161
		PreparedStatement pstmt = null;
2162
		try {
2163
			dbConn = DBConnectionPool.getDBConnection("MetacatReplication.repltoServer");
2164
			serialNumber = dbConn.getCheckOutSerialNumber();
2165
			pstmt = dbConn.prepareStatement("select replicate from "
2166
					+ "xml_replication where server like ? ");
2167
			pstmt.setString(1, server);
2168
			pstmt.execute();
2169
			ResultSet rs = pstmt.getResultSet();
2170
			boolean tablehasrows = rs.next();
2171
			if (tablehasrows) {
2172
				int i = rs.getInt(1);
2173
				if (i == 1) {
2174
					pstmt.close();
2175
					//conn.close();
2176
					return true;
2177
				} else {
2178
					pstmt.close();
2179
					//conn.close();
2180
					return false;
2181
				}
2182
			}
2183
		} catch (SQLException sqle) {
2184
			logMetacat.error("ReplicationService.replToServer - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
2185
			logReplication.error("ReplicationService.replToServer - SQL error in MetacatReplication.replToServer: "
2186
					+ sqle.getMessage());
2187
		} finally {
2188
			try {
2189
				pstmt.close();
2190
				//conn.close();
2191
			}//try
2192
			catch (Exception ee) {
2193
				logMetacat.error("ReplicationService.replToServer - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
2194
				logReplication.error("ReplicationService.replToServer - Error in MetacatReplication.replToServer: "
2195
						+ ee.getMessage());
2196
			}//catch
2197
			finally {
2198
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
2199
			}//finally
2200
		}//finally
2201
		return false;
2202
		//the default if this server does not exist is to not replicate to it.
2203
	}
2204

    
2205
}
(6-6/7)