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: daigle $'
9
 *     '$Date: 2009-10-30 15:39:35 -0700 (Fri, 30 Oct 2009) $'
10
 * '$Revision: 5098 $'
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.util.*;
30
import java.util.Date;
31
import java.io.*;
32
import java.sql.*;
33
import java.net.*;
34
import java.text.*;
35

    
36
import javax.servlet.http.*;
37

    
38
import edu.ucsb.nceas.metacat.DocInfoHandler;
39
import edu.ucsb.nceas.metacat.DocumentImpl;
40
import edu.ucsb.nceas.metacat.DocumentImplWrapper;
41
import edu.ucsb.nceas.metacat.EventLog;
42
import edu.ucsb.nceas.metacat.McdbException;
43
import edu.ucsb.nceas.metacat.accesscontrol.AccessControlForSingleFile;
44
import edu.ucsb.nceas.metacat.accesscontrol.XMLAccessDAO;
45
import edu.ucsb.nceas.metacat.database.DBConnection;
46
import edu.ucsb.nceas.metacat.database.DBConnectionPool;
47
import edu.ucsb.nceas.metacat.database.DatabaseService;
48
import edu.ucsb.nceas.metacat.properties.PropertyService;
49
import edu.ucsb.nceas.metacat.shared.BaseService;
50
import edu.ucsb.nceas.metacat.shared.HandlerException;
51
import edu.ucsb.nceas.metacat.shared.ServiceException;
52
import edu.ucsb.nceas.metacat.util.DocumentUtil;
53
import edu.ucsb.nceas.metacat.util.MetacatUtil;
54
import edu.ucsb.nceas.metacat.util.SystemUtil;
55
import edu.ucsb.nceas.utilities.FileUtil;
56
import edu.ucsb.nceas.utilities.GeneralPropertyException;
57
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
58

    
59
import org.apache.log4j.Logger;
60
import org.xml.sax.*;
61

    
62
public class ReplicationService extends BaseService {
63

    
64
	private static ReplicationService replicationService = null;
65

    
66
	private long timeInterval;
67
	private Date firstTime;
68
	private boolean timedReplicationIsOn = false;
69
	Timer replicationDaemon;
70
	private static Vector<String> fileLocks = new Vector<String>();
71
//	private Thread lockThread = null;
72
	public static final String FORCEREPLICATEDELETE = "forcereplicatedelete";
73
	private static String TIMEREPLICATION = "replication.timedreplication";
74
	private static String TIMEREPLICATIONINTERVAl ="replication.timedreplicationinterval";
75
	private static String FIRSTTIME = "replication.firsttimedreplication";
76
	private static final int TIMEINTERVALLIMIT = 7200000;
77
	public static final String REPLICATIONUSER = "replication";
78

    
79
	public static final String REPLICATION_LOG_FILE_NAME = "metacatreplication.log";
80
	public static String METACAT_REPL_ERROR_MSG = null;
81
	private static Logger logReplication = Logger.getLogger("ReplicationLogging");
82
	private static Logger logMetacat = Logger.getLogger(ReplicationService.class);
83

    
84
	private ReplicationService() throws ServiceException {
85
		_serviceName = "ReplicationService";
86
		
87
		initialize();
88
	}
89
	
90
	private void initialize() throws ServiceException {
91
				
92
		// initialize db connections to handle any update requests
93
		// deltaT = util.getProperty("replication.deltaT");
94
		// the default deltaT can be set from metacat.properties
95
		// create a thread to do the delta-T check but don't execute it yet
96
		replicationDaemon = new Timer(true);
97
		try {
98
			String replLogFile = PropertyService.getProperty("replication.logdir")
99
				+ FileUtil.getFS() + REPLICATION_LOG_FILE_NAME;
100
			METACAT_REPL_ERROR_MSG = "An error occurred in replication.  Please see the " +
101
				"replication log at: " + replLogFile;
102
			
103
			String timedRepIsOnStr = 
104
				PropertyService.getProperty("replication.timedreplication");
105
			timedReplicationIsOn = (new Boolean(timedRepIsOnStr)).booleanValue();
106
			logReplication.info("ReplicationService.initialize - The timed replication on is" + timedReplicationIsOn);
107

    
108
			String timeIntervalStr = 
109
				PropertyService.getProperty("replication.timedreplicationinterval");
110
			timeInterval = (new Long(timeIntervalStr)).longValue();
111
			logReplication.info("ReplicationService.initialize - The timed replication time Interval is " + timeInterval);
112

    
113
			String firstTimeStr = 
114
				PropertyService.getProperty("replication.firsttimedreplication");
115
			logReplication.info("ReplicationService.initialize - first replication time form property is " + firstTimeStr);
116
			firstTime = ReplicationHandler.combinateCurrentDateAndGivenTime(firstTimeStr);
117

    
118
			logReplication.info("ReplicationService.initialize - After combine current time, the real first time is "
119
					+ firstTime.toString() + " minisec");
120

    
121
			// set up time replication if it is on
122
			if (timedReplicationIsOn) {
123
				replicationDaemon.scheduleAtFixedRate(new ReplicationHandler(),
124
						firstTime, timeInterval);
125
				logReplication.info("ReplicationService.initialize - deltaT handler started with rate="
126
						+ timeInterval + " mini seconds at " + firstTime.toString());
127
			}
128

    
129
		} catch (PropertyNotFoundException pnfe) {
130
			throw new ServiceException(
131
					"ReplicationService.initialize - Property error while instantiating "
132
							+ "replication service: " + pnfe.getMessage());
133
		} catch (HandlerException he) {
134
			throw new ServiceException(
135
					"ReplicationService.initialize - Handler error while instantiating "
136
							+ "replication service" + he.getMessage());
137
		} 
138
	}
139

    
140
	/**
141
	 * Get the single instance of SessionService.
142
	 * 
143
	 * @return the single instance of SessionService
144
	 */
145
	public static ReplicationService getInstance() throws ServiceException {
146
		if (replicationService == null) {
147
			replicationService = new ReplicationService();
148
		}
149
		return replicationService;
150
	}
151

    
152
	public boolean refreshable() {
153
		return true;
154
	}
155

    
156
	protected void doRefresh() throws ServiceException {
157
		return;
158
	}
159
	
160
	public void stop() throws ServiceException{
161
		
162
	}
163

    
164
	public void stopReplication() throws ServiceException {
165
	      //stop the replication server
166
	      replicationDaemon.cancel();
167
	      replicationDaemon = new Timer(true);
168
	      timedReplicationIsOn = false;
169
	      try {
170
	    	  PropertyService.setProperty("replication.timedreplication", (new Boolean(timedReplicationIsOn)).toString());
171
	      } catch (GeneralPropertyException gpe) {
172
	    	  logReplication.warn("ReplicationService.stopReplication - Could not set replication.timedreplication property: " + gpe.getMessage());
173
	      }
174

    
175
	      logReplication.info("ReplicationService.stopReplication - deltaT handler stopped");
176
		return;
177
	}
178
	
179
	protected void startReplication(Hashtable<String, String[]> params) throws ServiceException {
180

    
181
	       String firstTimeStr = "";
182
	      //start the replication server
183
	       if ( params.containsKey("rate") ) {
184
	        timeInterval = new Long(
185
	               new String(((String[])params.get("rate"))[0])).longValue();
186
	        if(timeInterval < TIMEINTERVALLIMIT) {
187
	            //deltaT<30 is a timing mess!
188
	            timeInterval = TIMEINTERVALLIMIT;
189
	            throw new ServiceException("Replication deltaT rate cannot be less than "+
190
	                    TIMEINTERVALLIMIT + " millisecs and system automatically setup the rate to "+TIMEINTERVALLIMIT);
191
	        }
192
	      } else {
193
	        timeInterval = TIMEINTERVALLIMIT ;
194
	      }
195
	      logReplication.info("ReplicationService.startReplication - New rate is: " + timeInterval + " mini seconds.");
196
	      if ( params.containsKey("firsttime"))
197
	      {
198
	         firstTimeStr = ((String[])params.get("firsttime"))[0];
199
	         try
200
	         {
201
	           firstTime = ReplicationHandler.combinateCurrentDateAndGivenTime(firstTimeStr);
202
	           logReplication.info("ReplicationService.startReplication - The first time setting is "+firstTime.toString());
203
	         }
204
	         catch (HandlerException e)
205
	         {
206
	            throw new ServiceException(e.getMessage());
207
	         }
208
	         logReplication.warn("After combine current time, the real first time is "
209
	                                  +firstTime.toString()+" minisec");
210
	      }
211
	      else
212
	      {
213
	    	  logMetacat.error("ReplicationService.startReplication - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
214
	          logReplication.error("ReplicationService.startReplication - You should specify the first time " +
215
	                                  "to start a time replication");
216
	          return;
217
	      }
218
	      
219
	      timedReplicationIsOn = true;
220
	      try {
221
	      // save settings to property file
222
	      PropertyService.setProperty(TIMEREPLICATION, (new Boolean(timedReplicationIsOn)).toString());
223
	      // note we couldn't use firstTime object because it has date info
224
	      // we only need time info such as 10:00 PM
225
	      PropertyService.setProperty(FIRSTTIME, firstTimeStr);
226
	      PropertyService.setProperty(TIMEREPLICATIONINTERVAl, (new Long(timeInterval)).toString());
227
	      } catch (GeneralPropertyException gpe) {
228
	    	  logReplication.warn("ReplicationService.startReplication - Could not set property: " + gpe.getMessage());
229
	      }
230
	      replicationDaemon.cancel();
231
	      replicationDaemon = new Timer(true);
232
	      replicationDaemon.scheduleAtFixedRate(new ReplicationHandler(), firstTime,
233
	                                            timeInterval);
234
	      
235
	      logReplication.info("ReplicationService.startReplication - deltaT handler started with rate=" +
236
	                                    timeInterval + " milliseconds at " +firstTime.toString());
237

    
238
	}
239
	
240
	public void runOnce() throws ServiceException {
241
	      //updates this server exactly once
242
	      replicationDaemon.schedule(new ReplicationHandler(), 0);
243
	}
244

    
245
	/**
246
	 * This method can add, delete and list the servers currently included in
247
	 * xml_replication.
248
	 * action           subaction            other needed params
249
	 * ---------------------------------------------------------
250
	 * servercontrol    add                  server
251
	 * servercontrol    delete               server
252
	 * servercontrol    list
253
	 */
254
	protected static void handleServerControlRequest(PrintWriter out,
255
			Hashtable<String, String[]> params, HttpServletResponse response) {
256
		String subaction = ((String[]) params.get("subaction"))[0];
257
		DBConnection dbConn = null;
258
		int serialNumber = -1;
259
		PreparedStatement pstmt = null;
260
		String replicate = null;
261
		String server = null;
262
		String dataReplicate = null;
263
		String hub = null;
264
		try {
265
			//conn = util.openDBConnection();
266
			dbConn = DBConnectionPool
267
					.getDBConnection("MetacatReplication.handleServerControlRequest");
268
			serialNumber = dbConn.getCheckOutSerialNumber();
269

    
270
			// add server to server list
271
			if (subaction.equals("add")) {
272
				replicate = ((String[]) params.get("replicate"))[0];
273
				server = ((String[]) params.get("server"))[0];
274

    
275
				//Get data replication value
276
				dataReplicate = ((String[]) params.get("datareplicate"))[0];
277
				//Get hub value
278
				hub = ((String[]) params.get("hub"))[0];
279

    
280
				/*pstmt = dbConn.prepareStatement("INSERT INTO xml_replication " +
281
				          "(server, last_checked, replicate, datareplicate, hub) " +
282
				                              "VALUES ('" + server + "', to_date(" +
283
				                              "'01/01/00', 'MM/DD/YY'), '" +
284
				                              replicate +"', '" +dataReplicate+"', '"
285
				                              + hub +"')");*/
286
				pstmt = dbConn.prepareStatement("INSERT INTO xml_replication "
287
						+ "(server, last_checked, replicate, datareplicate, hub) "
288
						+ "VALUES ('"
289
						+ server
290
						+ "', "
291
						+ DatabaseService.getDBAdapter().toDate("01/01/1980",
292
								"MM/DD/YYYY") + ", '" + replicate + "', '"
293
						+ dataReplicate + "', '" + hub + "')");
294

    
295
				pstmt.execute();
296
				pstmt.close();
297
				dbConn.commit();
298
				out.println("Server " + server + " added");
299
				response.setContentType("text/html");
300
				out.println("<html><body><table border=\"1\">");
301
				out.println("<tr><td><b>server</b></td><td><b>last_checked</b></td><td>");
302
				out.println("<b>replicate</b></td>");
303
				out.println("<td><b>datareplicate</b></td>");
304
				out.println("<td><b>hub</b></td></tr>");
305
				pstmt = dbConn.prepareStatement("SELECT * FROM xml_replication");
306
				//increase dbconnection usage
307
				dbConn.increaseUsageCount(1);
308

    
309
				pstmt.execute();
310
				ResultSet rs = pstmt.getResultSet();
311
				boolean tablehasrows = rs.next();
312
				while (tablehasrows) {
313
					out.println("<tr><td>" + rs.getString(2) + "</td><td>");
314
					out.println(rs.getString(3) + "</td><td>");
315
					out.println(rs.getString(4) + "</td><td>");
316
					out.println(rs.getString(5) + "</td><td>");
317
					out.println(rs.getString(6) + "</td></tr>");
318

    
319
					tablehasrows = rs.next();
320
				}
321
				out.println("</table></body></html>");
322

    
323
				// download certificate with the public key on this server
324
				// and import it as a trusted certificate
325
				String certURL = ((String[]) params.get("certificate"))[0];
326
				downloadCertificate(certURL);
327

    
328
				// delete server from server list
329
			} else if (subaction.equals("delete")) {
330
				server = ((String[]) params.get("server"))[0];
331
				pstmt = dbConn.prepareStatement("DELETE FROM xml_replication "
332
						+ "WHERE server LIKE '" + server + "'");
333
				pstmt.execute();
334
				pstmt.close();
335
				dbConn.commit();
336
				out.println("Server " + server + " deleted");
337
				response.setContentType("text/html");
338
				out.println("<html><body><table border=\"1\">");
339
				out.println("<tr><td><b>server</b></td><td><b>last_checked</b></td><td>");
340
				out.println("<b>replicate</b></td>");
341
				out.println("<td><b>datareplicate</b></td>");
342
				out.println("<td><b>hub</b></td></tr>");
343

    
344
				pstmt = dbConn.prepareStatement("SELECT * FROM xml_replication");
345
				//increase dbconnection usage
346
				dbConn.increaseUsageCount(1);
347
				pstmt.execute();
348
				ResultSet rs = pstmt.getResultSet();
349
				boolean tablehasrows = rs.next();
350
				while (tablehasrows) {
351
					out.println("<tr><td>" + rs.getString(2) + "</td><td>");
352
					out.println(rs.getString(3) + "</td><td>");
353
					out.println(rs.getString(4) + "</td><td>");
354
					out.println(rs.getString(5) + "</td><td>");
355
					out.println(rs.getString(6) + "</td></tr>");
356
					tablehasrows = rs.next();
357
				}
358
				out.println("</table></body></html>");
359

    
360
				// list servers in server list
361
			} else if (subaction.equals("list")) {
362
				response.setContentType("text/html");
363
				out.println("<html><body><table border=\"1\">");
364
				out.println("<tr><td><b>server</b></td><td><b>last_checked</b></td><td>");
365
				out.println("<b>replicate</b></td>");
366
				out.println("<td><b>datareplicate</b></td>");
367
				out.println("<td><b>hub</b></td></tr>");
368
				pstmt = dbConn.prepareStatement("SELECT * FROM xml_replication");
369
				pstmt.execute();
370
				ResultSet rs = pstmt.getResultSet();
371
				boolean tablehasrows = rs.next();
372
				while (tablehasrows) {
373
					out.println("<tr><td>" + rs.getString(2) + "</td><td>");
374
					out.println(rs.getString(3) + "</td><td>");
375
					out.println(rs.getString(4) + "</td><td>");
376
					out.println(rs.getString(5) + "</td><td>");
377
					out.println(rs.getString(6) + "</td></tr>");
378
					tablehasrows = rs.next();
379
				}
380
				out.println("</table></body></html>");
381
			} else {
382

    
383
				out.println("<error>Unkonwn subaction</error>");
384

    
385
			}
386
			pstmt.close();
387
			//conn.close();
388

    
389
		} catch (Exception e) {
390
			logMetacat.error("ReplicationService.handleServerControlRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
391
			logReplication.error("ReplicationService.handleServerControlRequest - Error in "
392
					+ "MetacatReplication.handleServerControlRequest " + e.getMessage());
393
			e.printStackTrace(System.out);
394
		} finally {
395
			try {
396
				pstmt.close();
397
			}//try
398
			catch (SQLException ee) {
399
				logMetacat.error("ReplicationService.handleServerControlRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
400
				logReplication.error("ReplicationService.handleServerControlRequest - Error in MetacatReplication.handleServerControlRequest to close pstmt "
401
						+ ee.getMessage());
402
			}//catch
403
			finally {
404
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
405
			}//finally
406
		}//finally
407

    
408
	}
409

    
410
	// download certificate with the public key from certURL and
411
	// upload it onto this server; it then must be imported as a
412
	// trusted certificate
413
	private static void downloadCertificate(String certURL) throws FileNotFoundException,
414
			IOException, MalformedURLException, PropertyNotFoundException {
415

    
416
		// the path to be uploaded to
417
		String certPath = SystemUtil.getContextDir();
418

    
419
		// get filename from the URL of the certificate
420
		String filename = certURL;
421
		int slash = Math.max(filename.lastIndexOf('/'), filename.lastIndexOf('\\'));
422
		if (slash > -1) {
423
			filename = filename.substring(slash + 1);
424
		}
425

    
426
		// open file output strem to write the input into it
427
		File f = new File(certPath, filename);
428
		synchronized (f) {
429
			try {
430
				if (f.exists()) {
431
					throw new IOException("File already exist: " + f.getCanonicalFile());
432
					// if ( f.exists() && !f.canWrite() ) {
433
					// throw new IOException("Not writable: " +
434
					// f.getCanonicalFile());
435
				}
436
			} catch (SecurityException se) {
437
				// if a security manager exists,
438
				// its checkRead method is called for f.exist()
439
				// or checkWrite method is called for f.canWrite()
440
				throw se;
441
			}
442

    
443
			// create a buffered byte output stream
444
			// that uses a default-sized output buffer
445
			FileOutputStream fos = new FileOutputStream(f);
446
			BufferedOutputStream out = new BufferedOutputStream(fos);
447

    
448
			// this should be http url
449
			URL url = new URL(certURL);
450
			BufferedInputStream bis = null;
451
			try {
452
				bis = new BufferedInputStream(url.openStream());
453
				byte[] buf = new byte[4 * 1024]; // 4K buffer
454
				int b = bis.read(buf);
455
				while (b != -1) {
456
					out.write(buf, 0, b);
457
					b = bis.read(buf);
458
				}
459
			} finally {
460
				if (bis != null)
461
					bis.close();
462
			}
463
			// the input and the output streams must be closed
464
			bis.close();
465
			out.flush();
466
			out.close();
467
			fos.close();
468
		} // end of synchronized(f)
469
	}
470

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

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

    
504
			// get the document info from server
505
			URL docinfourl = new URL("https://" + server + "?server="
506
					+ MetacatUtil.getLocalReplicationServerName()
507
					+ "&action=getdocumentinfo&docid=" + docid);
508

    
509
			String docInfoStr = ReplicationService.getURLContent(docinfourl);
510

    
511
			//dih is the parser for the docinfo xml format
512
			DocInfoHandler dih = new DocInfoHandler();
513
			XMLReader docinfoParser = ReplicationHandler.initParser(dih);
514
			docinfoParser.parse(new InputSource(new StringReader(docInfoStr)));
515
			//      Hashtable<String,Vector<AccessControlForSingleFile>> docinfoHash = dih.getDocInfo();
516
			Hashtable<String, String> docinfoHash = dih.getDocInfo();
517

    
518
			// Get user owner of this docid
519
			String user = (String) docinfoHash.get("user_owner");
520
			// Get home server of this docid
521
			String homeServer = (String) docinfoHash.get("home_server");
522
			String createdDate = (String) docinfoHash.get("date_created");
523
			String updatedDate = (String) docinfoHash.get("date_updated");
524
			logReplication.info("ReplicationService.handleForceReplicateRequest - homeServer: " + homeServer);
525
			// Get Document type
526
			String docType = (String) docinfoHash.get("doctype");
527
			logReplication.info("ReplicationService.handleForceReplicateRequest - docType: " + docType);
528
			String parserBase = null;
529
			// this for eml2 and we need user eml2 parser
530
			if (docType != null
531
					&& (docType.trim()).equals(DocumentImpl.EML2_0_0NAMESPACE)) {
532
				logReplication.warn("ReplicationService.handleForceReplicateRequest - This is an eml200 document!");
533
				parserBase = DocumentImpl.EML200;
534
			} else if (docType != null
535
					&& (docType.trim()).equals(DocumentImpl.EML2_0_1NAMESPACE)) {
536
				logReplication.warn("ReplicationService.handleForceReplicateRequest - This is an eml2.0.1 document!");
537
				parserBase = DocumentImpl.EML200;
538
			} else if (docType != null
539
					&& (docType.trim()).equals(DocumentImpl.EML2_1_0NAMESPACE)) {
540
				logReplication.warn("ReplicationService.handleForceReplicateRequest - This is an eml2.1.0 document!");
541
				parserBase = DocumentImpl.EML210;
542
			}
543
			logReplication.warn("ReplicationService.handleForceReplicateRequest - The parserBase is: " + parserBase);
544

    
545
			// Get DBConnection from pool
546
			dbConn = DBConnectionPool
547
					.getDBConnection("MetacatReplication.handleForceReplicateRequest");
548
			serialNumber = dbConn.getCheckOutSerialNumber();
549
			// write the document to local database
550
			DocumentImplWrapper wrapper = new DocumentImplWrapper(parserBase, false);
551
			//try this independently so we can set
552
			Exception writeException = null;
553
			try {
554
				wrapper.writeReplication(dbConn, new StringReader(xmldoc), null, null,
555
						dbaction, docid, user, null, homeServer, server, createdDate,
556
						updatedDate);
557
			} catch (Exception e) {
558
				writeException = e;
559
			}
560

    
561
			//process extra access rules before dealing with the write exception (doc exist already)
562
//			Vector<AccessControlForSingleFile> accessControlList = dih
563
//					.getAccessControlList();
564
			
565
	        Vector<XMLAccessDAO> accessControlList = dih.getAccessControlList();
566
	        if (accessControlList != null) {
567
	        	AccessControlForSingleFile acfsf = new AccessControlForSingleFile(docid);
568
	        	for (XMLAccessDAO xmlAccessDAO : accessControlList) {
569
	        		if (!acfsf.accessControlExists(xmlAccessDAO)) {
570
	        			acfsf.insertPermissions(xmlAccessDAO);
571
						logReplication.info("ReplicationService.handleForceReplicateRequest - document " + docid
572
								+ " permissions added to DB");
573
	        		}
574
	            }
575
	        }
576
//			if (accessControlList != null) {
577
//				for (int i = 0; i < accessControlList.size(); i++) {
578
//					AccessControlForSingleFile acfsf = (AccessControlForSingleFile) accessControlList
579
//							.get(i);
580
//					if (!acfsf.accessControlExists()) {
581
//						acfsf.insertPermissions();
582
//						logReplication.info("ReplicationService.handleForceReplicateRequest - document " + docid
583
//								+ " permissions added to DB");
584
//					}
585
//				}
586
//			}
587

    
588
			if (writeException != null) {
589
				throw writeException;
590
			}
591

    
592
			logReplication.info("ReplicationService.handleForceReplicateRequest - document " + docid + " added to DB with "
593
					+ "action " + dbaction);
594
			EventLog.getInstance().log(request.getRemoteAddr(), REPLICATIONUSER, docid,
595
					dbaction);
596
		}//try
597
		catch (Exception e) {
598
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
599
			logReplication.error("document " + docid
600
					+ " failed to added to DB with " + "action " + dbaction + " because "
601
					+ e.getMessage());
602
			logReplication.error("ReplicationService.handleForceReplicateRequest - "
603
					+ "error: " + e.getMessage());
604

    
605
		}//catch
606
		finally {
607
			// Return the checked out DBConnection
608
			DBConnectionPool.returnDBConnection(dbConn, serialNumber);
609
		}//finally
610
	}
611

    
612
	/*
613
	 * when a forcereplication delete request comes in, local host will delete this
614
	 * document
615
	 */
616
	protected static void handleForceReplicateDeleteRequest(PrintWriter out,
617
			Hashtable<String, String[]> params, HttpServletResponse response,
618
			HttpServletRequest request) {
619
		String server = ((String[]) params.get("server"))[0]; // the server that
620
		String docid = ((String[]) params.get("docid"))[0]; // sent the document
621
		try {
622
			logReplication.info("ReplicationService.handleForceReplicateDeleteRequest - force replication delete request from " + server);
623
			logReplication.info("ReplicationService.handleForceReplicateDeleteRequest - force replication delete docid " + docid);
624
			logReplication.info("ReplicationService.handleForceReplicateDeleteRequest - Force replication delete request from: " + server);
625
			logReplication.info("ReplicationService.handleForceReplicateDeleteRequest - Force replication delete docid: " + docid);
626
			DocumentImpl.delete(docid, null, null, server);
627
			logReplication.info("ReplicationService.handleForceReplicateDeleteRequest - document " + docid + " was successfully deleted ");
628
			EventLog.getInstance().log(request.getRemoteAddr(), REPLICATIONUSER, docid,
629
					"delete");
630
			logReplication.info("ReplicationService.handleForceReplicateDeleteRequest - document " + docid + " was successfully deleted ");
631
		} catch (Exception e) {
632
			logMetacat.error("ReplicationService.handleForceReplicateDeleteRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
633
			logReplication.error("document " + docid
634
					+ " failed to delete because " + e.getMessage());
635
			logReplication.error("ReplicationService.handleForceReplicateDeleteRequest - error: " + e.getMessage());
636

    
637
		}//catch
638

    
639
	}
640

    
641
	/**
642
	 * when a forcereplication data file request comes in, local host sends a
643
	 * readdata request to the requesting server (remote server) for the specified
644
	 * docid. Then store it in local database and file system
645
	 */
646
	protected static void handleForceReplicateDataFileRequest(Hashtable<String, String[]> params,
647
			HttpServletRequest request) {
648

    
649
		//make sure there is some parameters
650
		if (params.isEmpty()) {
651
			return;
652
		}
653
		// Get remote server
654
		String server = ((String[]) params.get("server"))[0];
655
		// the docid should include rev number
656
		String docid = ((String[]) params.get("docid"))[0];
657
		// Make sure there is a docid and server
658
		if (docid == null || server == null || server.equals("")) {
659
			logMetacat.error("ReplicationService.handleForceReplicateDataFileRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
660
			logReplication.error("ReplicationService.handleForceReplicateDataFileRequest - Didn't specify docid or server for replication");
661
			return;
662
		}
663

    
664
		// Overide or not
665
		//    boolean override = false;
666
		// dbaction - update or insert
667
		String dbaction = null;
668

    
669
		try {
670
			//docid was switch to two parts uinque code and rev
671
			//String uniqueCode=MetacatUtil.getDocIdFromString(docid);
672
			//int rev=MetacatUtil.getVersionFromString(docid);
673
			if (params.containsKey("dbaction")) {
674
				dbaction = ((String[]) params.get("dbaction"))[0];
675
			} else//default value is update
676
			{
677
				dbaction = "update";
678
			}
679

    
680
			logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - force replication request from " + server);
681
			logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - Force replication request from: " + server);
682
			logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - Force replication docid: " + docid);
683
			logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - Force replication action: " + dbaction);
684
			// get the document info from server
685
			URL docinfourl = new URL("https://" + server + "?server="
686
					+ MetacatUtil.getLocalReplicationServerName()
687
					+ "&action=getdocumentinfo&docid=" + docid);
688

    
689
			String docInfoStr = ReplicationService.getURLContent(docinfourl);
690

    
691
			//dih is the parser for the docinfo xml format
692
			DocInfoHandler dih = new DocInfoHandler();
693
			XMLReader docinfoParser = ReplicationHandler.initParser(dih);
694
			docinfoParser.parse(new InputSource(new StringReader(docInfoStr)));
695
			Hashtable<String, String> docinfoHash = dih.getDocInfo();
696
			String user = (String) docinfoHash.get("user_owner");
697

    
698
			String docName = (String) docinfoHash.get("docname");
699

    
700
			String docType = (String) docinfoHash.get("doctype");
701

    
702
			String docHomeServer = (String) docinfoHash.get("home_server");
703

    
704
			String createdDate = (String) docinfoHash.get("date_created");
705

    
706
			String updatedDate = (String) docinfoHash.get("date_updated");
707
			logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - docHomeServer of datafile: " + docHomeServer);
708

    
709
			//if action is delete, we don't delete the data file. Just archieve
710
			//the xml_documents
711
			/*if (dbaction.equals("delete"))
712
			{
713
			  //conn = util.getConnection();
714
			  DocumentImpl.delete(docid,user,null);
715
			  //util.returnConnection(conn);
716
			}*/
717
			//To data file insert or update is same
718
			if (dbaction.equals("insert") || dbaction.equals("update")) {
719
				//Get data file and store it into local file system.
720
				// sending back readdata request to server
721
				URL url = new URL("https://" + server + "?server="
722
						+ MetacatUtil.getLocalReplicationServerName()
723
						+ "&action=readdata&docid=" + docid);
724
				String datafilePath = PropertyService
725
						.getProperty("application.datafilepath");
726

    
727
				Exception writeException = null;
728
				//register data file into xml_documents table and wite data file
729
				//into file system
730
				try {
731
					DocumentImpl.writeDataFileInReplication(url.openStream(),
732
							datafilePath, docName, docType, docid, user, docHomeServer,
733
							server, DocumentImpl.DOCUMENTTABLE, false, createdDate,
734
							updatedDate);
735
				} catch (Exception e) {
736
					writeException = e;
737
				}
738
				//process extra access rules
739
//				Vector<AccessControlForSingleFile> accessControlList = dih
740
//						.getAccessControlList();
741
//				if (accessControlList != null) {
742
//					for (int i = 0; i < accessControlList.size(); i++) {
743
//						AccessControlForSingleFile acfsf = (AccessControlForSingleFile) accessControlList
744
//								.get(i);
745
//						if (!acfsf.accessControlExists()) {
746
//							acfsf.insertPermissions();
747
//							logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - datafile " + docid
748
//									+ " permissions added to DB");
749
//						}
750
//					}
751
//				}
752
				
753
		        Vector<XMLAccessDAO> accessControlList = dih.getAccessControlList();
754
		        if (accessControlList != null) {
755
		        	AccessControlForSingleFile acfsf = new AccessControlForSingleFile(docid);
756
		        	for (XMLAccessDAO xmlAccessDAO : accessControlList) {
757
		        		if (!acfsf.accessControlExists(xmlAccessDAO)) {
758
		        			acfsf.insertPermissions(xmlAccessDAO);
759
							logReplication.info("ReplicationService.handleForceReplicateRequest - document " + docid
760
									+ " permissions added to DB");
761
		        		}
762
		            }
763
		        }
764

    
765
				if (writeException != null) {
766
					throw writeException;
767
				}
768

    
769
				//false means non-timed replication
770
				logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - datafile " + docid + " added to DB with "
771
						+ "action " + dbaction);
772
				EventLog.getInstance().log(request.getRemoteAddr(), REPLICATIONUSER,
773
						docid, dbaction);
774
			}
775

    
776
		} catch (Exception e) {
777
			logMetacat.error("ReplicationService.handleForceReplicateDataFileRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
778
			logReplication.error("ReplicationService.handleForceReplicateDataFileRequest - Datafile " + docid
779
					+ " failed to added to DB with " + "action " + dbaction + " because "
780
					+ e.getMessage());
781
			logReplication.error("ReplicationService.handleForceReplicateDataFileRequest - ERROR in MetacatReplication.handleForceDataFileReplicate"
782
					+ "Request(): " + e.getMessage());
783
		}
784
	}
785

    
786
	/**
787
	 * Grants or denies a lock to a requesting host.
788
	 * The servlet parameters of interrest are:
789
	 * docid: the docid of the file the lock is being requested for
790
	 * currentdate: the timestamp of the document on the remote server
791
	 *
792
	 */
793
	protected static void handleGetLockRequest(PrintWriter out,
794
			Hashtable<String, String[]> params, HttpServletResponse response) {
795

    
796
		try {
797

    
798
			String docid = ((String[]) params.get("docid"))[0];
799
			String remoteRev = ((String[]) params.get("updaterev"))[0];
800
			DocumentImpl requestDoc = new DocumentImpl(docid);
801
			logReplication.info("ReplicationService.handleGetLockRequest - lock request for " + docid);
802
			int localRevInt = requestDoc.getRev();
803
			int remoteRevInt = Integer.parseInt(remoteRev);
804

    
805
			if (remoteRevInt >= localRevInt) {
806
				if (!fileLocks.contains(docid)) { //grant the lock if it is not already locked
807
					fileLocks.add(0, docid); //insert at the beginning of the queue Vector
808
					//send a message back to the the remote host authorizing the insert
809
					out
810
							.println("<lockgranted><docid>" + docid
811
									+ "</docid></lockgranted>");
812
					//          lockThread = new Thread(this);
813
					//          lockThread.setPriority(Thread.MIN_PRIORITY);
814
					//          lockThread.start();
815
					logReplication.info("ReplicationService.handleGetLockRequest - lock granted for " + docid);
816
				} else { //deny the lock
817
					out.println("<filelocked><docid>" + docid + "</docid></filelocked>");
818
					logReplication.info("ReplicationService.handleGetLockRequest - lock denied for " + docid
819
							+ "reason: file already locked");
820
				}
821
			} else {//deny the lock.
822
				out.println("<outdatedfile><docid>" + docid + "</docid></filelocked>");
823
				logReplication.info("ReplicationService.handleGetLockRequest - lock denied for " + docid
824
						+ "reason: client has outdated file");
825
			}
826
			//conn.close();
827
		} catch (Exception e) {
828
			logMetacat.error("ReplicationService.handleGetLockRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
829
			logReplication.error("ReplicationService.handleGetLockRequest - error requesting file lock from MetacatReplication."
830
					+ "handleGetLockRequest: " + e.getMessage());
831
			e.printStackTrace(System.out);
832
		}
833
	}
834

    
835
	/**
836
	 * Sends all of the xml_documents information encoded in xml to a requestor
837
	 * the format is:
838
	 * <!ELEMENT documentinfo (docid, docname, doctype, doctitle, user_owner,
839
	 *                  user_updated, home_server, public_access, rev)/>
840
	 * all of the subelements of document info are #PCDATA
841
	 */
842
	protected static void handleGetDocumentInfoRequest(PrintWriter out,
843
			Hashtable<String, String[]> params, HttpServletResponse response) {
844
		String docid = ((String[]) (params.get("docid")))[0];
845
		StringBuffer sb = new StringBuffer();
846

    
847
		try {
848

    
849
			DocumentImpl doc = new DocumentImpl(docid);
850
			sb.append("<documentinfo><docid>").append(docid);
851
			sb.append("</docid><docname>").append(doc.getDocname());
852
			sb.append("</docname><doctype>").append(doc.getDoctype());
853
			sb.append("</doctype>");
854
			sb.append("<user_owner>").append(doc.getUserowner());
855
			sb.append("</user_owner><user_updated>").append(doc.getUserupdated());
856
			sb.append("</user_updated>");
857
			sb.append("<date_created>");
858
			sb.append(doc.getCreateDate());
859
			sb.append("</date_created>");
860
			sb.append("<date_updated>");
861
			sb.append(doc.getUpdateDate());
862
			sb.append("</date_updated>");
863
			sb.append("<home_server>");
864
			sb.append(doc.getDocHomeServer());
865
			sb.append("</home_server>");
866
			sb.append("<public_access>").append(doc.getPublicaccess());
867
			sb.append("</public_access><rev>").append(doc.getRev());
868
			sb.append("</rev>");
869

    
870
			sb.append("<accessControl>");
871

    
872
			AccessControlForSingleFile acfsf = new AccessControlForSingleFile(docid); 
873
			sb.append(acfsf.getAccessString());
874
			
875
			sb.append("</accessControl>");
876

    
877
			sb.append("</documentinfo>");
878
			response.setContentType("text/xml");
879
			out.println(sb.toString());
880

    
881
		} catch (Exception e) {
882
			logMetacat.error("ReplicationService.handleGetDocumentInfoRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
883
			logReplication.error("ReplicationService.handleGetDocumentInfoRequest - error in metacatReplication.handlegetdocumentinforequest "
884
					+ "for doc: " + docid + " : " + e.getMessage());
885
		}
886

    
887
	}
888

    
889
	/**
890
	 * Sends a datafile to a remote host
891
	 */
892
	protected static void handleGetDataFileRequest(OutputStream outPut,
893
			Hashtable<String, String[]> params, HttpServletResponse response)
894

    
895
	{
896
		// File path for data file
897
		String filepath;
898
		// Request docid
899
		String docId = ((String[]) (params.get("docid")))[0];
900
		//check if the doicd is null
901
		if (docId == null) {
902
			logMetacat.error("ReplicationService.handleGetDataFileRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
903
			logReplication.error("ReplicationService.handleGetDataFileRequest - Didn't specify docid for replication");
904
			return;
905
		}
906

    
907
		//try to open a https stream to test if the request server's public key
908
		//in the key store, this is security issue
909
		try {
910
			filepath = PropertyService.getProperty("application.datafilepath");
911
			String server = params.get("server")[0];
912
			URL u = new URL("https://" + server + "?server="
913
					+ MetacatUtil.getLocalReplicationServerName() + "&action=test");
914
			String test = ReplicationService.getURLContent(u);
915
			//couldn't pass the test
916
			if (test.indexOf("successfully") == -1) {
917
				//response.setContentType("text/xml");
918
				//outPut.println("<error>Couldn't pass the trust test</error>");
919
				logMetacat.error("ReplicationService.handleGetDataFileRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
920
				logReplication.error("ReplicationService.handleGetDataFileRequest - Couldn't pass the trust test");
921
				return;
922
			}
923
		}//try
924
		catch (Exception ee) {
925
			return;
926
		}//catch
927

    
928
		if (!filepath.endsWith("/")) {
929
			filepath += "/";
930
		}
931
		// Get file aboslute file name
932
		String filename = filepath + docId;
933

    
934
		//MIME type
935
		String contentType = null;
936
		if (filename.endsWith(".xml")) {
937
			contentType = "text/xml";
938
		} else if (filename.endsWith(".css")) {
939
			contentType = "text/css";
940
		} else if (filename.endsWith(".dtd")) {
941
			contentType = "text/plain";
942
		} else if (filename.endsWith(".xsd")) {
943
			contentType = "text/xml";
944
		} else if (filename.endsWith("/")) {
945
			contentType = "text/html";
946
		} else {
947
			File f = new File(filename);
948
			if (f.isDirectory()) {
949
				contentType = "text/html";
950
			} else {
951
				contentType = "application/octet-stream";
952
			}
953
		}
954

    
955
		// Set the mime type
956
		response.setContentType(contentType);
957

    
958
		// Get the content of the file
959
		FileInputStream fin = null;
960
		try {
961
			// FileInputStream to metacat
962
			fin = new FileInputStream(filename);
963
			// 4K buffer
964
			byte[] buf = new byte[4 * 1024];
965
			// Read data from file input stream to byte array
966
			int b = fin.read(buf);
967
			// Write to outStream from byte array
968
			while (b != -1) {
969
				outPut.write(buf, 0, b);
970
				b = fin.read(buf);
971
			}
972
			// close file input stream
973
			fin.close();
974

    
975
		}//try
976
		catch (Exception e) {
977
			logMetacat.error("ReplicationService.handleGetDataFileRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
978
			logReplication.error("ReplicationService.handleGetDataFileRequest - error getting data file from MetacatReplication."
979
					+ "handlGetDataFileRequest " + e.getMessage());
980
			e.printStackTrace(System.out);
981
		}//catch
982

    
983
	}
984

    
985
	/**
986
	 * Sends a document to a remote host
987
	 */
988
	protected static void handleGetDocumentRequest(PrintWriter out,
989
			Hashtable<String, String[]> params, HttpServletResponse response) {
990

    
991
		String urlString = null;
992
		String documentPath = null;
993
		try {
994
			// try to open a https stream to test if the request server's public
995
			// key
996
			// in the key store, this is security issue
997
			String server = params.get("server")[0];
998
			urlString = "https://" + server + "?server="
999
					+ MetacatUtil.getLocalReplicationServerName() + "&action=test";
1000
			URL u = new URL(urlString);
1001
			String test = ReplicationService.getURLContent(u);
1002
			// couldn't pass the test
1003
			if (test.indexOf("successfully") == -1) {
1004
				response.setContentType("text/xml");
1005
				out.println("<error>Couldn't pass the trust test " + test + " </error>");
1006
				out.close();
1007
				return;
1008
			}
1009

    
1010
			String docid = params.get("docid")[0];
1011
			logReplication.debug("ReplicationService.handleGetDocumentRequest - MetacatReplication.handleGetDocumentRequest for docid: "
1012
					+ docid);
1013
			DocumentImpl di = new DocumentImpl(docid);
1014

    
1015
			String documentDir = PropertyService
1016
					.getProperty("application.documentfilepath");
1017
			documentPath = documentDir + FileUtil.getFS() + docid;
1018

    
1019
			// if the document does not exist on disk, read it from db and write
1020
			// it to disk.
1021
			if (FileUtil.getFileStatus(documentPath) == FileUtil.DOES_NOT_EXIST
1022
					|| FileUtil.getFileSize(documentPath) == 0) {
1023
				FileWriter fileWriter = new FileWriter(documentPath);
1024
				di.toXml(fileWriter, null, null, true);
1025
			}
1026

    
1027
			// read the file from disk and sent it to PrintWriter
1028
			// PrintWriter out = new PrintWriter(streamOut);
1029
			di.readFromFileSystem(out, null, null, documentPath);
1030

    
1031
			// response.setContentType("text/xml");
1032
			// out.print(di.toString(null, null, true));
1033

    
1034
			logReplication.info("ReplicationService.handleGetDocumentRequest - document " + docid + " sent");
1035

    
1036
		} catch (MalformedURLException mue) {
1037
			logMetacat.error("ReplicationService.handleGetDocumentRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1038
			logReplication.error("ReplicationService.handleGetDocumentRequest - Url error when getting document from MetacatReplication."
1039
					+ "handlGetDocumentRequest for url: " + urlString + " : "
1040
					+ mue.getMessage());
1041
			// e.printStackTrace(System.out);
1042
			response.setContentType("text/xml");
1043
			out.println("<error>" + mue.getMessage() + "</error>");
1044
		} catch (IOException ioe) {
1045
			logMetacat.error("ReplicationService.handleGetDocumentRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1046
			logReplication.error("ReplicationService.handleGetDocumentRequest - I/O error when getting document from MetacatReplication."
1047
					+ "handlGetDocumentRequest for file: " + documentPath + " : "
1048
					+ ioe.getMessage());
1049
			// e.printStackTrace(System.out);
1050
			response.setContentType("text/xml");
1051
			out.println("<error>" + ioe.getMessage() + "</error>");
1052
		} catch (PropertyNotFoundException pnfe) {
1053
			logMetacat.error("ReplicationService.handleGetDocumentRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1054
			logReplication
1055
					.error("ReplicationService.handleGetDocumentRequest - Error getting property when getting document from MetacatReplication."
1056
							+ "handlGetDocumentRequest for file: "
1057
							+ documentPath
1058
							+ " : "
1059
							+ pnfe.getMessage());
1060
			// e.printStackTrace(System.out);
1061
			response.setContentType("text/xml");
1062
			out.println("<error>" + pnfe.getMessage() + "</error>");
1063
		} catch (McdbException me) {
1064
			logReplication
1065
					.error("ReplicationService.handleGetDocumentRequest - Document implementation error  getting property when getting document from MetacatReplication."
1066
							+ "handlGetDocumentRequest for file: "
1067
							+ documentPath
1068
							+ " : "
1069
							+ me.getMessage());
1070
			// e.printStackTrace(System.out);
1071
			response.setContentType("text/xml");
1072
			out.println("<error>" + me.getMessage() + "</error>");
1073
		}
1074

    
1075
	}
1076

    
1077
	/**
1078
	 * Sends a list of all of the documents on this sever along with their
1079
	 * revision numbers. The format is: <!ELEMENT replication (server, updates)>
1080
	 * <!ELEMENT server (#PCDATA)> <!ELEMENT updates ((updatedDocument |
1081
	 * deleteDocument | revisionDocument)*)> <!ELEMENT updatedDocument (docid,
1082
	 * rev, datafile*)> <!ELEMENT deletedDocument (docid, rev)> <!ELEMENT
1083
	 * revisionDocument (docid, rev, datafile*)> <!ELEMENT docid (#PCDATA)>
1084
	 * <!ELEMENT rev (#PCDATA)> <!ELEMENT datafile (#PCDATA)> note that the rev
1085
	 * in deletedDocument is always empty. I just left it in there to make the
1086
	 * parser implementation easier.
1087
	 */
1088
	protected static void handleUpdateRequest(PrintWriter out, Hashtable<String, String[]> params,
1089
			HttpServletResponse response) {
1090
		// Checked out DBConnection
1091
		DBConnection dbConn = null;
1092
		// DBConenction serial number when checked it out
1093
		int serialNumber = -1;
1094
		PreparedStatement pstmt = null;
1095
		// Server list to store server info of xml_replication table
1096
		ReplicationServerList serverList = null;
1097

    
1098
		try {
1099
			// Check out a DBConnection from pool
1100
			dbConn = DBConnectionPool
1101
					.getDBConnection("MetacatReplication.handleUpdateRequest");
1102
			serialNumber = dbConn.getCheckOutSerialNumber();
1103
			// Create a server list from xml_replication table
1104
			serverList = new ReplicationServerList();
1105

    
1106
			// Get remote server name from param
1107
			String server = ((String[]) params.get("server"))[0];
1108
			// If no servr name in param, return a error
1109
			if (server == null || server.equals("")) {
1110
				response.setContentType("text/xml");
1111
				out.println("<error>Request didn't specify server name</error>");
1112
				out.close();
1113
				return;
1114
			}//if
1115

    
1116
			//try to open a https stream to test if the request server's public key
1117
			//in the key store, this is security issue
1118
			URL u = new URL("https://" + server + "?server="
1119
					+ MetacatUtil.getLocalReplicationServerName() + "&action=test");
1120
			String test = ReplicationService.getURLContent(u);
1121
			//couldn't pass the test
1122
			if (test.indexOf("successfully") == -1) {
1123
				response.setContentType("text/xml");
1124
				out.println("<error>Couldn't pass the trust test</error>");
1125
				out.close();
1126
				return;
1127
			}
1128

    
1129
			// Check if local host configure to replicate xml documents to remote
1130
			// server. If not send back a error message
1131
			if (!serverList.getReplicationValue(server)) {
1132
				response.setContentType("text/xml");
1133
				out
1134
						.println("<error>Configuration not allow to replicate document to you</error>");
1135
				out.close();
1136
				return;
1137
			}//if
1138

    
1139
			// Store the sql command
1140
			StringBuffer docsql = new StringBuffer();
1141
			StringBuffer revisionSql = new StringBuffer();
1142
			// Stroe the docid list
1143
			StringBuffer doclist = new StringBuffer();
1144
			// Store the deleted docid list
1145
			StringBuffer delsql = new StringBuffer();
1146
			// Store the data set file
1147
			Vector<Vector<String>> packageFiles = new Vector<Vector<String>>();
1148

    
1149
			// Append local server's name and replication servlet to doclist
1150
			doclist.append("<?xml version=\"1.0\"?><replication>");
1151
			doclist.append("<server>")
1152
					.append(MetacatUtil.getLocalReplicationServerName());
1153
			//doclist.append(util.getProperty("replicationpath"));
1154
			doclist.append("</server><updates>");
1155

    
1156
			// Get correct docid that reside on this server according the requesting
1157
			// server's replicate and data replicate value in xml_replication table
1158
			docsql.append(DatabaseService.getDBAdapter().getReplicationDocumentListSQL());
1159
			//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)) ");
1160
			revisionSql.append("select docid, rev, doctype from xml_revisions ");
1161
			// If the localhost is not a hub to the remote server, only replicate
1162
			// the docid' which home server is local host (server_location =1)
1163
			if (!serverList.getHubValue(server)) {
1164
				String serverLocationDoc = " and a.server_location = 1";
1165
				String serverLocationRev = "where server_location = 1";
1166
				docsql.append(serverLocationDoc);
1167
				revisionSql.append(serverLocationRev);
1168
			}
1169
			logReplication.info("ReplicationService.handleUpdateRequest - Doc sql: " + docsql.toString());
1170

    
1171
			// Get any deleted documents
1172
			delsql.append("select distinct docid from ");
1173
			delsql.append("xml_revisions where docid not in (select docid from ");
1174
			delsql.append("xml_documents) ");
1175
			// If the localhost is not a hub to the remote server, only replicate
1176
			// the docid' which home server is local host (server_location =1)
1177
			if (!serverList.getHubValue(server)) {
1178
				delsql.append("and server_location = 1");
1179
			}
1180
			logReplication.info("ReplicationService.handleUpdateRequest - Deleted sql: " + delsql.toString());
1181

    
1182
			// Get docid list of local host
1183
			pstmt = dbConn.prepareStatement(docsql.toString());
1184
			pstmt.execute();
1185
			ResultSet rs = pstmt.getResultSet();
1186
			boolean tablehasrows = rs.next();
1187
			//If metacat configed to replicate data file
1188
			//if ((util.getProperty("replicationsenddata")).equals("on"))
1189
			boolean replicateData = serverList.getDataReplicationValue(server);
1190
			if (replicateData) {
1191
				while (tablehasrows) {
1192
					String recordDoctype = rs.getString(3);
1193
					Vector<String> packagedoctypes = MetacatUtil
1194
							.getOptionList(PropertyService
1195
									.getProperty("xml.packagedoctype"));
1196
					//if this is a package file, put it at the end
1197
					//because if a package file is read before all of the files it
1198
					//refers to are loaded then there is an error
1199
					if (recordDoctype != null && !packagedoctypes.contains(recordDoctype)) {
1200
						//If this is not data file
1201
						if (!recordDoctype.equals("BIN")) {
1202
							//for non-data file document
1203
							doclist.append("<updatedDocument>");
1204
							doclist.append("<docid>").append(rs.getString(1));
1205
							doclist.append("</docid><rev>").append(rs.getInt(2));
1206
							doclist.append("</rev>");
1207
							doclist.append("</updatedDocument>");
1208
						}//if
1209
						else {
1210
							//for data file document, in datafile attributes
1211
							//we put "datafile" value there
1212
							doclist.append("<updatedDocument>");
1213
							doclist.append("<docid>").append(rs.getString(1));
1214
							doclist.append("</docid><rev>").append(rs.getInt(2));
1215
							doclist.append("</rev>");
1216
							doclist.append("<datafile>");
1217
							doclist.append(PropertyService
1218
									.getProperty("replication.datafileflag"));
1219
							doclist.append("</datafile>");
1220
							doclist.append("</updatedDocument>");
1221
						}//else
1222
					}//if packagedoctpes
1223
					else { //the package files are saved to be put into the xml later.
1224
						Vector<String> v = new Vector<String>();
1225
						v.add(rs.getString(1));
1226
						v.add(String.valueOf(rs.getInt(2)));
1227
						packageFiles.add(v);
1228
					}//esle
1229
					tablehasrows = rs.next();
1230
				}//while
1231
			}//if
1232
			else //metacat was configured not to send data file
1233
			{
1234
				while (tablehasrows) {
1235
					String recordDoctype = rs.getString(3);
1236
					if (!recordDoctype.equals("BIN")) { //don't replicate data files
1237
						Vector<String> packagedoctypes = MetacatUtil
1238
								.getOptionList(PropertyService
1239
										.getProperty("xml.packagedoctype"));
1240
						if (recordDoctype != null
1241
								&& !packagedoctypes.contains(recordDoctype)) { //if this is a package file, put it at the end
1242
							//because if a package file is read before all of the files it
1243
							//refers to are loaded then there is an error
1244
							doclist.append("<updatedDocument>");
1245
							doclist.append("<docid>").append(rs.getString(1));
1246
							doclist.append("</docid><rev>").append(rs.getInt(2));
1247
							doclist.append("</rev>");
1248
							doclist.append("</updatedDocument>");
1249
						} else { //the package files are saved to be put into the xml later.
1250
							Vector<String> v = new Vector<String>();
1251
							v.add(rs.getString(1));
1252
							v.add(String.valueOf(rs.getInt(2)));
1253
							packageFiles.add(v);
1254
						}
1255
					}//if
1256
					tablehasrows = rs.next();
1257
				}//while
1258
			}//else
1259

    
1260
			pstmt = dbConn.prepareStatement(delsql.toString());
1261
			//usage count should increas 1
1262
			dbConn.increaseUsageCount(1);
1263

    
1264
			pstmt.execute();
1265
			rs = pstmt.getResultSet();
1266
			tablehasrows = rs.next();
1267
			while (tablehasrows) { //handle the deleted documents
1268
				doclist.append("<deletedDocument><docid>").append(rs.getString(1));
1269
				doclist.append("</docid><rev></rev></deletedDocument>");
1270
				//note that rev is always empty for deleted docs
1271
				tablehasrows = rs.next();
1272
			}
1273

    
1274
			//now we can put the package files into the xml results
1275
			for (int i = 0; i < packageFiles.size(); i++) {
1276
				Vector<String> v = packageFiles.elementAt(i);
1277
				doclist.append("<updatedDocument>");
1278
				doclist.append("<docid>").append(v.elementAt(0));
1279
				doclist.append("</docid><rev>");
1280
				doclist.append(v.elementAt(1));
1281
				doclist.append("</rev>");
1282
				doclist.append("</updatedDocument>");
1283
			}
1284
			// add revision doc list  
1285
			doclist.append(prepareRevisionDoc(dbConn, revisionSql.toString(),
1286
					replicateData));
1287

    
1288
			doclist.append("</updates></replication>");
1289
			logReplication.info("ReplicationService.handleUpdateRequest - doclist: " + doclist.toString());
1290
			pstmt.close();
1291
			//conn.close();
1292
			response.setContentType("text/xml");
1293
			out.println(doclist.toString());
1294

    
1295
		} catch (Exception e) {
1296
			logMetacat.error("ReplicationService.handleUpdateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1297
			logReplication.error("ReplicationService.handleUpdateRequest - error in MetacatReplication." + "handleupdaterequest: "
1298
					+ e.getMessage());
1299
			//e.printStackTrace(System.out);
1300
			response.setContentType("text/xml");
1301
			out.println("<error>" + e.getMessage() + "</error>");
1302
		} finally {
1303
			try {
1304
				pstmt.close();
1305
			}//try
1306
			catch (SQLException ee) {
1307
				logMetacat.error("ReplicationService.handleUpdateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1308
				logReplication.error("ReplicationService.handleUpdateRequest - Error in MetacatReplication."
1309
						+ "handleUpdaterequest to close pstmt: " + ee.getMessage());
1310
			}//catch
1311
			finally {
1312
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1313
			}//finally
1314
		}//finally
1315

    
1316
	}//handlUpdateRequest
1317

    
1318
	/*
1319
	 * This method will get the xml string for document in xml_revision
1320
	 * The schema look like <!ELEMENT revisionDocument (docid, rev, datafile*)>
1321
	 */
1322
	private static String prepareRevisionDoc(DBConnection dbConn, String revSql,
1323
			boolean replicateData) throws Exception {
1324
		logReplication.warn("ReplicationService.prepareRevisionDoc - The revision document sql is " + revSql);
1325
		StringBuffer revDocList = new StringBuffer();
1326
		PreparedStatement pstmt = dbConn.prepareStatement(revSql);
1327
		//usage count should increas 1
1328
		dbConn.increaseUsageCount(1);
1329

    
1330
		pstmt.execute();
1331
		ResultSet rs = pstmt.getResultSet();
1332
		boolean tablehasrows = rs.next();
1333
		while (tablehasrows) {
1334
			String recordDoctype = rs.getString(3);
1335

    
1336
			//If this is data file and it isn't configured to replicate data
1337
			if (recordDoctype.equals("BIN") && !replicateData) {
1338
				// do nothing
1339
				continue;
1340
			} else {
1341

    
1342
				revDocList.append("<revisionDocument>");
1343
				revDocList.append("<docid>").append(rs.getString(1));
1344
				revDocList.append("</docid><rev>").append(rs.getInt(2));
1345
				revDocList.append("</rev>");
1346
				// data file
1347
				if (recordDoctype.equals("BIN")) {
1348
					revDocList.append("<datafile>");
1349
					revDocList.append(PropertyService
1350
							.getProperty("replication.datafileflag"));
1351
					revDocList.append("</datafile>");
1352
				}
1353
				revDocList.append("</revisionDocument>");
1354

    
1355
			}//else
1356
			tablehasrows = rs.next();
1357
		}
1358
		//System.out.println("The revision list is"+ revDocList.toString());
1359
		return revDocList.toString();
1360
	}
1361

    
1362
	/**
1363
	 * Returns the xml_catalog table encoded in xml
1364
	 */
1365
	public static String getCatalogXML() {
1366
		return handleGetCatalogRequest(null, null, null, false);
1367
	}
1368

    
1369
	/**
1370
	 * Sends the contents of the xml_catalog table encoded in xml
1371
	 * The xml format is:
1372
	 * <!ELEMENT xml_catalog (row*)>
1373
	 * <!ELEMENT row (entry_type, source_doctype, target_doctype, public_id,
1374
	 *                system_id)>
1375
	 * All of the sub elements of row are #PCDATA
1376

    
1377
	 * If printFlag == false then do not print to out.
1378
	 */
1379
	protected static String handleGetCatalogRequest(PrintWriter out,
1380
			Hashtable<String, String[]> params, HttpServletResponse response,
1381
			boolean printFlag) {
1382
		DBConnection dbConn = null;
1383
		int serialNumber = -1;
1384
		PreparedStatement pstmt = null;
1385
		try {
1386
			/*conn = MetacatReplication.getDBConnection("MetacatReplication." +
1387
			                                          "handleGetCatalogRequest");*/
1388
			dbConn = DBConnectionPool
1389
					.getDBConnection("MetacatReplication.handleGetCatalogRequest");
1390
			serialNumber = dbConn.getCheckOutSerialNumber();
1391
			pstmt = dbConn.prepareStatement("select entry_type, "
1392
					+ "source_doctype, target_doctype, public_id, "
1393
					+ "system_id from xml_catalog");
1394
			pstmt.execute();
1395
			ResultSet rs = pstmt.getResultSet();
1396
			boolean tablehasrows = rs.next();
1397
			StringBuffer sb = new StringBuffer();
1398
			sb.append("<?xml version=\"1.0\"?><xml_catalog>");
1399
			while (tablehasrows) {
1400
				sb.append("<row><entry_type>").append(rs.getString(1));
1401
				sb.append("</entry_type><source_doctype>").append(rs.getString(2));
1402
				sb.append("</source_doctype><target_doctype>").append(rs.getString(3));
1403
				sb.append("</target_doctype><public_id>").append(rs.getString(4));
1404
				// system id may not have server url on front.  Add it if not.
1405
				String systemID = rs.getString(5);
1406
				if (!systemID.startsWith("http://")) {
1407
					systemID = SystemUtil.getContextURL() + systemID;
1408
				}
1409
				sb.append("</public_id><system_id>").append(systemID);
1410
				sb.append("</system_id></row>");
1411

    
1412
				tablehasrows = rs.next();
1413
			}
1414
			sb.append("</xml_catalog>");
1415
			//conn.close();
1416
			if (printFlag) {
1417
				response.setContentType("text/xml");
1418
				out.println(sb.toString());
1419
			}
1420
			pstmt.close();
1421
			return sb.toString();
1422
		} catch (Exception e) {
1423
			logMetacat.error("ReplicationService.handleGetCatalogRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1424
			logReplication.error("ReplicationService.handleGetCatalogRequest - error in MetacatReplication.handleGetCatalogRequest:"
1425
					+ e.getMessage());
1426
			e.printStackTrace(System.out);
1427
			if (printFlag) {
1428
				out.println("<error>" + e.getMessage() + "</error>");
1429
			}
1430
		} finally {
1431
			try {
1432
				pstmt.close();
1433
			}//try
1434
			catch (SQLException ee) {
1435
				logMetacat.error("ReplicationService.handleGetCatalogRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1436
				logReplication.error("ReplicationService.handleGetCatalogRequest - Error in MetacatReplication.handleGetCatalogRequest: "
1437
						+ ee.getMessage());
1438
			}//catch
1439
			finally {
1440
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1441
			}//finally
1442
		}//finally
1443

    
1444
		return null;
1445
	}
1446

    
1447
	/**
1448
	 * Sends the current system date to the remote server.  Using this action
1449
	 * for replication gets rid of any problems with syncronizing clocks
1450
	 * because a time specific to a document is always kept on its home server.
1451
	 */
1452
	protected static void handleGetTimeRequest(PrintWriter out,
1453
			Hashtable<String, String[]> params, HttpServletResponse response) {
1454
		SimpleDateFormat formatter = new SimpleDateFormat("MM/dd/yy HH:mm:ss");
1455
		java.util.Date localtime = new java.util.Date();
1456
		String dateString = formatter.format(localtime);
1457
		response.setContentType("text/xml");
1458

    
1459
		out.println("<timestamp>" + dateString + "</timestamp>");
1460
	}
1461

    
1462
	/**
1463
	 * this method handles the timeout for a file lock.  when a lock is
1464
	 * granted it is granted for 30 seconds.  When this thread runs out
1465
	 * it deletes the docid from the queue, thus eliminating the lock.
1466
	 */
1467
	public void run() {
1468
		try {
1469
			logReplication.info("ReplicationService.run - thread started for docid: "
1470
					+ (String) fileLocks.elementAt(0));
1471

    
1472
			Thread.sleep(30000); //the lock will expire in 30 seconds
1473
			logReplication.info("thread for docid: "
1474
					+ (String) fileLocks.elementAt(fileLocks.size() - 1) + " exiting.");
1475

    
1476
			fileLocks.remove(fileLocks.size() - 1);
1477
			//fileLocks is treated as a FIFO queue.  If there are more than one lock
1478
			//in the vector, the first one inserted will be removed.
1479
		} catch (Exception e) {
1480
			logMetacat.error("ReplicationService.run - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1481
			logReplication.error("ReplicationService.run - error in file lock thread from "
1482
					+ "MetacatReplication.run: " + e.getMessage());
1483
		}
1484
	}
1485

    
1486
	/**
1487
	 * Returns the name of a server given a serverCode
1488
	 * @param serverCode the serverid of the server
1489
	 * @return the servername or null if the specified serverCode does not
1490
	 *         exist.
1491
	 */
1492
	public static String getServerNameForServerCode(int serverCode) {
1493
		//System.out.println("serverid: " + serverCode);
1494
		DBConnection dbConn = null;
1495
		int serialNumber = -1;
1496
		PreparedStatement pstmt = null;
1497
		try {
1498
			dbConn = DBConnectionPool.getDBConnection("MetacatReplication.getServer");
1499
			serialNumber = dbConn.getCheckOutSerialNumber();
1500
			String sql = new String("select server from "
1501
					+ "xml_replication where serverid = " + serverCode);
1502
			pstmt = dbConn.prepareStatement(sql);
1503
			//System.out.println("getserver sql: " + sql);
1504
			pstmt.execute();
1505
			ResultSet rs = pstmt.getResultSet();
1506
			boolean tablehasrows = rs.next();
1507
			if (tablehasrows) {
1508
				//System.out.println("server: " + rs.getString(1));
1509
				return rs.getString(1);
1510
			}
1511

    
1512
			//conn.close();
1513
		} catch (Exception e) {
1514
			logMetacat.error("ReplicationService.getServerNameForServerCode - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1515
			logReplication.error("ReplicationService.getServerNameForServerCode - Error in MetacatReplication.getServer: " + e.getMessage());
1516
		} finally {
1517
			try {
1518
				pstmt.close();
1519
			}//try
1520
			catch (SQLException ee) {
1521
				logMetacat.error("ReplicationService.getServerNameForServerCode - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1522
				logReplication.error("ReplicationService.getServerNameForServerCode - Error in MetacactReplication.getserver: "
1523
						+ ee.getMessage());
1524
			}//catch
1525
			finally {
1526
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1527
			}//fianlly
1528
		}//finally
1529

    
1530
		return null;
1531
		//return null if the server does not exist
1532
	}
1533

    
1534
	/**
1535
	 * Returns a server code given a server name
1536
	 * @param server the name of the server
1537
	 * @return integer > 0 representing the code of the server, 0 if the server
1538
	 *  does not exist.
1539
	 */
1540
	public static int getServerCodeForServerName(String server) throws ServiceException {
1541
		DBConnection dbConn = null;
1542
		int serialNumber = -1;
1543
		PreparedStatement pstmt = null;
1544
		int serverCode = 0;
1545

    
1546
		try {
1547

    
1548
			//conn = util.openDBConnection();
1549
			dbConn = DBConnectionPool.getDBConnection("MetacatReplication.getServerCode");
1550
			serialNumber = dbConn.getCheckOutSerialNumber();
1551
			pstmt = dbConn.prepareStatement("SELECT serverid FROM xml_replication "
1552
					+ "WHERE server LIKE '" + server + "'");
1553
			pstmt.execute();
1554
			ResultSet rs = pstmt.getResultSet();
1555
			boolean tablehasrows = rs.next();
1556
			if (tablehasrows) {
1557
				serverCode = rs.getInt(1);
1558
				pstmt.close();
1559
				//conn.close();
1560
				return serverCode;
1561
			}
1562

    
1563
		} catch (SQLException sqle) {
1564
			throw new ServiceException("ReplicationService.getServerCodeForServerName - " 
1565
					+ "SQL error when getting server code: " + sqle.getMessage());
1566

    
1567
		} finally {
1568
			try {
1569
				pstmt.close();
1570
				//conn.close();
1571
			}//try
1572
			catch (Exception ee) {
1573
				logMetacat.error("ReplicationService.getServerCodeForServerName - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1574
				logReplication.error("ReplicationService.getServerNameForServerCode - Error in MetacatReplicatio.getServerCode: "
1575
						+ ee.getMessage());
1576

    
1577
			}//catch
1578
			finally {
1579
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1580
			}//finally
1581
		}//finally
1582

    
1583
		return serverCode;
1584
	}
1585

    
1586
	/**
1587
	 * Method to get a host server information for given docid
1588
	 * @param conn a connection to the database
1589
	 */
1590
	public static Hashtable<String, String> getHomeServerInfoForDocId(String docId) {
1591
		Hashtable<String, String> sl = new Hashtable<String, String>();
1592
		DBConnection dbConn = null;
1593
		int serialNumber = -1;
1594
		docId = DocumentUtil.getDocIdFromString(docId);
1595
		PreparedStatement pstmt = null;
1596
		int serverLocation;
1597
		try {
1598
			//get conection
1599
			dbConn = DBConnectionPool.getDBConnection("ReplicationHandler.getHomeServer");
1600
			serialNumber = dbConn.getCheckOutSerialNumber();
1601
			//get a server location from xml_document table
1602
			pstmt = dbConn.prepareStatement("select server_location from xml_documents "
1603
					+ "where docid = ?");
1604
			pstmt.setString(1, docId);
1605
			pstmt.execute();
1606
			ResultSet serverName = pstmt.getResultSet();
1607
			//get a server location
1608
			if (serverName.next()) {
1609
				serverLocation = serverName.getInt(1);
1610
				pstmt.close();
1611
			} else {
1612
				pstmt.close();
1613
				//ut.returnConnection(conn);
1614
				return null;
1615
			}
1616
			pstmt = dbConn.prepareStatement("select server, last_checked, replicate "
1617
					+ "from xml_replication where serverid = ?");
1618
			//increase usage count
1619
			dbConn.increaseUsageCount(1);
1620
			pstmt.setInt(1, serverLocation);
1621
			pstmt.execute();
1622
			ResultSet rs = pstmt.getResultSet();
1623
			boolean tableHasRows = rs.next();
1624
			if (tableHasRows) {
1625

    
1626
				String server = rs.getString(1);
1627
				String last_checked = rs.getString(2);
1628
				if (!server.equals("localhost")) {
1629
					sl.put(server, last_checked);
1630
				}
1631

    
1632
			} else {
1633
				pstmt.close();
1634
				//ut.returnConnection(conn);
1635
				return null;
1636
			}
1637
			pstmt.close();
1638
		} catch (Exception e) {
1639
			logMetacat.error("ReplicationService.getHomeServerInfoForDocId - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1640
			logReplication.error("ReplicationService.getHomeServerInfoForDocId - error in replicationHandler.getHomeServer(): "
1641
					+ e.getMessage());
1642
		} finally {
1643
			try {
1644
				pstmt.close();
1645
				//ut.returnConnection(conn);
1646
			} catch (Exception ee) {
1647
				logMetacat.error("ReplicationService.getHomeServerInfoForDocId - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1648
				logReplication.error("ReplicationService.getHomeServerInfoForDocId - Eror irn rplicationHandler.getHomeServer() "
1649
						+ "to close pstmt: " + ee.getMessage());
1650
			} finally {
1651
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1652
			}
1653

    
1654
		}//finally
1655
		return sl;
1656
	}
1657

    
1658
	/**
1659
	 * Returns a home server location  given a accnum
1660
	 * @param accNum , given accNum for a document
1661
	 *
1662
	 */
1663
	public static int getHomeServerCodeForDocId(String accNum) throws ServiceException {
1664
		DBConnection dbConn = null;
1665
		int serialNumber = -1;
1666
		PreparedStatement pstmt = null;
1667
		int serverCode = 1;
1668
		String docId = DocumentUtil.getDocIdFromString(accNum);
1669

    
1670
		try {
1671

    
1672
			// Get DBConnection
1673
			dbConn = DBConnectionPool
1674
					.getDBConnection("ReplicationHandler.getServerLocation");
1675
			serialNumber = dbConn.getCheckOutSerialNumber();
1676
			pstmt = dbConn.prepareStatement("SELECT server_location FROM xml_documents "
1677
					+ "WHERE docid LIKE '" + docId + "'");
1678
			pstmt.execute();
1679
			ResultSet rs = pstmt.getResultSet();
1680
			boolean tablehasrows = rs.next();
1681
			//If a document is find, return the server location for it
1682
			if (tablehasrows) {
1683
				serverCode = rs.getInt(1);
1684
				pstmt.close();
1685
				//conn.close();
1686
				return serverCode;
1687
			}
1688
			//if couldn't find in xml_documents table, we think server code is 1
1689
			//(this is new document)
1690
			else {
1691
				pstmt.close();
1692
				//conn.close();
1693
				return serverCode;
1694
			}
1695

    
1696
		} catch (SQLException sqle) {
1697
			throw new ServiceException("ReplicationService.getHomeServerCodeForDocId - " 
1698
					+ "SQL error when getting home server code for docid: " + docId + " : " 
1699
					+ sqle.getMessage());
1700

    
1701
		} finally {
1702
			try {
1703
				pstmt.close();
1704
				//conn.close();
1705

    
1706
			} catch (SQLException sqle) {
1707
				logMetacat.error("ReplicationService.getHomeServerCodeForDocId - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1708
				logReplication.error("ReplicationService.getHomeServerCodeForDocId - ReplicationService.getHomeServerCodeForDocId - " 
1709
						+ "SQL error when getting home server code for docid: " + docId + " : " 
1710
						+ sqle.getMessage());
1711
			} finally {
1712
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1713
			}//finally
1714
		}//finally
1715
		//return serverCode;
1716
	}
1717

    
1718
	/**
1719
	 * This method returns the content of a url
1720
	 * @param u the url to return the content from
1721
	 * @return a string representing the content of the url
1722
	 * @throws java.io.IOException
1723
	 */
1724
	public static String getURLContent(URL u) throws java.io.IOException {
1725
		char istreamChar;
1726
		int istreamInt;
1727
		logReplication.info("ReplicationService.getURLContent - Before open the stream" + u.toString());
1728
		InputStream input = u.openStream();
1729
		logReplication.info("ReplicationService.getURLContent - After open the stream" + u.toString());
1730
		InputStreamReader istream = new InputStreamReader(input);
1731
		StringBuffer serverResponse = new StringBuffer();
1732
		while ((istreamInt = istream.read()) != -1) {
1733
			istreamChar = (char) istreamInt;
1734
			serverResponse.append(istreamChar);
1735
		}
1736
		istream.close();
1737
		input.close();
1738

    
1739
		return serverResponse.toString();
1740
	}
1741

    
1742
//	/**
1743
//	 * Method for writing replication messages to a log file specified in
1744
//	 * metacat.properties
1745
//	 */
1746
//	public static void replLog(String message) {
1747
//		try {
1748
//			FileOutputStream fos = new FileOutputStream(PropertyService
1749
//					.getProperty("replication.logdir")
1750
//					+ "/metacatreplication.log", true);
1751
//			PrintWriter pw = new PrintWriter(fos);
1752
//			SimpleDateFormat formatter = new SimpleDateFormat("yy-MM-dd HH:mm:ss");
1753
//			java.util.Date localtime = new java.util.Date();
1754
//			String dateString = formatter.format(localtime);
1755
//			dateString += " :: " + message;
1756
//			// time stamp each entry
1757
//			pw.println(dateString);
1758
//			pw.flush();
1759
//		} catch (Exception e) {
1760
//			logReplication.error("error writing to replication log from "
1761
//					+ "MetacatReplication.replLog: " + e.getMessage());
1762
//			// e.printStackTrace(System.out);
1763
//		}
1764
//	}
1765

    
1766
//	/**
1767
//	 * Method for writing replication messages to a log file specified in
1768
//	 * metacat.properties
1769
//	 */
1770
//	public static void replErrorLog(String message) {
1771
//		try {
1772
//			FileOutputStream fos = new FileOutputStream(PropertyService
1773
//					.getProperty("replication.logdir")
1774
//					+ "/metacatreplicationerror.log", true);
1775
//			PrintWriter pw = new PrintWriter(fos);
1776
//			SimpleDateFormat formatter = new SimpleDateFormat("yy-MM-dd HH:mm:ss");
1777
//			java.util.Date localtime = new java.util.Date();
1778
//			String dateString = formatter.format(localtime);
1779
//			dateString += " :: " + message;
1780
//			//time stamp each entry
1781
//			pw.println(dateString);
1782
//			pw.flush();
1783
//		} catch (Exception e) {
1784
//			logReplication.error("error writing to replication error log from "
1785
//					+ "MetacatReplication.replErrorLog: " + e.getMessage());
1786
//			//e.printStackTrace(System.out);
1787
//		}
1788
//	}
1789

    
1790
	/**
1791
	 * Returns true if the replicate field for server in xml_replication is 1.
1792
	 * Returns false otherwise
1793
	 */
1794
	public static boolean replToServer(String server) {
1795
		DBConnection dbConn = null;
1796
		int serialNumber = -1;
1797
		PreparedStatement pstmt = null;
1798
		try {
1799
			dbConn = DBConnectionPool.getDBConnection("MetacatReplication.repltoServer");
1800
			serialNumber = dbConn.getCheckOutSerialNumber();
1801
			pstmt = dbConn.prepareStatement("select replicate from "
1802
					+ "xml_replication where server like '" + server + "'");
1803
			pstmt.execute();
1804
			ResultSet rs = pstmt.getResultSet();
1805
			boolean tablehasrows = rs.next();
1806
			if (tablehasrows) {
1807
				int i = rs.getInt(1);
1808
				if (i == 1) {
1809
					pstmt.close();
1810
					//conn.close();
1811
					return true;
1812
				} else {
1813
					pstmt.close();
1814
					//conn.close();
1815
					return false;
1816
				}
1817
			}
1818
		} catch (SQLException sqle) {
1819
			logMetacat.error("ReplicationService.replToServer - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1820
			logReplication.error("ReplicationService.replToServer - SQL error in MetacatReplication.replToServer: "
1821
					+ sqle.getMessage());
1822
		} finally {
1823
			try {
1824
				pstmt.close();
1825
				//conn.close();
1826
			}//try
1827
			catch (Exception ee) {
1828
				logMetacat.error("ReplicationService.replToServer - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1829
				logReplication.error("ReplicationService.replToServer - Error in MetacatReplication.replToServer: "
1830
						+ ee.getMessage());
1831
			}//catch
1832
			finally {
1833
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1834
			}//finally
1835
		}//finally
1836
		return false;
1837
		//the default if this server does not exist is to not replicate to it.
1838
	}
1839

    
1840
}
(6-6/7)