Project

General

Profile

1
/**
2
 *  '$RCSfile$'
3
 *    Purpose: A Class that implements replication for metacat
4
 *  Copyright: 2000 Regents of the University of California and the
5
 *             National Center for Ecological Analysis and Synthesis
6
 *    Authors: Chad Berkley
7
 *
8
 *   '$Author: leinfelder $'
9
 *     '$Date: 2011-11-29 13:05:52 -0800 (Tue, 29 Nov 2011) $'
10
 * '$Revision: 6708 $'
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 wite 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
		        Vector<XMLAccessDAO> accessControlList = dih.getAccessControlList();
796
		        if (accessControlList != null) {
797
		        	AccessControlForSingleFile acfsf = new AccessControlForSingleFile(docid);
798
		        	for (XMLAccessDAO xmlAccessDAO : accessControlList) {
799
		        		if (!acfsf.accessControlExists(xmlAccessDAO)) {
800
		        			acfsf.insertPermissions(xmlAccessDAO);
801
							logReplication.info("ReplicationService.handleForceReplicateRequest - document " + docid
802
									+ " permissions added to DB");
803
		        		}
804
		            }
805
		        }
806
		        
807
		        // process system metadata
808
		        if (systemMetadataXML != null) {
809
		      	  SystemMetadata sysMeta = 
810
		      		TypeMarshaller.unmarshalTypeFromStream(
811
		      				  SystemMetadata.class, 
812
		      				  new ByteArrayInputStream(systemMetadataXML.getBytes("UTF-8")));
813
		      	  // need the guid-to-docid mapping
814
		      	  IdentifierManager.getInstance().createMapping(sysMeta.getIdentifier().getValue(), docid);
815
		      	  // save the system metadata
816
		      	  HazelcastService.getInstance().getSystemMetadataMap().put(sysMeta.getIdentifier(), sysMeta);
817
		        }
818

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

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

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

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

    
850
		try {
851

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

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

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

    
904
		try {
905
			// get docinfo as XML string
906
			String docinfoXML = getDocumentInfo(docid);
907
			
908
			// get a writer for sending back to response
909
			response.setContentType("text/xml");
910
			Writer out = response.getWriter();
911
			out.write(docinfoXML);
912
			out.close();
913

    
914
		} catch (Exception e) {
915
			logMetacat.error("ReplicationService.handleGetDocumentInfoRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
916
			logReplication.error("ReplicationService.handleGetDocumentInfoRequest - error in metacatReplication.handlegetdocumentinforequest "
917
					+ "for doc: " + docid + " : " + e.getMessage());
918
		}
919

    
920
	}
921
	
922
	public static Hashtable<String, String> getDocumentInfoMap(String docid)
923
			throws HandlerException, AccessControlException, JiBXException,
924
			IOException, McdbException, SAXException {
925
		
926
		// Try get docid info from remote server
927
		DocInfoHandler dih = new DocInfoHandler();
928
		XMLReader docinfoParser = ReplicationHandler.initParser(dih);
929

    
930
		String docInfoStr = getDocumentInfo(docid);
931

    
932
		// strip out the system metadata portion
933
		String systemMetadataXML = ReplicationUtil.getSystemMetadataContent(docInfoStr);
934
		docInfoStr = ReplicationUtil.getContentWithoutSystemMetadata(docInfoStr);
935

    
936
		docinfoParser.parse(new InputSource(new StringReader(docInfoStr)));
937
		Hashtable<String, String> docinfoHash = dih.getDocInfo();
938

    
939
		return docinfoHash;
940
	}
941
	
942
	/**
943
	 * Gets a docInfo XML snippet for the replication API
944
	 * @param docid
945
	 * @return
946
	 * @throws AccessControlException
947
	 * @throws JiBXException
948
	 * @throws IOException
949
	 * @throws McdbException
950
	 */
951
	public static String getDocumentInfo(String docid) throws AccessControlException, JiBXException, IOException, McdbException {
952
		StringBuffer sb = new StringBuffer();
953

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

    
996
		sb.append("<accessControl>");
997

    
998
		AccessControlForSingleFile acfsf = new AccessControlForSingleFile(docid); 
999
		sb.append(acfsf.getAccessString());
1000
		
1001
		sb.append("</accessControl>");
1002

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

    
1029
		} catch (Exception e) {
1030
			String msg = "ReplicationService.handleGetSystemMetadataRequest for guid: " + guid + " : " + e.getMessage();
1031
			logMetacat.error(msg);                         
1032
			logReplication.error(msg);
1033
		}
