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-12-02 16:00:41 -0800 (Wed, 02 Dec 2009) $'
10
 * '$Revision: 5151 $'
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
				String toDateSql = DatabaseService.getDBAdapter().toDate("01/01/1980","MM/DD/YYYY");
281
				String sql = "INSERT INTO xml_replication "
282
						+ "(server, last_checked, replicate, datareplicate, hub) "
283
						+ "VALUES (?," + toDateSql + ",?,?,?)";
284
				
285
				pstmt = dbConn.prepareStatement(sql);
286
						
287
				pstmt.setString(1, server);
288
				pstmt.setInt(2, Integer.parseInt(replicate));
289
				pstmt.setInt(3, Integer.parseInt(dataReplicate));
290
				pstmt.setInt(4, Integer.parseInt(hub));
291
				
292
				String sqlReport = "XMLAccessAccess.getXMLAccessForDoc - SQL: " + sql;
293
				sqlReport += " [" + server + "," + replicate + 
294
					"," + dataReplicate + "," + hub + "]";
295
				
296
				logMetacat.info(sqlReport);
297
				
298
				pstmt.execute();
299
				pstmt.close();
300
				dbConn.commit();
301
				out.println("Server " + server + " added");
302
				response.setContentType("text/html");
303
				out.println("<html><body><table border=\"1\">");
304
				out.println("<tr><td><b>server</b></td><td><b>last_checked</b></td><td>");
305
				out.println("<b>replicate</b></td>");
306
				out.println("<td><b>datareplicate</b></td>");
307
				out.println("<td><b>hub</b></td></tr>");
308
				pstmt = dbConn.prepareStatement("SELECT * FROM xml_replication");
309
				//increase dbconnection usage
310
				dbConn.increaseUsageCount(1);
311

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

    
322
					tablehasrows = rs.next();
323
				}
324
				out.println("</table></body></html>");
325

    
326
				// download certificate with the public key on this server
327
				// and import it as a trusted certificate
328
				String certURL = ((String[]) params.get("certificate"))[0];
329
				if (certURL != null && !certURL.equals("")) {
330
					downloadCertificate(certURL);
331
				}
332

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

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

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

    
388
				out.println("<error>Unkonwn subaction</error>");
389

    
390
			}
391
			pstmt.close();
392
			//conn.close();
393

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

    
413
	}
414

    
415
	// download certificate with the public key from certURL and
416
	// upload it onto this server; it then must be imported as a
417
	// trusted certificate
418
	private static void downloadCertificate(String certURL) throws FileNotFoundException,
419
			IOException, MalformedURLException, PropertyNotFoundException {
420

    
421
		// the path to be uploaded to
422
		String certPath = SystemUtil.getContextDir();
423

    
424
		// get filename from the URL of the certificate
425
		String filename = certURL;
426
		int slash = Math.max(filename.lastIndexOf('/'), filename.lastIndexOf('\\'));
427
		if (slash > -1) {
428
			filename = filename.substring(slash + 1);
429
		}
430

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

    
448
			// create a buffered byte output stream
449
			// that uses a default-sized output buffer
450
			FileOutputStream fos = new FileOutputStream(f);
451
			BufferedOutputStream out = new BufferedOutputStream(fos);
452

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

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

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

    
509
			// get the document info from server
510
			URL docinfourl = new URL("https://" + server + "?server="
511
					+ MetacatUtil.getLocalReplicationServerName()
512
					+ "&action=getdocumentinfo&docid=" + docid);
513

    
514
			String docInfoStr = ReplicationService.getURLContent(docinfourl);
515

    
516
			//dih is the parser for the docinfo xml format
517
			DocInfoHandler dih = new DocInfoHandler();
518
			XMLReader docinfoParser = ReplicationHandler.initParser(dih);
519
			docinfoParser.parse(new InputSource(new StringReader(docInfoStr)));
520
			//      Hashtable<String,Vector<AccessControlForSingleFile>> docinfoHash = dih.getDocInfo();
521
			Hashtable<String, String> docinfoHash = dih.getDocInfo();
522

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

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

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

    
593
			if (writeException != null) {
594
				throw writeException;
595
			}
596

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

    
610
		}//catch
