Project

General

Profile

1
/**
2
 *  '$RCSfile$'
3
 *    Purpose: A Class that implements replication for metacat
4
 *  Copyright: 2000 Regents of the University of California and the
5
 *             National Center for Ecological Analysis and Synthesis
6
 *    Authors: Chad Berkley
7
 *
8
 *   '$Author: leinfelder $'
9
 *     '$Date: 2011-12-13 16:18:34 -0800 (Tue, 13 Dec 2011) $'
10
 * '$Revision: 6780 $'
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 systemMetadataReplicate = null;
303
		String hub = null;
304
		Writer out = null;
305
		try {
306
			response.setContentType("text/xml");
307
			out = response.getWriter();
308
			
309
			//conn = util.openDBConnection();
310
			dbConn = DBConnectionPool
311
					.getDBConnection("MetacatReplication.handleServerControlRequest");
312
			serialNumber = dbConn.getCheckOutSerialNumber();
313

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

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

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

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

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

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

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

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

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

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

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

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

    
473
	}
474

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

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

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

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

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

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

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

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

    
686
		}//catch
687

    
688
	}
689

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

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

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

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

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

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

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

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

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

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

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

    
825
		        // throw the write exception now -- this happens when access changes on an object
826
				if (writeException != null) {
827
					throw writeException;
828
				}
829

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

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

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

    
857
		try {
858

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

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

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

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

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

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

    
937
		String docInfoStr = getDocumentInfo(docid);
938

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1176
	}
1177

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

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

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

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

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

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

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

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

    
1283
	}
1284

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

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

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

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

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

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

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

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

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

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

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

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

    
1490
			//now we can put the package files into the xml results
1491
			for (int i = 0; i < packageFiles.size(); i++) {
1492
				Vector<String> v = packageFiles.elementAt(i);
1493
				doclist.append("<updatedDocument>");
1494
				doclist.append("<docid>").append(v.elementAt(0));
1495
				doclist.append("</docid><rev>");
1496
				doclist.append(v.elementAt(1));
1497
				doclist.append("</rev>");
1498
				doclist.append("</updatedDocument>");
1499
			}
1500
			// add revision doc list  
1501
			doclist.append(prepareRevisionDoc(dbConn, revisionSql.toString(),
1502
					replicateData));
1503
			
1504
			// add the system metadata entries if configured to replicate them
1505
			boolean replicateSystemMetadata = serverList.getSystemMetadataReplicationValue(server);
1506
			if (replicateSystemMetadata) {
1507
				Date since = new Date(System.currentTimeMillis());
1508
				since = serverList.getLastCheckedDate(server);
1509
				List<String> systemMetadataEntries = 
1510
					IdentifierManager.getInstance().getUpdatedSystemMetadataIds(since);
1511
				for (int i = 0; i < systemMetadataEntries.size(); i++) {
1512
					String guid = systemMetadataEntries.get(i);
1513
					doclist.append("<updatedSystemMetadata>");
1514
					doclist.append("<guid>");
1515
					doclist.append(guid);
1516
					doclist.append("</guid>");
1517
					doclist.append("</updatedSystemMetadata>");
1518
				}
1519
			}
1520

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

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

    
1556
	}//handlUpdateRequest
1557

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

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

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

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

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

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

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

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

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

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

    
1731
		return null;
1732
	}
1733

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

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

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

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

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

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

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

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

    
1843
		try {
1844

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

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

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

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

    
1881
		return serverCode;
1882
	}
1883

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

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

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

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

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

    
1968
		try {
1969

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

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

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

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

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

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

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

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

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

    
2204
}
(7-7/8)