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: 2010-01-19 10:25:28 -0800 (Tue, 19 Jan 2010) $'
10
 * '$Revision: 5195 $'
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.AccessControlException;
44
import edu.ucsb.nceas.metacat.accesscontrol.AccessControlForSingleFile;
45
import edu.ucsb.nceas.metacat.accesscontrol.PermOrderException;
46
import edu.ucsb.nceas.metacat.accesscontrol.XMLAccessDAO;
47
import edu.ucsb.nceas.metacat.database.DBConnection;
48
import edu.ucsb.nceas.metacat.database.DBConnectionPool;
49
import edu.ucsb.nceas.metacat.database.DatabaseService;
50
import edu.ucsb.nceas.metacat.properties.PropertyService;
51
import edu.ucsb.nceas.metacat.shared.BaseService;
52
import edu.ucsb.nceas.metacat.shared.HandlerException;
53
import edu.ucsb.nceas.metacat.shared.ServiceException;
54
import edu.ucsb.nceas.metacat.util.DocumentUtil;
55
import edu.ucsb.nceas.metacat.util.MetacatUtil;
56
import edu.ucsb.nceas.metacat.util.SystemUtil;
57
import edu.ucsb.nceas.utilities.FileUtil;
58
import edu.ucsb.nceas.utilities.GeneralPropertyException;
59
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
60

    
61
import org.apache.log4j.Logger;
62
import org.xml.sax.*;
63

    
64
public class ReplicationService extends BaseService {
65

    
66
	private static ReplicationService replicationService = null;
67

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

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

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

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

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

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

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

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

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

    
154
	public boolean refreshable() {
155
		return true;
156
	}
157

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
390
				out.println("<error>Unkonwn subaction</error>");
391

    
392
			}
393
			pstmt.close();
394
			//conn.close();
395

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

    
415
	}
416

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

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

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

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

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

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

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

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

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

    
516
			String docInfoStr = ReplicationService.getURLContent(docinfourl);
517

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

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

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

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

    
591
//				if (writeException != null) {
592
//					throw writeException;
593
//				}
594

    
595
				logReplication.info("ReplicationService.handleForceReplicateRequest - document " + docid + " added to DB with "
596
						+ "action " + dbaction);
597
				EventLog.getInstance().log(request.getRemoteAddr(), REPLICATIONUSER, docid,
598
						dbaction);
599
			}
600
		} catch (SQLException sqle) {
601
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
602
			logReplication.error("ReplicationService.handleForceReplicateRequest - SQL error when adding doc " + docid + 
603
					" to DB with action " + dbaction + ": " + sqle.getMessage());
604
		} catch (MalformedURLException mue) {
605
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
606
			logReplication.error("ReplicationService.handleForceReplicateRequest - URL error when adding doc " + docid + 
607
					" to DB with action " + dbaction + ": " + mue.getMessage());
608
		} catch (SAXException se) {
609
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
610
			logReplication.error("ReplicationService.handleForceReplicateRequest - SAX parsing error when adding doc " + docid + 
611
					" to DB with action " + dbaction + ": " + se.getMessage());
612
		} catch (HandlerException he) {
613
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
614
			logReplication.error("ReplicationService.handleForceReplicateRequest - Handler error when adding doc " + docid + 
615
					" to DB with action " + dbaction + ": " + he.getMessage());
616
		} catch (IOException ioe) {
617
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
618
			logReplication.error("ReplicationService.handleForceReplicateRequest - I/O error when adding doc " + docid + 
619
					" to DB with action " + dbaction + ": " + ioe.getMessage());
620
		} catch (PermOrderException poe) {
621
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
622
			logReplication.error("ReplicationService.handleForceReplicateRequest - Permissions order error when adding doc " + docid + 
623
					" to DB with action " + dbaction + ": " + poe.getMessage());
624
		} catch (AccessControlException ace) {
625
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
626
			logReplication.error("ReplicationService.handleForceReplicateRequest - Permissions order error when adding doc " + docid + 
627
					" to DB with action " + dbaction + ": " + ace.getMessage());
628
		} catch (Exception e) {
629
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
630
			logReplication.error("ReplicationService.handleForceReplicateRequest - General error when adding doc " + docid + 
631
					" to DB with action " + dbaction + ": " + e.getMessage());
632
		} finally {
633
			// Return the checked out DBConnection
634
			DBConnectionPool.returnDBConnection(dbConn, serialNumber);
635
		}//finally
636
	}
637

    
638
	/*
639
	 * when a forcereplication delete request comes in, local host will delete this
640
	 * document
641
	 */
