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-04-09 15:18:39 -0700 (Mon, 09 Apr 2012) $'
10
 * '$Revision: 7128 $'
11
 *
12
 * This program is free software; you can redistribute it and/or modify
13
 * it under the terms of the GNU General Public License as published by
14
 * the Free Software Foundation; either version 2 of the License, or
15
 * (at your option) any later version.
16
 *
17
 * This program is distributed in the hope that it will be useful,
18
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20
 * GNU General Public License for more details.
21
 *
22
 * You should have received a copy of the GNU General Public License
23
 * along with this program; if not, write to the Free Software
24
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
25
 */
26

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

    
29
import java.io.ByteArrayInputStream;
30
import java.io.ByteArrayOutputStream;
31
import java.io.File;
32
import java.io.FileInputStream;
33
import java.io.FileNotFoundException;
34
import java.io.FileOutputStream;
35
import java.io.IOException;
36
import java.io.InputStream;
37
import java.io.InputStreamReader;
38
import java.io.OutputStream;
39
import java.io.StringReader;
40
import java.io.Writer;
41
import java.net.MalformedURLException;
42
import java.net.URL;
43
import java.security.PrivateKey;
44
import java.security.cert.X509Certificate;
45
import java.sql.PreparedStatement;
46
import java.sql.ResultSet;
47
import java.sql.SQLException;
48
import java.sql.Timestamp;
49
import java.util.Calendar;
50
import java.util.Date;
51
import java.util.Hashtable;
52
import java.util.List;
53
import java.util.Timer;
54
import java.util.Vector;
55

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

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

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

    
101
public class ReplicationService extends BaseService {
102

    
103
	private static ReplicationService replicationService = null;
104

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
464
	}
465

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

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

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

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

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

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

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

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

    
689
		}//catch
690

    
691
	}
692

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

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

    
716
		// Overide or not
717
		//    boolean override = false;
718
		// dbaction - update or insert
719
		String dbaction = null;
720

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

    
733
			logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - Force replication request from: " + server);
734
			logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - Force replication docid: " + docid);
735
			logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - Force replication action: " + dbaction);
736
			// get the document info from server
737
			URL docinfourl = new URL("https://" + server + "?server="
738
					+ MetacatUtil.getLocalReplicationServerName()
739
					+ "&action=getdocumentinfo&docid=" + docid);
740

    
741
			String docInfoStr = ReplicationService.getURLContent(docinfourl);
742
			
743
			// strip out the system metadata portion
744
		    String systemMetadataXML = ReplicationUtil.getSystemMetadataContent(docInfoStr);
745
		   	docInfoStr = ReplicationUtil.getContentWithoutSystemMetadata(docInfoStr);
746

    
747
			//dih is the parser for the docinfo xml format
748
			DocInfoHandler dih = new DocInfoHandler();
749
			XMLReader docinfoParser = ReplicationHandler.initParser(dih);
750
			docinfoParser.parse(new InputSource(new StringReader(docInfoStr)));
751
			Hashtable<String, String> docinfoHash = dih.getDocInfo();
752
			
753
			String docName = (String) docinfoHash.get("docname");
754

    
755
			String docType = (String) docinfoHash.get("doctype");
756

    
757
			String docHomeServer = (String) docinfoHash.get("home_server");
758
			
759
			String createdDateString = docinfoHash.get("date_created");
760
			String updatedDateString = docinfoHash.get("date_updated");
761
			
762
			Date createdDate = DateTimeMarshaller.deserializeDateToUTC(createdDateString);
763
			Date updatedDate = DateTimeMarshaller.deserializeDateToUTC(updatedDateString);
764
			
765
			logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - docHomeServer of datafile: " + docHomeServer);
766

    
767
			// in case we have a write exception, we still want to track access and sysmeta
768
			Exception writeException = null;
769

    
770
			// do we need the object content?