611
		finally {
612
			// Return the checked out DBConnection
613
			DBConnectionPool.returnDBConnection(dbConn, serialNumber);
614
		}//finally
615
	}
616

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

    
642
		}//catch
643

    
644
	}
645

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

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

    
669
		// Overide or not
670
		//    boolean override = false;
671
		// dbaction - update or insert
672
		String dbaction = null;
673

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

    
685
			logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - force replication request from " + server);
686
			logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - Force replication request from: " + server);
687
			logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - Force replication docid: " + docid);
688
			logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - Force replication action: " + dbaction);
689
			// get the document info from server
690
			URL docinfourl = new URL("https://" + server + "?server="
691
					+ MetacatUtil.getLocalReplicationServerName()
692
					+ "&action=getdocumentinfo&docid=" + docid);
693

    
694
			String docInfoStr = ReplicationService.getURLContent(docinfourl);
695

    
696
			//dih is the parser for the docinfo xml format
697
			DocInfoHandler dih = new DocInfoHandler();
698
			XMLReader docinfoParser = ReplicationHandler.initParser(dih);
699
			docinfoParser.parse(new InputSource(new StringReader(docInfoStr)));
700
			Hashtable<String, String> docinfoHash = dih.getDocInfo();
701
			String user = (String) docinfoHash.get("user_owner");
702

    
703
			String docName = (String) docinfoHash.get("docname");
704

    
705
			String docType = (String) docinfoHash.get("doctype");
706

    
707
			String docHomeServer = (String) docinfoHash.get("home_server");
708

    
709
			String createdDate = (String) docinfoHash.get("date_created");
710

    
711
			String updatedDate = (String) docinfoHash.get("date_updated");
712
			logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - docHomeServer of datafile: " + docHomeServer);
713

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

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

    
770
				if (writeException != null) {
771
					throw writeException;
772
				}
773

    
774
				//false means non-timed replication
775
				logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - datafile " + docid + " added to DB with "
776
						+ "action " + dbaction);
777
				EventLog.getInstance().log(request.getRemoteAddr(), REPLICATIONUSER,
778
						docid, dbaction);
779
			}
780

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

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

    
801
		try {
802

    
803
			String docid = ((String[]) params.get("docid"))[0];
804
			String remoteRev = ((String[]) params.get("updaterev"))[0];
805
			DocumentImpl requestDoc = new DocumentImpl(docid);
806
			logReplication.info("ReplicationService.handleGetLockRequest - lock request for " + docid);
807
			int localRevInt = requestDoc.getRev();
808
			int remoteRevInt = Integer.parseInt(remoteRev);
809

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

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

    
852
		try {
853

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

    
875
			sb.append("<accessControl>");
876

    
877
			AccessControlForSingleFile acfsf = new AccessControlForSingleFile(docid); 
878
			sb.append(acfsf.getAccessString());
879
			
880
			sb.append("</accessControl>");
881

    
882
			sb.append("</documentinfo>");
883
			response.setContentType("text/xml");
884
			out.println(sb.toString());
885

    
886
		} catch (Exception e) {
887
			logMetacat.error("ReplicationService.handleGetDocumentInfoRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
888
			logReplication.error("ReplicationService.handleGetDocumentInfoRequest - error in metacatReplication.handlegetdocumentinforequest "
889
					+ "for doc: " + docid + " : " + e.getMessage());
890
		}
891

    
892
	}
893

    
894
	/**
895
	 * Sends a datafile to a remote host
896
	 */
897
	protected static void handleGetDataFileRequest(OutputStream outPut,
898
			Hashtable<String, String[]> params, HttpServletResponse response)
899

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

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

    
933
		if (!filepath.endsWith("/")) {
934
			filepath += "/";
935
		}
936
		// Get file aboslute file name
937
		String filename = filepath + docId;
938

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

    
960
		// Set the mime type
961
		response.setContentType(contentType);
962

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

    
980
		}//try
