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-01 15:23:28 -0700 (Tue, 01 Nov 2011) $'
10
 * '$Revision: 6582 $'
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.text.SimpleDateFormat;
51
import java.util.Date;
52
import java.util.Hashtable;
53
import java.util.List;
54
import java.util.Timer;
55
import java.util.Vector;
56

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

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

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

    
101
public class ReplicationService extends BaseService {
102

    
103
	private static ReplicationService replicationService = null;
104

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
376
				// download certificate with the public key on this server
377
				// and import it as a trusted certificate
378
				String certURL = ((String[]) params.get("certificate"))[0];
379
				if (certURL != null && !certURL.equals("")) {
380
					downloadCertificate(certURL);
381
				}
382

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

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

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

    
440
					tablehasrows = rs.next();
441
				}
442
				out.write("</table></body></html>");
443
			} else {
444

    
445
				out.write("<error>Unkonwn subaction</error>");
446

    
447
			}
448
			pstmt.close();
449
			//conn.close();
450

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

    
477
	}
478

    
479
	// download certificate with the public key from certURL and
480
	// upload it onto this server; it then must be imported as a
481
	// trusted certificate
482
	private static void downloadCertificate(String certURL) throws FileNotFoundException,
483
			IOException, MalformedURLException, PropertyNotFoundException {
484

    
485
		// the path to be uploaded to
486
		String certPath = SystemUtil.getContextDir();
487

    
488
		// get filename from the URL of the certificate
489
		String filename = certURL;
490
		int slash = Math.max(filename.lastIndexOf('/'), filename.lastIndexOf('\\'));
491
		if (slash > -1) {
492
			filename = filename.substring(slash + 1);
493
		}
494

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

    
512
			// create a buffered byte output stream
513
			// that uses a default-sized output buffer
514
			FileOutputStream fos = new FileOutputStream(f);
515
			BufferedOutputStream out = new BufferedOutputStream(fos);
516

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

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

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

    
573
			// get the document info from server
574
			URL docinfourl = new URL("https://" + server + "?server="
575
					+ MetacatUtil.getLocalReplicationServerName()
576
					+ "&action=getdocumentinfo&docid=" + docid);
577
			
578

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

    
632
			// Get DBConnection from pool
633
			dbConn = DBConnectionPool
634
					.getDBConnection("MetacatReplication.handleForceReplicateRequest");
635
			serialNumber = dbConn.getCheckOutSerialNumber();
636
			// write the document to local database
637
			DocumentImplWrapper wrapper = new DocumentImplWrapper(parserBase, false);
638
			//try this independently so we can set access even if the update action is invalid (i.e docid has not changed)
639
			try {
640
				wrapper.writeReplication(dbConn, xmldoc, null, null,
641
						dbaction, docid, null, null, homeServer, server, createdDate,
642
						updatedDate);
643
			} finally {
644

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

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

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

    
746
		}//catch
747

    
748
	}
749

    
750
	/**
751
	 * when a forcereplication data file request comes in, local host sends a
752
	 * readdata request to the requesting server (remote server) for the specified
753
	 * docid. Then store it in local database and file system
754
	 */