642
	protected static void handleForceReplicateDeleteRequest(PrintWriter out,
643
			Hashtable<String, String[]> params, HttpServletResponse response,
644
			HttpServletRequest request) {
645
		String server = ((String[]) params.get("server"))[0]; // the server that
646
		String docid = ((String[]) params.get("docid"))[0]; // sent the document
647
		try {
648
			logReplication.info("ReplicationService.handleForceReplicateDeleteRequest - force replication delete request from " + server);
649
			logReplication.info("ReplicationService.handleForceReplicateDeleteRequest - force replication delete docid " + docid);
650
			logReplication.info("ReplicationService.handleForceReplicateDeleteRequest - Force replication delete request from: " + server);
651
			logReplication.info("ReplicationService.handleForceReplicateDeleteRequest - Force replication delete docid: " + docid);
652
			DocumentImpl.delete(docid, null, null, server);
653
			logReplication.info("ReplicationService.handleForceReplicateDeleteRequest - document " + docid + " was successfully deleted ");
654
			EventLog.getInstance().log(request.getRemoteAddr(), REPLICATIONUSER, docid,
655
					"delete");
656
			logReplication.info("ReplicationService.handleForceReplicateDeleteRequest - document " + docid + " was successfully deleted ");
657
		} catch (Exception e) {
658
			logMetacat.error("ReplicationService.handleForceReplicateDeleteRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
659
			logReplication.error("document " + docid
660
					+ " failed to delete because " + e.getMessage());
661
			logReplication.error("ReplicationService.handleForceReplicateDeleteRequest - error: " + e.getMessage());
662

    
663
		}//catch
664

    
665
	}
666

    
667
	/**
668
	 * when a forcereplication data file request comes in, local host sends a
669
	 * readdata request to the requesting server (remote server) for the specified
670
	 * docid. Then store it in local database and file system
671
	 */
672
	protected static void handleForceReplicateDataFileRequest(Hashtable<String, String[]> params,
673
			HttpServletRequest request) {
674

    
675
		//make sure there is some parameters
676
		if (params.isEmpty()) {
677
			return;
678
		}
679
		// Get remote server
680
		String server = ((String[]) params.get("server"))[0];
681
		// the docid should include rev number
682
		String docid = ((String[]) params.get("docid"))[0];
683
		// Make sure there is a docid and server
684
		if (docid == null || server == null || server.equals("")) {
685
			logMetacat.error("ReplicationService.handleForceReplicateDataFileRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
686
			logReplication.error("ReplicationService.handleForceReplicateDataFileRequest - Didn't specify docid or server for replication");
687
			return;
688
		}
689

    
690
		// Overide or not
691
		//    boolean override = false;
692
		// dbaction - update or insert
693
		String dbaction = null;
694

    
695
		try {
696
			//docid was switch to two parts uinque code and rev
697
			//String uniqueCode=MetacatUtil.getDocIdFromString(docid);
698
			//int rev=MetacatUtil.getVersionFromString(docid);
699
			if (params.containsKey("dbaction")) {
700
				dbaction = ((String[]) params.get("dbaction"))[0];
701
			} else//default value is update
702
			{
703
				dbaction = "update";
704
			}
705

    
706
			logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - force replication request from " + server);
707
			logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - Force replication request from: " + server);
708
			logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - Force replication docid: " + docid);
709
			logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - Force replication action: " + dbaction);
710
			// get the document info from server
711
			URL docinfourl = new URL("https://" + server + "?server="
712
					+ MetacatUtil.getLocalReplicationServerName()
713
					+ "&action=getdocumentinfo&docid=" + docid);
714

    
715
			String docInfoStr = ReplicationService.getURLContent(docinfourl);
716

    
717
			//dih is the parser for the docinfo xml format
718
			DocInfoHandler dih = new DocInfoHandler();
719
			XMLReader docinfoParser = ReplicationHandler.initParser(dih);
720
			docinfoParser.parse(new InputSource(new StringReader(docInfoStr)));
721
			Hashtable<String, String> docinfoHash = dih.getDocInfo();
722
			String user = (String) docinfoHash.get("user_owner");
723

    
724
			String docName = (String) docinfoHash.get("docname");
725

    
726
			String docType = (String) docinfoHash.get("doctype");
727

    
728
			String docHomeServer = (String) docinfoHash.get("home_server");
729

    
730
			String createdDate = (String) docinfoHash.get("date_created");
731

    
732
			String updatedDate = (String) docinfoHash.get("date_updated");
733
			logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - docHomeServer of datafile: " + docHomeServer);
734

    
735
			//if action is delete, we don't delete the data file. Just archieve
736
			//the xml_documents
737
			/*if (dbaction.equals("delete"))
738
			{
739
			  //conn = util.getConnection();
740
			  DocumentImpl.delete(docid,user,null);
741
			  //util.returnConnection(conn);
742
			}*/
743
			//To data file insert or update is same
744
			if (dbaction.equals("insert") || dbaction.equals("update")) {
745
				//Get data file and store it into local file system.
746
				// sending back readdata request to server
747
				URL url = new URL("https://" + server + "?server="
748
						+ MetacatUtil.getLocalReplicationServerName()
749
						+ "&action=readdata&docid=" + docid);
750
				String datafilePath = PropertyService
751
						.getProperty("application.datafilepath");
752

    
753
				Exception writeException = null;
754
				//register data file into xml_documents table and wite data file
755
				//into file system
756
				try {
757
					DocumentImpl.writeDataFileInReplication(url.openStream(),
758
							datafilePath, docName, docType, docid, user, docHomeServer,
759
							server, DocumentImpl.DOCUMENTTABLE, false, createdDate,
760
							updatedDate);
761
				} catch (Exception e) {
762
					writeException = e;
763
				}
764
				//process extra access rules
765
//				Vector<AccessControlForSingleFile> accessControlList = dih
766
//						.getAccessControlList();
767
//				if (accessControlList != null) {
768
//					for (int i = 0; i < accessControlList.size(); i++) {
769
//						AccessControlForSingleFile acfsf = (AccessControlForSingleFile) accessControlList
770
//								.get(i);
771
//						if (!acfsf.accessControlExists()) {
772
//							acfsf.insertPermissions();
773
//							logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - datafile " + docid
774
//									+ " permissions added to DB");
775
//						}
776
//					}
777
//				}
778
				
779
		        Vector<XMLAccessDAO> accessControlList = dih.getAccessControlList();
780
		        if (accessControlList != null) {
781
		        	AccessControlForSingleFile acfsf = new AccessControlForSingleFile(docid);
782
		        	for (XMLAccessDAO xmlAccessDAO : accessControlList) {
783
		        		if (!acfsf.accessControlExists(xmlAccessDAO)) {
784
		        			acfsf.insertPermissions(xmlAccessDAO);
785
							logReplication.info("ReplicationService.handleForceReplicateRequest - document " + docid
786
									+ " permissions added to DB");
787
		        		}
788
		            }
789
		        }
790

    
791
				if (writeException != null) {
792
					throw writeException;
793
				}
794

    
795
				//false means non-timed replication
796
				logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - datafile " + docid + " added to DB with "
797
						+ "action " + dbaction);
798
				EventLog.getInstance().log(request.getRemoteAddr(), REPLICATIONUSER,
799
						docid, dbaction);
800
			}
801

    
802
		} catch (Exception e) {
803
			logMetacat.error("ReplicationService.handleForceReplicateDataFileRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
804
			logReplication.error("ReplicationService.handleForceReplicateDataFileRequest - Datafile " + docid
805
					+ " failed to added to DB with " + "action " + dbaction + " because "
806
					+ e.getMessage());
807
			logReplication.error("ReplicationService.handleForceReplicateDataFileRequest - ERROR in MetacatReplication.handleForceDataFileReplicate"
808
					+ "Request(): " + e.getMessage());
809
		}
810
	}
811

    
812
	/**
813
	 * Grants or denies a lock to a requesting host.
814
	 * The servlet parameters of interrest are:
815
	 * docid: the docid of the file the lock is being requested for
816
	 * currentdate: the timestamp of the document on the remote server
817
	 *
818
	 */
819
	protected static void handleGetLockRequest(PrintWriter out,
820
			Hashtable<String, String[]> params, HttpServletResponse response) {
821

    
822
		try {
823

    
824
			String docid = ((String[]) params.get("docid"))[0];
825
			String remoteRev = ((String[]) params.get("updaterev"))[0];
826
			DocumentImpl requestDoc = new DocumentImpl(docid);
827
			logReplication.info("ReplicationService.handleGetLockRequest - lock request for " + docid);
828
			int localRevInt = requestDoc.getRev();
829
			int remoteRevInt = Integer.parseInt(remoteRev);
830

    
831
			if (remoteRevInt >= localRevInt) {
832
				if (!fileLocks.contains(docid)) { //grant the lock if it is not already locked
833
					fileLocks.add(0, docid); //insert at the beginning of the queue Vector
834
					//send a message back to the the remote host authorizing the insert
835
					out
836
							.println("<lockgranted><docid>" + docid
837
									+ "</docid></lockgranted>");
838
					//          lockThread = new Thread(this);
839
					//          lockThread.setPriority(Thread.MIN_PRIORITY);
840
					//          lockThread.start();
841
					logReplication.info("ReplicationService.handleGetLockRequest - lock granted for " + docid);
842
				} else { //deny the lock
843
					out.println("<filelocked><docid>" + docid + "</docid></filelocked>");
844
					logReplication.info("ReplicationService.handleGetLockRequest - lock denied for " + docid
845
							+ "reason: file already locked");
846
				}
847
			} else {//deny the lock.
848
				out.println("<outdatedfile><docid>" + docid + "</docid></filelocked>");
849
				logReplication.info("ReplicationService.handleGetLockRequest - lock denied for " + docid
850
						+ "reason: client has outdated file");
851
			}
852
			//conn.close();
853
		} catch (Exception e) {
854
			logMetacat.error("ReplicationService.handleGetLockRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
855
			logReplication.error("ReplicationService.handleGetLockRequest - error requesting file lock from MetacatReplication."
856
					+ "handleGetLockRequest: " + e.getMessage());
857
			e.printStackTrace(System.out);
858
		}
859
	}
860

    
861
	/**
862
	 * Sends all of the xml_documents information encoded in xml to a requestor
863
	 * the format is:
864
	 * <!ELEMENT documentinfo (docid, docname, doctype, doctitle, user_owner,
865
	 *                  user_updated, home_server, public_access, rev)/>
866
	 * all of the subelements of document info are #PCDATA
867
	 */
868
	protected static void handleGetDocumentInfoRequest(PrintWriter out,
869
			Hashtable<String, String[]> params, HttpServletResponse response) {
870
		String docid = ((String[]) (params.get("docid")))[0];
871
		StringBuffer sb = new StringBuffer();
872

    
873
		try {
874

    
875
			DocumentImpl doc = new DocumentImpl(docid);
876
			sb.append("<documentinfo><docid>").append(docid);
877
			sb.append("</docid><docname>").append(doc.getDocname());
878
			sb.append("</docname><doctype>").append(doc.getDoctype());
879
			sb.append("</doctype>");
880
			sb.append("<user_owner>").append(doc.getUserowner());
881
			sb.append("</user_owner><user_updated>").append(doc.getUserupdated());
882
			sb.append("</user_updated>");
883
			sb.append("<date_created>");
884
			sb.append(doc.getCreateDate());
885
			sb.append("</date_created>");
886
			sb.append("<date_updated>");
887
			sb.append(doc.getUpdateDate());
888
			sb.append("</date_updated>");
889
			sb.append("<home_server>");
890
			sb.append(doc.getDocHomeServer());
891
			sb.append("</home_server>");
892
			sb.append("<public_access>").append(doc.getPublicaccess());
893
			sb.append("</public_access><rev>").append(doc.getRev());
894
			sb.append("</rev>");
895

    
896
			sb.append("<accessControl>");
897

    
898
			AccessControlForSingleFile acfsf = new AccessControlForSingleFile(docid); 
899
			sb.append(acfsf.getAccessString());
900
			
901
			sb.append("</accessControl>");
902

    
903
			sb.append("</documentinfo>");
904
			response.setContentType("text/xml");
905
			out.println(sb.toString());
906

    
907
		} catch (Exception e) {
908
			logMetacat.error("ReplicationService.handleGetDocumentInfoRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
909
			logReplication.error("ReplicationService.handleGetDocumentInfoRequest - error in metacatReplication.handlegetdocumentinforequest "
910
					+ "for doc: " + docid + " : " + e.getMessage());
911
		}
912

    
913
	}
914

    
915
	/**
916
	 * Sends a datafile to a remote host
917
	 */
918
	protected static void handleGetDataFileRequest(OutputStream outPut,
919
			Hashtable<String, String[]> params, HttpServletResponse response)
920

    
921
	{
922
		// File path for data file
923
		String filepath;
924
		// Request docid
925
		String docId = ((String[]) (params.get("docid")))[0];
926
		//check if the doicd is null
927
		if (docId == null) {
928
			logMetacat.error("ReplicationService.handleGetDataFileRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
929
			logReplication.error("ReplicationService.handleGetDataFileRequest - Didn't specify docid for replication");
930
			return;
931
		}
932

    
933
		//try to open a https stream to test if the request server's public key
934
		//in the key store, this is security issue
935
		try {
936
			filepath = PropertyService.getProperty("application.datafilepath");
937
			String server = params.get("server")[0];
938
			URL u = new URL("https://" + server + "?server="
939
					+ MetacatUtil.getLocalReplicationServerName() + "&action=test");
940
			String test = ReplicationService.getURLContent(u);
941
			//couldn't pass the test
942
			if (test.indexOf("successfully") == -1) {
943
				//response.setContentType("text/xml");
944
				//outPut.println("<error>Couldn't pass the trust test</error>");
945
				logMetacat.error("ReplicationService.handleGetDataFileRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
946
				logReplication.error("ReplicationService.handleGetDataFileRequest - Couldn't pass the trust test");
947
				return;
948
			}
949
		}//try
950
		catch (Exception ee) {
951
			return;
952
		}//catch
953

    
954
		if (!filepath.endsWith("/")) {
955
			filepath += "/";
956
		}
957
		// Get file aboslute file name
958
		String filename = filepath + docId;
959

    
960
		//MIME type
961
		String contentType = null;
962
		if (filename.endsWith(".xml")) {
963
			contentType = "text/xml";
964
		} else if (filename.endsWith(".css")) {
965
			contentType = "text/css";
966
		} else if (filename.endsWith(".dtd")) {
967
			contentType = "text/plain";
968
		} else if (filename.endsWith(".xsd")) {
969
			contentType = "text/xml";
970
		} else if (filename.endsWith("/")) {
971
			contentType = "text/html";
972
		} else {
973
			File f = new File(filename);
974
			if (f.isDirectory()) {
975
				contentType = "text/html";
976
			} else {
977
				contentType = "application/octet-stream";
978
			}
979
		}
980

    
981
		// Set the mime type
982
		response.setContentType(contentType);
983

    
984
		// Get the content of the file
985
		FileInputStream fin = null;
986
		try {
987
			// FileInputStream to metacat
988
			fin = new FileInputStream(filename);
989
			// 4K buffer
990
			byte[] buf = new byte[4 * 1024];
991
			// Read data from file input stream to byte array
992
			int b = fin.read(buf);
993
			// Write to outStream from byte array
994
			while (b != -1) {
995
				outPut.write(buf, 0, b);
996
				b = fin.read(buf);
997
			}
998
			// close file input stream
999
			fin.close();
1000

    
1001
		}//try
1002
		catch (Exception e) {
1003
			logMetacat.error("ReplicationService.handleGetDataFileRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1004
			logReplication.error("ReplicationService.handleGetDataFileRequest - error getting data file from MetacatReplication."
1005
					+ "handlGetDataFileRequest " + e.getMessage());
1006
			e.printStackTrace(System.out);
1007
		}//catch
1008

    
1009
	}
1010

    
1011
	/**
1012
	 * Sends a document to a remote host
1013
	 */
1014
	protected static void handleGetDocumentRequest(PrintWriter out,
1015
			Hashtable<String, String[]> params, HttpServletResponse response) {
1016

    
1017
		String urlString = null;
1018
		String documentPath = null;
1019
		try {
1020
			// try to open a https stream to test if the request server's public
1021
			// key
1022
			// in the key store, this is security issue
1023
			String server = params.get("server")[0];
1024
			urlString = "https://" + server + "?server="
1025
					+ MetacatUtil.getLocalReplicationServerName() + "&action=test";
1026
			URL u = new URL(urlString);
1027
			String test = ReplicationService.getURLContent(u);
1028
			// couldn't pass the test
1029
			if (test.indexOf("successfully") == -1) {
1030
				response.setContentType("text/xml");
1031
				out.println("<error>Couldn't pass the trust test " + test + " </error>");
1032
				out.close();
1033
				return;
1034
			}
1035

    
1036
			String docid = params.get("docid")[0];
1037
			logReplication.debug("ReplicationService.handleGetDocumentRequest - MetacatReplication.handleGetDocumentRequest for docid: "
1038
					+ docid);
1039
			DocumentImpl di = new DocumentImpl(docid);
1040

    
1041
			String documentDir = PropertyService
1042
					.getProperty("application.documentfilepath");
1043
			documentPath = documentDir + FileUtil.getFS() + docid;
1044

    
1045
			// if the document does not exist on disk, read it from db and write
1046
			// it to disk.
1047
			if (FileUtil.getFileStatus(documentPath) == FileUtil.DOES_NOT_EXIST
1048
					|| FileUtil.getFileSize(documentPath) == 0) {
1049
				FileWriter fileWriter = new FileWriter(documentPath);
1050
				di.toXml(fileWriter, null, null, true);
1051
			}
1052

    
1053
			// read the file from disk and sent it to PrintWriter
1054
			// PrintWriter out = new PrintWriter(streamOut);
1055
			di.readFromFileSystem(out, null, null, documentPath);
1056

    
1057
			// response.setContentType("text/xml");
1058
			// out.print(di.toString(null, null, true));
1059

    
1060
			logReplication.info("ReplicationService.handleGetDocumentRequest - document " + docid + " sent");
1061

    
1062
		} catch (MalformedURLException mue) {
1063
			logMetacat.error("ReplicationService.handleGetDocumentRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1064
			logReplication.error("ReplicationService.handleGetDocumentRequest - Url error when getting document from MetacatReplication."
1065
					+ "handlGetDocumentRequest for url: " + urlString + " : "
1066
					+ mue.getMessage());
1067
			// e.printStackTrace(System.out);
1068
			response.setContentType("text/xml");
1069
			out.println("<error>" + mue.getMessage() + "</error>");
1070
		} catch (IOException ioe) {
1071
			logMetacat.error("ReplicationService.handleGetDocumentRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1072
			logReplication.error("ReplicationService.handleGetDocumentRequest - I/O error when getting document from MetacatReplication."
1073
					+ "handlGetDocumentRequest for file: " + documentPath + " : "
1074
					+ ioe.getMessage());
1075
			// e.printStackTrace(System.out);
1076
			response.setContentType("text/xml");
1077
			out.println("<error>" + ioe.getMessage() + "</error>");
1078
		} catch (PropertyNotFoundException pnfe) {
1079
			logMetacat.error("ReplicationService.handleGetDocumentRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1080
			logReplication
1081
					.error("ReplicationService.handleGetDocumentRequest - Error getting property when getting document from MetacatReplication."
1082
							+ "handlGetDocumentRequest for file: "
1083
							+ documentPath
1084
							+ " : "
1085
							+ pnfe.getMessage());
1086
			// e.printStackTrace(System.out);
1087
			response.setContentType("text/xml");
1088
			out.println("<error>" + pnfe.getMessage() + "</error>");
1089
		} catch (McdbException me) {
1090
			logReplication
1091
					.error("ReplicationService.handleGetDocumentRequest - Document implementation error  getting property when getting document from MetacatReplication."
1092
							+ "handlGetDocumentRequest for file: "
1093
							+ documentPath
1094
							+ " : "
1095
							+ me.getMessage());
1096
			// e.printStackTrace(System.out);
1097
			response.setContentType("text/xml");
1098
			out.println("<error>" + me.getMessage() + "</error>");
1099
		}
1100

    
1101
	}
1102

    
1103
	/**
1104
	 * Sends a list of all of the documents on this sever along with their
1105
	 * revision numbers. The format is: <!ELEMENT replication (server, updates)>
1106
	 * <!ELEMENT server (#PCDATA)> <!ELEMENT updates ((updatedDocument |
1107
	 * deleteDocument | revisionDocument)*)> <!ELEMENT updatedDocument (docid,
1108
	 * rev, datafile*)> <!ELEMENT deletedDocument (docid, rev)> <!ELEMENT
1109
	 * revisionDocument (docid, rev, datafile*)> <!ELEMENT docid (#PCDATA)>
1110
	 * <!ELEMENT rev (#PCDATA)> <!ELEMENT datafile (#PCDATA)> note that the rev
1111
	 * in deletedDocument is always empty. I just left it in there to make the
1112
	 * parser implementation easier.
1113
	 */
1114
	protected static void handleUpdateRequest(PrintWriter out, Hashtable<String, String[]> params,
1115
			HttpServletResponse response) {
1116
		// Checked out DBConnection
1117
		DBConnection dbConn = null;
1118
		// DBConenction serial number when checked it out
1119
		int serialNumber = -1;
1120
		PreparedStatement pstmt = null;
1121
		// Server list to store server info of xml_replication table
1122
		ReplicationServerList serverList = null;
1123

    
1124
		try {
1125
			// Check out a DBConnection from pool
1126
			dbConn = DBConnectionPool
1127
					.getDBConnection("MetacatReplication.handleUpdateRequest");
1128
			serialNumber = dbConn.getCheckOutSerialNumber();
1129
			// Create a server list from xml_replication table
1130
			serverList = new ReplicationServerList();
1131

    
1132
			// Get remote server name from param
1133
			String server = ((String[]) params.get("server"))[0];
1134
			// If no servr name in param, return a error
1135
			if (server == null || server.equals("")) {
1136
				response.setContentType("text/xml");
1137
				out.println("<error>Request didn't specify server name</error>");
1138
				out.close();
1139
				return;
1140
			}//if
1141

    
1142
			//try to open a https stream to test if the request server's public key
1143
			//in the key store, this is security issue
1144
			URL u = new URL("https://" + server + "?server="
1145
					+ MetacatUtil.getLocalReplicationServerName() + "&action=test");
1146
			String test = ReplicationService.getURLContent(u);
1147
			//couldn't pass the test
1148
			if (test.indexOf("successfully") == -1) {
1149
				response.setContentType("text/xml");
1150
				out.println("<error>Couldn't pass the trust test</error>");
1151
				out.close();
1152
				return;
1153
			}
1154

    
1155
			// Check if local host configure to replicate xml documents to remote
1156
			// server. If not send back a error message
1157
			if (!serverList.getReplicationValue(server)) {
1158
				response.setContentType("text/xml");
1159
				out
1160
						.println("<error>Configuration not allow to replicate document to you</error>");
1161
				out.close();
1162
				return;
1163
			}//if
1164

    
1165
			// Store the sql command
1166
			StringBuffer docsql = new StringBuffer();
1167
			StringBuffer revisionSql = new StringBuffer();
1168
			// Stroe the docid list
1169
			StringBuffer doclist = new StringBuffer();
1170
			// Store the deleted docid list
1171
			StringBuffer delsql = new StringBuffer();
1172
			// Store the data set file
1173
			Vector<Vector<String>> packageFiles = new Vector<Vector<String>>();
1174

    
1175
			// Append local server's name and replication servlet to doclist
1176
			doclist.append("<?xml version=\"1.0\"?><replication>");
1177
			doclist.append("<server>")
1178
					.append(MetacatUtil.getLocalReplicationServerName());
1179
			//doclist.append(util.getProperty("replicationpath"));
1180
			doclist.append("</server><updates>");
1181

    
1182
			// Get correct docid that reside on this server according the requesting
1183
			// server's replicate and data replicate value in xml_replication table
1184
			docsql.append(DatabaseService.getDBAdapter().getReplicationDocumentListSQL());
1185
			//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)) ");
1186
			revisionSql.append("select docid, rev, doctype from xml_revisions ");
1187
			// If the localhost is not a hub to the remote server, only replicate
1188
			// the docid' which home server is local host (server_location =1)
1189
			if (!serverList.getHubValue(server)) {
1190
				String serverLocationDoc = " and a.server_location = 1";
1191
				String serverLocationRev = "where server_location = 1";
1192
				docsql.append(serverLocationDoc);
1193
				revisionSql.append(serverLocationRev);
1194
			}
1195
			logReplication.info("ReplicationService.handleUpdateRequest - Doc sql: " + docsql.toString());
1196

    
1197
			// Get any deleted documents
1198
			delsql.append("select distinct docid from ");
1199
			delsql.append("xml_revisions where docid not in (select docid from ");
1200
			delsql.append("xml_documents) ");
1201
			// If the localhost is not a hub to the remote server, only replicate
1202
			// the docid' which home server is local host (server_location =1)
1203
			if (!serverList.getHubValue(server)) {
1204
				delsql.append("and server_location = 1");
1205
			}
1206
			logReplication.info("ReplicationService.handleUpdateRequest - Deleted sql: " + delsql.toString());
1207

    
1208
			// Get docid list of local host
1209
			pstmt = dbConn.prepareStatement(docsql.toString());
1210
			pstmt.execute();
1211
			ResultSet rs = pstmt.getResultSet();
1212
			boolean tablehasrows = rs.next();
1213
			//If metacat configed to replicate data file
1214
			//if ((util.getProperty("replicationsenddata")).equals("on"))
1215
			boolean replicateData = serverList.getDataReplicationValue(server);
1216
			if (replicateData) {
1217
				while (tablehasrows) {
1218
					String recordDoctype = rs.getString(3);
1219
					Vector<String> packagedoctypes = MetacatUtil
1220
							.getOptionList(PropertyService
1221
									.getProperty("xml.packagedoctype"));
1222
					//if this is a package file, put it at the end
1223
					//because if a package file is read before all of the files it
1224
					//refers to are loaded then there is an error
1225
					if (recordDoctype != null && !packagedoctypes.contains(recordDoctype)) {
1226
						//If this is not data file
1227
						if (!recordDoctype.equals("BIN")) {
1228
							//for non-data file document
1229
							doclist.append("<updatedDocument>");
1230
							doclist.append("<docid>").append(rs.getString(1));
1231
							doclist.append("</docid><rev>").append(rs.getInt(2));
1232
							doclist.append("</rev>");
1233
							doclist.append("</updatedDocument>");
1234
						}//if
1235
						else {
1236
							//for data file document, in datafile attributes
1237
							//we put "datafile" value there
1238
							doclist.append("<updatedDocument>");
1239
							doclist.append("<docid>").append(rs.getString(1));
1240
							doclist.append("</docid><rev>").append(rs.getInt(2));
1241
							doclist.append("</rev>");
1242
							doclist.append("<datafile>");
1243
							doclist.append(PropertyService
1244
									.getProperty("replication.datafileflag"));
1245
							doclist.append("</datafile>");
1246
							doclist.append("</updatedDocument>");
1247
						}//else
1248
					}//if packagedoctpes
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
					}//esle
1255
					tablehasrows = rs.next();
1256
				}//while
1257
			}//if
1258
			else //metacat was configured not to send data file
1259
			{
1260
				while (tablehasrows) {
1261
					String recordDoctype = rs.getString(3);
1262
					if (!recordDoctype.equals("BIN")) { //don't replicate data files
1263
						Vector<String> packagedoctypes = MetacatUtil
1264
								.getOptionList(PropertyService
1265
										.getProperty("xml.packagedoctype"));
1266
						if (recordDoctype != null
1267
								&& !packagedoctypes.contains(recordDoctype)) { //if this is a package file, put it at the end
1268
							//because if a package file is read before all of the files it
1269
							//refers to are loaded then there is an error
1270
							doclist.append("<updatedDocument>");
1271
							doclist.append("<docid>").append(rs.getString(1));
1272
							doclist.append("</docid><rev>").append(rs.getInt(2));
1273
							doclist.append("</rev>");
1274
							doclist.append("</updatedDocument>");
1275
						} else { //the package files are saved to be put into the xml later.
1276
							Vector<String> v = new Vector<String>();
1277
							v.add(rs.getString(1));
1278
							v.add(String.valueOf(rs.getInt(2)));
1279
							packageFiles.add(v);
1280
						}
1281
					}//if
1282
					tablehasrows = rs.next();
1283
				}//while
1284
			}//else
1285

    
1286
			pstmt = dbConn.prepareStatement(delsql.toString());
1287
			//usage count should increas 1
1288
			dbConn.increaseUsageCount(1);
1289

    
1290
			pstmt.execute();
1291
			rs = pstmt.getResultSet();
1292
			tablehasrows = rs.next();
1293
			while (tablehasrows) { //handle the deleted documents
1294
				doclist.append("<deletedDocument><docid>").append(rs.getString(1));
1295
				doclist.append("</docid><rev></rev></deletedDocument>");
1296
				//note that rev is always empty for deleted docs
1297
				tablehasrows = rs.next();
1298
			}
1299

    
1300
			//now we can put the package files into the xml results
1301
			for (int i = 0; i < packageFiles.size(); i++) {
1302
				Vector<String> v = packageFiles.elementAt(i);
1303
				doclist.append("<updatedDocument>");
1304
				doclist.append("<docid>").append(v.elementAt(0));
1305
				doclist.append("</docid><rev>");
1306
				doclist.append(v.elementAt(1));
1307
				doclist.append("</rev>");
1308
				doclist.append("</updatedDocument>");
1309
			}
1310
			// add revision doc list  
1311
			doclist.append(prepareRevisionDoc(dbConn, revisionSql.toString(),
1312
					replicateData));
1313

    
1314
			doclist.append("</updates></replication>");
1315
			logReplication.info("ReplicationService.handleUpdateRequest - doclist: " + doclist.toString());
1316
			pstmt.close();
1317
			//conn.close();
1318
			response.setContentType("text/xml");
1319
			out.println(doclist.toString());
1320

    
1321
		} catch (Exception e) {
1322
			logMetacat.error("ReplicationService.handleUpdateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1323
			logReplication.error("ReplicationService.handleUpdateRequest - error in MetacatReplication." + "handleupdaterequest: "
1324
					+ e.getMessage());
1325
			//e.printStackTrace(System.out);
1326
			response.setContentType("text/xml");
1327
			out.println("<error>" + e.getMessage() + "</error>");
1328
		} finally {
1329
			try {
1330
				pstmt.close();
1331
			}//try
1332
			catch (SQLException ee) {
1333
				logMetacat.error("ReplicationService.handleUpdateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1334
				logReplication.error("ReplicationService.handleUpdateRequest - Error in MetacatReplication."
1335
						+ "handleUpdaterequest to close pstmt: " + ee.getMessage());
1336
			}//catch
1337
			finally {
1338
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1339
			}//finally
1340
		}//finally
1341

    
1342
	}//handlUpdateRequest
1343

    
1344
	/*
1345
	 * This method will get the xml string for document in xml_revision
1346
	 * The schema look like <!ELEMENT revisionDocument (docid, rev, datafile*)>
1347
	 */
1348
	private static String prepareRevisionDoc(DBConnection dbConn, String revSql,
1349
			boolean replicateData) throws Exception {
1350
		logReplication.warn("ReplicationService.prepareRevisionDoc - The revision document sql is " + revSql);
1351
		StringBuffer revDocList = new StringBuffer();
1352
		PreparedStatement pstmt = dbConn.prepareStatement(revSql);
1353
		//usage count should increas 1
1354
		dbConn.increaseUsageCount(1);
1355

    
1356
		pstmt.execute();
1357
		ResultSet rs = pstmt.getResultSet();
1358
		boolean tablehasrows = rs.next();
1359
		while (tablehasrows) {
1360
			String recordDoctype = rs.getString(3);
1361

    
1362
			//If this is data file and it isn't configured to replicate data
1363
			if (recordDoctype.equals("BIN") && !replicateData) {
1364
				// do nothing
1365
				continue;
1366
			} else {
1367

    
1368
				revDocList.append("<revisionDocument>");
1369
				revDocList.append("<docid>").append(rs.getString(1));
1370
				revDocList.append("</docid><rev>").append(rs.getInt(2));
1371
				revDocList.append("</rev>");
1372
				// data file
1373
				if (recordDoctype.equals("BIN")) {
1374
					revDocList.append("<datafile>");
1375
					revDocList.append(PropertyService
1376
							.getProperty("replication.datafileflag"));
1377
					revDocList.append("</datafile>");
1378
				}
1379
				revDocList.append("</revisionDocument>");
1380

    
1381
			}//else
1382
			tablehasrows = rs.next();
1383
		}
1384
		//System.out.println("The revision list is"+ revDocList.toString());
1385
		return revDocList.toString();
1386
	}
1387

    
1388
	/**
1389
	 * Returns the xml_catalog table encoded in xml
1390
	 */
1391
	public static String getCatalogXML() {
1392
		return handleGetCatalogRequest(null, null, null, false);
1393
	}
1394

    
1395
	/**
1396
	 * Sends the contents of the xml_catalog table encoded in xml
1397
	 * The xml format is:
1398
	 * <!ELEMENT xml_catalog (row*)>
1399
	 * <!ELEMENT row (entry_type, source_doctype, target_doctype, public_id,
1400
	 *                system_id)>
1401
	 * All of the sub elements of row are #PCDATA
1402

    
1403
	 * If printFlag == false then do not print to out.
1404
	 */
1405
	protected static String handleGetCatalogRequest(PrintWriter out,
1406
			Hashtable<String, String[]> params, HttpServletResponse response,
1407
			boolean printFlag) {
1408
		DBConnection dbConn = null;
1409
		int serialNumber = -1;
1410
		PreparedStatement pstmt = null;
1411
		try {
1412
			/*conn = MetacatReplication.getDBConnection("MetacatReplication." +
1413
			                                          "handleGetCatalogRequest");*/
1414
			dbConn = DBConnectionPool
1415
					.getDBConnection("MetacatReplication.handleGetCatalogRequest");
1416
			serialNumber = dbConn.getCheckOutSerialNumber();
1417
			pstmt = dbConn.prepareStatement("select entry_type, "
1418
					+ "source_doctype, target_doctype, public_id, "
1419
					+ "system_id from xml_catalog");
1420
			pstmt.execute();
1421
			ResultSet rs = pstmt.getResultSet();
1422
			boolean tablehasrows = rs.next();
1423
			StringBuffer sb = new StringBuffer();
1424
			sb.append("<?xml version=\"1.0\"?><xml_catalog>");
1425
			while (tablehasrows) {
1426
				sb.append("<row><entry_type>").append(rs.getString(1));
1427
				sb.append("</entry_type><source_doctype>").append(rs.getString(2));
1428
				sb.append("</source_doctype><target_doctype>").append(rs.getString(3));
1429
				sb.append("</target_doctype><public_id>").append(rs.getString(4));
1430
				// system id may not have server url on front.  Add it if not.
1431
				String systemID = rs.getString(5);
1432
				if (!systemID.startsWith("http://")) {
1433
					systemID = SystemUtil.getContextURL() + systemID;
1434
				}
1435
				sb.append("</public_id><system_id>").append(systemID);
1436
				sb.append("</system_id></row>");
1437

    
1438
				tablehasrows = rs.next();
1439
			}
1440
			sb.append("</xml_catalog>");
1441
			//conn.close();
1442
			if (printFlag) {
1443
				response.setContentType("text/xml");
1444
				out.println(sb.toString());
1445
			}
1446
			pstmt.close();
1447
			return sb.toString();
1448
		} catch (Exception e) {
1449
			logMetacat.error("ReplicationService.handleGetCatalogRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1450
			logReplication.error("ReplicationService.handleGetCatalogRequest - error in MetacatReplication.handleGetCatalogRequest:"
1451
					+ e.getMessage());
1452
			e.printStackTrace(System.out);
1453
			if (printFlag) {
1454
				out.println("<error>" + e.getMessage() + "</error>");
1455
			}
1456
		} finally {
1457
			try {
1458
				pstmt.close();
1459
			}//try
1460
			catch (SQLException ee) {
1461
				logMetacat.error("ReplicationService.handleGetCatalogRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1462
				logReplication.error("ReplicationService.handleGetCatalogRequest - Error in MetacatReplication.handleGetCatalogRequest: "
1463
						+ ee.getMessage());
1464
			}//catch
1465
			finally {
1466
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1467
			}//finally
1468
		}//finally
1469

    
1470
		return null;
1471
	}
1472

    
1473
	/**
1474
	 * Sends the current system date to the remote server.  Using this action
1475
	 * for replication gets rid of any problems with syncronizing clocks
1476
	 * because a time specific to a document is always kept on its home server.
1477
	 */
1478
	protected static void handleGetTimeRequest(PrintWriter out,
1479
			Hashtable<String, String[]> params, HttpServletResponse response) {
1480
		SimpleDateFormat formatter = new SimpleDateFormat("MM/dd/yy HH:mm:ss");
1481
		java.util.Date localtime = new java.util.Date();
1482
		String dateString = formatter.format(localtime);
1483
		response.setContentType("text/xml");
1484

    
1485
		out.println("<timestamp>" + dateString + "</timestamp>");
1486
	}
1487

    
1488
	/**
1489
	 * this method handles the timeout for a file lock.  when a lock is
1490
	 * granted it is granted for 30 seconds.  When this thread runs out
1491
	 * it deletes the docid from the queue, thus eliminating the lock.
1492
	 */
1493
	public void run() {
1494
		try {
1495
			logReplication.info("ReplicationService.run - thread started for docid: "
1496
					+ (String) fileLocks.elementAt(0));
1497

    
1498
			Thread.sleep(30000); //the lock will expire in 30 seconds
1499
			logReplication.info("thread for docid: "
1500
					+ (String) fileLocks.elementAt(fileLocks.size() - 1) + " exiting.");
1501

    
1502
			fileLocks.remove(fileLocks.size() - 1);
1503
			//fileLocks is treated as a FIFO queue.  If there are more than one lock
1504
			//in the vector, the first one inserted will be removed.
1505
		} catch (Exception e) {
1506
			logMetacat.error("ReplicationService.run - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1507
			logReplication.error("ReplicationService.run - error in file lock thread from "
1508
					+ "MetacatReplication.run: " + e.getMessage());
1509
		}
1510
	}
1511

    
1512
	/**
1513
	 * Returns the name of a server given a serverCode
1514
	 * @param serverCode the serverid of the server
1515
	 * @return the servername or null if the specified serverCode does not
1516
	 *         exist.
1517
	 */
1518
	public static String getServerNameForServerCode(int serverCode) {
1519
		//System.out.println("serverid: " + serverCode);
1520
		DBConnection dbConn = null;
1521
		int serialNumber = -1;
1522
		PreparedStatement pstmt = null;
1523
		try {
1524
			dbConn = DBConnectionPool.getDBConnection("MetacatReplication.getServer");
1525
			serialNumber = dbConn.getCheckOutSerialNumber();
1526
			String sql = new String("select server from "
1527
					+ "xml_replication where serverid = " + serverCode);
1528
			pstmt = dbConn.prepareStatement(sql);
1529
			//System.out.println("getserver sql: " + sql);
1530
			pstmt.execute();
1531
			ResultSet rs = pstmt.getResultSet();
1532
			boolean tablehasrows = rs.next();
1533
			if (tablehasrows) {
1534
				//System.out.println("server: " + rs.getString(1));
1535
				return rs.getString(1);
1536
			}
1537

    
1538
			//conn.close();
1539
		} catch (Exception e) {
1540
			logMetacat.error("ReplicationService.getServerNameForServerCode - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1541
			logReplication.error("ReplicationService.getServerNameForServerCode - Error in MetacatReplication.getServer: " + e.getMessage());
1542
		} finally {
1543
			try {
1544
				pstmt.close();
1545
			}//try
1546
			catch (SQLException ee) {
1547
				logMetacat.error("ReplicationService.getServerNameForServerCode - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1548
				logReplication.error("ReplicationService.getServerNameForServerCode - Error in MetacactReplication.getserver: "
1549
						+ ee.getMessage());
1550
			}//catch
1551
			finally {
1552
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1553
			}//fianlly
1554
		}//finally
1555

    
1556
		return null;
1557
		//return null if the server does not exist
1558
	}
1559

    
1560
	/**
1561
	 * Returns a server code given a server name
1562
	 * @param server the name of the server
1563
	 * @return integer > 0 representing the code of the server, 0 if the server
1564
	 *  does not exist.
1565
	 */
1566
	public static int getServerCodeForServerName(String server) throws ServiceException {
1567
		DBConnection dbConn = null;
1568
		int serialNumber = -1;
1569
		PreparedStatement pstmt = null;
1570
		int serverCode = 0;
1571

    
1572
		try {
1573

    
1574
			//conn = util.openDBConnection();
1575
			dbConn = DBConnectionPool.getDBConnection("MetacatReplication.getServerCode");
1576
			serialNumber = dbConn.getCheckOutSerialNumber();
1577
			pstmt = dbConn.prepareStatement("SELECT serverid FROM xml_replication "
1578
					+ "WHERE server LIKE '" + server + "'");
1579
			pstmt.execute();
1580
			ResultSet rs = pstmt.getResultSet();
1581
			boolean tablehasrows = rs.next();
1582
			if (tablehasrows) {
1583
				serverCode = rs.getInt(1);
1584
				pstmt.close();
1585
				//conn.close();
1586
				return serverCode;
1587
			}
1588

    
1589
		} catch (SQLException sqle) {
1590
			throw new ServiceException("ReplicationService.getServerCodeForServerName - " 
1591
					+ "SQL error when getting server code: " + sqle.getMessage());
1592

    
1593
		} finally {
1594
			try {
1595
				pstmt.close();
1596
				//conn.close();
1597
			}//try
1598
			catch (Exception ee) {
1599
				logMetacat.error("ReplicationService.getServerCodeForServerName - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1600
				logReplication.error("ReplicationService.getServerNameForServerCode - Error in MetacatReplicatio.getServerCode: "
1601
						+ ee.getMessage());
1602

    
1603
			}//catch
1604
			finally {
1605
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1606
			}//finally
1607
		}//finally
1608

    
1609
		return serverCode;
1610
	}
1611

    
1612
	/**
1613
	 * Method to get a host server information for given docid
1614
	 * @param conn a connection to the database
1615
	 */
1616
	public static Hashtable<String, String> getHomeServerInfoForDocId(String docId) {
1617
		Hashtable<String, String> sl = new Hashtable<String, String>();
1618
		DBConnection dbConn = null;
1619
		int serialNumber = -1;
1620
		docId = DocumentUtil.getDocIdFromString(docId);
1621
		PreparedStatement pstmt = null;
1622
		int serverLocation;
1623
		try {
1624
			//get conection
1625
			dbConn = DBConnectionPool.getDBConnection("ReplicationHandler.getHomeServer");
1626
			serialNumber = dbConn.getCheckOutSerialNumber();
1627
			//get a server location from xml_document table
1628
			pstmt = dbConn.prepareStatement("select server_location from xml_documents "
1629
					+ "where docid = ?");
1630
			pstmt.setString(1, docId);
1631
			pstmt.execute();
1632
			ResultSet serverName = pstmt.getResultSet();
1633
			//get a server location
1634
			if (serverName.next()) {
1635
				serverLocation = serverName.getInt(1);
1636
				pstmt.close();
1637
			} else {
1638
				pstmt.close();
1639
				//ut.returnConnection(conn);
1640
				return null;
1641
			}
1642
			pstmt = dbConn.prepareStatement("select server, last_checked, replicate "
1643
					+ "from xml_replication where serverid = ?");
1644
			//increase usage count
1645
			dbConn.increaseUsageCount(1);
1646
			pstmt.setInt(1, serverLocation);
1647
			pstmt.execute();
1648
			ResultSet rs = pstmt.getResultSet();
1649
			boolean tableHasRows = rs.next();
1650
			if (tableHasRows) {
1651

    
1652
				String server = rs.getString(1);
1653
				String last_checked = rs.getString(2);
1654
				if (!server.equals("localhost")) {
1655
					sl.put(server, last_checked);
1656
				}
1657

    
1658
			} else {
1659
				pstmt.close();
1660
				//ut.returnConnection(conn);
1661
				return null;
1662
			}
1663
			pstmt.close();
1664
		} catch (Exception e) {
1665
			logMetacat.error("ReplicationService.getHomeServerInfoForDocId - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1666
			logReplication.error("ReplicationService.getHomeServerInfoForDocId - error in replicationHandler.getHomeServer(): "
1667
					+ e.getMessage());
1668
		} finally {
1669
			try {
1670
				pstmt.close();
1671
				//ut.returnConnection(conn);
1672
			} catch (Exception ee) {
1673
				logMetacat.error("ReplicationService.getHomeServerInfoForDocId - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1674
				logReplication.error("ReplicationService.getHomeServerInfoForDocId - Eror irn rplicationHandler.getHomeServer() "
1675
						+ "to close pstmt: " + ee.getMessage());
1676
			} finally {
1677
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1678
			}
1679

    
1680
		}//finally
1681
		return sl;
1682
	}
1683

    
1684
	/**
1685
	 * Returns a home server location  given a accnum
1686
	 * @param accNum , given accNum for a document
1687
	 *
1688
	 */
1689
	public static int getHomeServerCodeForDocId(String accNum) throws ServiceException {
1690
		DBConnection dbConn = null;
1691
		int serialNumber = -1;
1692
		PreparedStatement pstmt = null;
1693
		int serverCode = 1;
1694
		String docId = DocumentUtil.getDocIdFromString(accNum);
1695

    
1696
		try {
1697

    
1698
			// Get DBConnection
1699
			dbConn = DBConnectionPool
1700
					.getDBConnection("ReplicationHandler.getServerLocation");
1701
			serialNumber = dbConn.getCheckOutSerialNumber();
1702
			pstmt = dbConn.prepareStatement("SELECT server_location FROM xml_documents "
1703
					+ "WHERE docid LIKE '" + docId + "'");
1704
			pstmt.execute();
1705
			ResultSet rs = pstmt.getResultSet();
1706
			boolean tablehasrows = rs.next();
1707
			//If a document is find, return the server location for it
1708
			if (tablehasrows) {
1709
				serverCode = rs.getInt(1);
1710
				pstmt.close();
1711
				//conn.close();
1712
				return serverCode;
1713
			}
1714
			//if couldn't find in xml_documents table, we think server code is 1
1715
			//(this is new document)
1716
			else {
1717
				pstmt.close();
1718
				//conn.close();
1719
				return serverCode;
1720
			}
1721

    
1722
		} catch (SQLException sqle) {
1723
			throw new ServiceException("ReplicationService.getHomeServerCodeForDocId - " 
1724
					+ "SQL error when getting home server code for docid: " + docId + " : " 
1725
					+ sqle.getMessage());
1726

    
1727
		} finally {
1728
			try {
1729
				pstmt.close();
1730
				//conn.close();
1731

    
1732
			} catch (SQLException sqle) {
1733
				logMetacat.error("ReplicationService.getHomeServerCodeForDocId - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1734
				logReplication.error("ReplicationService.getHomeServerCodeForDocId - ReplicationService.getHomeServerCodeForDocId - " 
1735
						+ "SQL error when getting home server code for docid: " + docId + " : " 
1736
						+ sqle.getMessage());
1737
			} finally {
1738
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1739
			}//finally
1740
		}//finally
1741
		//return serverCode;
1742
	}
1743

    
1744
	/**
1745
	 * This method returns the content of a url
1746
	 * @param u the url to return the content from
1747
	 * @return a string representing the content of the url
1748
	 * @throws java.io.IOException
1749
	 */
1750
	public static String getURLContent(URL u) throws java.io.IOException {
1751
		char istreamChar;
1752
		int istreamInt;
1753
		logReplication.debug("ReplicationService.getURLContent - Before open the stream" + u.toString());
1754
		InputStream input = u.openStream();
1755
		logReplication.debug("ReplicationService.getURLContent - After open the stream" + u.toString());
1756
		InputStreamReader istream = new InputStreamReader(input);
1757
		StringBuffer serverResponse = new StringBuffer();
1758
		while ((istreamInt = istream.read()) != -1) {
1759
			istreamChar = (char) istreamInt;
1760
			serverResponse.append(istreamChar);
1761
		}
1762
		istream.close();
1763
		input.close();
1764

    
1765
		return serverResponse.toString();
1766
	}
1767

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

    
1792
//	/**
1793
//	 * Method for writing replication messages to a log file specified in
1794
//	 * metacat.properties
1795
//	 */
1796
//	public static void replErrorLog(String message) {
1797
//		try {
1798
//			FileOutputStream fos = new FileOutputStream(PropertyService
1799
//					.getProperty("replication.logdir")
1800
//					+ "/metacatreplicationerror.log", true);
1801
//			PrintWriter pw = new PrintWriter(fos);
1802
//			SimpleDateFormat formatter = new SimpleDateFormat("yy-MM-dd HH:mm:ss");
1803
//			java.util.Date localtime = new java.util.Date();
1804
//			String dateString = formatter.format(localtime);
1805
//			dateString += " :: " + message;
1806
//			//time stamp each entry
1807
//			pw.println(dateString);
1808
//			pw.flush();
1809
//		} catch (Exception e) {
1810
//			logReplication.error("error writing to replication error log from "
1811
//					+ "MetacatReplication.replErrorLog: " + e.getMessage());
1812
//			//e.printStackTrace(System.out);
1813
//		}
1814
//	}
1815

    
1816
	/**
1817
	 * Returns true if the replicate field for server in xml_replication is 1.
1818
	 * Returns false otherwise
1819
	 */
1820
	public static boolean replToServer(String server) {
1821
		DBConnection dbConn = null;
1822
		int serialNumber = -1;
1823
		PreparedStatement pstmt = null;
1824
		try {
1825
			dbConn = DBConnectionPool.getDBConnection("MetacatReplication.repltoServer");
1826
			serialNumber = dbConn.getCheckOutSerialNumber();
1827
			pstmt = dbConn.prepareStatement("select replicate from "
1828
					+ "xml_replication where server like '" + server + "'");
1829
			pstmt.execute();
1830
			ResultSet rs = pstmt.getResultSet();
1831
			boolean tablehasrows = rs.next();
1832
			if (tablehasrows) {
1833
				int i = rs.getInt(1);
1834
				if (i == 1) {
1835
					pstmt.close();
1836
					//conn.close();
1837
					return true;
1838
				} else {
1839
					pstmt.close();
1840
					//conn.close();
1841
					return false;
1842
				}
1843
			}
1844
		} catch (SQLException sqle) {
1845
			logMetacat.error("ReplicationService.replToServer - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1846
			logReplication.error("ReplicationService.replToServer - SQL error in MetacatReplication.replToServer: "
1847
					+ sqle.getMessage());
1848
		} finally {
1849
			try {
1850
				pstmt.close();
1851
				//conn.close();
1852
			}//try
1853
			catch (Exception ee) {
1854
				logMetacat.error("ReplicationService.replToServer - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1855
				logReplication.error("ReplicationService.replToServer - Error in MetacatReplication.replToServer: "
1856
						+ ee.getMessage());
1857
			}//catch
1858
			finally {
1859
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1860
			}//finally
1861
		}//finally
1862
		return false;
1863
		//the default if this server does not exist is to not replicate to it.
1864
	}
1865

    
1866
}
(6-6/7)