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-07 10:55:28 -0800 (Mon, 07 Nov 2011) $'
10
 * '$Revision: 6611 $'
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.BufferedInputStream;
30
import java.io.BufferedOutputStream;
31
import java.io.ByteArrayInputStream;
32
import java.io.ByteArrayOutputStream;
33
import java.io.File;
34
import java.io.FileInputStream;
35
import java.io.FileNotFoundException;
36
import java.io.FileOutputStream;
37
import java.io.IOException;
38
import java.io.InputStream;
39
import java.io.InputStreamReader;
40
import java.io.OutputStream;
41
import java.io.StringReader;
42
import java.io.Writer;
43
import java.net.MalformedURLException;
44
import java.net.URL;
45
import java.security.PrivateKey;
46
import java.security.cert.X509Certificate;
47
import java.sql.PreparedStatement;
48
import java.sql.ResultSet;
49
import java.sql.SQLException;
50
import java.sql.Timestamp;
51
import java.text.SimpleDateFormat;
52
import java.util.Calendar;
53
import java.util.Date;
54
import java.util.Hashtable;
55
import java.util.List;
56
import java.util.Timer;
57
import java.util.Vector;
58

    
59
import javax.servlet.http.HttpServletRequest;
60
import javax.servlet.http.HttpServletResponse;
61
import javax.xml.bind.DatatypeConverter;
62

    
63
import org.apache.http.HttpResponse;
64
import org.apache.http.conn.scheme.Scheme;
65
import org.apache.http.conn.ssl.SSLSocketFactory;
66
import org.apache.log4j.Logger;
67
import org.dataone.client.RestClient;
68
import org.dataone.client.auth.CertificateManager;
69
import org.dataone.service.types.v1.Session;
70
import org.dataone.service.types.v1.SystemMetadata;
71
import org.dataone.service.util.TypeMarshaller;
72
import org.xml.sax.InputSource;
73
import org.xml.sax.SAXException;
74
import org.xml.sax.XMLReader;
75

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

    
104
public class ReplicationService extends BaseService {
105

    
106
	private static ReplicationService replicationService = null;
107

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

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

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

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

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

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

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

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

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

    
194
	public boolean refreshable() {
195
		return true;
196
	}
197

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

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

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

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

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

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

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

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

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

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

    
377
					tablehasrows = rs.next();
378
				}
379
				out.write("</table></body></html>");
380

    
381
				// download certificate with the public key on this server
382
				// and import it as a trusted certificate
383
				String certURL = ((String[]) params.get("certificate"))[0];
384
				if (certURL != null && !certURL.equals("")) {
385
					downloadCertificate(certURL);
386
				}
387

    
388
				// delete server from server list
389
			} else if (subaction.equals("delete")) {
390
				server = ((String[]) params.get("server"))[0];
391
				pstmt = dbConn.prepareStatement("DELETE FROM xml_replication "
392
						+ "WHERE server LIKE ?");
393
				pstmt.setString(1, server);
394
				pstmt.execute();
395
				pstmt.close();
396
				dbConn.commit();
397
				out.write("Server " + server + " deleted");
398
				response.setContentType("text/html");
399
				out.write("<html><body><table border=\"1\">");
400
				out.write("<tr><td><b>server</b></td>");
401
				out.write("<td><b>last_checked</b></td>");
402
				out.write("<td><b>replicate</b></td>");
403
				out.write("<td><b>datareplicate</b></td>");
404
				out.write("<td><b>systemmetadatareplicate</b></td>");
405
				out.write("<td><b>hub</b></td></tr>");
406

    
407
				pstmt = dbConn.prepareStatement("SELECT serverid, server, last_checked, replicate, datareplicate, systemmetadatareplicate, hub FROM xml_replication");
408
				//increase dbconnection usage
409
				dbConn.increaseUsageCount(1);
410
				pstmt.execute();
411
				ResultSet rs = pstmt.getResultSet();
412
				boolean tablehasrows = rs.next();
413
				while (tablehasrows) {
414
					out.write("<tr><td>" + rs.getString(2) + "</td><td>");
415
					out.write(rs.getString(3) + "</td><td>");
416
					out.write(rs.getString(4) + "</td><td>");
417
					out.write(rs.getString(5) + "</td><td>");
418
					out.write(rs.getString(6) + "</td><td>");
419
					out.write(rs.getString(7) + "</td></tr>");
420
					tablehasrows = rs.next();
421
				}
422
				out.write("</table></body></html>");
423

    
424
				// list servers in server list
425
			} else if (subaction.equals("list")) {
426
				response.setContentType("text/html");
427
				out.write("<html><body><table border=\"1\">");
428
				out.write("<tr><td><b>server</b></td>");
429
				out.write("<td><b>last_checked</b></td>");
430
				out.write("<td><b>replicate</b></td>");
431
				out.write("<td><b>datareplicate</b></td>");
432
				out.write("<td><b>systemmetadatareplicate</b></td>");
433
				out.write("<td><b>hub</b></td></tr>");
434
				pstmt = dbConn.prepareStatement("SELECT serverid, server, last_checked, replicate, datareplicate, systemmetadatareplicate, hub FROM xml_replication");
435
				pstmt.execute();
436
				ResultSet rs = pstmt.getResultSet();
437
				boolean tablehasrows = rs.next();
438
				while (tablehasrows) {
439
					out.write("<tr><td>" + rs.getString(2) + "</td><td>");
440
					out.write(rs.getString(3) + "</td><td>");
441
					out.write(rs.getString(4) + "</td><td>");
442
					out.write(rs.getString(5) + "</td><td>");
443
					out.write(rs.getString(6) + "</td><td>");
444
					out.write(rs.getString(7) + "</td></tr>");
445

    
446
					tablehasrows = rs.next();
447
				}
448
				out.write("</table></body></html>");
449
			} else {
450

    
451
				out.write("<error>Unkonwn subaction</error>");
452

    
453
			}
454
			pstmt.close();
455
			//conn.close();
