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: berkley $'
9
 *     '$Date: 2010-04-26 12:29:33 -0700 (Mon, 26 Apr 2010) $'
10
 * '$Revision: 5322 $'
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.metacat.IdentifierManager;
58
import edu.ucsb.nceas.metacat.McdbDocNotFoundException;
59
import edu.ucsb.nceas.utilities.FileUtil;
60
import edu.ucsb.nceas.utilities.GeneralPropertyException;
61
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
62

    
63
import org.apache.log4j.Logger;
64
import org.xml.sax.*;
65

    
66
public class ReplicationService extends BaseService {
67

    
68
	private static ReplicationService replicationService = null;
69

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

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

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

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

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

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

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

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

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

    
156
	public boolean refreshable() {
157
		return true;
158
	}
159

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
392
				out.println("<error>Unkonwn subaction</error>");
393

    
394
			}
395
			pstmt.close();
396
			//conn.close();
397

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

    
417
	}
418

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

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

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

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

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

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

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

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

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

    
518
			String docInfoStr = ReplicationService.getURLContent(docinfourl);
519

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

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

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

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

    
595
//				if (writeException != null) {
596
//					throw writeException;
597
//				}
598

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

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

    
667
		}//catch
668

    
669
	}
670

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

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

    
694
		// Overide or not
695
		//    boolean override = false;
696
		// dbaction - update or insert
697
		String dbaction = null;
698

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

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

    
719
			String docInfoStr = ReplicationService.getURLContent(docinfourl);
720

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

    
728
			String docName = (String) docinfoHash.get("docname");
729

    
730
			String docType = (String) docinfoHash.get("doctype");
731

    
732
			String docHomeServer = (String) docinfoHash.get("home_server");
733

    
734
			String createdDate = (String) docinfoHash.get("date_created");
735

    
736
			String updatedDate = (String) docinfoHash.get("date_updated");
737
			logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - docHomeServer of datafile: " + docHomeServer);
738

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

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

    
795
				if (writeException != null) {
796
					throw writeException;
797
				}