1034

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

    
1069
		} catch (Exception e) {
1070
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG, e);                         
1071
			logReplication.error("ReplicationService.handleForceReplicateRequest - General error when processing guid: " + guid, e);
1072
		}
1073
	}
1074

    
1075
	/**
1076
	 * Sends a datafile to a remote host
1077
	 */
1078
	protected static void handleGetDataFileRequest(OutputStream outPut,
1079
			Hashtable<String, String[]> params, HttpServletResponse response)
1080

    
1081
	{
1082
		// File path for data file
1083
		String filepath;
1084
		// Request docid
1085
		String docId = ((String[]) (params.get("docid")))[0];
1086
		//check if the doicd is null
1087
		if (docId == null) {
1088
			logMetacat.error("ReplicationService.handleGetDataFileRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1089
			logReplication.error("ReplicationService.handleGetDataFileRequest - Didn't specify docid for replication");
1090
			return;
1091
		}
1092

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

    
1114
		if (!filepath.endsWith("/")) {
1115
			filepath += "/";
1116
		}
1117
		// Get file aboslute file name
1118
		String filename = filepath + docId;
1119

    
1120
		//MIME type
1121
		String contentType = null;
1122
		if (filename.endsWith(".xml")) {
1123
			contentType = "text/xml";
1124
		} else if (filename.endsWith(".css")) {
1125
			contentType = "text/css";
1126
		} else if (filename.endsWith(".dtd")) {
1127
			contentType = "text/plain";
1128
		} else if (filename.endsWith(".xsd")) {
1129
			contentType = "text/xml";
1130
		} else if (filename.endsWith("/")) {
1131
			contentType = "text/html";
1132
		} else {
1133
			File f = new File(filename);
1134
			if (f.isDirectory()) {
1135
				contentType = "text/html";
1136
			} else {
1137
				contentType = "application/octet-stream";
1138
			}
1139
		}
1140

    
1141
		// Set the mime type
1142
		response.setContentType(contentType);
1143

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

    
1161
		}//try
1162
		catch (Exception e) {
1163
			logMetacat.error("ReplicationService.handleGetDataFileRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1164
			logReplication.error("ReplicationService.handleGetDataFileRequest - error getting data file from MetacatReplication."
1165
					+ "handlGetDataFileRequest " + e.getMessage());
1166
			e.printStackTrace(System.out);
1167
		}//catch
1168

    
1169
	}
1170

    
1171
	/**
1172
	 * Sends a document to a remote host
1173
	 */
1174
	protected static void handleGetDocumentRequest(
1175
			Hashtable<String, String[]> params, HttpServletResponse response) {
1176

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

    
1198
			String docid = params.get("docid")[0];
1199
			logReplication.debug("ReplicationService.handleGetDocumentRequest - MetacatReplication.handleGetDocumentRequest for docid: "
1200
					+ docid);
1201
			DocumentImpl di = new DocumentImpl(docid);
1202

    
1203
			String documentDir = PropertyService
1204
					.getProperty("application.documentfilepath");
1205
			documentPath = documentDir + FileUtil.getFS() + docid;
1206

    
1207
			// if the document does not exist on disk, read it from db and write
1208
			// it to disk.
1209
			if (FileUtil.getFileStatus(documentPath) == FileUtil.DOES_NOT_EXIST
1210
					|| FileUtil.getFileSize(documentPath) == 0) {
1211
				FileOutputStream fos = new FileOutputStream(documentPath);
1212
				di.toXml(fos, null, null, true);
1213
			}
1214

    
1215
			// read the file from disk and send it to outputstream
1216
			OutputStream outputStream = response.getOutputStream();
1217
			di.readFromFileSystem(outputStream, null, null, documentPath);
1218

    
1219
			logReplication.info("ReplicationService.handleGetDocumentRequest - document " + docid + " sent");
1220

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

    
1276
	}
1277

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

    
1302
		try {
1303
			// get writer, TODO: encoding?
1304
			response.setContentType("text/xml");
1305
			out = response.getWriter();
1306
			
1307
			// Check out a DBConnection from pool
1308
			dbConn = DBConnectionPool
1309
					.getDBConnection("MetacatReplication.handleUpdateRequest");
1310
			serialNumber = dbConn.getCheckOutSerialNumber();
1311
			// Create a server list from xml_replication table
1312
			serverList = new ReplicationServerList();
1313

    
1314
			// Get remote server name from param
1315
			String server = ((String[]) params.get("server"))[0];
1316
			// If no servr name in param, return a error
1317
			if (server == null || server.equals("")) {
1318
				out.write("<error>Request didn't specify server name</error>");
1319
				out.close();
1320
				return;
1321
			}//if
1322

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

    
1340
			// Check if local host configure to replicate xml documents to remote
1341
			// server. If not send back a error message
1342
			if (!serverList.getReplicationValue(server)) {
1343
				out.write("<error>Configuration not allow to replicate document to you</error>");
1344
				out.close();
1345
				return;
1346
			}//if
1347

    
1348
			// Store the sql command
1349
			StringBuffer docsql = new StringBuffer();
1350
			StringBuffer revisionSql = new StringBuffer();
1351
			// Stroe the docid list
1352
			StringBuffer doclist = new StringBuffer();
1353
			// Store the deleted docid list
1354
			StringBuffer delsql = new StringBuffer();
1355
			// Store the data set file
1356
			Vector<Vector<String>> packageFiles = new Vector<Vector<String>>();
1357

    
1358
			// Append local server's name and replication servlet to doclist
1359
			doclist.append("<?xml version=\"1.0\"?><replication>");
1360
			doclist.append("<server>")
1361
					.append(MetacatUtil.getLocalReplicationServerName());
1362
			//doclist.append(util.getProperty("replicationpath"));
1363
			doclist.append("</server><updates>");
1364

    
1365
			// Get correct docid that reside on this server according the requesting
1366
			// server's replicate and data replicate value in xml_replication table
1367
			docsql.append(DatabaseService.getInstance().getDBAdapter().getReplicationDocumentListSQL());
1368
			//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)) ");
1369
			revisionSql.append("select docid, rev, doctype from xml_revisions ");
1370
			// If the localhost is not a hub to the remote server, only replicate
1371
			// the docid' which home server is local host (server_location =1)
1372
			if (!serverList.getHubValue(server)) {
1373
				String serverLocationDoc = " and a.server_location = 1";
1374
				String serverLocationRev = "where server_location = 1";
1375
				docsql.append(serverLocationDoc);
1376
				revisionSql.append(serverLocationRev);
1377
			}
1378
			logReplication.info("ReplicationService.handleUpdateRequest - Doc sql: " + docsql.toString());
1379

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

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

    
1469
			pstmt = dbConn.prepareStatement(delsql.toString());
1470
			//usage count should increas 1
1471
			dbConn.increaseUsageCount(1);
1472

    
1473
			pstmt.execute();
1474
			rs = pstmt.getResultSet();
1475
			tablehasrows = rs.next();
1476
			while (tablehasrows) { //handle the deleted documents
1477
				doclist.append("<deletedDocument><docid>").append(rs.getString(1));
1478
				doclist.append("</docid><rev></rev></deletedDocument>");
1479
				//note that rev is always empty for deleted docs
1480
				tablehasrows = rs.next();
1481
			}
1482

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

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

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

    
1549
	}//handlUpdateRequest
1550

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

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

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

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

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

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

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

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

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

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

    
1724
		return null;
1725
	}
1726

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

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

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

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

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

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

    
1820
		return null;
1821
		//return null if the server does not exist
1822
	}
1823

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

    
1836
		try {
1837

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

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

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

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

    
1874
		return serverCode;
1875
	}
1876

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

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

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

    
1945
		}//finally
1946
		return sl;
1947
	}
1948

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

    
1961
		try {
1962

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

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

    
1993
		} finally {
1994
			try {
1995
				pstmt.close();
1996
				//conn.close();
1997

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

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

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

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

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

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

    
2197
}
(7-7/8)