771
			if (dbaction != null && (dbaction.equals("insert") || dbaction.equals("update"))) {
772
				//Get data file and store it into local file system.
773
				// sending back readdata request to server
774
				URL url = new URL("https://" + server + "?server="
775
						+ MetacatUtil.getLocalReplicationServerName()
776
						+ "&action=readdata&docid=" + docid);
777
				String datafilePath = PropertyService
778
						.getProperty("application.datafilepath");
779

    
780
				InputStream inputStream = getURLStream(url);
781
				
782
				//register data file into xml_documents table and write data file
783
				//into file system
784
				try {
785
					DocumentImpl.writeDataFileInReplication(inputStream,
786
							datafilePath, docName, docType, docid, null, docHomeServer,
787
							server, DocumentImpl.DOCUMENTTABLE, false, createdDate,
788
							updatedDate);
789
				} catch (Exception e) {
790
					writeException = e;
791
				}
792

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

    
839
			logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - datafile " + docid + " added to DB with "
840
					+ "action " + dbaction);
841
			EventLog.getInstance().log(request.getRemoteAddr(), request.getHeader("User-Agent"), REPLICATIONUSER,
842
					docid, dbaction);
843

    
844
		} catch (Exception e) {
845
			e.printStackTrace();
846
			logMetacat.error("ReplicationService.handleForceReplicateDataFileRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG, e);                         
847
			logReplication.error("ReplicationService.handleForceReplicateDataFileRequest - Datafile " + docid
848
					+ " failed to added to DB with " + "action " + dbaction + " because "
849
					+ e.getMessage());
850
			logReplication.error("ReplicationService.handleForceReplicateDataFileRequest - ERROR in MetacatReplication.handleForceDataFileReplicate"
851
					+ "Request(): " + e.getMessage());
852
		}
853
	}
854

    
855
	/**
856
	 * Grants or denies a lock to a requesting host.
857
	 * The servlet parameters of interrest are:
858
	 * docid: the docid of the file the lock is being requested for
859
	 * currentdate: the timestamp of the document on the remote server
860
	 *
861
	 */
862
	protected static void handleGetLockRequest(
863
			Hashtable<String, String[]> params, HttpServletResponse response) {
864

    
865
		try {
866

    
867
			String docid = ((String[]) params.get("docid"))[0];
868
			String remoteRev = ((String[]) params.get("updaterev"))[0];
869
			DocumentImpl requestDoc = new DocumentImpl(docid);
870
			logReplication.info("ReplicationService.handleGetLockRequest - lock request for " + docid);
871
			int localRevInt = requestDoc.getRev();
872
			int remoteRevInt = Integer.parseInt(remoteRev);
873

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

    
908
	/**
909
	 * Sends all of the xml_documents information encoded in xml to a requestor
910
	 * the format is:
911
	 * <!ELEMENT documentinfo (docid, docname, doctype, doctitle, user_owner,
912
	 *                  user_updated, home_server, public_access, rev)/>
913
	 * all of the subelements of document info are #PCDATA
914
	 */
915
	protected static void handleGetDocumentInfoRequest(
916
			Hashtable<String, String[]> params, HttpServletResponse response) {
917
		String docid = ((String[]) (params.get("docid")))[0];
918

    
919
		try {
920
			// get docinfo as XML string
921
			String docinfoXML = getDocumentInfo(docid);
922
			
923
			// get a writer for sending back to response
924
			response.setContentType("text/xml");
925
			Writer out = response.getWriter();
926
			out.write(docinfoXML);
927
			out.close();
928

    
929
		} catch (Exception e) {
930
			logMetacat.error("ReplicationService.handleGetDocumentInfoRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
931
			logReplication.error("ReplicationService.handleGetDocumentInfoRequest - error in metacatReplication.handlegetdocumentinforequest "
932
					+ "for doc: " + docid + " : " + e.getMessage());
933
		}
934

    
935
	}
936
	
937
	public static Hashtable<String, String> getDocumentInfoMap(String docid)
938
			throws HandlerException, AccessControlException, JiBXException,
939
			IOException, McdbException, SAXException {
940
		
941
		// Try get docid info from remote server
942
		DocInfoHandler dih = new DocInfoHandler();
943
		XMLReader docinfoParser = ReplicationHandler.initParser(dih);
944

    
945
		String docInfoStr = getDocumentInfo(docid);
946

    
947
		// strip out the system metadata portion
948
		String systemMetadataXML = ReplicationUtil.getSystemMetadataContent(docInfoStr);
949
		docInfoStr = ReplicationUtil.getContentWithoutSystemMetadata(docInfoStr);
950

    
951
		docinfoParser.parse(new InputSource(new StringReader(docInfoStr)));
952
		Hashtable<String, String> docinfoHash = dih.getDocInfo();
953

    
954
		return docinfoHash;
955
	}
956
	
957
	/**
958
	 * Gets a docInfo XML snippet for the replication API
959
	 * @param docid
960
	 * @return
961
	 * @throws AccessControlException
962
	 * @throws JiBXException
963
	 * @throws IOException
964
	 * @throws McdbException
965
	 */
966
	public static String getDocumentInfo(String docid) throws AccessControlException, JiBXException, IOException, McdbException {
967
		StringBuffer sb = new StringBuffer();
968

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

    
1011
		sb.append("<accessControl>");
1012

    
1013
		AccessControlForSingleFile acfsf = new AccessControlForSingleFile(docid); 
1014
		sb.append(acfsf.getAccessString());
1015
		
1016
		sb.append("</accessControl>");
1017

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

    
1044
		} catch (Exception e) {
1045
			String msg = "ReplicationService.handleGetSystemMetadataRequest for guid: " + guid + " : " + e.getMessage();
1046
			logMetacat.error(msg);                         
1047
			logReplication.error(msg);
1048
		}
1049

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

    
1084
		} catch (Exception e) {
1085
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG, e);                         
1086
			logReplication.error("ReplicationService.handleForceReplicateRequest - General error when processing guid: " + guid, e);
1087
		}
1088
	}