755
	protected static void handleForceReplicateDataFileRequest(Hashtable<String, String[]> params,
756
			HttpServletRequest request) {
757

    
758
		//make sure there is some parameters
759
		if (params.isEmpty()) {
760
			return;
761
		}
762
		// Get remote server
763
		String server = ((String[]) params.get("server"))[0];
764
		// the docid should include rev number
765
		String docid = ((String[]) params.get("docid"))[0];
766
		// Make sure there is a docid and server
767
		if (docid == null || server == null || server.equals("")) {
768
			logMetacat.error("ReplicationService.handleForceReplicateDataFileRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
769
			logReplication.error("ReplicationService.handleForceReplicateDataFileRequest - Didn't specify docid or server for replication");
770
			return;
771
		}
772

    
773
		// Overide or not
774
		//    boolean override = false;
775
		// dbaction - update or insert
776
		String dbaction = null;
777

    
778
		try {
779
			//docid was switch to two parts uinque code and rev
780
			//String uniqueCode=MetacatUtil.getDocIdFromString(docid);
781
			//int rev=MetacatUtil.getVersionFromString(docid);
782
			if (params.containsKey("dbaction")) {
783
				dbaction = ((String[]) params.get("dbaction"))[0];
784
			} else//default value is update
785
			{
786
				dbaction = "update";
787
			}
788

    
789
			logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - Force replication request from: " + server);
790
			logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - Force replication docid: " + docid);
791
			logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - Force replication action: " + dbaction);
792
			// get the document info from server
793
			URL docinfourl = new URL("https://" + server + "?server="
794
					+ MetacatUtil.getLocalReplicationServerName()
795
					+ "&action=getdocumentinfo&docid=" + docid);
796

    
797
			String docInfoStr = ReplicationService.getURLContent(docinfourl);
798
			
799
			// strip out the system metadata portion
800
		    String systemMetadataXML = ReplicationUtil.getSystemMetadataContent(docInfoStr);
801
		   	docInfoStr = ReplicationUtil.getContentWithoutSystemMetadata(docInfoStr);
802

    
803
			//dih is the parser for the docinfo xml format
804
			DocInfoHandler dih = new DocInfoHandler();
805
			XMLReader docinfoParser = ReplicationHandler.initParser(dih);
806
			docinfoParser.parse(new InputSource(new StringReader(docInfoStr)));
807
			Hashtable<String, String> docinfoHash = dih.getDocInfo();
808
			
809
			String docName = (String) docinfoHash.get("docname");
810

    
811
			String docType = (String) docinfoHash.get("doctype");
812

    
813
			String docHomeServer = (String) docinfoHash.get("home_server");
814

    
815
			String createdDate = (String) docinfoHash.get("date_created");
816

    
817
			String updatedDate = (String) docinfoHash.get("date_updated");
818
			logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - docHomeServer of datafile: " + docHomeServer);
819

    
820
			if (dbaction.equals("insert") || dbaction.equals("update")) {
821
				//Get data file and store it into local file system.
822
				// sending back readdata request to server
823
				URL url = new URL("https://" + server + "?server="
824
						+ MetacatUtil.getLocalReplicationServerName()
825
						+ "&action=readdata&docid=" + docid);
826
				String datafilePath = PropertyService
827
						.getProperty("application.datafilepath");
828

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

    
872
				if (writeException != null) {
873
					throw writeException;
874
				}
875

    
876
				logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - datafile " + docid + " added to DB with "
877
						+ "action " + dbaction);
878
				EventLog.getInstance().log(request.getRemoteAddr(), request.getHeader("User-Agent"), REPLICATIONUSER,
879
						docid, dbaction);
880
			}
881

    
882
		} catch (Exception e) {
883
			logMetacat.error("ReplicationService.handleForceReplicateDataFileRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
884
			logReplication.error("ReplicationService.handleForceReplicateDataFileRequest - Datafile " + docid
885
					+ " failed to added to DB with " + "action " + dbaction + " because "
886
					+ e.getMessage());
887
			logReplication.error("ReplicationService.handleForceReplicateDataFileRequest - ERROR in MetacatReplication.handleForceDataFileReplicate"
888
					+ "Request(): " + e.getMessage());
889
		}
890
	}
891

    
892
	/**
893
	 * Grants or denies a lock to a requesting host.
894
	 * The servlet parameters of interrest are:
895
	 * docid: the docid of the file the lock is being requested for
896
	 * currentdate: the timestamp of the document on the remote server
897
	 *
898
	 */
899
	protected static void handleGetLockRequest(
900
			Hashtable<String, String[]> params, HttpServletResponse response) {
901

    
902
		try {
903

    
904
			String docid = ((String[]) params.get("docid"))[0];
905
			String remoteRev = ((String[]) params.get("updaterev"))[0];
906
			DocumentImpl requestDoc = new DocumentImpl(docid);
907
			logReplication.info("ReplicationService.handleGetLockRequest - lock request for " + docid);
908
			int localRevInt = requestDoc.getRev();
909
			int remoteRevInt = Integer.parseInt(remoteRev);
910

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

    
945
	/**
946
	 * Sends all of the xml_documents information encoded in xml to a requestor
947
	 * the format is:
948
	 * <!ELEMENT documentinfo (docid, docname, doctype, doctitle, user_owner,
949
	 *                  user_updated, home_server, public_access, rev)/>
950
	 * all of the subelements of document info are #PCDATA
951
	 */
952
	protected static void handleGetDocumentInfoRequest(
953
			Hashtable<String, String[]> params, HttpServletResponse response) {
954
		String docid = ((String[]) (params.get("docid")))[0];
955
		StringBuffer sb = new StringBuffer();
956

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

    
994
			sb.append("<accessControl>");
995

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

    
1001
			sb.append("</documentinfo>");
1002
			// get a writer for sending back to response
1003
			response.setContentType("text/xml");
1004
			Writer out = response.getWriter();
1005
			out.write(sb.toString());
1006
			out.close();
1007

    
1008
		} catch (Exception e) {
1009
			logMetacat.error("ReplicationService.handleGetDocumentInfoRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1010
			logReplication.error("ReplicationService.handleGetDocumentInfoRequest - error in metacatReplication.handlegetdocumentinforequest "
1011
					+ "for doc: " + docid + " : " + e.getMessage());
1012
		}
1013

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

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

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

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

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

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

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

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

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

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

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

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

    
1177
	}
1178

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

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

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

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

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

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

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

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

    
1284
	}
1285

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1557
	}//handlUpdateRequest
1558

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

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

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

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

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

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

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

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

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

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

    
1732
		return null;
1733
	}