981
		catch (Exception e) {
982
			logMetacat.error("ReplicationService.handleGetDataFileRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
983
			logReplication.error("ReplicationService.handleGetDataFileRequest - error getting data file from MetacatReplication."
984
					+ "handlGetDataFileRequest " + e.getMessage());
985
			e.printStackTrace(System.out);
986
		}//catch
987

    
988
	}
989

    
990
	/**
991
	 * Sends a document to a remote host
992
	 */
993
	protected static void handleGetDocumentRequest(PrintWriter out,
994
			Hashtable<String, String[]> params, HttpServletResponse response) {
995

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

    
1015
			String docid = params.get("docid")[0];
1016
			logReplication.debug("ReplicationService.handleGetDocumentRequest - MetacatReplication.handleGetDocumentRequest for docid: "
1017
					+ docid);
1018
			DocumentImpl di = new DocumentImpl(docid);
1019

    
1020
			String documentDir = PropertyService
1021
					.getProperty("application.documentfilepath");
1022
			documentPath = documentDir + FileUtil.getFS() + docid;
1023

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

    
1032
			// read the file from disk and sent it to PrintWriter
1033
			// PrintWriter out = new PrintWriter(streamOut);
1034
			di.readFromFileSystem(out, null, null, documentPath);
1035

    
1036
			// response.setContentType("text/xml");
1037
			// out.print(di.toString(null, null, true));
1038

    
1039
			logReplication.info("ReplicationService.handleGetDocumentRequest - document " + docid + " sent");
1040

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

    
1080
	}
1081

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

    
1103
		try {
1104
			// Check out a DBConnection from pool
1105
			dbConn = DBConnectionPool
1106
					.getDBConnection("MetacatReplication.handleUpdateRequest");
1107
			serialNumber = dbConn.getCheckOutSerialNumber();
1108
			// Create a server list from xml_replication table
1109
			serverList = new ReplicationServerList();
1110

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

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

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

    
1144
			// Store the sql command
1145
			StringBuffer docsql = new StringBuffer();
1146
			StringBuffer revisionSql = new StringBuffer();
1147
			// Stroe the docid list
1148
			StringBuffer doclist = new StringBuffer();
1149
			// Store the deleted docid list
1150
			StringBuffer delsql = new StringBuffer();
1151
			// Store the data set file
1152
			Vector<Vector<String>> packageFiles = new Vector<Vector<String>>();
1153

    
1154
			// Append local server's name and replication servlet to doclist
1155
			doclist.append("<?xml version=\"1.0\"?><replication>");
1156
			doclist.append("<server>")
1157
					.append(MetacatUtil.getLocalReplicationServerName());
1158
			//doclist.append(util.getProperty("replicationpath"));
1159
			doclist.append("</server><updates>");
1160

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

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

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

    
1265
			pstmt = dbConn.prepareStatement(delsql.toString());
1266
			//usage count should increas 1
1267
			dbConn.increaseUsageCount(1);
1268

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

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

    
1293
			doclist.append("</updates></replication>");
1294
			logReplication.info("ReplicationService.handleUpdateRequest - doclist: " + doclist.toString());
1295
			pstmt.close();
1296
			//conn.close();
1297
			response.setContentType("text/xml");
1298
			out.println(doclist.toString());
1299

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

    
1321
	}//handlUpdateRequest
1322

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

    
1335
		pstmt.execute();
1336
		ResultSet rs = pstmt.getResultSet();
1337
		boolean tablehasrows = rs.next();