1089

    
1090
	/**
1091
	 * Sends a datafile to a remote host
1092
	 */
1093
	protected static void handleGetDataFileRequest(OutputStream outPut,
1094
			Hashtable<String, String[]> params, HttpServletResponse response)
1095

    
1096
	{
1097
		// File path for data file
1098
		String filepath;
1099
		// Request docid
1100
		String docId = ((String[]) (params.get("docid")))[0];
1101
		//check if the doicd is null
1102
		if (docId == null) {
1103
			logMetacat.error("ReplicationService.handleGetDataFileRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1104
			logReplication.error("ReplicationService.handleGetDataFileRequest - Didn't specify docid for replication");
1105
			return;
1106
		}
1107

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

    
1129
		if (!filepath.endsWith("/")) {
1130
			filepath += "/";
1131
		}
1132
		// Get file aboslute file name
1133
		String filename = filepath + docId;
1134

    
1135
		//MIME type
1136
		String contentType = null;
1137
		if (filename.endsWith(".xml")) {
1138
			contentType = "text/xml";
1139
		} else if (filename.endsWith(".css")) {
1140
			contentType = "text/css";
1141
		} else if (filename.endsWith(".dtd")) {
1142
			contentType = "text/plain";
1143
		} else if (filename.endsWith(".xsd")) {
1144
			contentType = "text/xml";
1145
		} else if (filename.endsWith("/")) {
1146
			contentType = "text/html";
1147
		} else {
1148
			File f = new File(filename);
1149
			if (f.isDirectory()) {
1150
				contentType = "text/html";
1151
			} else {
1152
				contentType = "application/octet-stream";
1153
			}
1154
		}
1155

    
1156
		// Set the mime type
1157
		response.setContentType(contentType);
1158

    
1159
		// Get the content of the file
1160
		FileInputStream fin = null;
1161
		try {
1162
			// FileInputStream to metacat
1163
			fin = new FileInputStream(filename);
1164
			// 4K buffer
1165
			byte[] buf = new byte[4 * 1024];
1166
			// Read data from file input stream to byte array
1167
			int b = fin.read(buf);
1168
			// Write to outStream from byte array
1169
			while (b != -1) {
1170
				outPut.write(buf, 0, b);
1171
				b = fin.read(buf);
1172
			}
1173
			// close file input stream
1174
			fin.close();
1175

    
1176
		}//try
1177
		catch (Exception e) {
1178
			logMetacat.error("ReplicationService.handleGetDataFileRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1179
			logReplication.error("ReplicationService.handleGetDataFileRequest - error getting data file from MetacatReplication."
1180
					+ "handlGetDataFileRequest " + e.getMessage());
1181
			e.printStackTrace(System.out);
1182
		}//catch
1183

    
1184
	}
1185

    
1186
	/**
1187
	 * Sends a document to a remote host
1188
	 */
1189
	protected static void handleGetDocumentRequest(
1190
			Hashtable<String, String[]> params, HttpServletResponse response) {
1191

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

    
1213
			String docid = params.get("docid")[0];
1214
			logReplication.debug("ReplicationService.handleGetDocumentRequest - MetacatReplication.handleGetDocumentRequest for docid: "
1215
					+ docid);
1216
			DocumentImpl di = new DocumentImpl(docid);
1217

    
1218
			String documentDir = PropertyService
1219
					.getProperty("application.documentfilepath");
1220
			documentPath = documentDir + FileUtil.getFS() + docid;
1221

    
1222
			// if the document does not exist on disk, read it from db and write
1223
			// it to disk.
1224
			if (FileUtil.getFileStatus(documentPath) == FileUtil.DOES_NOT_EXIST
1225
					|| FileUtil.getFileSize(documentPath) == 0) {
1226
				FileOutputStream fos = new FileOutputStream(documentPath);
1227
				di.toXml(fos, null, null, true);
1228
			}
1229

    
1230
			// read the file from disk and send it to outputstream
1231
			OutputStream outputStream = response.getOutputStream();
1232
			di.readFromFileSystem(outputStream, null, null, documentPath);
1233

    
1234
			logReplication.info("ReplicationService.handleGetDocumentRequest - document " + docid + " sent");
1235

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

    
1291
	}
1292

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

    
1317
		try {
1318
			// get writer, TODO: encoding?
1319
			response.setContentType("text/xml");
1320
			out = response.getWriter();
1321
			
1322
			// Check out a DBConnection from pool
1323
			dbConn = DBConnectionPool
1324
					.getDBConnection("MetacatReplication.handleUpdateRequest");
1325
			serialNumber = dbConn.getCheckOutSerialNumber();
1326
			// Create a server list from xml_replication table
1327
			serverList = new ReplicationServerList();
1328

    
1329
			// Get remote server name from param
1330
			String server = ((String[]) params.get("server"))[0];
1331
			// If no servr name in param, return a error
1332
			if (server == null || server.equals("")) {
1333
				out.write("<error>Request didn't specify server name</error>");
1334
				out.close();
1335
				return;
1336
			}//if
1337

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

    
1355
			// Check if local host configure to replicate xml documents to remote
1356
			// server. If not send back a error message
1357
			if (!serverList.getReplicationValue(server)) {
1358
				out.write("<error>Configuration not allow to replicate document to you</error>");
1359
				out.close();
1360
				return;
1361
			}//if
1362

    
1363
			// Store the sql command
1364
			StringBuffer docsql = new StringBuffer();
1365
			StringBuffer revisionSql = new StringBuffer();
1366
			// Stroe the docid list
1367
			StringBuffer doclist = new StringBuffer();
1368
			// Store the deleted docid list
1369
			StringBuffer delsql = new StringBuffer();
1370
			// Store the data set file
1371
			Vector<Vector<String>> packageFiles = new Vector<Vector<String>>();
1372

    
1373
			// Append local server's name and replication servlet to doclist
1374
			doclist.append("<?xml version=\"1.0\"?><replication>");
1375
			doclist.append("<server>")
1376
					.append(MetacatUtil.getLocalReplicationServerName());
1377
			//doclist.append(util.getProperty("replicationpath"));
1378
			doclist.append("</server><updates>");
1379

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

    
1395
			// Get any deleted documents
1396
			delsql.append("select distinct docid from ");
1397
			delsql.append("xml_revisions where docid not in (select docid from ");
1398
			delsql.append("xml_documents) ");
1399
			// If the localhost is not a hub to the remote server, only replicate
1400
			// the docid' which home server is local host (server_location =1)
1401
			if (!serverList.getHubValue(server)) {
1402
				delsql.append("and server_location = 1");
1403
			}
1404
			logReplication.info("ReplicationService.handleUpdateRequest - Deleted sql: " + delsql.toString());
1405

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

    
1484
			pstmt = dbConn.prepareStatement(delsql.toString());
1485
			//usage count should increas 1
1486
			dbConn.increaseUsageCount(1);
1487

    
1488
			pstmt.execute();
1489
			rs = pstmt.getResultSet();
1490
			tablehasrows = rs.next();
1491
			while (tablehasrows) { //handle the deleted documents
1492
				doclist.append("<deletedDocument><docid>").append(rs.getString(1));
1493
				doclist.append("</docid><rev></rev></deletedDocument>");
1494
				//note that rev is always empty for deleted docs
1495
				tablehasrows = rs.next();
1496
			}
1497

    
1498
			//now we can put the package files into the xml results
1499
			for (int i = 0; i < packageFiles.size(); i++) {
1500
				Vector<String> v = packageFiles.elementAt(i);
1501
				doclist.append("<updatedDocument>");
1502
				doclist.append("<docid>").append(v.elementAt(0));
1503
				doclist.append("</docid><rev>");
1504
				doclist.append(v.elementAt(1));
1505
				doclist.append("</rev>");
1506
				doclist.append("</updatedDocument>");
1507
			}
1508
			// add revision doc list  
1509
			doclist.append(prepareRevisionDoc(dbConn, revisionSql.toString(),
1510
					replicateData));
1511

    
1512
			doclist.append("</updates></replication>");
1513
			logReplication.info("ReplicationService.handleUpdateRequest - doclist: " + doclist.toString());
1514
			pstmt.close();
1515
			//conn.close();
1516
			out.write(doclist.toString());
1517

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

    
1547
	}//handlUpdateRequest
1548

    
1549
	/**
1550
	 * 
1551
	 * @param dbConn connection for doing the update
1552
	 * @param docid the document id to update
1553
	 * @param owner the user_owner
1554
	 * @param updater the user_updated
1555
	 * @throws SQLException
1556
	 */
1557
	public static void updateUserOwner(DBConnection dbConn, String docid, String owner, String updater) throws SQLException {
1558
	
1559
		String sql = 
1560
			"UPDATE xml_documents " +
1561
			"SET user_owner = ?, " +
1562
			"user_updated = ? " +
1563
			"WHERE docid = ?;";
1564
		PreparedStatement pstmt = dbConn.prepareStatement(sql);
1565
		//usage count should increas 1
1566
		dbConn.increaseUsageCount(1);
1567

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

    
1590
		pstmt.execute();
1591
		ResultSet rs = pstmt.getResultSet();
1592
		boolean tablehasrows = rs.next();
1593
		while (tablehasrows) {
1594
			String recordDoctype = rs.getString(3);
1595

    
1596
			//If this is data file and it isn't configured to replicate data
1597
			if (recordDoctype.equals("BIN") && !replicateData) {
1598
				// do nothing
1599
				continue;
1600
			} else {
1601

    
1602
				revDocList.append("<revisionDocument>");
1603
				revDocList.append("<docid>").append(rs.getString(1));
1604
				revDocList.append("</docid><rev>").append(rs.getInt(2));
1605
				revDocList.append("</rev>");
1606
				// data file
1607
				if (recordDoctype.equals("BIN")) {
1608
					revDocList.append("<datafile>");
1609
					revDocList.append(PropertyService
1610
							.getProperty("replication.datafileflag"));
1611
					revDocList.append("</datafile>");
1612
				}
1613
				revDocList.append("</revisionDocument>");
1614

    
1615
			}//else
1616
			tablehasrows = rs.next();
1617
		}
1618
		//System.out.println("The revision list is"+ revDocList.toString());
1619
		return revDocList.toString();
1620
	}
1621

    
1622
	/**
1623
	 * Returns the xml_catalog table encoded in xml
1624
	 */
1625
	public static String getCatalogXML() {
1626
		return handleGetCatalogRequest(null, null, false);
1627
	}
1628

    
1629
	/**
1630
	 * Sends the contents of the xml_catalog table encoded in xml
1631
	 * The xml format is:
1632
	 * <!ELEMENT xml_catalog (row*)>
1633
	 * <!ELEMENT row (entry_type, source_doctype, target_doctype, public_id,
1634
	 *                system_id)>
1635
	 * All of the sub elements of row are #PCDATA
1636

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

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

    
1722
		return null;
1723
	}
1724

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

    
1749
	/**
1750
	 * this method handles the timeout for a file lock.  when a lock is
1751
	 * granted it is granted for 30 seconds.  When this thread runs out
1752
	 * it deletes the docid from the queue, thus eliminating the lock.
1753
	 */
1754
	public void run() {
1755
		try {
1756
			logReplication.info("ReplicationService.run - thread started for docid: "
1757
					+ (String) fileLocks.elementAt(0));
1758

    
1759
			Thread.sleep(30000); //the lock will expire in 30 seconds
1760
			logReplication.info("thread for docid: "
1761
					+ (String) fileLocks.elementAt(fileLocks.size() - 1) + " exiting.");
1762

    
1763
			fileLocks.remove(fileLocks.size() - 1);
1764
			//fileLocks is treated as a FIFO queue.  If there are more than one lock
1765
			//in the vector, the first one inserted will be removed.
1766
		} catch (Exception e) {
1767
			logMetacat.error("ReplicationService.run - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1768
			logReplication.error("ReplicationService.run - error in file lock thread from "
1769
					+ "MetacatReplication.run: " + e.getMessage());
1770
		}
1771
	}
1772

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

    
1800
			//conn.close();
1801
		} catch (Exception e) {
1802
			logMetacat.error("ReplicationService.getServerNameForServerCode - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1803
			logReplication.error("ReplicationService.getServerNameForServerCode - Error in MetacatReplication.getServer: " + e.getMessage());
1804
		} finally {
1805
			try {
1806
				pstmt.close();
1807
			}//try
1808
			catch (SQLException ee) {
1809
				logMetacat.error("ReplicationService.getServerNameForServerCode - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1810
				logReplication.error("ReplicationService.getServerNameForServerCode - Error in MetacactReplication.getserver: "
1811
						+ ee.getMessage());
1812
			}//catch
1813
			finally {
1814
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1815
			}//fianlly
1816
		}//finally
1817

    
1818
		return null;
1819
		//return null if the server does not exist
1820
	}
1821

    
1822
	/**
1823
	 * Returns a server code given a server name
1824
	 * @param server the name of the server
1825
	 * @return integer > 0 representing the code of the server, 0 if the server
1826
	 *  does not exist.
1827
	 */
1828
	public static int getServerCodeForServerName(String server) throws ServiceException {
1829
		DBConnection dbConn = null;
1830
		int serialNumber = -1;
1831
		PreparedStatement pstmt = null;
1832
		int serverCode = 0;
1833

    
1834
		try {
1835

    
1836
			//conn = util.openDBConnection();
1837
			dbConn = DBConnectionPool.getDBConnection("MetacatReplication.getServerCode");
1838
			serialNumber = dbConn.getCheckOutSerialNumber();
1839
			pstmt = dbConn.prepareStatement("SELECT serverid FROM xml_replication "
1840
					+ "WHERE server LIKE ?");
1841
			pstmt.setString(1, server);
1842
			pstmt.execute();
1843
			ResultSet rs = pstmt.getResultSet();
1844
			boolean tablehasrows = rs.next();
1845
			if (tablehasrows) {
1846
				serverCode = rs.getInt(1);
1847
				pstmt.close();
1848
				//conn.close();
1849
				return serverCode;
1850
			}
1851

    
1852
		} catch (SQLException sqle) {
1853
			throw new ServiceException("ReplicationService.getServerCodeForServerName - " 
1854
					+ "SQL error when getting server code: " + sqle.getMessage());
1855

    
1856
		} finally {
1857
			try {
1858
				pstmt.close();
1859
				//conn.close();
1860
			}//try
1861
			catch (Exception ee) {
1862
				logMetacat.error("ReplicationService.getServerCodeForServerName - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1863
				logReplication.error("ReplicationService.getServerNameForServerCode - Error in MetacatReplicatio.getServerCode: "
1864
						+ ee.getMessage());
1865

    
1866
			}//catch
1867
			finally {
1868
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1869
			}//finally
1870
		}//finally
1871

    
1872
		return serverCode;
1873
	}
1874

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

    
1915
				String server = rs.getString(1);
1916
				String last_checked = rs.getString(2);
1917
				if (!server.equals("localhost")) {
1918
					sl.put(server, last_checked);
1919
				}
1920

    
1921
			} else {
1922
				pstmt.close();
1923
				//ut.returnConnection(conn);
1924
				return null;
1925
			}
1926
			pstmt.close();
1927
		} catch (Exception e) {
1928
			logMetacat.error("ReplicationService.getHomeServerInfoForDocId - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1929
			logReplication.error("ReplicationService.getHomeServerInfoForDocId - error in replicationHandler.getHomeServer(): "
1930
					+ e.getMessage());
1931
		} finally {
1932
			try {
1933
				pstmt.close();
1934
				//ut.returnConnection(conn);
1935
			} catch (Exception ee) {
1936
				logMetacat.error("ReplicationService.getHomeServerInfoForDocId - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1937
				logReplication.error("ReplicationService.getHomeServerInfoForDocId - Eror irn rplicationHandler.getHomeServer() "
1938
						+ "to close pstmt: " + ee.getMessage());
1939
			} finally {
1940
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1941
			}
1942

    
1943
		}//finally
1944
		return sl;
1945
	}
1946

    
1947
	/**
1948
	 * Returns a home server location  given a accnum
1949
	 * @param accNum , given accNum for a document
1950
	 *
1951
	 */
1952
	public static int getHomeServerCodeForDocId(String accNum) throws ServiceException {
1953
		DBConnection dbConn = null;
1954
		int serialNumber = -1;
1955
		PreparedStatement pstmt = null;
1956
		int serverCode = 1;
1957
		String docId = DocumentUtil.getDocIdFromString(accNum);
1958

    
1959
		try {
1960

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

    
1986
		} catch (SQLException sqle) {
1987
			throw new ServiceException("ReplicationService.getHomeServerCodeForDocId - " 
1988
					+ "SQL error when getting home server code for docid: " + docId + " : " 
1989
					+ sqle.getMessage());
1990

    
1991
		} finally {
1992
			try {
1993
				pstmt.close();
1994
				//conn.close();
1995

    
1996
			} catch (SQLException sqle) {
1997
				logMetacat.error("ReplicationService.getHomeServerCodeForDocId - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1998
				logReplication.error("ReplicationService.getHomeServerCodeForDocId - ReplicationService.getHomeServerCodeForDocId - " 
1999
						+ "SQL error when getting home server code for docid: " + docId + " : " 
2000
						+ sqle.getMessage());
2001
			} finally {
2002
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
2003
			}//finally
2004
		}//finally
2005
		//return serverCode;
2006
	}
2007

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

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

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

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

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

    
2195
}
(6-6/7)