456

    
457
		} catch (Exception e) {
458
			logMetacat.error("ReplicationService.handleServerControlRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
459
			logReplication.error("ReplicationService.handleServerControlRequest - Error in "
460
					+ "MetacatReplication.handleServerControlRequest " + e.getMessage());
461
			e.printStackTrace(System.out);
462
		} finally {
463
			try {
464
				pstmt.close();
465
			}//try
466
			catch (SQLException ee) {
467
				logMetacat.error("ReplicationService.handleServerControlRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
468
				logReplication.error("ReplicationService.handleServerControlRequest - Error in MetacatReplication.handleServerControlRequest to close pstmt "
469
						+ ee.getMessage());
470
			}//catch
471
			finally {
472
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
473
			}//finally
474
			if (out != null) {
475
				try {
476
					out.close();
477
				} catch (IOException e) {
478
					logMetacat.error(e.getMessage(), e);
479
				}
480
			}
481
		}//finally
482

    
483
	}
484

    
485
	// download certificate with the public key from certURL and
486
	// upload it onto this server; it then must be imported as a
487
	// trusted certificate
488
	private static void downloadCertificate(String certURL) throws FileNotFoundException,
489
			IOException, MalformedURLException, PropertyNotFoundException {
490

    
491
		// the path to be uploaded to
492
		String certPath = SystemUtil.getContextDir();
493

    
494
		// get filename from the URL of the certificate
495
		String filename = certURL;
496
		int slash = Math.max(filename.lastIndexOf('/'), filename.lastIndexOf('\\'));
497
		if (slash > -1) {
498
			filename = filename.substring(slash + 1);
499
		}
500

    
501
		// open file output strem to write the input into it
502
		File f = new File(certPath, filename);
503
		synchronized (f) {
504
			try {
505
				if (f.exists()) {
506
					throw new IOException("File already exist: " + f.getCanonicalFile());
507
					// if ( f.exists() && !f.canWrite() ) {
508
					// throw new IOException("Not writable: " +
509
					// f.getCanonicalFile());
510
				}
511
			} catch (SecurityException se) {
512
				// if a security manager exists,
513
				// its checkRead method is called for f.exist()
514
				// or checkWrite method is called for f.canWrite()
515
				throw se;
516
			}
517

    
518
			// create a buffered byte output stream
519
			// that uses a default-sized output buffer
520
			FileOutputStream fos = new FileOutputStream(f);
521
			BufferedOutputStream out = new BufferedOutputStream(fos);
522

    
523
			// this should be http url
524
			URL url = new URL(certURL);
525
			BufferedInputStream bis = null;
526
			try {
527
				bis = new BufferedInputStream(url.openStream());
528
				byte[] buf = new byte[4 * 1024]; // 4K buffer
529
				int b = bis.read(buf);
530
				while (b != -1) {
531
					out.write(buf, 0, b);
532
					b = bis.read(buf);
533
				}
534
			} finally {
535
				if (bis != null)
536
					bis.close();
537
			}
538
			// the input and the output streams must be closed
539
			bis.close();
540
			out.flush();
541
			out.close();
542
			fos.close();
543
		} // end of synchronized(f)
544
	}
545

    
546
	/**
547
	 * when a forcereplication request comes in, local host sends a read request
548
	 * to the requesting server (remote server) for the specified docid. Then
549
	 * store it in local database.
550
	 */
551
	protected static void handleForceReplicateRequest(
552
			Hashtable<String, String[]> params, HttpServletResponse response,
553
			HttpServletRequest request) {
554
		String server = ((String[]) params.get("server"))[0]; // the server that
555
		String docid = ((String[]) params.get("docid"))[0]; // sent the document
556
		String dbaction = "UPDATE"; // the default action is UPDATE
557
		//    boolean override = false;
558
		//    int serverCode = 1;
559
		DBConnection dbConn = null;
560
		int serialNumber = -1;
561
		String docName = null;
562

    
563
		try {
564
			//if the url contains a dbaction then the default action is overridden
565
			if (params.containsKey("dbaction")) {
566
				dbaction = ((String[]) params.get("dbaction"))[0];
567
				//serverCode = MetacatReplication.getServerCode(server);
568
				//override = true; //we are now overriding the default action
569
			}
570
			logReplication.info("ReplicationService.handleForceReplicateRequest - Force replication request from: " + server);
571
			logReplication.info("ReplicationService.handleForceReplicateRequest - Force replication docid: " + docid);
572
			logReplication.info("ReplicationService.handleForceReplicateRequest - Force replication action: " + dbaction);
573
			// sending back read request to remote server
574
			URL u = new URL("https://" + server + "?server="
575
					+ MetacatUtil.getLocalReplicationServerName() + "&action=read&docid="
576
					+ docid);
577
			String xmldoc = ReplicationService.getURLContent(u);
578

    
579
			// get the document info from server
580
			URL docinfourl = new URL("https://" + server + "?server="
581
					+ MetacatUtil.getLocalReplicationServerName()
582
					+ "&action=getdocumentinfo&docid=" + docid);
583
			
584

    
585
			String docInfoStr = ReplicationService.getURLContent(docinfourl);
586
			// strip out the system metadata portion
587
			String systemMetadataXML = ReplicationUtil.getSystemMetadataContent(docInfoStr);
588
			docInfoStr = ReplicationUtil.getContentWithoutSystemMetadata(docInfoStr);
589
		   	  
590
			//dih is the parser for the docinfo xml format
591
			DocInfoHandler dih = new DocInfoHandler();
592
			XMLReader docinfoParser = ReplicationHandler.initParser(dih);
593
			docinfoParser.parse(new InputSource(new StringReader(docInfoStr)));
594
			//      Hashtable<String,Vector<AccessControlForSingleFile>> docinfoHash = dih.getDocInfo();
595
			Hashtable<String, String> docinfoHash = dih.getDocInfo();
596
			
597
			// Get home server of this docid
598
			String homeServer = (String) docinfoHash.get("home_server");
599
			
600
			// process system metadata
601
			if (systemMetadataXML != null) {
602
				SystemMetadata sysMeta = 
603
					TypeMarshaller.unmarshalTypeFromStream(
604
							SystemMetadata.class,
605
							new ByteArrayInputStream(systemMetadataXML.getBytes("UTF-8")));
606
				// need the guid-to-docid mapping
607
				IdentifierManager.getInstance().createMapping(sysMeta.getIdentifier().getValue(), docid);
608
			}
609
      
610
			// dates
611
			String createdDateString = docinfoHash.get("date_created");
612
			String updatedDateString = docinfoHash.get("date_updated");
613
			Date createdDate = DatatypeConverter.parseDateTime(createdDateString).getTime();
614
			Date updatedDate = DatatypeConverter.parseDateTime(updatedDateString).getTime();
615
		      
616
			logReplication.info("ReplicationService.handleForceReplicateRequest - homeServer: " + homeServer);
617
			// Get Document type
618
			String docType = (String) docinfoHash.get("doctype");
619
			logReplication.info("ReplicationService.handleForceReplicateRequest - docType: " + docType);
620
			String parserBase = null;
621
			// this for eml2 and we need user eml2 parser
622
			if (docType != null
623
					&& (docType.trim()).equals(DocumentImpl.EML2_0_0NAMESPACE)) {
624
				logReplication.warn("ReplicationService.handleForceReplicateRequest - This is an eml200 document!");
625
				parserBase = DocumentImpl.EML200;
626
			} else if (docType != null
627
					&& (docType.trim()).equals(DocumentImpl.EML2_0_1NAMESPACE)) {
628
				logReplication.warn("ReplicationService.handleForceReplicateRequest - This is an eml2.0.1 document!");
629
				parserBase = DocumentImpl.EML200;
630
			} else if (docType != null
631
					&& (docType.trim()).equals(DocumentImpl.EML2_1_0NAMESPACE)) {
632
				logReplication.warn("ReplicationService.handleForceReplicateRequest - This is an eml2.1.0 document!");
633
				parserBase = DocumentImpl.EML210;
634
			} else if (docType != null
635
					&& (docType.trim()).equals(DocumentImpl.EML2_1_1NAMESPACE)) {
636
				logReplication.warn("ReplicationService.handleForceReplicateRequest - This is an eml2.1.1 document!");
637
				parserBase = DocumentImpl.EML210;
638
			}
639
			logReplication.warn("ReplicationService.handleForceReplicateRequest - The parserBase is: " + parserBase);
640

    
641
			// Get DBConnection from pool
642
			dbConn = DBConnectionPool
643
					.getDBConnection("MetacatReplication.handleForceReplicateRequest");
644
			serialNumber = dbConn.getCheckOutSerialNumber();
645
			// write the document to local database
646
			DocumentImplWrapper wrapper = new DocumentImplWrapper(parserBase, false);
647
			//try this independently so we can set access even if the update action is invalid (i.e docid has not changed)
648
			try {
649
				wrapper.writeReplication(dbConn, xmldoc, null, null,
650
						dbaction, docid, null, null, homeServer, server, createdDate,
651
						updatedDate);
652
			} finally {
653

    
654
				//process extra access rules before dealing with the write exception (doc exist already)			
655
		        Vector<XMLAccessDAO> accessControlList = dih.getAccessControlList();
656
		        if (accessControlList != null) {
657
		        	AccessControlForSingleFile acfsf = new AccessControlForSingleFile(docid);
658
		        	for (XMLAccessDAO xmlAccessDAO : accessControlList) {
659
		        		if (!acfsf.accessControlExists(xmlAccessDAO)) {
660
		        			acfsf.insertPermissions(xmlAccessDAO);
661
							logReplication.info("ReplicationService.handleForceReplicateRequest - document " + docid
662
									+ " permissions added to DB");
663
		        		}
664
		            }
665
		        }
666
		        
667
		        // process the real owner and updater
668
				String user = (String) docinfoHash.get("user_owner");
669
				String updated = (String) docinfoHash.get("user_updated");
670
		        updateUserOwner(dbConn, docid, user, updated);
671

    
672
				logReplication.info("ReplicationService.handleForceReplicateRequest - document " + docid + " added to DB with "
673
						+ "action " + dbaction);
674
				
675
				EventLog.getInstance().log(request.getRemoteAddr(), request.getHeader("User-Agent"), REPLICATIONUSER, docid, dbaction);
676
			}
677
		} catch (SQLException sqle) {
678
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
679
			logReplication.error("ReplicationService.handleForceReplicateRequest - SQL error when adding doc " + docid + 
680
					" to DB with action " + dbaction + ": " + sqle.getMessage());
681
		} catch (MalformedURLException mue) {
682
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
683
			logReplication.error("ReplicationService.handleForceReplicateRequest - URL error when adding doc " + docid + 
684
					" to DB with action " + dbaction + ": " + mue.getMessage());
685
		} catch (SAXException se) {
686
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
687
			logReplication.error("ReplicationService.handleForceReplicateRequest - SAX parsing error when adding doc " + docid + 
688
					" to DB with action " + dbaction + ": " + se.getMessage());
689
		} catch (HandlerException he) {
690
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
691
			logReplication.error("ReplicationService.handleForceReplicateRequest - Handler error when adding doc " + docid + 
692
					" to DB with action " + dbaction + ": " + he.getMessage());
693
		} catch (IOException ioe) {
694
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
695
			logReplication.error("ReplicationService.handleForceReplicateRequest - I/O error when adding doc " + docid + 
696
					" to DB with action " + dbaction + ": " + ioe.getMessage());
697
		} catch (PermOrderException poe) {
698
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
699
			logReplication.error("ReplicationService.handleForceReplicateRequest - Permissions order error when adding doc " + docid + 
700
					" to DB with action " + dbaction + ": " + poe.getMessage());
701
		} catch (AccessControlException ace) {
702
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
703
			logReplication.error("ReplicationService.handleForceReplicateRequest - Permissions order error when adding doc " + docid + 
704
					" to DB with action " + dbaction + ": " + ace.getMessage());
705
		} catch (Exception e) {
706
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
707
			logReplication.error("ReplicationService.handleForceReplicateRequest - General error when adding doc " + docid + 
708
					" to DB with action " + dbaction + ": " + e.getMessage());
709
		} finally {
710
			// Return the checked out DBConnection
711
			DBConnectionPool.returnDBConnection(dbConn, serialNumber);
712
		}//finally
713
	}
714

    
715
	/*
716
	 * when a forcereplication delete request comes in, local host will delete this
717
	 * document
718
	 */
719
	protected static void handleForceReplicateDeleteRequest(
720
			Hashtable<String, String[]> params, HttpServletResponse response,
721
			HttpServletRequest request) {
722
		String server = ((String[]) params.get("server"))[0]; // the server that
723
		String docid = ((String[]) params.get("docid"))[0]; // sent the document
724
		try {
725
			logReplication.info("ReplicationService.handleForceReplicateDeleteRequest - force replication delete request from " + server);
726
			logReplication.info("ReplicationService.handleForceReplicateDeleteRequest - force replication delete docid " + docid);
727
			logReplication.info("ReplicationService.handleForceReplicateDeleteRequest - Force replication delete request from: " + server);
728
			logReplication.info("ReplicationService.handleForceReplicateDeleteRequest - Force replication delete docid: " + docid);
729
			DocumentImpl.delete(docid, null, null, server);
730
			logReplication.info("ReplicationService.handleForceReplicateDeleteRequest - document " + docid + " was successfully deleted ");
731
			EventLog.getInstance().log(request.getRemoteAddr(), request.getHeader("User-Agent"), REPLICATIONUSER, docid,
732
					"delete");
733
			logReplication.info("ReplicationService.handleForceReplicateDeleteRequest - document " + docid + " was successfully deleted ");
734
		} catch (McdbDocNotFoundException e) {
735
			logMetacat.error("ReplicationService.handleForceReplicateDeleteRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
736
			logReplication.error("document " + docid
737
					+ " failed to delete because " + e.getMessage());
738
			logReplication.error("ReplicationService.handleForceReplicateDeleteRequest - error: " + e.getMessage());
739
		} catch (InsufficientKarmaException e) {
740
			logMetacat.error("ReplicationService.handleForceReplicateDeleteRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
741
			logReplication.error("document " + docid
742
					+ " failed to delete because " + e.getMessage());
743
			logReplication.error("ReplicationService.handleForceReplicateDeleteRequest - error: " + e.getMessage());
744
		} catch (SQLException e) {
745
			logMetacat.error("ReplicationService.handleForceReplicateDeleteRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
746
			logReplication.error("document " + docid
747
					+ " failed to delete because " + e.getMessage());
748
			logReplication.error("ReplicationService.handleForceReplicateDeleteRequest - error: " + e.getMessage());
749
		} catch (Exception e) {
750
			logMetacat.error("ReplicationService.handleForceReplicateDeleteRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
751
			logReplication.error("document " + docid
752
					+ " failed to delete because " + e.getMessage());
753
			logReplication.error("ReplicationService.handleForceReplicateDeleteRequest - error: " + e.getMessage());
754

    
755
		}//catch
756

    
757
	}
758

    
759
	/**
760
	 * when a forcereplication data file request comes in, local host sends a
761
	 * readdata request to the requesting server (remote server) for the specified
762
	 * docid. Then store it in local database and file system
763
	 */
764
	protected static void handleForceReplicateDataFileRequest(Hashtable<String, String[]> params,
765
			HttpServletRequest request) {
766

    
767
		//make sure there is some parameters
768
		if (params.isEmpty()) {
769
			return;
770
		}
771
		// Get remote server
772
		String server = ((String[]) params.get("server"))[0];
773
		// the docid should include rev number
774
		String docid = ((String[]) params.get("docid"))[0];
775
		// Make sure there is a docid and server
776
		if (docid == null || server == null || server.equals("")) {
777
			logMetacat.error("ReplicationService.handleForceReplicateDataFileRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
778
			logReplication.error("ReplicationService.handleForceReplicateDataFileRequest - Didn't specify docid or server for replication");
779
			return;
780
		}
781

    
782
		// Overide or not
783
		//    boolean override = false;
784
		// dbaction - update or insert
785
		String dbaction = null;
786

    
787
		try {
788
			//docid was switch to two parts uinque code and rev
789
			//String uniqueCode=MetacatUtil.getDocIdFromString(docid);
790
			//int rev=MetacatUtil.getVersionFromString(docid);
791
			if (params.containsKey("dbaction")) {
792
				dbaction = ((String[]) params.get("dbaction"))[0];
793
			} else//default value is update
794
			{
795
				dbaction = "update";
796
			}
797

    
798
			logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - Force replication request from: " + server);
799
			logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - Force replication docid: " + docid);
800
			logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - Force replication action: " + dbaction);
801
			// get the document info from server
802
			URL docinfourl = new URL("https://" + server + "?server="
803
					+ MetacatUtil.getLocalReplicationServerName()
804
					+ "&action=getdocumentinfo&docid=" + docid);
805

    
806
			String docInfoStr = ReplicationService.getURLContent(docinfourl);
807
			
808
			// strip out the system metadata portion
809
		    String systemMetadataXML = ReplicationUtil.getSystemMetadataContent(docInfoStr);
810
		   	docInfoStr = ReplicationUtil.getContentWithoutSystemMetadata(docInfoStr);
811

    
812
			//dih is the parser for the docinfo xml format
813
			DocInfoHandler dih = new DocInfoHandler();
814
			XMLReader docinfoParser = ReplicationHandler.initParser(dih);
815
			docinfoParser.parse(new InputSource(new StringReader(docInfoStr)));
816
			Hashtable<String, String> docinfoHash = dih.getDocInfo();
817
			
818
			String docName = (String) docinfoHash.get("docname");
819

    
820
			String docType = (String) docinfoHash.get("doctype");
821

    
822
			String docHomeServer = (String) docinfoHash.get("home_server");
823
			
824
			String createdDateString = docinfoHash.get("date_created");
825
			String updatedDateString = docinfoHash.get("date_updated");
826
			
827
			Date createdDate = DatatypeConverter.parseDateTime(createdDateString).getTime();
828
			Date updatedDate = DatatypeConverter.parseDateTime(updatedDateString).getTime();
829
			
830
			logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - docHomeServer of datafile: " + docHomeServer);
831

    
832
			if (dbaction.equals("insert") || dbaction.equals("update")) {
833
				//Get data file and store it into local file system.
834
				// sending back readdata request to server
835
				URL url = new URL("https://" + server + "?server="
836
						+ MetacatUtil.getLocalReplicationServerName()
837
						+ "&action=readdata&docid=" + docid);
838
				String datafilePath = PropertyService
839
						.getProperty("application.datafilepath");
840

    
841
				InputStream inputStream = getURLStream(url);
842
				
843
				Exception writeException = null;
844
				//register data file into xml_documents table and wite data file
845
				//into file system
846
				try {
847
					DocumentImpl.writeDataFileInReplication(inputStream,
848
							datafilePath, docName, docType, docid, null, docHomeServer,
849
							server, DocumentImpl.DOCUMENTTABLE, false, createdDate,
850
							updatedDate);
851
				} catch (Exception e) {
852
					writeException = e;
853
				}
854
				
855
				// process the real owner and updater
856
				DBConnection dbConn = DBConnectionPool.getDBConnection("ReplicationService.handleForceDataFileRequest");
857
		        int serialNumber = dbConn.getCheckOutSerialNumber();
858
		        dbConn.setAutoCommit(false);
859
				String user = (String) docinfoHash.get("user_owner");
860
				String updated = (String) docinfoHash.get("user_updated");
861
		        updateUserOwner(dbConn, docid, user, updated);
862
		        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
863
		        
864
		        Vector<XMLAccessDAO> accessControlList = dih.getAccessControlList();
865
		        if (accessControlList != null) {
866
		        	AccessControlForSingleFile acfsf = new AccessControlForSingleFile(docid);
867
		        	for (XMLAccessDAO xmlAccessDAO : accessControlList) {
868
		        		if (!acfsf.accessControlExists(xmlAccessDAO)) {
869
		        			acfsf.insertPermissions(xmlAccessDAO);
870
							logReplication.info("ReplicationService.handleForceReplicateRequest - document " + docid
871
									+ " permissions added to DB");
872
		        		}
873
		            }
874
		        }
875
		        
876
		        // process system metadata
877
		        if (systemMetadataXML != null) {
878
		      	  SystemMetadata sysMeta = 
879
		      		TypeMarshaller.unmarshalTypeFromStream(
880
		      				  SystemMetadata.class, 
881
		      				  new ByteArrayInputStream(systemMetadataXML.getBytes("UTF-8")));
882
		      	  // need the guid-to-docid mapping
883
		      	  IdentifierManager.getInstance().createMapping(sysMeta.getIdentifier().getValue(), docid);
884
		        }
885

    
886
				if (writeException != null) {
887
					throw writeException;
888
				}
889

    
890
				logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - datafile " + docid + " added to DB with "
891
						+ "action " + dbaction);
892
				EventLog.getInstance().log(request.getRemoteAddr(), request.getHeader("User-Agent"), REPLICATIONUSER,
893
						docid, dbaction);
894
			}
895

    
896
		} catch (Exception e) {
897
			logMetacat.error("ReplicationService.handleForceReplicateDataFileRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
898
			logReplication.error("ReplicationService.handleForceReplicateDataFileRequest - Datafile " + docid
899
					+ " failed to added to DB with " + "action " + dbaction + " because "
900
					+ e.getMessage());
901
			logReplication.error("ReplicationService.handleForceReplicateDataFileRequest - ERROR in MetacatReplication.handleForceDataFileReplicate"
902
					+ "Request(): " + e.getMessage());
903
		}
904
	}
905

    
906
	/**
907
	 * Grants or denies a lock to a requesting host.
908
	 * The servlet parameters of interrest are:
909
	 * docid: the docid of the file the lock is being requested for
910
	 * currentdate: the timestamp of the document on the remote server
911
	 *
912
	 */
913
	protected static void handleGetLockRequest(
914
			Hashtable<String, String[]> params, HttpServletResponse response) {
915

    
916
		try {
917

    
918
			String docid = ((String[]) params.get("docid"))[0];
919
			String remoteRev = ((String[]) params.get("updaterev"))[0];
920
			DocumentImpl requestDoc = new DocumentImpl(docid);
921
			logReplication.info("ReplicationService.handleGetLockRequest - lock request for " + docid);
922
			int localRevInt = requestDoc.getRev();
923
			int remoteRevInt = Integer.parseInt(remoteRev);
924

    
925
			// get a writer for sending back to response
926
			response.setContentType("text/xml");
927
			Writer out = response.getWriter();
928
			
929
			if (remoteRevInt >= localRevInt) {
930
				if (!fileLocks.contains(docid)) { //grant the lock if it is not already locked
931
					fileLocks.add(0, docid); //insert at the beginning of the queue Vector
932
					//send a message back to the the remote host authorizing the insert
933
					out.write("<lockgranted><docid>" + docid
934
									+ "</docid></lockgranted>");
935
					//          lockThread = new Thread(this);
936
					//          lockThread.setPriority(Thread.MIN_PRIORITY);
937
					//          lockThread.start();
938
					logReplication.info("ReplicationService.handleGetLockRequest - lock granted for " + docid);
939
				} else { //deny the lock
940
					out.write("<filelocked><docid>" + docid + "</docid></filelocked>");
941
					logReplication.info("ReplicationService.handleGetLockRequest - lock denied for " + docid
942
							+ "reason: file already locked");
943
				}
944
			} else {//deny the lock.
945
				out.write("<outdatedfile><docid>" + docid + "</docid></filelocked>");
946
				logReplication.info("ReplicationService.handleGetLockRequest - lock denied for " + docid
947
						+ "reason: client has outdated file");
948
			}
949
			out.close();
950
			//conn.close();
951
		} catch (Exception e) {
952
			logMetacat.error("ReplicationService.handleGetLockRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
953
			logReplication.error("ReplicationService.handleGetLockRequest - error requesting file lock from MetacatReplication."
954
					+ "handleGetLockRequest: " + e.getMessage());
955
			e.printStackTrace(System.out);
956
		}
957
	}
958

    
959
	/**
960
	 * Sends all of the xml_documents information encoded in xml to a requestor
961
	 * the format is:
962
	 * <!ELEMENT documentinfo (docid, docname, doctype, doctitle, user_owner,
963
	 *                  user_updated, home_server, public_access, rev)/>
964
	 * all of the subelements of document info are #PCDATA
965
	 */
966
	protected static void handleGetDocumentInfoRequest(
967
			Hashtable<String, String[]> params, HttpServletResponse response) {
968
		String docid = ((String[]) (params.get("docid")))[0];
969
		StringBuffer sb = new StringBuffer();
970

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

    
1014
			sb.append("<accessControl>");
1015

    
1016
			AccessControlForSingleFile acfsf = new AccessControlForSingleFile(docid); 
1017
			sb.append(acfsf.getAccessString());
1018
			
1019
			sb.append("</accessControl>");
1020

    
1021
			sb.append("</documentinfo>");
1022
			// get a writer for sending back to response
1023
			response.setContentType("text/xml");
1024
			Writer out = response.getWriter();
1025
			out.write(sb.toString());
1026
			out.close();
1027

    
1028
		} catch (Exception e) {
1029
			logMetacat.error("ReplicationService.handleGetDocumentInfoRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1030
			logReplication.error("ReplicationService.handleGetDocumentInfoRequest - error in metacatReplication.handlegetdocumentinforequest "
1031
					+ "for doc: " + docid + " : " + e.getMessage());
1032
		}
1033

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

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

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

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

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

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

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

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

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

    
1169
		// Set the mime type
1170
		response.setContentType(contentType);
1171

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

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

    
1197
	}
1198

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

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

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

    
1231
			String documentDir = PropertyService
1232
					.getProperty("application.documentfilepath");
1233
			documentPath = documentDir + FileUtil.getFS() + docid;
1234

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

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

    
1247
			logReplication.info("ReplicationService.handleGetDocumentRequest - document " + docid + " sent");
1248

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

    
1304
	}
1305

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

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

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

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

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

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

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

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

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

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

    
1497
			pstmt = dbConn.prepareStatement(delsql.toString());
1498
			//usage count should increas 1
1499
			dbConn.increaseUsageCount(1);
1500

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

    
1511
			//now we can put the package files into the xml results
1512
			for (int i = 0; i < packageFiles.size(); i++) {
1513
				Vector<String> v = packageFiles.elementAt(i);
1514
				doclist.append("<updatedDocument>");
1515
				doclist.append("<docid>").append(v.elementAt(0));
1516
				doclist.append("</docid><rev>");
1517
				doclist.append(v.elementAt(1));
1518
				doclist.append("</rev>");
1519
				doclist.append("</updatedDocument>");
1520
			}
1521
			// add revision doc list  
1522
			doclist.append(prepareRevisionDoc(dbConn, revisionSql.toString(),
1523
					replicateData));
1524
			
1525
			// add the system metadata entries if configured to replicate them
1526
			boolean replicateSystemMetadata = serverList.getSystemMetadataReplicationValue(server);
1527
			if (replicateSystemMetadata) {
1528
				Date since = new Date(System.currentTimeMillis());
1529
				since = serverList.getLastCheckedDate(server);
1530
				List<String> systemMetadataEntries = 
1531
					IdentifierManager.getInstance().getUpdatedSystemMetadataIds(since);
1532
				for (int i = 0; i < systemMetadataEntries.size(); i++) {
1533
					String guid = systemMetadataEntries.get(i);
1534
					doclist.append("<updatedSystemMetadata>");
1535
					doclist.append("<guid>");
1536
					doclist.append(guid);
1537
					doclist.append("</guid>");
1538
					doclist.append("</updatedSystemMetadata>");
1539
				}
1540
			}
1541

    
1542
			doclist.append("</updates></replication>");
1543
			logReplication.info("ReplicationService.handleUpdateRequest - doclist: " + doclist.toString());
1544
			pstmt.close();
1545
			//conn.close();
1546
			out.write(doclist.toString());
1547

    
1548
		} catch (Exception e) {
1549
			logMetacat.error("ReplicationService.handleUpdateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1550
			logReplication.error("ReplicationService.handleUpdateRequest - error in MetacatReplication." + "handleupdaterequest: "
1551
					+ e.getMessage());
1552
			//e.printStackTrace(System.out);
1553
			try {
1554
				out.write("<error>" + e.getMessage() + "</error>");
1555
			} catch (IOException e1) {
1556
				logMetacat.error(e1.getMessage(), e1);
1557
			}
1558
		} finally {
1559
			try {
1560
				pstmt.close();
1561
			}//try
1562
			catch (SQLException ee) {
1563
				logMetacat.error("ReplicationService.handleUpdateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1564
				logReplication.error("ReplicationService.handleUpdateRequest - Error in MetacatReplication."
1565
						+ "handleUpdaterequest to close pstmt: " + ee.getMessage());
1566
			}//catch
1567
			finally {
1568
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1569
			}//finally
1570
			try {
1571
				out.close();
1572
			} catch (IOException e) {
1573
				logMetacat.error(e.getMessage(), e);
1574
			}
1575
		}//finally
1576

    
1577
	}//handlUpdateRequest
1578

    
1579
	/**
1580
	 * 
1581
	 * @param dbConn connection for doing the update
1582
	 * @param docid the document id to update
1583
	 * @param owner the user_owner
1584
	 * @param updater the user_updated
1585
	 * @throws SQLException
1586
	 */
1587
	public static void updateUserOwner(DBConnection dbConn, String docid, String owner, String updater) throws SQLException {
1588
	
1589
		String sql = 
1590
			"UPDATE xml_documents " +
1591
			"SET user_owner = ?, " +
1592
			"user_updated = ? " +
1593
			"WHERE docid = ?;";
1594
		PreparedStatement pstmt = dbConn.prepareStatement(sql);
1595
		//usage count should increas 1
1596
		dbConn.increaseUsageCount(1);
1597

    
1598
		docid = DocumentUtil.getSmartDocId(docid);
1599
		pstmt.setString(1, owner);
1600
		pstmt.setString(2, updater);
1601
		pstmt.setString(3, docid);
1602
		pstmt.execute();
1603
		pstmt.close();
1604
		
1605
		dbConn.commit();
1606
	}
1607
	
1608
	/*
1609
	 * This method will get the xml string for document in xml_revision
1610
	 * The schema look like <!ELEMENT revisionDocument (docid, rev, datafile*)>
1611
	 */
1612
	private static String prepareRevisionDoc(DBConnection dbConn, String revSql,
1613
			boolean replicateData) throws Exception {
1614
		logReplication.warn("ReplicationService.prepareRevisionDoc - The revision document sql is " + revSql);
1615
		StringBuffer revDocList = new StringBuffer();
1616
		PreparedStatement pstmt = dbConn.prepareStatement(revSql);
1617
		//usage count should increas 1
1618
		dbConn.increaseUsageCount(1);
1619

    
1620
		pstmt.execute();
1621
		ResultSet rs = pstmt.getResultSet();
1622
		boolean tablehasrows = rs.next();
1623
		while (tablehasrows) {
1624
			String recordDoctype = rs.getString(3);
1625

    
1626
			//If this is data file and it isn't configured to replicate data
1627
			if (recordDoctype.equals("BIN") && !replicateData) {
1628
				// do nothing
1629
				continue;
1630
			} else {
1631

    
1632
				revDocList.append("<revisionDocument>");
1633
				revDocList.append("<docid>").append(rs.getString(1));
1634
				revDocList.append("</docid><rev>").append(rs.getInt(2));
1635
				revDocList.append("</rev>");
1636
				// data file
1637
				if (recordDoctype.equals("BIN")) {
1638
					revDocList.append("<datafile>");
1639
					revDocList.append(PropertyService
1640
							.getProperty("replication.datafileflag"));
1641
					revDocList.append("</datafile>");
1642
				}
1643
				revDocList.append("</revisionDocument>");
1644

    
1645
			}//else
1646
			tablehasrows = rs.next();
1647
		}
1648
		//System.out.println("The revision list is"+ revDocList.toString());
1649
		return revDocList.toString();
1650
	}
1651

    
1652
	/**
1653
	 * Returns the xml_catalog table encoded in xml
1654
	 */
1655
	public static String getCatalogXML() {
1656
		return handleGetCatalogRequest(null, null, false);
1657
	}
1658

    
1659
	/**
1660
	 * Sends the contents of the xml_catalog table encoded in xml
1661
	 * The xml format is:
1662
	 * <!ELEMENT xml_catalog (row*)>
1663
	 * <!ELEMENT row (entry_type, source_doctype, target_doctype, public_id,
1664
	 *                system_id)>
1665
	 * All of the sub elements of row are #PCDATA
1666

    
1667
	 * If printFlag == false then do not print to out.
1668
	 */
1669
	protected static String handleGetCatalogRequest(
1670
			Hashtable<String, String[]> params, HttpServletResponse response,
1671
			boolean printFlag) {
1672
		DBConnection dbConn = null;
1673
		int serialNumber = -1;
1674
		PreparedStatement pstmt = null;
1675
		Writer out = null;
1676
		try {
1677
			// get writer, TODO: encoding?
1678
		    if(printFlag)
1679
		    {
1680
		        response.setContentType("text/xml");
1681
		        out = response.getWriter();
1682
		    }
1683
			/*conn = MetacatReplication.getDBConnection("MetacatReplication." +
1684
			                                          "handleGetCatalogRequest");*/
1685
			dbConn = DBConnectionPool
1686
					.getDBConnection("MetacatReplication.handleGetCatalogRequest");
1687
			serialNumber = dbConn.getCheckOutSerialNumber();
1688
			pstmt = dbConn.prepareStatement("select entry_type, "
1689
					+ "source_doctype, target_doctype, public_id, "
1690
					+ "system_id from xml_catalog");
1691
			pstmt.execute();
1692
			ResultSet rs = pstmt.getResultSet();
1693
			boolean tablehasrows = rs.next();
1694
			StringBuffer sb = new StringBuffer();
1695
			sb.append("<?xml version=\"1.0\"?><xml_catalog>");
1696
			while (tablehasrows) {
1697
				sb.append("<row><entry_type>").append(rs.getString(1));
1698
				sb.append("</entry_type><source_doctype>").append(rs.getString(2));
1699
				sb.append("</source_doctype><target_doctype>").append(rs.getString(3));
1700
				sb.append("</target_doctype><public_id>").append(rs.getString(4));
1701
				// system id may not have server url on front.  Add it if not.
1702
				String systemID = rs.getString(5);
1703
				if (!systemID.startsWith("http://")) {
1704
					systemID = SystemUtil.getContextURL() + systemID;
1705
				}
1706
				sb.append("</public_id><system_id>").append(systemID);
1707
				sb.append("</system_id></row>");
1708

    
1709
				tablehasrows = rs.next();
1710
			}
1711
			sb.append("</xml_catalog>");
1712
			//conn.close();
1713
			if (printFlag) {
1714
				response.setContentType("text/xml");
1715
				out.write(sb.toString());
1716
			}
1717
			pstmt.close();
1718
			return sb.toString();
1719
		} catch (Exception e) {
1720
			logMetacat.error("ReplicationService.handleGetCatalogRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1721
			logReplication.error("ReplicationService.handleGetCatalogRequest - error in MetacatReplication.handleGetCatalogRequest:"
1722
					+ e.getMessage());
1723
			e.printStackTrace(System.out);
1724
			if (printFlag) {
1725
				try {
1726
					out.write("<error>" + e.getMessage() + "</error>");
1727
				} catch (IOException e1) {
1728
					logMetacat.error(e1.getMessage(), e1);
1729
				}
1730
			}
1731
		} finally {
1732
			try {
1733
				pstmt.close();
1734
			}//try
1735
			catch (SQLException ee) {
1736
				logMetacat.error("ReplicationService.handleGetCatalogRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1737
				logReplication.error("ReplicationService.handleGetCatalogRequest - Error in MetacatReplication.handleGetCatalogRequest: "
1738
						+ ee.getMessage());
1739
			}//catch
1740
			finally {
1741
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1742
			}//finally
1743
			if (out != null) {
1744
				try {
1745
					out.close();
1746
				} catch (IOException e1) {
1747
					logMetacat.error(e1.getMessage(), e1);
1748
				}
1749
			}
1750
		}//finally
1751

    
1752
		return null;
1753
	}
1754

    
1755
	/**
1756
	 * Sends the current system date to the remote server.  Using this action
1757
	 * for replication gets rid of any problems with syncronizing clocks
1758
	 * because a time specific to a document is always kept on its home server.
1759
	 */
1760
	protected static void handleGetTimeRequest(
1761
			Hashtable<String, String[]> params, HttpServletResponse response) {
1762
		
1763
		// use standard ISO format -- the receiving end wants this too
1764
		String dateString = DatatypeConverter.printDateTime(Calendar.getInstance());
1765
		
1766
		// get a writer for sending back to response
1767
		response.setContentType("text/xml");
1768
		Writer out = null;
1769
		try {
1770
			out = response.getWriter();
1771
			out.write("<timestamp>" + dateString + "</timestamp>");
1772
			out.close();
1773
		} catch (IOException e) {
1774
			logMetacat.error(e.getMessage(), e);
1775
		}
1776
		
1777
	}
1778

    
1779
	/**
1780
	 * this method handles the timeout for a file lock.  when a lock is
1781
	 * granted it is granted for 30 seconds.  When this thread runs out
1782
	 * it deletes the docid from the queue, thus eliminating the lock.
1783
	 */
1784
	public void run() {
1785
		try {
1786
			logReplication.info("ReplicationService.run - thread started for docid: "
1787
					+ (String) fileLocks.elementAt(0));
1788

    
1789
			Thread.sleep(30000); //the lock will expire in 30 seconds
1790
			logReplication.info("thread for docid: "
1791
					+ (String) fileLocks.elementAt(fileLocks.size() - 1) + " exiting.");
1792

    
1793
			fileLocks.remove(fileLocks.size() - 1);
1794
			//fileLocks is treated as a FIFO queue.  If there are more than one lock
1795
			//in the vector, the first one inserted will be removed.
1796
		} catch (Exception e) {
1797
			logMetacat.error("ReplicationService.run - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1798
			logReplication.error("ReplicationService.run - error in file lock thread from "
1799
					+ "MetacatReplication.run: " + e.getMessage());
1800
		}
1801
	}
1802

    
1803
	/**
1804
	 * Returns the name of a server given a serverCode
1805
	 * @param serverCode the serverid of the server
1806
	 * @return the servername or null if the specified serverCode does not
1807
	 *         exist.
1808
	 */
1809
	public static String getServerNameForServerCode(int serverCode) {
1810
		//System.out.println("serverid: " + serverCode);
1811
		DBConnection dbConn = null;
1812
		int serialNumber = -1;
1813
		PreparedStatement pstmt = null;
1814
		try {
1815
			dbConn = DBConnectionPool.getDBConnection("MetacatReplication.getServer");
1816
			serialNumber = dbConn.getCheckOutSerialNumber();
1817
			String sql = new String("select server from "
1818
					+ "xml_replication where serverid = ?");
1819
			pstmt = dbConn.prepareStatement(sql);
1820
			pstmt.setInt(1, serverCode);
1821
			//System.out.println("getserver sql: " + sql);
1822
			pstmt.execute();
1823
			ResultSet rs = pstmt.getResultSet();
1824
			boolean tablehasrows = rs.next();
1825
			if (tablehasrows) {
1826
				//System.out.println("server: " + rs.getString(1));
1827
				return rs.getString(1);
1828
			}
1829

    
1830
			//conn.close();
1831
		} catch (Exception e) {
1832
			logMetacat.error("ReplicationService.getServerNameForServerCode - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1833
			logReplication.error("ReplicationService.getServerNameForServerCode - Error in MetacatReplication.getServer: " + e.getMessage());
1834
		} finally {
1835
			try {
1836
				pstmt.close();
1837
			}//try
1838
			catch (SQLException ee) {
1839
				logMetacat.error("ReplicationService.getServerNameForServerCode - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1840
				logReplication.error("ReplicationService.getServerNameForServerCode - Error in MetacactReplication.getserver: "
1841
						+ ee.getMessage());
1842
			}//catch
1843
			finally {
1844
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1845
			}//fianlly
1846
		}//finally
1847

    
1848
		return null;
1849
		//return null if the server does not exist
1850
	}
1851

    
1852
	/**
1853
	 * Returns a server code given a server name
1854
	 * @param server the name of the server
1855
	 * @return integer > 0 representing the code of the server, 0 if the server
1856
	 *  does not exist.
1857
	 */
1858
	public static int getServerCodeForServerName(String server) throws ServiceException {
1859
		DBConnection dbConn = null;
1860
		int serialNumber = -1;
1861
		PreparedStatement pstmt = null;
1862
		int serverCode = 0;
1863

    
1864
		try {
1865

    
1866
			//conn = util.openDBConnection();
1867
			dbConn = DBConnectionPool.getDBConnection("MetacatReplication.getServerCode");
1868
			serialNumber = dbConn.getCheckOutSerialNumber();
1869
			pstmt = dbConn.prepareStatement("SELECT serverid FROM xml_replication "
1870
					+ "WHERE server LIKE ?");
1871
			pstmt.setString(1, server);
1872
			pstmt.execute();
1873
			ResultSet rs = pstmt.getResultSet();
1874
			boolean tablehasrows = rs.next();
1875
			if (tablehasrows) {
1876
				serverCode = rs.getInt(1);
1877
				pstmt.close();
1878
				//conn.close();
1879
				return serverCode;
1880
			}
1881

    
1882
		} catch (SQLException sqle) {
1883
			throw new ServiceException("ReplicationService.getServerCodeForServerName - " 
1884
					+ "SQL error when getting server code: " + sqle.getMessage());
1885

    
1886
		} finally {
1887
			try {
1888
				pstmt.close();
1889
				//conn.close();
1890
			}//try
1891
			catch (Exception ee) {
1892
				logMetacat.error("ReplicationService.getServerCodeForServerName - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1893
				logReplication.error("ReplicationService.getServerNameForServerCode - Error in MetacatReplicatio.getServerCode: "
1894
						+ ee.getMessage());
1895

    
1896
			}//catch
1897
			finally {
1898
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1899
			}//finally
1900
		}//finally
1901

    
1902
		return serverCode;
1903
	}
1904

    
1905
	/**
1906
	 * Method to get a host server information for given docid
1907
	 * @param conn a connection to the database
1908
	 */
1909
	public static Hashtable<String, String> getHomeServerInfoForDocId(String docId) {
1910
		Hashtable<String, String> sl = new Hashtable<String, String>();
1911
		DBConnection dbConn = null;
1912
		int serialNumber = -1;
1913
		docId = DocumentUtil.getDocIdFromString(docId);
1914
		PreparedStatement pstmt = null;
1915
		int serverLocation;
1916
		try {
1917
			//get conection
1918
			dbConn = DBConnectionPool.getDBConnection("ReplicationHandler.getHomeServer");
1919
			serialNumber = dbConn.getCheckOutSerialNumber();
1920
			//get a server location from xml_document table
1921
			pstmt = dbConn.prepareStatement("select server_location from xml_documents "
1922
					+ "where docid = ?");
1923
			pstmt.setString(1, docId);
1924
			pstmt.execute();
1925
			ResultSet serverName = pstmt.getResultSet();
1926
			//get a server location
1927
			if (serverName.next()) {
1928
				serverLocation = serverName.getInt(1);
1929
				pstmt.close();
1930
			} else {
1931
				pstmt.close();
1932
				//ut.returnConnection(conn);
1933
				return null;
1934
			}
1935
			pstmt = dbConn.prepareStatement("select server, last_checked, replicate "
1936
					+ "from xml_replication where serverid = ?");
1937
			//increase usage count
1938
			dbConn.increaseUsageCount(1);
1939
			pstmt.setInt(1, serverLocation);
1940
			pstmt.execute();
1941
			ResultSet rs = pstmt.getResultSet();
1942
			boolean tableHasRows = rs.next();
1943
			if (tableHasRows) {
1944

    
1945
				String server = rs.getString(1);
1946
				String last_checked = rs.getString(2);
1947
				if (!server.equals("localhost")) {
1948
					sl.put(server, last_checked);
1949
				}
1950

    
1951
			} else {
1952
				pstmt.close();
1953
				//ut.returnConnection(conn);
1954
				return null;
1955
			}
1956
			pstmt.close();
1957
		} catch (Exception e) {
1958
			logMetacat.error("ReplicationService.getHomeServerInfoForDocId - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1959
			logReplication.error("ReplicationService.getHomeServerInfoForDocId - error in replicationHandler.getHomeServer(): "
1960
					+ e.getMessage());
1961
		} finally {
1962
			try {
1963
				pstmt.close();
1964
				//ut.returnConnection(conn);
1965
			} catch (Exception ee) {
1966
				logMetacat.error("ReplicationService.getHomeServerInfoForDocId - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1967
				logReplication.error("ReplicationService.getHomeServerInfoForDocId - Eror irn rplicationHandler.getHomeServer() "
1968
						+ "to close pstmt: " + ee.getMessage());
1969
			} finally {
1970
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1971
			}
1972

    
1973
		}//finally
1974
		return sl;
1975
	}
1976

    
1977
	/**
1978
	 * Returns a home server location  given a accnum
1979
	 * @param accNum , given accNum for a document
1980
	 *
1981
	 */
1982
	public static int getHomeServerCodeForDocId(String accNum) throws ServiceException {
1983
		DBConnection dbConn = null;
1984
		int serialNumber = -1;
1985
		PreparedStatement pstmt = null;
1986
		int serverCode = 1;
1987
		String docId = DocumentUtil.getDocIdFromString(accNum);
1988

    
1989
		try {
1990

    
1991
			// Get DBConnection
1992
			dbConn = DBConnectionPool
1993
					.getDBConnection("ReplicationHandler.getServerLocation");
1994
			serialNumber = dbConn.getCheckOutSerialNumber();
1995
			pstmt = dbConn.prepareStatement("SELECT server_location FROM xml_documents "
1996
					+ "WHERE docid LIKE ? ");
1997
			pstmt.setString(1, docId);
1998
			pstmt.execute();
1999
			ResultSet rs = pstmt.getResultSet();
2000
			boolean tablehasrows = rs.next();
2001
			//If a document is find, return the server location for it
2002
			if (tablehasrows) {
2003
				serverCode = rs.getInt(1);
2004
				pstmt.close();
2005
				//conn.close();
2006
				return serverCode;
2007
			}
2008
			//if couldn't find in xml_documents table, we think server code is 1
2009
			//(this is new document)
2010
			else {
2011
				pstmt.close();
2012
				//conn.close();
2013
				return serverCode;
2014
			}
2015

    
2016
		} catch (SQLException sqle) {
2017
			throw new ServiceException("ReplicationService.getHomeServerCodeForDocId - " 
2018
					+ "SQL error when getting home server code for docid: " + docId + " : " 
2019
					+ sqle.getMessage());
2020

    
2021
		} finally {
2022
			try {
2023
				pstmt.close();
2024
				//conn.close();
2025

    
2026
			} catch (SQLException sqle) {
2027
				logMetacat.error("ReplicationService.getHomeServerCodeForDocId - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
2028
				logReplication.error("ReplicationService.getHomeServerCodeForDocId - ReplicationService.getHomeServerCodeForDocId - " 
2029
						+ "SQL error when getting home server code for docid: " + docId + " : " 
2030
						+ sqle.getMessage());
2031
			} finally {
2032
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
2033
			}//finally
2034
		}//finally
2035
		//return serverCode;
2036
	}
2037

    
2038
	/**
2039
	 * This method returns the content of a url
2040
	 * @param u the url to return the content from
2041
	 * @return a string representing the content of the url
2042
	 * @throws java.io.IOException
2043
	 */
2044
	public static String getURLContent(URL u) throws java.io.IOException {
2045
		char istreamChar;
2046
		int istreamInt;
2047
		// get the response content
2048
		InputStream input = getURLStream(u);
2049
		logReplication.info("ReplicationService.getURLContent - After getting response from: " + u.toString());
2050
		InputStreamReader istream = new InputStreamReader(input);
2051
		StringBuffer serverResponse = new StringBuffer();
2052
		while ((istreamInt = istream.read()) != -1) {
2053
			istreamChar = (char) istreamInt;
2054
			serverResponse.append(istreamChar);
2055
		}
2056
		istream.close();
2057
		input.close();
2058

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

    
2122
//	/**
2123
//	 * Method for writing replication messages to a log file specified in
2124
//	 * metacat.properties
2125
//	 */
2126
//	public static void replLog(String message) {
2127
//		try {
2128
//			FileOutputStream fos = new FileOutputStream(PropertyService
2129
//					.getProperty("replication.logdir")
2130
//					+ "/metacatreplication.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 log from "
2141
//					+ "MetacatReplication.replLog: " + e.getMessage());
2142
//			// e.printStackTrace(System.out);
2143
//		}
2144
//	}
2145

    
2146
//	/**
2147
//	 * Method for writing replication messages to a log file specified in
2148
//	 * metacat.properties
2149
//	 */
2150
//	public static void replErrorLog(String message) {
2151
//		try {
2152
//			FileOutputStream fos = new FileOutputStream(PropertyService
2153
//					.getProperty("replication.logdir")
2154
//					+ "/metacatreplicationerror.log", true);
2155
//			PrintWriter pw = new PrintWriter(fos);
2156
//			SimpleDateFormat formatter = new SimpleDateFormat("yy-MM-dd HH:mm:ss");
2157
//			java.util.Date localtime = new java.util.Date();
2158
//			String dateString = formatter.format(localtime);
2159
//			dateString += " :: " + message;
2160
//			//time stamp each entry
2161
//			pw.println(dateString);
2162
//			pw.flush();
2163
//		} catch (Exception e) {
2164
//			logReplication.error("error writing to replication error log from "
2165
//					+ "MetacatReplication.replErrorLog: " + e.getMessage());
2166
//			//e.printStackTrace(System.out);
2167
//		}
2168
//	}
2169

    
2170
	/**
2171
	 * Returns true if the replicate field for server in xml_replication is 1.
2172
	 * Returns false otherwise
2173
	 */
2174
	public static boolean replToServer(String server) {
2175
		DBConnection dbConn = null;
2176
		int serialNumber = -1;
2177
		PreparedStatement pstmt = null;
2178
		try {
2179
			dbConn = DBConnectionPool.getDBConnection("MetacatReplication.repltoServer");
2180
			serialNumber = dbConn.getCheckOutSerialNumber();
2181
			pstmt = dbConn.prepareStatement("select replicate from "
2182
					+ "xml_replication where server like ? ");
2183
			pstmt.setString(1, server);
2184
			pstmt.execute();
2185
			ResultSet rs = pstmt.getResultSet();
2186
			boolean tablehasrows = rs.next();
2187
			if (tablehasrows) {
2188
				int i = rs.getInt(1);
2189
				if (i == 1) {
2190
					pstmt.close();
2191
					//conn.close();
2192
					return true;
2193
				} else {
2194
					pstmt.close();
2195
					//conn.close();
2196
					return false;
2197
				}
2198
			}
2199
		} catch (SQLException sqle) {
2200
			logMetacat.error("ReplicationService.replToServer - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
2201
			logReplication.error("ReplicationService.replToServer - SQL error in MetacatReplication.replToServer: "
2202
					+ sqle.getMessage());
2203
		} finally {
2204
			try {
2205
				pstmt.close();
2206
				//conn.close();
2207
			}//try
2208
			catch (Exception ee) {
2209
				logMetacat.error("ReplicationService.replToServer - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
2210
				logReplication.error("ReplicationService.replToServer - Error in MetacatReplication.replToServer: "
2211
						+ ee.getMessage());
2212
			}//catch
2213
			finally {
2214
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
2215
			}//finally
2216
		}//finally
2217
		return false;
2218
		//the default if this server does not exist is to not replicate to it.
2219
	}
2220

    
2221
}
(7-7/8)