1338
		while (tablehasrows) {
1339
			String recordDoctype = rs.getString(3);
1340

    
1341
			//If this is data file and it isn't configured to replicate data
1342
			if (recordDoctype.equals("BIN") && !replicateData) {
1343
				// do nothing
1344
				continue;
1345
			} else {
1346

    
1347
				revDocList.append("<revisionDocument>");
1348
				revDocList.append("<docid>").append(rs.getString(1));
1349
				revDocList.append("</docid><rev>").append(rs.getInt(2));
1350
				revDocList.append("</rev>");
1351
				// data file
1352
				if (recordDoctype.equals("BIN")) {
1353
					revDocList.append("<datafile>");
1354
					revDocList.append(PropertyService
1355
							.getProperty("replication.datafileflag"));
1356
					revDocList.append("</datafile>");
1357
				}
1358
				revDocList.append("</revisionDocument>");
1359

    
1360
			}//else
1361
			tablehasrows = rs.next();
1362
		}
1363
		//System.out.println("The revision list is"+ revDocList.toString());
1364
		return revDocList.toString();
1365
	}
1366

    
1367
	/**
1368
	 * Returns the xml_catalog table encoded in xml
1369
	 */
1370
	public static String getCatalogXML() {
1371
		return handleGetCatalogRequest(null, null, null, false);
1372
	}
1373

    
1374
	/**
1375
	 * Sends the contents of the xml_catalog table encoded in xml
1376
	 * The xml format is:
1377
	 * <!ELEMENT xml_catalog (row*)>
1378
	 * <!ELEMENT row (entry_type, source_doctype, target_doctype, public_id,
1379
	 *                system_id)>
1380
	 * All of the sub elements of row are #PCDATA
1381

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

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

    
1449
		return null;
1450
	}
1451

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

    
1464
		out.println("<timestamp>" + dateString + "</timestamp>");
1465
	}
1466

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

    
1477
			Thread.sleep(30000); //the lock will expire in 30 seconds
1478
			logReplication.info("thread for docid: "
1479
					+ (String) fileLocks.elementAt(fileLocks.size() - 1) + " exiting.");
1480

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

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

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

    
1535
		return null;
1536
		//return null if the server does not exist
1537
	}
1538

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

    
1551
		try {
1552

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

    
1568
		} catch (SQLException sqle) {
1569
			throw new ServiceException("ReplicationService.getServerCodeForServerName - " 
1570
					+ "SQL error when getting server code: " + sqle.getMessage());
1571

    
1572
		} finally {
1573
			try {
1574
				pstmt.close();
1575
				//conn.close();
1576
			}//try
1577
			catch (Exception ee) {
1578
				logMetacat.error("ReplicationService.getServerCodeForServerName - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1579
				logReplication.error("ReplicationService.getServerNameForServerCode - Error in MetacatReplicatio.getServerCode: "
1580
						+ ee.getMessage());
1581

    
1582
			}//catch
1583
			finally {
1584
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1585
			}//finally
1586
		}//finally
1587

    
1588
		return serverCode;
1589
	}
1590

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

    
1631
				String server = rs.getString(1);
1632
				String last_checked = rs.getString(2);
1633
				if (!server.equals("localhost")) {
1634
					sl.put(server, last_checked);
1635
				}
1636

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

    
1659
		}//finally
1660
		return sl;
1661
	}
1662

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

    
1675
		try {
1676

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

    
1701
		} catch (SQLException sqle) {
1702
			throw new ServiceException("ReplicationService.getHomeServerCodeForDocId - " 
1703
					+ "SQL error when getting home server code for docid: " + docId + " : " 
1704
					+ sqle.getMessage());
1705

    
1706
		} finally {
1707
			try {
1708
				pstmt.close();
1709
				//conn.close();
1710

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

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

    
1744
		return serverResponse.toString();
1745
	}
1746

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

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

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

    
1845
}
(6-6/7)