798

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

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

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

    
826
		try {
827

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

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

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

    
877
		try {
878
		  IdentifierManager idman = IdentifierManager.getInstance();
879

    
880
			DocumentImpl doc = new DocumentImpl(docid);
881
			sb.append("<documentinfo><docid>").append(docid);
882
			sb.append("</docid>");
883
			try
884
			{
885
			  sb.append("<guid>").append(idman.getGUID(doc.getDocID(), doc.getRev())).append("</guid>");
886
			}
887
			catch(McdbDocNotFoundException e)
888
			{
889
			  //do nothing, there was no guid for this document
890
			}
891
			sb.append("<docname>").append(doc.getDocname());
892
			sb.append("</docname><doctype>").append(doc.getDoctype());
893
			sb.append("</doctype>");
894
			sb.append("<user_owner>").append(doc.getUserowner());
895
			sb.append("</user_owner><user_updated>").append(doc.getUserupdated());
896
			sb.append("</user_updated>");
897
			sb.append("<date_created>");
898
			sb.append(doc.getCreateDate());
899
			sb.append("</date_created>");
900
			sb.append("<date_updated>");
901
			sb.append(doc.getUpdateDate());
902
			sb.append("</date_updated>");
903
			sb.append("<home_server>");
904
			sb.append(doc.getDocHomeServer());
905
			sb.append("</home_server>");
906
			sb.append("<public_access>").append(doc.getPublicaccess());
907
			sb.append("</public_access><rev>").append(doc.getRev());
908
			sb.append("</rev>");
909

    
910
			sb.append("<accessControl>");
911

    
912
			AccessControlForSingleFile acfsf = new AccessControlForSingleFile(docid); 
913
			sb.append(acfsf.getAccessString());
914
			
915
			sb.append("</accessControl>");
916

    
917
			sb.append("</documentinfo>");
918
			response.setContentType("text/xml");
919
			out.println(sb.toString());
920

    
921
		} catch (Exception e) {
922
			logMetacat.error("ReplicationService.handleGetDocumentInfoRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
923
			logReplication.error("ReplicationService.handleGetDocumentInfoRequest - error in metacatReplication.handlegetdocumentinforequest "
924
					+ "for doc: " + docid + " : " + e.getMessage());
925
		}
926

    
927
	}
928

    
929
	/**
930
	 * Sends a datafile to a remote host
931
	 */
932
	protected static void handleGetDataFileRequest(OutputStream outPut,
933
			Hashtable<String, String[]> params, HttpServletResponse response)
934

    
935
	{
936
		// File path for data file
937
		String filepath;
938
		// Request docid
939
		String docId = ((String[]) (params.get("docid")))[0];
940
		//check if the doicd is null
941
		if (docId == null) {
942
			logMetacat.error("ReplicationService.handleGetDataFileRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
943
			logReplication.error("ReplicationService.handleGetDataFileRequest - Didn't specify docid for replication");
944
			return;
945
		}
946

    
947
		//try to open a https stream to test if the request server's public key
948
		//in the key store, this is security issue
949
		try {
950
			filepath = PropertyService.getProperty("application.datafilepath");
951
			String server = params.get("server")[0];
952
			URL u = new URL("https://" + server + "?server="
953
					+ MetacatUtil.getLocalReplicationServerName() + "&action=test");
954
			String test = ReplicationService.getURLContent(u);
955
			//couldn't pass the test
956
			if (test.indexOf("successfully") == -1) {
957
				//response.setContentType("text/xml");
958
				//outPut.println("<error>Couldn't pass the trust test</error>");
959
				logMetacat.error("ReplicationService.handleGetDataFileRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
960
				logReplication.error("ReplicationService.handleGetDataFileRequest - Couldn't pass the trust test");
961
				return;
962
			}
963
		}//try
964
		catch (Exception ee) {
965
			return;
966
		}//catch
967

    
968
		if (!filepath.endsWith("/")) {
969
			filepath += "/";
970
		}
971
		// Get file aboslute file name
972
		String filename = filepath + docId;
973

    
974
		//MIME type
975
		String contentType = null;
976
		if (filename.endsWith(".xml")) {
977
			contentType = "text/xml";
978
		} else if (filename.endsWith(".css")) {
979
			contentType = "text/css";
980
		} else if (filename.endsWith(".dtd")) {
981
			contentType = "text/plain";
982
		} else if (filename.endsWith(".xsd")) {
983
			contentType = "text/xml";
984
		} else if (filename.endsWith("/")) {
985
			contentType = "text/html";
986
		} else {
987
			File f = new File(filename);
988
			if (f.isDirectory()) {
989
				contentType = "text/html";
990
			} else {
991
				contentType = "application/octet-stream";
992
			}
993
		}
994

    
995
		// Set the mime type
996
		response.setContentType(contentType);
997

    
998
		// Get the content of the file
999
		FileInputStream fin = null;
1000
		try {
1001
			// FileInputStream to metacat
1002
			fin = new FileInputStream(filename);
1003
			// 4K buffer
1004
			byte[] buf = new byte[4 * 1024];
1005
			// Read data from file input stream to byte array
1006
			int b = fin.read(buf);
1007
			// Write to outStream from byte array
1008
			while (b != -1) {
1009
				outPut.write(buf, 0, b);
1010
				b = fin.read(buf);
1011
			}
1012
			// close file input stream
1013
			fin.close();
1014

    
1015
		}//try
1016
		catch (Exception e) {
1017
			logMetacat.error("ReplicationService.handleGetDataFileRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1018
			logReplication.error("ReplicationService.handleGetDataFileRequest - error getting data file from MetacatReplication."
1019
					+ "handlGetDataFileRequest " + e.getMessage());
1020
			e.printStackTrace(System.out);
1021
		}//catch
1022

    
1023
	}
1024

    
1025
	/**
1026
	 * Sends a document to a remote host
1027
	 */
1028
	protected static void handleGetDocumentRequest(PrintWriter out,
1029
			Hashtable<String, String[]> params, HttpServletResponse response) {
1030

    
1031
		String urlString = null;
1032
		String documentPath = null;
1033
		try {
1034
			// try to open a https stream to test if the request server's public
1035
			// key
1036
			// in the key store, this is security issue
1037
			String server = params.get("server")[0];
1038
			urlString = "https://" + server + "?server="
1039
					+ MetacatUtil.getLocalReplicationServerName() + "&action=test";
1040
			URL u = new URL(urlString);
1041
			String test = ReplicationService.getURLContent(u);
1042
			// couldn't pass the test
1043
			if (test.indexOf("successfully") == -1) {
1044
				response.setContentType("text/xml");
1045
				out.println("<error>Couldn't pass the trust test " + test + " </error>");
1046
				out.close();
1047
				return;
1048
			}
1049

    
1050
			String docid = params.get("docid")[0];
1051
			logReplication.debug("ReplicationService.handleGetDocumentRequest - MetacatReplication.handleGetDocumentRequest for docid: "
1052
					+ docid);
1053
			DocumentImpl di = new DocumentImpl(docid);
1054

    
1055
			String documentDir = PropertyService
1056
					.getProperty("application.documentfilepath");
1057
			documentPath = documentDir + FileUtil.getFS() + docid;
1058

    
1059
			// if the document does not exist on disk, read it from db and write
1060
			// it to disk.
1061
			if (FileUtil.getFileStatus(documentPath) == FileUtil.DOES_NOT_EXIST
1062
					|| FileUtil.getFileSize(documentPath) == 0) {
1063
				FileWriter fileWriter = new FileWriter(documentPath);
1064
				di.toXml(fileWriter, null, null, true);
1065
			}
1066

    
1067
			// read the file from disk and sent it to PrintWriter
1068
			// PrintWriter out = new PrintWriter(streamOut);
1069
			di.readFromFileSystem(out, null, null, documentPath);
1070

    
1071
			// response.setContentType("text/xml");
1072
			// out.print(di.toString(null, null, true));
1073

    
1074
			logReplication.info("ReplicationService.handleGetDocumentRequest - document " + docid + " sent");
1075

    
1076
		} catch (MalformedURLException mue) {
1077
			logMetacat.error("ReplicationService.handleGetDocumentRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1078
			logReplication.error("ReplicationService.handleGetDocumentRequest - Url error when getting document from MetacatReplication."
1079
					+ "handlGetDocumentRequest for url: " + urlString + " : "
1080
					+ mue.getMessage());
1081
			// e.printStackTrace(System.out);
1082
			response.setContentType("text/xml");
1083
			out.println("<error>" + mue.getMessage() + "</error>");
1084
		} catch (IOException ioe) {
1085
			logMetacat.error("ReplicationService.handleGetDocumentRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1086
			logReplication.error("ReplicationService.handleGetDocumentRequest - I/O error when getting document from MetacatReplication."
1087
					+ "handlGetDocumentRequest for file: " + documentPath + " : "
1088
					+ ioe.getMessage());
1089
			// e.printStackTrace(System.out);
1090
			response.setContentType("text/xml");
1091
			out.println("<error>" + ioe.getMessage() + "</error>");
1092
		} catch (PropertyNotFoundException pnfe) {
1093
			logMetacat.error("ReplicationService.handleGetDocumentRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1094
			logReplication
1095
					.error("ReplicationService.handleGetDocumentRequest - Error getting property when getting document from MetacatReplication."
1096
							+ "handlGetDocumentRequest for file: "
1097
							+ documentPath
1098
							+ " : "
1099
							+ pnfe.getMessage());
1100
			// e.printStackTrace(System.out);
1101
			response.setContentType("text/xml");
1102
			out.println("<error>" + pnfe.getMessage() + "</error>");
1103
		} catch (McdbException me) {
1104
			logReplication
1105
					.error("ReplicationService.handleGetDocumentRequest - Document implementation error  getting property when getting document from MetacatReplication."
1106
							+ "handlGetDocumentRequest for file: "
1107
							+ documentPath
1108
							+ " : "
1109
							+ me.getMessage());
1110
			// e.printStackTrace(System.out);
1111
			response.setContentType("text/xml");
1112
			out.println("<error>" + me.getMessage() + "</error>");
1113
		}
1114

    
1115
	}
1116

    
1117
	/**
1118
	 * Sends a list of all of the documents on this sever along with their
1119
	 * revision numbers. The format is: <!ELEMENT replication (server, updates)>
1120
	 * <!ELEMENT server (#PCDATA)> <!ELEMENT updates ((updatedDocument |
1121
	 * deleteDocument | revisionDocument)*)> <!ELEMENT updatedDocument (docid,
1122
	 * rev, datafile*)> <!ELEMENT deletedDocument (docid, rev)> <!ELEMENT
1123
	 * revisionDocument (docid, rev, datafile*)> <!ELEMENT docid (#PCDATA)>
1124
	 * <!ELEMENT rev (#PCDATA)> <!ELEMENT datafile (#PCDATA)> note that the rev
1125
	 * in deletedDocument is always empty. I just left it in there to make the
1126
	 * parser implementation easier.
1127
	 */
1128
	protected static void handleUpdateRequest(PrintWriter out, Hashtable<String, String[]> params,
1129
			HttpServletResponse response) {
1130
		// Checked out DBConnection
1131
		DBConnection dbConn = null;
1132
		// DBConenction serial number when checked it out
1133
		int serialNumber = -1;
1134
		PreparedStatement pstmt = null;
1135
		// Server list to store server info of xml_replication table
1136
		ReplicationServerList serverList = null;
1137

    
1138
		try {
1139
			// Check out a DBConnection from pool
1140
			dbConn = DBConnectionPool
1141
					.getDBConnection("MetacatReplication.handleUpdateRequest");
1142
			serialNumber = dbConn.getCheckOutSerialNumber();
1143
			// Create a server list from xml_replication table
1144
			serverList = new ReplicationServerList();
1145

    
1146
			// Get remote server name from param
1147
			String server = ((String[]) params.get("server"))[0];
1148
			// If no servr name in param, return a error
1149
			if (server == null || server.equals("")) {
1150
				response.setContentType("text/xml");
1151
				out.println("<error>Request didn't specify server name</error>");
1152
				out.close();
1153
				return;
1154
			}//if
1155

    
1156
			//try to open a https stream to test if the request server's public key
1157
			//in the key store, this is security issue
1158
			URL u = new URL("https://" + server + "?server="
1159
					+ MetacatUtil.getLocalReplicationServerName() + "&action=test");
1160
			String test = ReplicationService.getURLContent(u);
1161
			//couldn't pass the test
1162
			if (test.indexOf("successfully") == -1) {
1163
				response.setContentType("text/xml");
1164
				out.println("<error>Couldn't pass the trust test</error>");
1165
				out.close();
1166
				return;
1167
			}
1168

    
1169
			// Check if local host configure to replicate xml documents to remote
1170
			// server. If not send back a error message
1171
			if (!serverList.getReplicationValue(server)) {
1172
				response.setContentType("text/xml");
1173
				out
1174
						.println("<error>Configuration not allow to replicate document to you</error>");
1175
				out.close();
1176
				return;
1177
			}//if
1178

    
1179
			// Store the sql command
1180
			StringBuffer docsql = new StringBuffer();
1181
			StringBuffer revisionSql = new StringBuffer();
1182
			// Stroe the docid list
1183
			StringBuffer doclist = new StringBuffer();
1184
			// Store the deleted docid list
1185
			StringBuffer delsql = new StringBuffer();
1186
			// Store the data set file
1187
			Vector<Vector<String>> packageFiles = new Vector<Vector<String>>();
1188

    
1189
			// Append local server's name and replication servlet to doclist
1190
			doclist.append("<?xml version=\"1.0\"?><replication>");
1191
			doclist.append("<server>")
1192
					.append(MetacatUtil.getLocalReplicationServerName());
1193
			//doclist.append(util.getProperty("replicationpath"));
1194
			doclist.append("</server><updates>");
1195

    
1196
			// Get correct docid that reside on this server according the requesting
1197
			// server's replicate and data replicate value in xml_replication table
1198
			docsql.append(DatabaseService.getInstance().getDBAdapter().getReplicationDocumentListSQL());
1199
			//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)) ");
1200
			revisionSql.append("select docid, rev, doctype from xml_revisions ");
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
				String serverLocationDoc = " and a.server_location = 1";
1205
				String serverLocationRev = "where server_location = 1";
1206
				docsql.append(serverLocationDoc);
1207
				revisionSql.append(serverLocationRev);
1208
			}
1209
			logReplication.info("ReplicationService.handleUpdateRequest - Doc sql: " + docsql.toString());
1210

    
1211
			// Get any deleted documents
1212
			delsql.append("select distinct docid from ");
1213
			delsql.append("xml_revisions where docid not in (select docid from ");
1214
			delsql.append("xml_documents) ");
1215
			// If the localhost is not a hub to the remote server, only replicate
1216
			// the docid' which home server is local host (server_location =1)
1217
			if (!serverList.getHubValue(server)) {
1218
				delsql.append("and server_location = 1");
1219
			}
1220
			logReplication.info("ReplicationService.handleUpdateRequest - Deleted sql: " + delsql.toString());
1221

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

    
1300
			pstmt = dbConn.prepareStatement(delsql.toString());
1301
			//usage count should increas 1
1302
			dbConn.increaseUsageCount(1);
1303

    
1304
			pstmt.execute();
1305
			rs = pstmt.getResultSet();
1306
			tablehasrows = rs.next();
1307
			while (tablehasrows) { //handle the deleted documents
1308
				doclist.append("<deletedDocument><docid>").append(rs.getString(1));
1309
				doclist.append("</docid><rev></rev></deletedDocument>");
1310
				//note that rev is always empty for deleted docs
1311
				tablehasrows = rs.next();
1312
			}
1313

    
1314
			//now we can put the package files into the xml results
1315
			for (int i = 0; i < packageFiles.size(); i++) {
1316
				Vector<String> v = packageFiles.elementAt(i);
1317
				doclist.append("<updatedDocument>");
1318
				doclist.append("<docid>").append(v.elementAt(0));
1319
				doclist.append("</docid><rev>");
1320
				doclist.append(v.elementAt(1));
1321
				doclist.append("</rev>");
1322
				doclist.append("</updatedDocument>");
1323
			}
1324
			// add revision doc list  
1325
			doclist.append(prepareRevisionDoc(dbConn, revisionSql.toString(),
1326
					replicateData));
1327

    
1328
			doclist.append("</updates></replication>");
1329
			logReplication.info("ReplicationService.handleUpdateRequest - doclist: " + doclist.toString());
1330
			pstmt.close();
1331
			//conn.close();
1332
			response.setContentType("text/xml");
1333
			out.println(doclist.toString());
1334

    
1335
		} catch (Exception e) {
1336
			logMetacat.error("ReplicationService.handleUpdateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1337
			logReplication.error("ReplicationService.handleUpdateRequest - error in MetacatReplication." + "handleupdaterequest: "
1338
					+ e.getMessage());
1339
			//e.printStackTrace(System.out);
1340
			response.setContentType("text/xml");
1341
			out.println("<error>" + e.getMessage() + "</error>");
1342
		} finally {
1343
			try {
1344
				pstmt.close();
1345
			}//try
1346
			catch (SQLException ee) {
1347
				logMetacat.error("ReplicationService.handleUpdateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1348
				logReplication.error("ReplicationService.handleUpdateRequest - Error in MetacatReplication."
1349
						+ "handleUpdaterequest to close pstmt: " + ee.getMessage());
1350
			}//catch
1351
			finally {
1352
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1353
			}//finally
1354
		}//finally
1355

    
1356
	}//handlUpdateRequest
1357

    
1358
	/*
1359
	 * This method will get the xml string for document in xml_revision
1360
	 * The schema look like <!ELEMENT revisionDocument (docid, rev, datafile*)>
1361
	 */
1362
	private static String prepareRevisionDoc(DBConnection dbConn, String revSql,
1363
			boolean replicateData) throws Exception {
1364
		logReplication.warn("ReplicationService.prepareRevisionDoc - The revision document sql is " + revSql);
1365
		StringBuffer revDocList = new StringBuffer();
1366
		PreparedStatement pstmt = dbConn.prepareStatement(revSql);
1367
		//usage count should increas 1
1368
		dbConn.increaseUsageCount(1);
1369

    
1370
		pstmt.execute();
1371
		ResultSet rs = pstmt.getResultSet();
1372
		boolean tablehasrows = rs.next();
1373
		while (tablehasrows) {
1374
			String recordDoctype = rs.getString(3);
1375

    
1376
			//If this is data file and it isn't configured to replicate data
1377
			if (recordDoctype.equals("BIN") && !replicateData) {
1378
				// do nothing
1379
				continue;
1380
			} else {
1381

    
1382
				revDocList.append("<revisionDocument>");
1383
				revDocList.append("<docid>").append(rs.getString(1));
1384
				revDocList.append("</docid><rev>").append(rs.getInt(2));
1385
				revDocList.append("</rev>");
1386
				// data file
1387
				if (recordDoctype.equals("BIN")) {
1388
					revDocList.append("<datafile>");
1389
					revDocList.append(PropertyService
1390
							.getProperty("replication.datafileflag"));
1391
					revDocList.append("</datafile>");
1392
				}
1393
				revDocList.append("</revisionDocument>");
1394

    
1395
			}//else
1396
			tablehasrows = rs.next();
1397
		}
1398
		//System.out.println("The revision list is"+ revDocList.toString());
1399
		return revDocList.toString();
1400
	}
1401

    
1402
	/**
1403
	 * Returns the xml_catalog table encoded in xml
1404
	 */
1405
	public static String getCatalogXML() {
1406
		return handleGetCatalogRequest(null, null, null, false);
1407
	}
1408

    
1409
	/**
1410
	 * Sends the contents of the xml_catalog table encoded in xml
1411
	 * The xml format is:
1412
	 * <!ELEMENT xml_catalog (row*)>
1413
	 * <!ELEMENT row (entry_type, source_doctype, target_doctype, public_id,
1414
	 *                system_id)>
1415
	 * All of the sub elements of row are #PCDATA
1416

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

    
1452
				tablehasrows = rs.next();
1453
			}
1454
			sb.append("</xml_catalog>");
1455
			//conn.close();
1456
			if (printFlag) {
1457
				response.setContentType("text/xml");
1458
				out.println(sb.toString());
1459
			}
1460
			pstmt.close();
1461
			return sb.toString();
1462
		} catch (Exception e) {
1463
			logMetacat.error("ReplicationService.handleGetCatalogRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1464
			logReplication.error("ReplicationService.handleGetCatalogRequest - error in MetacatReplication.handleGetCatalogRequest:"
1465
					+ e.getMessage());
1466
			e.printStackTrace(System.out);
1467
			if (printFlag) {
1468
				out.println("<error>" + e.getMessage() + "</error>");
1469
			}
1470
		} finally {
1471
			try {
1472
				pstmt.close();
1473
			}//try
1474
			catch (SQLException ee) {
1475
				logMetacat.error("ReplicationService.handleGetCatalogRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1476
				logReplication.error("ReplicationService.handleGetCatalogRequest - Error in MetacatReplication.handleGetCatalogRequest: "
1477
						+ ee.getMessage());
1478
			}//catch
1479
			finally {
1480
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1481
			}//finally
1482
		}//finally
1483

    
1484
		return null;
1485
	}
1486

    
1487
	/**
1488
	 * Sends the current system date to the remote server.  Using this action
1489
	 * for replication gets rid of any problems with syncronizing clocks
1490
	 * because a time specific to a document is always kept on its home server.
1491
	 */
1492
	protected static void handleGetTimeRequest(PrintWriter out,
1493
			Hashtable<String, String[]> params, HttpServletResponse response) {
1494
		SimpleDateFormat formatter = new SimpleDateFormat("MM/dd/yy HH:mm:ss");
1495
		java.util.Date localtime = new java.util.Date();
1496
		String dateString = formatter.format(localtime);
1497
		response.setContentType("text/xml");
1498

    
1499
		out.println("<timestamp>" + dateString + "</timestamp>");
1500
	}
1501

    
1502
	/**
1503
	 * this method handles the timeout for a file lock.  when a lock is
1504
	 * granted it is granted for 30 seconds.  When this thread runs out
1505
	 * it deletes the docid from the queue, thus eliminating the lock.
1506
	 */
1507
	public void run() {
1508
		try {
1509
			logReplication.info("ReplicationService.run - thread started for docid: "
1510
					+ (String) fileLocks.elementAt(0));
1511

    
1512
			Thread.sleep(30000); //the lock will expire in 30 seconds
1513
			logReplication.info("thread for docid: "
1514
					+ (String) fileLocks.elementAt(fileLocks.size() - 1) + " exiting.");
1515

    
1516
			fileLocks.remove(fileLocks.size() - 1);
1517
			//fileLocks is treated as a FIFO queue.  If there are more than one lock
1518
			//in the vector, the first one inserted will be removed.
1519
		} catch (Exception e) {
1520
			logMetacat.error("ReplicationService.run - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1521
			logReplication.error("ReplicationService.run - error in file lock thread from "
1522
					+ "MetacatReplication.run: " + e.getMessage());
1523
		}
1524
	}
1525

    
1526
	/**
1527
	 * Returns the name of a server given a serverCode
1528
	 * @param serverCode the serverid of the server
1529
	 * @return the servername or null if the specified serverCode does not
1530
	 *         exist.
1531
	 */
1532
	public static String getServerNameForServerCode(int serverCode) {
1533
		//System.out.println("serverid: " + serverCode);
1534
		DBConnection dbConn = null;
1535
		int serialNumber = -1;
1536
		PreparedStatement pstmt = null;
1537
		try {
1538
			dbConn = DBConnectionPool.getDBConnection("MetacatReplication.getServer");
1539
			serialNumber = dbConn.getCheckOutSerialNumber();
1540
			String sql = new String("select server from "
1541
					+ "xml_replication where serverid = " + serverCode);
1542
			pstmt = dbConn.prepareStatement(sql);
1543
			//System.out.println("getserver sql: " + sql);
1544
			pstmt.execute();
1545
			ResultSet rs = pstmt.getResultSet();
1546
			boolean tablehasrows = rs.next();
1547
			if (tablehasrows) {
1548
				//System.out.println("server: " + rs.getString(1));
1549
				return rs.getString(1);
1550
			}
1551

    
1552
			//conn.close();
1553
		} catch (Exception e) {
1554
			logMetacat.error("ReplicationService.getServerNameForServerCode - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1555
			logReplication.error("ReplicationService.getServerNameForServerCode - Error in MetacatReplication.getServer: " + e.getMessage());
1556
		} finally {
1557
			try {
1558
				pstmt.close();
1559
			}//try
1560
			catch (SQLException ee) {
1561
				logMetacat.error("ReplicationService.getServerNameForServerCode - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1562
				logReplication.error("ReplicationService.getServerNameForServerCode - Error in MetacactReplication.getserver: "
1563
						+ ee.getMessage());
1564
			}//catch
1565
			finally {
1566
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1567
			}//fianlly
1568
		}//finally
1569

    
1570
		return null;
1571
		//return null if the server does not exist
1572
	}
1573

    
1574
	/**
1575
	 * Returns a server code given a server name
1576
	 * @param server the name of the server
1577
	 * @return integer > 0 representing the code of the server, 0 if the server
1578
	 *  does not exist.
1579
	 */
1580
	public static int getServerCodeForServerName(String server) throws ServiceException {
1581
		DBConnection dbConn = null;
1582
		int serialNumber = -1;
1583
		PreparedStatement pstmt = null;
1584
		int serverCode = 0;
1585

    
1586
		try {
1587

    
1588
			//conn = util.openDBConnection();
1589
			dbConn = DBConnectionPool.getDBConnection("MetacatReplication.getServerCode");
1590
			serialNumber = dbConn.getCheckOutSerialNumber();
1591
			pstmt = dbConn.prepareStatement("SELECT serverid FROM xml_replication "
1592
					+ "WHERE server LIKE '" + server + "'");
1593
			pstmt.execute();
1594
			ResultSet rs = pstmt.getResultSet();
1595
			boolean tablehasrows = rs.next();
1596
			if (tablehasrows) {
1597
				serverCode = rs.getInt(1);
1598
				pstmt.close();
1599
				//conn.close();
1600
				return serverCode;
1601
			}
1602

    
1603
		} catch (SQLException sqle) {
1604
			throw new ServiceException("ReplicationService.getServerCodeForServerName - " 
1605
					+ "SQL error when getting server code: " + sqle.getMessage());
1606

    
1607
		} finally {
1608
			try {
1609
				pstmt.close();
1610
				//conn.close();
1611
			}//try
1612
			catch (Exception ee) {
1613
				logMetacat.error("ReplicationService.getServerCodeForServerName - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1614
				logReplication.error("ReplicationService.getServerNameForServerCode - Error in MetacatReplicatio.getServerCode: "
1615
						+ ee.getMessage());
1616

    
1617
			}//catch
1618
			finally {
1619
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1620
			}//finally
1621
		}//finally
1622

    
1623
		return serverCode;
1624
	}
1625

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

    
1666
				String server = rs.getString(1);
1667
				String last_checked = rs.getString(2);
1668
				if (!server.equals("localhost")) {
1669
					sl.put(server, last_checked);
1670
				}
1671

    
1672
			} else {
1673
				pstmt.close();
1674
				//ut.returnConnection(conn);
1675
				return null;
1676
			}
1677
			pstmt.close();
1678
		} catch (Exception e) {
1679
			logMetacat.error("ReplicationService.getHomeServerInfoForDocId - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1680
			logReplication.error("ReplicationService.getHomeServerInfoForDocId - error in replicationHandler.getHomeServer(): "
1681
					+ e.getMessage());
1682
		} finally {
1683
			try {
1684
				pstmt.close();
1685
				//ut.returnConnection(conn);
1686
			} catch (Exception ee) {
1687
				logMetacat.error("ReplicationService.getHomeServerInfoForDocId - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1688
				logReplication.error("ReplicationService.getHomeServerInfoForDocId - Eror irn rplicationHandler.getHomeServer() "
1689
						+ "to close pstmt: " + ee.getMessage());
1690
			} finally {
1691
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1692
			}
1693

    
1694
		}//finally
1695
		return sl;
1696
	}
1697

    
1698
	/**
1699
	 * Returns a home server location  given a accnum
1700
	 * @param accNum , given accNum for a document
1701
	 *
1702
	 */
1703
	public static int getHomeServerCodeForDocId(String accNum) throws ServiceException {
1704
		DBConnection dbConn = null;
1705
		int serialNumber = -1;
1706
		PreparedStatement pstmt = null;
1707
		int serverCode = 1;
1708
		String docId = DocumentUtil.getDocIdFromString(accNum);
1709

    
1710
		try {
1711

    
1712
			// Get DBConnection
1713
			dbConn = DBConnectionPool
1714
					.getDBConnection("ReplicationHandler.getServerLocation");
1715
			serialNumber = dbConn.getCheckOutSerialNumber();
1716
			pstmt = dbConn.prepareStatement("SELECT server_location FROM xml_documents "
1717
					+ "WHERE docid LIKE '" + docId + "'");
1718
			pstmt.execute();
1719
			ResultSet rs = pstmt.getResultSet();
1720
			boolean tablehasrows = rs.next();
1721
			//If a document is find, return the server location for it
1722
			if (tablehasrows) {
1723
				serverCode = rs.getInt(1);
1724
				pstmt.close();
1725
				//conn.close();
1726
				return serverCode;
1727
			}
1728
			//if couldn't find in xml_documents table, we think server code is 1
1729
			//(this is new document)
1730
			else {
1731
				pstmt.close();
1732
				//conn.close();
1733
				return serverCode;
1734
			}
1735

    
1736
		} catch (SQLException sqle) {
1737
			throw new ServiceException("ReplicationService.getHomeServerCodeForDocId - " 
1738
					+ "SQL error when getting home server code for docid: " + docId + " : " 
1739
					+ sqle.getMessage());
1740

    
1741
		} finally {
1742
			try {
1743
				pstmt.close();
1744
				//conn.close();
1745

    
1746
			} catch (SQLException sqle) {
1747
				logMetacat.error("ReplicationService.getHomeServerCodeForDocId - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1748
				logReplication.error("ReplicationService.getHomeServerCodeForDocId - ReplicationService.getHomeServerCodeForDocId - " 
1749
						+ "SQL error when getting home server code for docid: " + docId + " : " 
1750
						+ sqle.getMessage());
1751
			} finally {
1752
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1753
			}//finally
1754
		}//finally
1755
		//return serverCode;
1756
	}
1757

    
1758
	/**
1759
	 * This method returns the content of a url
1760
	 * @param u the url to return the content from
1761
	 * @return a string representing the content of the url
1762
	 * @throws java.io.IOException
1763
	 */
1764
	public static String getURLContent(URL u) throws java.io.IOException {
1765
		char istreamChar;
1766
		int istreamInt;
1767
		logReplication.debug("ReplicationService.getURLContent - Before open the stream" + u.toString());
1768
		InputStream input = u.openStream();
1769
		logReplication.debug("ReplicationService.getURLContent - After open the stream" + u.toString());
1770
		InputStreamReader istream = new InputStreamReader(input);
1771
		StringBuffer serverResponse = new StringBuffer();
1772
		while ((istreamInt = istream.read()) != -1) {
1773
			istreamChar = (char) istreamInt;
1774
			serverResponse.append(istreamChar);
1775
		}
1776
		istream.close();
1777
		input.close();
1778

    
1779
		return serverResponse.toString();
1780
	}
1781

    
1782
//	/**
1783
//	 * Method for writing replication messages to a log file specified in
1784
//	 * metacat.properties
1785
//	 */
1786
//	public static void replLog(String message) {
1787
//		try {
1788
//			FileOutputStream fos = new FileOutputStream(PropertyService
1789
//					.getProperty("replication.logdir")
1790
//					+ "/metacatreplication.log", true);
1791
//			PrintWriter pw = new PrintWriter(fos);
1792
//			SimpleDateFormat formatter = new SimpleDateFormat("yy-MM-dd HH:mm:ss");
1793
//			java.util.Date localtime = new java.util.Date();
1794
//			String dateString = formatter.format(localtime);
1795
//			dateString += " :: " + message;
1796
//			// time stamp each entry
1797
//			pw.println(dateString);
1798
//			pw.flush();
1799
//		} catch (Exception e) {
1800
//			logReplication.error("error writing to replication log from "
1801
//					+ "MetacatReplication.replLog: " + e.getMessage());
1802
//			// e.printStackTrace(System.out);
1803
//		}
1804
//	}
1805

    
1806
//	/**
1807
//	 * Method for writing replication messages to a log file specified in
1808
//	 * metacat.properties
1809
//	 */
1810
//	public static void replErrorLog(String message) {
1811
//		try {
1812
//			FileOutputStream fos = new FileOutputStream(PropertyService
1813
//					.getProperty("replication.logdir")
1814
//					+ "/metacatreplicationerror.log", true);
1815
//			PrintWriter pw = new PrintWriter(fos);
1816
//			SimpleDateFormat formatter = new SimpleDateFormat("yy-MM-dd HH:mm:ss");
1817
//			java.util.Date localtime = new java.util.Date();
1818
//			String dateString = formatter.format(localtime);
1819
//			dateString += " :: " + message;
1820
//			//time stamp each entry
1821
//			pw.println(dateString);
1822
//			pw.flush();
1823
//		} catch (Exception e) {
1824
//			logReplication.error("error writing to replication error log from "
1825
//					+ "MetacatReplication.replErrorLog: " + e.getMessage());
1826
//			//e.printStackTrace(System.out);
1827
//		}
1828
//	}
1829

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

    
1880
}
(6-6/7)