1734

    
1735
	/**
1736
	 * Sends the current system date to the remote server.  Using this action
1737
	 * for replication gets rid of any problems with syncronizing clocks
1738
	 * because a time specific to a document is always kept on its home server.
1739
	 */
1740
	protected static void handleGetTimeRequest(
1741
			Hashtable<String, String[]> params, HttpServletResponse response) {
1742
		SimpleDateFormat formatter = new SimpleDateFormat("MM/dd/yy HH:mm:ss");
1743
		java.util.Date localtime = new java.util.Date();
1744
		String dateString = formatter.format(localtime);
1745
		
1746
		// get a writer for sending back to response
1747
		response.setContentType("text/xml");
1748
		Writer out = null;
1749
		try {
1750
			out = response.getWriter();
1751
			out.write("<timestamp>" + dateString + "</timestamp>");
1752
			out.close();
1753
		} catch (IOException e) {
1754
			logMetacat.error(e.getMessage(), e);
1755
		}
1756
		
1757
	}
1758

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

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

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

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

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

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

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

    
1843
		try {
1844

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

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

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

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

    
1880
		return serverCode;
1881
	}
1882

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

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

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

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

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

    
1967
		try {
1968

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

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

    
1998
		} finally {
1999
			try {
2000
				pstmt.close();
2001
				//conn.close();
2002

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

    
2015
	/**
2016
	 * This method returns the content of a url
2017
	 * @param u the url to return the content from
2018
	 * @return a string representing the content of the url
2019
	 * @throws java.io.IOException
2020
	 */
2021
	public static String getURLContent(URL u) throws java.io.IOException {
2022
	    logReplication.info("Getting url content from " + u.toString());
2023
		char istreamChar;
2024
		int istreamInt;
2025
		logReplication.info("ReplicationService.getURLContent - Before sending request to: " + u.toString());
2026
		// use httpclient to set up SSL
2027
		RestClient client = getSSLClient();
2028
		HttpResponse response = client.doGetRequest(u.toString());
2029
		// get the response content
2030
		InputStream input = response.getEntity().getContent();
2031
		logReplication.info("ReplicationService.getURLContent - After getting response from: " + u.toString());
2032
		InputStreamReader istream = new InputStreamReader(input);
2033
		StringBuffer serverResponse = new StringBuffer();
2034
		while ((istreamInt = istream.read()) != -1) {
2035
			istreamChar = (char) istreamInt;
2036
			serverResponse.append(istreamChar);
2037
		}
2038
		istream.close();
2039
		input.close();
2040

    
2041
		return serverResponse.toString();
2042
	}
2043
	
2044
	/**
2045
	 * Sets up an HttpClient with SSL connection.
2046
	 * Sends client certificate to the server when doing the request.
2047
	 * @return
2048
	 */
2049
	private static RestClient getSSLClient() {
2050
		RestClient client = new RestClient();
2051
		
2052
		// set up this server's client identity
2053
		String subject = null;
2054
		try {
2055
			X509Certificate certificate = CertificateManager.getInstance().loadCertificateFromFile(PropertyService.getProperty("replication.certificate.file"));
2056
			PrivateKey key = CertificateManager.getInstance().loadPrivateKeyFromFile(PropertyService.getProperty("replication.privatekey.file"));
2057
			subject = CertificateManager.getInstance().getSubjectDN(certificate);
2058
			CertificateManager.getInstance().registerCertificate(subject, certificate, key);
2059
		} catch (Exception e) {
2060
			// this is pretty much required for replication communication
2061
			logReplication.warn("Could find server's client certificate/private key: " + e.getMessage());
2062
		}
2063
		SSLSocketFactory socketFactory = null;
2064
		try {
2065
			socketFactory = CertificateManager.getInstance().getSSLSocketFactory(subject);
2066
		} catch (FileNotFoundException e) {
2067
			// these are somewhat expected for anonymous client use
2068
			logReplication.warn("Could not set up SSL connection for client - likely because the certificate could not be located: " + e.getMessage());
2069
		} catch (Exception e) {
2070
			// this is likely more severe
2071
			logReplication.warn("Funky SSL going on: " + e.getClass() + ":: " + e.getMessage());
2072
		}
2073
		try {
2074
			//443 is the default port, this value is overridden if explicitly set in the URL
2075
			Scheme sch = new Scheme("https", 443, socketFactory);
2076
			client.getHttpClient().getConnectionManager().getSchemeRegistry().register(sch);
2077
		} catch (Exception e) {
2078
			// this is likely more severe
2079
			logReplication.error("Failed to set up SSL connection for client. Continuing. " + e.getClass() + ":: " + e.getMessage(), e);
2080
		}
2081
		return client;
2082
	}
2083
	
2084

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

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

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

    
2183
}
(7-7/8)