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 12:31:29 -0800 (Mon, 07 Nov 2011) $'
10
 * '$Revision: 6613 $'
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
			e.printStackTrace();
898
			logMetacat.error("ReplicationService.handleForceReplicateDataFileRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG, e);                         
899
			logReplication.error("ReplicationService.handleForceReplicateDataFileRequest - Datafile " + docid
900
					+ " failed to added to DB with " + "action " + dbaction + " because "
901
					+ e.getMessage());
902
			logReplication.error("ReplicationService.handleForceReplicateDataFileRequest - ERROR in MetacatReplication.handleForceDataFileReplicate"
903
					+ "Request(): " + e.getMessage());
904
		}
905
	}
906

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

    
917
		try {
918

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1198
	}
1199

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

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

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

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

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

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

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

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

    
1305
	}
1306

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1578
	}//handlUpdateRequest
1579

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

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

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

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

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

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

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

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

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

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

    
1753
		return null;
1754
	}
1755

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

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

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

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

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

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

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

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

    
1865
		try {
1866

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

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

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

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

    
1903
		return serverCode;
1904
	}
1905

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

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

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

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

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

    
1990
		try {
1991

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

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

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

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

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

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

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

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

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

    
2222
}
(7-7/8)