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-07-22 15:30:27 -0700 (Thu, 22 Jul 2010) $'
10
 * '$Revision: 5441 $'
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 docid: " + docid);
505
			logReplication.info("ReplicationService.handleForceReplicateRequest - Force replication action: " + dbaction);
506
			// sending back read request to remote server
507
			URL u = new URL("https://" + server + "?server="
508
					+ MetacatUtil.getLocalReplicationServerName() + "&action=read&docid="
509
					+ docid);
510
			String xmldoc = ReplicationService.getURLContent(u);
511

    
512
			// get the document info from server
513
			URL docinfourl = new URL("https://" + server + "?server="
514
					+ MetacatUtil.getLocalReplicationServerName()
515
					+ "&action=getdocumentinfo&docid=" + docid);
516
			
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.info("XXXXXXXXXXXXXXXX GUID found in dociinfoHash: " + guid);
533
			
534
			logReplication.debug("Processing guid " + guid + 
535
			  " information from handleForceReplicationRequest: " + 
536
			  docinfoHash.toString());
537
      IdentifierManager idman = IdentifierManager.getInstance();
538
      if(guid != null && !idman.identifierExists(guid))
539
      { //if the guid was passed in, put it in the identifiers table
540
        logReplication.info("XXXXXXXXXXXXXXXXXXX Creating guid/docid mapping for docid " + 
541
          docinfoHash.get("docid") + " and guid: " + guid);
542
        idman.createMapping(guid, docinfoHash.get("docid"));
543
      }
544
      else
545
      {
546
        logReplication.debug("No guid information was included with the replicated document");
547
      }
548
      
549
			String createdDate = (String) docinfoHash.get("date_created");
550
			String updatedDate = (String) docinfoHash.get("date_updated");
551
			logReplication.info("ReplicationService.handleForceReplicateRequest - homeServer: " + homeServer);
552
			// Get Document type
553
			String docType = (String) docinfoHash.get("doctype");
554
			logReplication.info("ReplicationService.handleForceReplicateRequest - docType: " + docType);
555
			String parserBase = null;
556
			// this for eml2 and we need user eml2 parser
557
			if (docType != null
558
					&& (docType.trim()).equals(DocumentImpl.EML2_0_0NAMESPACE)) {
559
				logReplication.warn("ReplicationService.handleForceReplicateRequest - This is an eml200 document!");
560
				parserBase = DocumentImpl.EML200;
561
			} else if (docType != null
562
					&& (docType.trim()).equals(DocumentImpl.EML2_0_1NAMESPACE)) {
563
				logReplication.warn("ReplicationService.handleForceReplicateRequest - This is an eml2.0.1 document!");
564
				parserBase = DocumentImpl.EML200;
565
			} else if (docType != null
566
					&& (docType.trim()).equals(DocumentImpl.EML2_1_0NAMESPACE)) {
567
				logReplication.warn("ReplicationService.handleForceReplicateRequest - This is an eml2.1.0 document!");
568
				parserBase = DocumentImpl.EML210;
569
			}
570
			logReplication.warn("ReplicationService.handleForceReplicateRequest - The parserBase is: " + parserBase);
571

    
572
			// Get DBConnection from pool
573
			dbConn = DBConnectionPool
574
					.getDBConnection("MetacatReplication.handleForceReplicateRequest");
575
			serialNumber = dbConn.getCheckOutSerialNumber();
576
			// write the document to local database
577
			DocumentImplWrapper wrapper = new DocumentImplWrapper(parserBase, false);
578
			//try this independently so we can set
579
//			Exception writeException = null;
580
			try {
581
				wrapper.writeReplication(dbConn, xmldoc, null, null,
582
						dbaction, docid, user, null, homeServer, server, createdDate,
583
						updatedDate);
584
			} finally {
585
//				writeException = e;
586

    
587
				//process extra access rules before dealing with the write exception (doc exist already)			
588
		        Vector<XMLAccessDAO> accessControlList = dih.getAccessControlList();
589
		        if (accessControlList != null) {
590
		        	AccessControlForSingleFile acfsf = new AccessControlForSingleFile(docid);
591
		        	for (XMLAccessDAO xmlAccessDAO : accessControlList) {
592
		        		if (!acfsf.accessControlExists(xmlAccessDAO)) {
593
		        			acfsf.insertPermissions(xmlAccessDAO);
594
							logReplication.info("ReplicationService.handleForceReplicateRequest - document " + docid
595
									+ " permissions added to DB");
596
		        		}
597
		            }
598
		        }
599
//				if (accessControlList != null) {
600
//					for (int i = 0; i < accessControlList.size(); i++) {
601
//						AccessControlForSingleFile acfsf = (AccessControlForSingleFile) accessControlList
602
//								.get(i);
603
//						if (!acfsf.accessControlExists()) {
604
//							acfsf.insertPermissions();
605
//							logReplication.info("ReplicationService.handleForceReplicateRequest - document " + docid
606
//									+ " permissions added to DB");
607
//						}
608
//					}
609
//				}
610

    
611
//				if (writeException != null) {
612
//					throw writeException;
613
//				}
614

    
615
				logReplication.info("ReplicationService.handleForceReplicateRequest - document " + docid + " added to DB with "
616
						+ "action " + dbaction);
617
				EventLog.getInstance().log(request.getRemoteAddr(), REPLICATIONUSER, docid,
618
						dbaction);
619
			}
620
		} catch (SQLException sqle) {
621
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
622
			logReplication.error("ReplicationService.handleForceReplicateRequest - SQL error when adding doc " + docid + 
623
					" to DB with action " + dbaction + ": " + sqle.getMessage());
624
		} catch (MalformedURLException mue) {
625
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
626
			logReplication.error("ReplicationService.handleForceReplicateRequest - URL error when adding doc " + docid + 
627
					" to DB with action " + dbaction + ": " + mue.getMessage());
628
		} catch (SAXException se) {
629
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
630
			logReplication.error("ReplicationService.handleForceReplicateRequest - SAX parsing error when adding doc " + docid + 
631
					" to DB with action " + dbaction + ": " + se.getMessage());
632
		} catch (HandlerException he) {
633
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
634
			logReplication.error("ReplicationService.handleForceReplicateRequest - Handler error when adding doc " + docid + 
635
					" to DB with action " + dbaction + ": " + he.getMessage());
636
		} catch (IOException ioe) {
637
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
638
			logReplication.error("ReplicationService.handleForceReplicateRequest - I/O error when adding doc " + docid + 
639
					" to DB with action " + dbaction + ": " + ioe.getMessage());
640
		} catch (PermOrderException poe) {
641
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
642
			logReplication.error("ReplicationService.handleForceReplicateRequest - Permissions order error when adding doc " + docid + 
643
					" to DB with action " + dbaction + ": " + poe.getMessage());
644
		} catch (AccessControlException ace) {
645
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
646
			logReplication.error("ReplicationService.handleForceReplicateRequest - Permissions order error when adding doc " + docid + 
647
					" to DB with action " + dbaction + ": " + ace.getMessage());
648
		} catch (Exception e) {
649
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
650
			logReplication.error("ReplicationService.handleForceReplicateRequest - General error when adding doc " + docid + 
651
					" to DB with action " + dbaction + ": " + e.getMessage());
652
		} finally {
653
			// Return the checked out DBConnection
654
			DBConnectionPool.returnDBConnection(dbConn, serialNumber);
655
		}//finally
656
	}
657

    
658
	/*
659
	 * when a forcereplication delete request comes in, local host will delete this
660
	 * document
661
	 */
662
	protected static void handleForceReplicateDeleteRequest(PrintWriter out,
663
			Hashtable<String, String[]> params, HttpServletResponse response,
664
			HttpServletRequest request) {
665
		String server = ((String[]) params.get("server"))[0]; // the server that
666
		String docid = ((String[]) params.get("docid"))[0]; // sent the document
667
		try {
668
			logReplication.info("ReplicationService.handleForceReplicateDeleteRequest - force replication delete request from " + server);
669
			logReplication.info("ReplicationService.handleForceReplicateDeleteRequest - force replication delete docid " + docid);
670
			logReplication.info("ReplicationService.handleForceReplicateDeleteRequest - Force replication delete request from: " + server);
671
			logReplication.info("ReplicationService.handleForceReplicateDeleteRequest - Force replication delete docid: " + docid);
672
			DocumentImpl.delete(docid, null, null, server);
673
			logReplication.info("ReplicationService.handleForceReplicateDeleteRequest - document " + docid + " was successfully deleted ");
674
			EventLog.getInstance().log(request.getRemoteAddr(), REPLICATIONUSER, docid,
675
					"delete");
676
			logReplication.info("ReplicationService.handleForceReplicateDeleteRequest - document " + docid + " was successfully deleted ");
677
		} catch (Exception e) {
678
			logMetacat.error("ReplicationService.handleForceReplicateDeleteRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
679
			logReplication.error("document " + docid
680
					+ " failed to delete because " + e.getMessage());
681
			logReplication.error("ReplicationService.handleForceReplicateDeleteRequest - error: " + e.getMessage());
682

    
683
		}//catch
684

    
685
	}
686

    
687
	/**
688
	 * when a forcereplication data file request comes in, local host sends a
689
	 * readdata request to the requesting server (remote server) for the specified
690
	 * docid. Then store it in local database and file system
691
	 */
692
	protected static void handleForceReplicateDataFileRequest(Hashtable<String, String[]> params,
693
			HttpServletRequest request) {
694

    
695
		//make sure there is some parameters
696
		if (params.isEmpty()) {
697
			return;
698
		}
699
		// Get remote server
700
		String server = ((String[]) params.get("server"))[0];
701
		// the docid should include rev number
702
		String docid = ((String[]) params.get("docid"))[0];
703
		// Make sure there is a docid and server
704
		if (docid == null || server == null || server.equals("")) {
705
			logMetacat.error("ReplicationService.handleForceReplicateDataFileRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
706
			logReplication.error("ReplicationService.handleForceReplicateDataFileRequest - Didn't specify docid or server for replication");
707
			return;
708
		}
709

    
710
		// Overide or not
711
		//    boolean override = false;
712
		// dbaction - update or insert
713
		String dbaction = null;
714

    
715
		try {
716
			//docid was switch to two parts uinque code and rev
717
			//String uniqueCode=MetacatUtil.getDocIdFromString(docid);
718
			//int rev=MetacatUtil.getVersionFromString(docid);
719
			if (params.containsKey("dbaction")) {
720
				dbaction = ((String[]) params.get("dbaction"))[0];
721
			} else//default value is update
722
			{
723
				dbaction = "update";
724
			}
725

    
726
			logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - force replication request from " + server);
727
			logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - Force replication request from: " + server);
728
			logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - Force replication docid: " + docid);
729
			logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - Force replication action: " + dbaction);
730
			// get the document info from server
731
			URL docinfourl = new URL("https://" + server + "?server="
732
					+ MetacatUtil.getLocalReplicationServerName()
733
					+ "&action=getdocumentinfo&docid=" + docid);
734

    
735
			String docInfoStr = ReplicationService.getURLContent(docinfourl);
736

    
737
			//dih is the parser for the docinfo xml format
738
			DocInfoHandler dih = new DocInfoHandler();
739
			XMLReader docinfoParser = ReplicationHandler.initParser(dih);
740
			docinfoParser.parse(new InputSource(new StringReader(docInfoStr)));
741
			Hashtable<String, String> docinfoHash = dih.getDocInfo();
742
			String user = (String) docinfoHash.get("user_owner");
743

    
744
			String docName = (String) docinfoHash.get("docname");
745

    
746
			String docType = (String) docinfoHash.get("doctype");
747

    
748
			String docHomeServer = (String) docinfoHash.get("home_server");
749

    
750
			String createdDate = (String) docinfoHash.get("date_created");
751

    
752
			String updatedDate = (String) docinfoHash.get("date_updated");
753
			logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - docHomeServer of datafile: " + docHomeServer);
754

    
755
			//if action is delete, we don't delete the data file. Just archieve
756
			//the xml_documents
757
			/*if (dbaction.equals("delete"))
758
			{
759
			  //conn = util.getConnection();
760
			  DocumentImpl.delete(docid,user,null);
761
			  //util.returnConnection(conn);
762
			}*/
763
			//To data file insert or update is same
764
			if (dbaction.equals("insert") || dbaction.equals("update")) {
765
				//Get data file and store it into local file system.
766
				// sending back readdata request to server
767
				URL url = new URL("https://" + server + "?server="
768
						+ MetacatUtil.getLocalReplicationServerName()
769
						+ "&action=readdata&docid=" + docid);
770
				String datafilePath = PropertyService
771
						.getProperty("application.datafilepath");
772

    
773
				Exception writeException = null;
774
				//register data file into xml_documents table and wite data file
775
				//into file system
776
				try {
777
					DocumentImpl.writeDataFileInReplication(url.openStream(),
778
							datafilePath, docName, docType, docid, user, docHomeServer,
779
							server, DocumentImpl.DOCUMENTTABLE, false, createdDate,
780
							updatedDate);
781
				} catch (Exception e) {
782
					writeException = e;
783
				}
784
				//process extra access rules
785
//				Vector<AccessControlForSingleFile> accessControlList = dih
786
//						.getAccessControlList();
787
//				if (accessControlList != null) {
788
//					for (int i = 0; i < accessControlList.size(); i++) {
789
//						AccessControlForSingleFile acfsf = (AccessControlForSingleFile) accessControlList
790
//								.get(i);
791
//						if (!acfsf.accessControlExists()) {
792
//							acfsf.insertPermissions();
793
//							logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - datafile " + docid
794
//									+ " permissions added to DB");
795
//						}
796
//					}
797
//				}
798
				
799
		        Vector<XMLAccessDAO> accessControlList = dih.getAccessControlList();
800
		        if (accessControlList != null) {
801
		        	AccessControlForSingleFile acfsf = new AccessControlForSingleFile(docid);
802
		        	for (XMLAccessDAO xmlAccessDAO : accessControlList) {
803
		        		if (!acfsf.accessControlExists(xmlAccessDAO)) {
804
		        			acfsf.insertPermissions(xmlAccessDAO);
805
							logReplication.info("ReplicationService.handleForceReplicateRequest - document " + docid
806
									+ " permissions added to DB");
807
		        		}
808
		            }
809
		        }
810

    
811
				if (writeException != null) {
812
					throw writeException;
813
				}
814

    
815
				//false means non-timed replication
816
				logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - datafile " + docid + " added to DB with "
817
						+ "action " + dbaction);
818
				EventLog.getInstance().log(request.getRemoteAddr(), REPLICATIONUSER,
819
						docid, dbaction);
820
			}
821

    
822
		} catch (Exception e) {
823
			logMetacat.error("ReplicationService.handleForceReplicateDataFileRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
824
			logReplication.error("ReplicationService.handleForceReplicateDataFileRequest - Datafile " + docid
825
					+ " failed to added to DB with " + "action " + dbaction + " because "
826
					+ e.getMessage());
827
			logReplication.error("ReplicationService.handleForceReplicateDataFileRequest - ERROR in MetacatReplication.handleForceDataFileReplicate"
828
					+ "Request(): " + e.getMessage());
829
		}
830
	}
831

    
832
	/**
833
	 * Grants or denies a lock to a requesting host.
834
	 * The servlet parameters of interrest are:
835
	 * docid: the docid of the file the lock is being requested for
836
	 * currentdate: the timestamp of the document on the remote server
837
	 *
838
	 */
839
	protected static void handleGetLockRequest(PrintWriter out,
840
			Hashtable<String, String[]> params, HttpServletResponse response) {
841

    
842
		try {
843

    
844
			String docid = ((String[]) params.get("docid"))[0];
845
			String remoteRev = ((String[]) params.get("updaterev"))[0];
846
			DocumentImpl requestDoc = new DocumentImpl(docid);
847
			logReplication.info("ReplicationService.handleGetLockRequest - lock request for " + docid);
848
			int localRevInt = requestDoc.getRev();
849
			int remoteRevInt = Integer.parseInt(remoteRev);
850

    
851
			if (remoteRevInt >= localRevInt) {
852
				if (!fileLocks.contains(docid)) { //grant the lock if it is not already locked
853
					fileLocks.add(0, docid); //insert at the beginning of the queue Vector
854
					//send a message back to the the remote host authorizing the insert
855
					out
856
							.println("<lockgranted><docid>" + docid
857
									+ "</docid></lockgranted>");
858
					//          lockThread = new Thread(this);
859
					//          lockThread.setPriority(Thread.MIN_PRIORITY);
860
					//          lockThread.start();
861
					logReplication.info("ReplicationService.handleGetLockRequest - lock granted for " + docid);
862
				} else { //deny the lock
863
					out.println("<filelocked><docid>" + docid + "</docid></filelocked>");
864
					logReplication.info("ReplicationService.handleGetLockRequest - lock denied for " + docid
865
							+ "reason: file already locked");
866
				}
867
			} else {//deny the lock.
868
				out.println("<outdatedfile><docid>" + docid + "</docid></filelocked>");
869
				logReplication.info("ReplicationService.handleGetLockRequest - lock denied for " + docid
870
						+ "reason: client has outdated file");
871
			}
872
			//conn.close();
873
		} catch (Exception e) {
874
			logMetacat.error("ReplicationService.handleGetLockRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
875
			logReplication.error("ReplicationService.handleGetLockRequest - error requesting file lock from MetacatReplication."
876
					+ "handleGetLockRequest: " + e.getMessage());
877
			e.printStackTrace(System.out);
878
		}
879
	}
880

    
881
	/**
882
	 * Sends all of the xml_documents information encoded in xml to a requestor
883
	 * the format is:
884
	 * <!ELEMENT documentinfo (docid, docname, doctype, doctitle, user_owner,
885
	 *                  user_updated, home_server, public_access, rev)/>
886
	 * all of the subelements of document info are #PCDATA
887
	 */
888
	protected static void handleGetDocumentInfoRequest(PrintWriter out,
889
			Hashtable<String, String[]> params, HttpServletResponse response) {
890
		String docid = ((String[]) (params.get("docid")))[0];
891
		StringBuffer sb = new StringBuffer();
892

    
893
		try {
894
		  IdentifierManager idman = IdentifierManager.getInstance();
895

    
896
			DocumentImpl doc = new DocumentImpl(docid);
897
			sb.append("<documentinfo><docid>").append(docid);
898
			sb.append("</docid>");
899
			try
900
			{
901
			  String guid = idman.getGUID(doc.getDocID(), doc.getRev());
902
			  sb.append("<guid>").append(guid).append("</guid>");
903
			}
904
			catch(McdbDocNotFoundException e)
905
			{
906
			  //do nothing, there was no guid for this document
907
			}
908
			sb.append("<docname>").append(doc.getDocname());
909
			sb.append("</docname><doctype>").append(doc.getDoctype());
910
			sb.append("</doctype>");
911
			sb.append("<user_owner>").append(doc.getUserowner());
912
			sb.append("</user_owner><user_updated>").append(doc.getUserupdated());
913
			sb.append("</user_updated>");
914
			sb.append("<date_created>");
915
			sb.append(doc.getCreateDate());
916
			sb.append("</date_created>");
917
			sb.append("<date_updated>");
918
			sb.append(doc.getUpdateDate());
919
			sb.append("</date_updated>");
920
			sb.append("<home_server>");
921
			sb.append(doc.getDocHomeServer());
922
			sb.append("</home_server>");
923
			sb.append("<public_access>").append(doc.getPublicaccess());
924
			sb.append("</public_access><rev>").append(doc.getRev());
925
			sb.append("</rev>");
926

    
927
			sb.append("<accessControl>");
928

    
929
			AccessControlForSingleFile acfsf = new AccessControlForSingleFile(docid); 
930
			sb.append(acfsf.getAccessString());
931
			
932
			sb.append("</accessControl>");
933

    
934
			sb.append("</documentinfo>");
935
			response.setContentType("text/xml");
936
			out.println(sb.toString());
937

    
938
		} catch (Exception e) {
939
			logMetacat.error("ReplicationService.handleGetDocumentInfoRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
940
			logReplication.error("ReplicationService.handleGetDocumentInfoRequest - error in metacatReplication.handlegetdocumentinforequest "
941
					+ "for doc: " + docid + " : " + e.getMessage());
942
		}
943

    
944
	}
945

    
946
	/**
947
	 * Sends a datafile to a remote host
948
	 */
949
	protected static void handleGetDataFileRequest(OutputStream outPut,
950
			Hashtable<String, String[]> params, HttpServletResponse response)
951

    
952
	{
953
		// File path for data file
954
		String filepath;
955
		// Request docid
956
		String docId = ((String[]) (params.get("docid")))[0];
957
		//check if the doicd is null
958
		if (docId == null) {
959
			logMetacat.error("ReplicationService.handleGetDataFileRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
960
			logReplication.error("ReplicationService.handleGetDataFileRequest - Didn't specify docid for replication");
961
			return;
962
		}
963

    
964
		//try to open a https stream to test if the request server's public key
965
		//in the key store, this is security issue
966
		try {
967
			filepath = PropertyService.getProperty("application.datafilepath");
968
			String server = params.get("server")[0];
969
			URL u = new URL("https://" + server + "?server="
970
					+ MetacatUtil.getLocalReplicationServerName() + "&action=test");
971
			String test = ReplicationService.getURLContent(u);
972
			//couldn't pass the test
973
			if (test.indexOf("successfully") == -1) {
974
				//response.setContentType("text/xml");
975
				//outPut.println("<error>Couldn't pass the trust test</error>");
976
				logMetacat.error("ReplicationService.handleGetDataFileRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
977
				logReplication.error("ReplicationService.handleGetDataFileRequest - Couldn't pass the trust test");
978
				return;
979
			}
980
		}//try
981
		catch (Exception ee) {
982
			return;
983
		}//catch
984

    
985
		if (!filepath.endsWith("/")) {
986
			filepath += "/";
987
		}
988
		// Get file aboslute file name
989
		String filename = filepath + docId;
990

    
991
		//MIME type
992
		String contentType = null;
993
		if (filename.endsWith(".xml")) {
994
			contentType = "text/xml";
995
		} else if (filename.endsWith(".css")) {
996
			contentType = "text/css";
997
		} else if (filename.endsWith(".dtd")) {
998
			contentType = "text/plain";
999
		} else if (filename.endsWith(".xsd")) {
1000
			contentType = "text/xml";
1001
		} else if (filename.endsWith("/")) {
1002
			contentType = "text/html";
1003
		} else {
1004
			File f = new File(filename);
1005
			if (f.isDirectory()) {
1006
				contentType = "text/html";
1007
			} else {
1008
				contentType = "application/octet-stream";
1009
			}
1010
		}
1011

    
1012
		// Set the mime type
1013
		response.setContentType(contentType);
1014

    
1015
		// Get the content of the file
1016
		FileInputStream fin = null;
1017
		try {
1018
			// FileInputStream to metacat
1019
			fin = new FileInputStream(filename);
1020
			// 4K buffer
1021
			byte[] buf = new byte[4 * 1024];
1022
			// Read data from file input stream to byte array
1023
			int b = fin.read(buf);
1024
			// Write to outStream from byte array
1025
			while (b != -1) {
1026
				outPut.write(buf, 0, b);
1027
				b = fin.read(buf);
1028
			}
1029
			// close file input stream
1030
			fin.close();
1031

    
1032
		}//try
1033
		catch (Exception e) {
1034
			logMetacat.error("ReplicationService.handleGetDataFileRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1035
			logReplication.error("ReplicationService.handleGetDataFileRequest - error getting data file from MetacatReplication."
1036
					+ "handlGetDataFileRequest " + e.getMessage());
1037
			e.printStackTrace(System.out);
1038
		}//catch
1039

    
1040
	}
1041

    
1042
	/**
1043
	 * Sends a document to a remote host
1044
	 */
1045
	protected static void handleGetDocumentRequest(PrintWriter out,
1046
			Hashtable<String, String[]> params, HttpServletResponse response) {
1047

    
1048
		String urlString = null;
1049
		String documentPath = null;
1050
		try {
1051
			// try to open a https stream to test if the request server's public
1052
			// key
1053
			// in the key store, this is security issue
1054
			String server = params.get("server")[0];
1055
			urlString = "https://" + server + "?server="
1056
					+ MetacatUtil.getLocalReplicationServerName() + "&action=test";
1057
			URL u = new URL(urlString);
1058
			String test = ReplicationService.getURLContent(u);
1059
			// couldn't pass the test
1060
			if (test.indexOf("successfully") == -1) {
1061
				response.setContentType("text/xml");
1062
				out.println("<error>Couldn't pass the trust test " + test + " </error>");
1063
				out.close();
1064
				return;
1065
			}
1066

    
1067
			String docid = params.get("docid")[0];
1068
			logReplication.debug("ReplicationService.handleGetDocumentRequest - MetacatReplication.handleGetDocumentRequest for docid: "
1069
					+ docid);
1070
			DocumentImpl di = new DocumentImpl(docid);
1071

    
1072
			String documentDir = PropertyService
1073
					.getProperty("application.documentfilepath");
1074
			documentPath = documentDir + FileUtil.getFS() + docid;
1075

    
1076
			// if the document does not exist on disk, read it from db and write
1077
			// it to disk.
1078
			if (FileUtil.getFileStatus(documentPath) == FileUtil.DOES_NOT_EXIST
1079
					|| FileUtil.getFileSize(documentPath) == 0) {
1080
				FileWriter fileWriter = new FileWriter(documentPath);
1081
				di.toXml(fileWriter, null, null, true);
1082
			}
1083

    
1084
			// read the file from disk and sent it to PrintWriter
1085
			// PrintWriter out = new PrintWriter(streamOut);
1086
			di.readFromFileSystem(out, null, null, documentPath);
1087

    
1088
			// response.setContentType("text/xml");
1089
			// out.print(di.toString(null, null, true));
1090

    
1091
			logReplication.info("ReplicationService.handleGetDocumentRequest - document " + docid + " sent");
1092

    
1093
		} catch (MalformedURLException mue) {
1094
			logMetacat.error("ReplicationService.handleGetDocumentRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1095
			logReplication.error("ReplicationService.handleGetDocumentRequest - Url error when getting document from MetacatReplication."
1096
					+ "handlGetDocumentRequest for url: " + urlString + " : "
1097
					+ mue.getMessage());
1098
			// e.printStackTrace(System.out);
1099
			response.setContentType("text/xml");
1100
			out.println("<error>" + mue.getMessage() + "</error>");
1101
		} catch (IOException ioe) {
1102
			logMetacat.error("ReplicationService.handleGetDocumentRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1103
			logReplication.error("ReplicationService.handleGetDocumentRequest - I/O error when getting document from MetacatReplication."
1104
					+ "handlGetDocumentRequest for file: " + documentPath + " : "
1105
					+ ioe.getMessage());
1106
			// e.printStackTrace(System.out);
1107
			response.setContentType("text/xml");
1108
			out.println("<error>" + ioe.getMessage() + "</error>");
1109
		} catch (PropertyNotFoundException pnfe) {
1110
			logMetacat.error("ReplicationService.handleGetDocumentRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1111
			logReplication
1112
					.error("ReplicationService.handleGetDocumentRequest - Error getting property when getting document from MetacatReplication."
1113
							+ "handlGetDocumentRequest for file: "
1114
							+ documentPath
1115
							+ " : "
1116
							+ pnfe.getMessage());
1117
			// e.printStackTrace(System.out);
1118
			response.setContentType("text/xml");
1119
			out.println("<error>" + pnfe.getMessage() + "</error>");
1120
		} catch (McdbException me) {
1121
			logReplication
1122
					.error("ReplicationService.handleGetDocumentRequest - Document implementation error  getting property when getting document from MetacatReplication."
1123
							+ "handlGetDocumentRequest for file: "
1124
							+ documentPath
1125
							+ " : "
1126
							+ me.getMessage());
1127
			// e.printStackTrace(System.out);
1128
			response.setContentType("text/xml");
1129
			out.println("<error>" + me.getMessage() + "</error>");
1130
		}
1131

    
1132
	}
1133

    
1134
	/**
1135
	 * Sends a list of all of the documents on this sever along with their
1136
	 * revision numbers. The format is: <!ELEMENT replication (server, updates)>
1137
	 * <!ELEMENT server (#PCDATA)> <!ELEMENT updates ((updatedDocument |
1138
	 * deleteDocument | revisionDocument)*)> <!ELEMENT updatedDocument (docid,
1139
	 * rev, datafile*)> <!ELEMENT deletedDocument (docid, rev)> <!ELEMENT
1140
	 * revisionDocument (docid, rev, datafile*)> <!ELEMENT docid (#PCDATA)>
1141
	 * <!ELEMENT rev (#PCDATA)> <!ELEMENT datafile (#PCDATA)> note that the rev
1142
	 * in deletedDocument is always empty. I just left it in there to make the
1143
	 * parser implementation easier.
1144
	 */
1145
	protected static void handleUpdateRequest(PrintWriter out, Hashtable<String, String[]> params,
1146
			HttpServletResponse response) {
1147
		// Checked out DBConnection
1148
		DBConnection dbConn = null;
1149
		// DBConenction serial number when checked it out
1150
		int serialNumber = -1;
1151
		PreparedStatement pstmt = null;
1152
		// Server list to store server info of xml_replication table
1153
		ReplicationServerList serverList = null;
1154

    
1155
		try {
1156
			// Check out a DBConnection from pool
1157
			dbConn = DBConnectionPool
1158
					.getDBConnection("MetacatReplication.handleUpdateRequest");
1159
			serialNumber = dbConn.getCheckOutSerialNumber();
1160
			// Create a server list from xml_replication table
1161
			serverList = new ReplicationServerList();
1162

    
1163
			// Get remote server name from param
1164
			String server = ((String[]) params.get("server"))[0];
1165
			// If no servr name in param, return a error
1166
			if (server == null || server.equals("")) {
1167
				response.setContentType("text/xml");
1168
				out.println("<error>Request didn't specify server name</error>");
1169
				out.close();
1170
				return;
1171
			}//if
1172

    
1173
			//try to open a https stream to test if the request server's public key
1174
			//in the key store, this is security issue
1175
			String testUrl = "https://" + server + "?server="
1176
            + MetacatUtil.getLocalReplicationServerName() + "&action=test";
1177
			logReplication.info("Running trust test: " + testUrl);
1178
			URL u = new URL(testUrl);
1179
			String test = ReplicationService.getURLContent(u);
1180
			logReplication.info("Ouput from test is '" + test + "'");
1181
			//couldn't pass the test
1182
			if (test.indexOf("successfully") == -1) {
1183
			    logReplication.error("Trust test failed.");
1184
				response.setContentType("text/xml");
1185
				out.println("<error>Couldn't pass the trust test</error>");
1186
				out.close();
1187
				return;
1188
			}
1189
			logReplication.info("Trust test succeeded.");
1190

    
1191
			// Check if local host configure to replicate xml documents to remote
1192
			// server. If not send back a error message
1193
			if (!serverList.getReplicationValue(server)) {
1194
				response.setContentType("text/xml");
1195
				out
1196
						.println("<error>Configuration not allow to replicate document to you</error>");
1197
				out.close();
1198
				return;
1199
			}//if
1200

    
1201
			// Store the sql command
1202
			StringBuffer docsql = new StringBuffer();
1203
			StringBuffer revisionSql = new StringBuffer();
1204
			// Stroe the docid list
1205
			StringBuffer doclist = new StringBuffer();
1206
			// Store the deleted docid list
1207
			StringBuffer delsql = new StringBuffer();
1208
			// Store the data set file
1209
			Vector<Vector<String>> packageFiles = new Vector<Vector<String>>();
1210

    
1211
			// Append local server's name and replication servlet to doclist
1212
			doclist.append("<?xml version=\"1.0\"?><replication>");
1213
			doclist.append("<server>")
1214
					.append(MetacatUtil.getLocalReplicationServerName());
1215
			//doclist.append(util.getProperty("replicationpath"));
1216
			doclist.append("</server><updates>");
1217

    
1218
			// Get correct docid that reside on this server according the requesting
1219
			// server's replicate and data replicate value in xml_replication table
1220
			docsql.append(DatabaseService.getInstance().getDBAdapter().getReplicationDocumentListSQL());
1221
			//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)) ");
1222
			revisionSql.append("select docid, rev, doctype from xml_revisions ");
1223
			// If the localhost is not a hub to the remote server, only replicate
1224
			// the docid' which home server is local host (server_location =1)
1225
			if (!serverList.getHubValue(server)) {
1226
				String serverLocationDoc = " and a.server_location = 1";
1227
				String serverLocationRev = "where server_location = 1";
1228
				docsql.append(serverLocationDoc);
1229
				revisionSql.append(serverLocationRev);
1230
			}
1231
			logReplication.info("ReplicationService.handleUpdateRequest - Doc sql: " + docsql.toString());
1232

    
1233
			// Get any deleted documents
1234
			delsql.append("select distinct docid from ");
1235
			delsql.append("xml_revisions where docid not in (select docid from ");
1236
			delsql.append("xml_documents) ");
1237
			// If the localhost is not a hub to the remote server, only replicate
1238
			// the docid' which home server is local host (server_location =1)
1239
			if (!serverList.getHubValue(server)) {
1240
				delsql.append("and server_location = 1");
1241
			}
1242
			logReplication.info("ReplicationService.handleUpdateRequest - Deleted sql: " + delsql.toString());
1243

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

    
1322
			pstmt = dbConn.prepareStatement(delsql.toString());
1323
			//usage count should increas 1
1324
			dbConn.increaseUsageCount(1);
1325

    
1326
			pstmt.execute();
1327
			rs = pstmt.getResultSet();
1328
			tablehasrows = rs.next();
1329
			while (tablehasrows) { //handle the deleted documents
1330
				doclist.append("<deletedDocument><docid>").append(rs.getString(1));
1331
				doclist.append("</docid><rev></rev></deletedDocument>");
1332
				//note that rev is always empty for deleted docs
1333
				tablehasrows = rs.next();
1334
			}
1335

    
1336
			//now we can put the package files into the xml results
1337
			for (int i = 0; i < packageFiles.size(); i++) {
1338
				Vector<String> v = packageFiles.elementAt(i);
1339
				doclist.append("<updatedDocument>");
1340
				doclist.append("<docid>").append(v.elementAt(0));
1341
				doclist.append("</docid><rev>");
1342
				doclist.append(v.elementAt(1));
1343
				doclist.append("</rev>");
1344
				doclist.append("</updatedDocument>");
1345
			}
1346
			// add revision doc list  
1347
			doclist.append(prepareRevisionDoc(dbConn, revisionSql.toString(),
1348
					replicateData));
1349

    
1350
			doclist.append("</updates></replication>");
1351
			logReplication.info("ReplicationService.handleUpdateRequest - doclist: " + doclist.toString());
1352
			pstmt.close();
1353
			//conn.close();
1354
			response.setContentType("text/xml");
1355
			out.println(doclist.toString());
1356

    
1357
		} catch (Exception e) {
1358
			logMetacat.error("ReplicationService.handleUpdateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1359
			logReplication.error("ReplicationService.handleUpdateRequest - error in MetacatReplication." + "handleupdaterequest: "
1360
					+ e.getMessage());
1361
			//e.printStackTrace(System.out);
1362
			response.setContentType("text/xml");
1363
			out.println("<error>" + e.getMessage() + "</error>");
1364
		} finally {
1365
			try {
1366
				pstmt.close();
1367
			}//try
1368
			catch (SQLException ee) {
1369
				logMetacat.error("ReplicationService.handleUpdateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1370
				logReplication.error("ReplicationService.handleUpdateRequest - Error in MetacatReplication."
1371
						+ "handleUpdaterequest to close pstmt: " + ee.getMessage());
1372
			}//catch
1373
			finally {
1374
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1375
			}//finally
1376
		}//finally
1377

    
1378
	}//handlUpdateRequest
1379

    
1380
	/*
1381
	 * This method will get the xml string for document in xml_revision
1382
	 * The schema look like <!ELEMENT revisionDocument (docid, rev, datafile*)>
1383
	 */
1384
	private static String prepareRevisionDoc(DBConnection dbConn, String revSql,
1385
			boolean replicateData) throws Exception {
1386
		logReplication.warn("ReplicationService.prepareRevisionDoc - The revision document sql is " + revSql);
1387
		StringBuffer revDocList = new StringBuffer();
1388
		PreparedStatement pstmt = dbConn.prepareStatement(revSql);
1389
		//usage count should increas 1
1390
		dbConn.increaseUsageCount(1);
1391

    
1392
		pstmt.execute();
1393
		ResultSet rs = pstmt.getResultSet();
1394
		boolean tablehasrows = rs.next();
1395
		while (tablehasrows) {
1396
			String recordDoctype = rs.getString(3);
1397

    
1398
			//If this is data file and it isn't configured to replicate data
1399
			if (recordDoctype.equals("BIN") && !replicateData) {
1400
				// do nothing
1401
				continue;
1402
			} else {
1403

    
1404
				revDocList.append("<revisionDocument>");
1405
				revDocList.append("<docid>").append(rs.getString(1));
1406
				revDocList.append("</docid><rev>").append(rs.getInt(2));
1407
				revDocList.append("</rev>");
1408
				// data file
1409
				if (recordDoctype.equals("BIN")) {
1410
					revDocList.append("<datafile>");
1411
					revDocList.append(PropertyService
1412
							.getProperty("replication.datafileflag"));
1413
					revDocList.append("</datafile>");
1414
				}
1415
				revDocList.append("</revisionDocument>");
1416

    
1417
			}//else
1418
			tablehasrows = rs.next();
1419
		}
1420
		//System.out.println("The revision list is"+ revDocList.toString());
1421
		return revDocList.toString();
1422
	}
1423

    
1424
	/**
1425
	 * Returns the xml_catalog table encoded in xml
1426
	 */
1427
	public static String getCatalogXML() {
1428
		return handleGetCatalogRequest(null, null, null, false);
1429
	}
1430

    
1431
	/**
1432
	 * Sends the contents of the xml_catalog table encoded in xml
1433
	 * The xml format is:
1434
	 * <!ELEMENT xml_catalog (row*)>
1435
	 * <!ELEMENT row (entry_type, source_doctype, target_doctype, public_id,
1436
	 *                system_id)>
1437
	 * All of the sub elements of row are #PCDATA
1438

    
1439
	 * If printFlag == false then do not print to out.
1440
	 */
1441
	protected static String handleGetCatalogRequest(PrintWriter out,
1442
			Hashtable<String, String[]> params, HttpServletResponse response,
1443
			boolean printFlag) {
1444
		DBConnection dbConn = null;
1445
		int serialNumber = -1;
1446
		PreparedStatement pstmt = null;
1447
		try {
1448
			/*conn = MetacatReplication.getDBConnection("MetacatReplication." +
1449
			                                          "handleGetCatalogRequest");*/
1450
			dbConn = DBConnectionPool
1451
					.getDBConnection("MetacatReplication.handleGetCatalogRequest");
1452
			serialNumber = dbConn.getCheckOutSerialNumber();
1453
			pstmt = dbConn.prepareStatement("select entry_type, "
1454
					+ "source_doctype, target_doctype, public_id, "
1455
					+ "system_id from xml_catalog");
1456
			pstmt.execute();
1457
			ResultSet rs = pstmt.getResultSet();
1458
			boolean tablehasrows = rs.next();
1459
			StringBuffer sb = new StringBuffer();
1460
			sb.append("<?xml version=\"1.0\"?><xml_catalog>");
1461
			while (tablehasrows) {
1462
				sb.append("<row><entry_type>").append(rs.getString(1));
1463
				sb.append("</entry_type><source_doctype>").append(rs.getString(2));
1464
				sb.append("</source_doctype><target_doctype>").append(rs.getString(3));
1465
				sb.append("</target_doctype><public_id>").append(rs.getString(4));
1466
				// system id may not have server url on front.  Add it if not.
1467
				String systemID = rs.getString(5);
1468
				if (!systemID.startsWith("http://")) {
1469
					systemID = SystemUtil.getContextURL() + systemID;
1470
				}
1471
				sb.append("</public_id><system_id>").append(systemID);
1472
				sb.append("</system_id></row>");
1473

    
1474
				tablehasrows = rs.next();
1475
			}
1476
			sb.append("</xml_catalog>");
1477
			//conn.close();
1478
			if (printFlag) {
1479
				response.setContentType("text/xml");
1480
				out.println(sb.toString());
1481
			}
1482
			pstmt.close();
1483
			return sb.toString();
1484
		} catch (Exception e) {
1485
			logMetacat.error("ReplicationService.handleGetCatalogRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1486
			logReplication.error("ReplicationService.handleGetCatalogRequest - error in MetacatReplication.handleGetCatalogRequest:"
1487
					+ e.getMessage());
1488
			e.printStackTrace(System.out);
1489
			if (printFlag) {
1490
				out.println("<error>" + e.getMessage() + "</error>");
1491
			}
1492
		} finally {
1493
			try {
1494
				pstmt.close();
1495
			}//try
1496
			catch (SQLException ee) {
1497
				logMetacat.error("ReplicationService.handleGetCatalogRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1498
				logReplication.error("ReplicationService.handleGetCatalogRequest - Error in MetacatReplication.handleGetCatalogRequest: "
1499
						+ ee.getMessage());
1500
			}//catch
1501
			finally {
1502
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1503
			}//finally
1504
		}//finally
1505

    
1506
		return null;
1507
	}
1508

    
1509
	/**
1510
	 * Sends the current system date to the remote server.  Using this action
1511
	 * for replication gets rid of any problems with syncronizing clocks
1512
	 * because a time specific to a document is always kept on its home server.
1513
	 */
1514
	protected static void handleGetTimeRequest(PrintWriter out,
1515
			Hashtable<String, String[]> params, HttpServletResponse response) {
1516
		SimpleDateFormat formatter = new SimpleDateFormat("MM/dd/yy HH:mm:ss");
1517
		java.util.Date localtime = new java.util.Date();
1518
		String dateString = formatter.format(localtime);
1519
		response.setContentType("text/xml");
1520

    
1521
		out.println("<timestamp>" + dateString + "</timestamp>");
1522
	}
1523

    
1524
	/**
1525
	 * this method handles the timeout for a file lock.  when a lock is
1526
	 * granted it is granted for 30 seconds.  When this thread runs out
1527
	 * it deletes the docid from the queue, thus eliminating the lock.
1528
	 */
1529
	public void run() {
1530
		try {
1531
			logReplication.info("ReplicationService.run - thread started for docid: "
1532
					+ (String) fileLocks.elementAt(0));
1533

    
1534
			Thread.sleep(30000); //the lock will expire in 30 seconds
1535
			logReplication.info("thread for docid: "
1536
					+ (String) fileLocks.elementAt(fileLocks.size() - 1) + " exiting.");
1537

    
1538
			fileLocks.remove(fileLocks.size() - 1);
1539
			//fileLocks is treated as a FIFO queue.  If there are more than one lock
1540
			//in the vector, the first one inserted will be removed.
1541
		} catch (Exception e) {
1542
			logMetacat.error("ReplicationService.run - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1543
			logReplication.error("ReplicationService.run - error in file lock thread from "
1544
					+ "MetacatReplication.run: " + e.getMessage());
1545
		}
1546
	}
1547

    
1548
	/**
1549
	 * Returns the name of a server given a serverCode
1550
	 * @param serverCode the serverid of the server
1551
	 * @return the servername or null if the specified serverCode does not
1552
	 *         exist.
1553
	 */
1554
	public static String getServerNameForServerCode(int serverCode) {
1555
		//System.out.println("serverid: " + serverCode);
1556
		DBConnection dbConn = null;
1557
		int serialNumber = -1;
1558
		PreparedStatement pstmt = null;
1559
		try {
1560
			dbConn = DBConnectionPool.getDBConnection("MetacatReplication.getServer");
1561
			serialNumber = dbConn.getCheckOutSerialNumber();
1562
			String sql = new String("select server from "
1563
					+ "xml_replication where serverid = " + serverCode);
1564
			pstmt = dbConn.prepareStatement(sql);
1565
			//System.out.println("getserver sql: " + sql);
1566
			pstmt.execute();
1567
			ResultSet rs = pstmt.getResultSet();
1568
			boolean tablehasrows = rs.next();
1569
			if (tablehasrows) {
1570
				//System.out.println("server: " + rs.getString(1));
1571
				return rs.getString(1);
1572
			}
1573

    
1574
			//conn.close();
1575
		} catch (Exception e) {
1576
			logMetacat.error("ReplicationService.getServerNameForServerCode - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1577
			logReplication.error("ReplicationService.getServerNameForServerCode - Error in MetacatReplication.getServer: " + e.getMessage());
1578
		} finally {
1579
			try {
1580
				pstmt.close();
1581
			}//try
1582
			catch (SQLException ee) {
1583
				logMetacat.error("ReplicationService.getServerNameForServerCode - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1584
				logReplication.error("ReplicationService.getServerNameForServerCode - Error in MetacactReplication.getserver: "
1585
						+ ee.getMessage());
1586
			}//catch
1587
			finally {
1588
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1589
			}//fianlly
1590
		}//finally
1591

    
1592
		return null;
1593
		//return null if the server does not exist
1594
	}
1595

    
1596
	/**
1597
	 * Returns a server code given a server name
1598
	 * @param server the name of the server
1599
	 * @return integer > 0 representing the code of the server, 0 if the server
1600
	 *  does not exist.
1601
	 */
1602
	public static int getServerCodeForServerName(String server) throws ServiceException {
1603
		DBConnection dbConn = null;
1604
		int serialNumber = -1;
1605
		PreparedStatement pstmt = null;
1606
		int serverCode = 0;
1607

    
1608
		try {
1609

    
1610
			//conn = util.openDBConnection();
1611
			dbConn = DBConnectionPool.getDBConnection("MetacatReplication.getServerCode");
1612
			serialNumber = dbConn.getCheckOutSerialNumber();
1613
			pstmt = dbConn.prepareStatement("SELECT serverid FROM xml_replication "
1614
					+ "WHERE server LIKE '" + server + "'");
1615
			pstmt.execute();
1616
			ResultSet rs = pstmt.getResultSet();
1617
			boolean tablehasrows = rs.next();
1618
			if (tablehasrows) {
1619
				serverCode = rs.getInt(1);
1620
				pstmt.close();
1621
				//conn.close();
1622
				return serverCode;
1623
			}
1624

    
1625
		} catch (SQLException sqle) {
1626
			throw new ServiceException("ReplicationService.getServerCodeForServerName - " 
1627
					+ "SQL error when getting server code: " + sqle.getMessage());
1628

    
1629
		} finally {
1630
			try {
1631
				pstmt.close();
1632
				//conn.close();
1633
			}//try
1634
			catch (Exception ee) {
1635
				logMetacat.error("ReplicationService.getServerCodeForServerName - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1636
				logReplication.error("ReplicationService.getServerNameForServerCode - Error in MetacatReplicatio.getServerCode: "
1637
						+ ee.getMessage());
1638

    
1639
			}//catch
1640
			finally {
1641
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1642
			}//finally
1643
		}//finally
1644

    
1645
		return serverCode;
1646
	}
1647

    
1648
	/**
1649
	 * Method to get a host server information for given docid
1650
	 * @param conn a connection to the database
1651
	 */
1652
	public static Hashtable<String, String> getHomeServerInfoForDocId(String docId) {
1653
		Hashtable<String, String> sl = new Hashtable<String, String>();
1654
		DBConnection dbConn = null;
1655
		int serialNumber = -1;
1656
		docId = DocumentUtil.getDocIdFromString(docId);
1657
		PreparedStatement pstmt = null;
1658
		int serverLocation;
1659
		try {
1660
			//get conection
1661
			dbConn = DBConnectionPool.getDBConnection("ReplicationHandler.getHomeServer");
1662
			serialNumber = dbConn.getCheckOutSerialNumber();
1663
			//get a server location from xml_document table
1664
			pstmt = dbConn.prepareStatement("select server_location from xml_documents "
1665
					+ "where docid = ?");
1666
			pstmt.setString(1, docId);
1667
			pstmt.execute();
1668
			ResultSet serverName = pstmt.getResultSet();
1669
			//get a server location
1670
			if (serverName.next()) {
1671
				serverLocation = serverName.getInt(1);
1672
				pstmt.close();
1673
			} else {
1674
				pstmt.close();
1675
				//ut.returnConnection(conn);
1676
				return null;
1677
			}
1678
			pstmt = dbConn.prepareStatement("select server, last_checked, replicate "
1679
					+ "from xml_replication where serverid = ?");
1680
			//increase usage count
1681
			dbConn.increaseUsageCount(1);
1682
			pstmt.setInt(1, serverLocation);
1683
			pstmt.execute();
1684
			ResultSet rs = pstmt.getResultSet();
1685
			boolean tableHasRows = rs.next();
1686
			if (tableHasRows) {
1687

    
1688
				String server = rs.getString(1);
1689
				String last_checked = rs.getString(2);
1690
				if (!server.equals("localhost")) {
1691
					sl.put(server, last_checked);
1692
				}
1693

    
1694
			} else {
1695
				pstmt.close();
1696
				//ut.returnConnection(conn);
1697
				return null;
1698
			}
1699
			pstmt.close();
1700
		} catch (Exception e) {
1701
			logMetacat.error("ReplicationService.getHomeServerInfoForDocId - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1702
			logReplication.error("ReplicationService.getHomeServerInfoForDocId - error in replicationHandler.getHomeServer(): "
1703
					+ e.getMessage());
1704
		} finally {
1705
			try {
1706
				pstmt.close();
1707
				//ut.returnConnection(conn);
1708
			} catch (Exception ee) {
1709
				logMetacat.error("ReplicationService.getHomeServerInfoForDocId - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1710
				logReplication.error("ReplicationService.getHomeServerInfoForDocId - Eror irn rplicationHandler.getHomeServer() "
1711
						+ "to close pstmt: " + ee.getMessage());
1712
			} finally {
1713
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1714
			}
1715

    
1716
		}//finally
1717
		return sl;
1718
	}
1719

    
1720
	/**
1721
	 * Returns a home server location  given a accnum
1722
	 * @param accNum , given accNum for a document
1723
	 *
1724
	 */
1725
	public static int getHomeServerCodeForDocId(String accNum) throws ServiceException {
1726
		DBConnection dbConn = null;
1727
		int serialNumber = -1;
1728
		PreparedStatement pstmt = null;
1729
		int serverCode = 1;
1730
		String docId = DocumentUtil.getDocIdFromString(accNum);
1731

    
1732
		try {
1733

    
1734
			// Get DBConnection
1735
			dbConn = DBConnectionPool
1736
					.getDBConnection("ReplicationHandler.getServerLocation");
1737
			serialNumber = dbConn.getCheckOutSerialNumber();
1738
			pstmt = dbConn.prepareStatement("SELECT server_location FROM xml_documents "
1739
					+ "WHERE docid LIKE '" + docId + "'");
1740
			pstmt.execute();
1741
			ResultSet rs = pstmt.getResultSet();
1742
			boolean tablehasrows = rs.next();
1743
			//If a document is find, return the server location for it
1744
			if (tablehasrows) {
1745
				serverCode = rs.getInt(1);
1746
				pstmt.close();
1747
				//conn.close();
1748
				return serverCode;
1749
			}
1750
			//if couldn't find in xml_documents table, we think server code is 1
1751
			//(this is new document)
1752
			else {
1753
				pstmt.close();
1754
				//conn.close();
1755
				return serverCode;
1756
			}
1757

    
1758
		} catch (SQLException sqle) {
1759
			throw new ServiceException("ReplicationService.getHomeServerCodeForDocId - " 
1760
					+ "SQL error when getting home server code for docid: " + docId + " : " 
1761
					+ sqle.getMessage());
1762

    
1763
		} finally {
1764
			try {
1765
				pstmt.close();
1766
				//conn.close();
1767

    
1768
			} catch (SQLException sqle) {
1769
				logMetacat.error("ReplicationService.getHomeServerCodeForDocId - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1770
				logReplication.error("ReplicationService.getHomeServerCodeForDocId - ReplicationService.getHomeServerCodeForDocId - " 
1771
						+ "SQL error when getting home server code for docid: " + docId + " : " 
1772
						+ sqle.getMessage());
1773
			} finally {
1774
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1775
			}//finally
1776
		}//finally
1777
		//return serverCode;
1778
	}
1779

    
1780
	/**
1781
	 * This method returns the content of a url
1782
	 * @param u the url to return the content from
1783
	 * @return a string representing the content of the url
1784
	 * @throws java.io.IOException
1785
	 */
1786
	public static String getURLContent(URL u) throws java.io.IOException {
1787
	    logReplication.info("Getting url content from " + u.toString());
1788
		char istreamChar;
1789
		int istreamInt;
1790
		logReplication.info("ReplicationService.getURLContent - Before open the stream" + u.toString());
1791
		InputStream input = u.openStream();
1792
		logReplication.info("ReplicationService.getURLContent - After open the stream" + u.toString());
1793
		InputStreamReader istream = new InputStreamReader(input);
1794
		StringBuffer serverResponse = new StringBuffer();
1795
		while ((istreamInt = istream.read()) != -1) {
1796
			istreamChar = (char) istreamInt;
1797
			serverResponse.append(istreamChar);
1798
		}
1799
		istream.close();
1800
		input.close();
1801

    
1802
		return serverResponse.toString();
1803
	}
1804

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

    
1829
//	/**
1830
//	 * Method for writing replication messages to a log file specified in
1831
//	 * metacat.properties
1832
//	 */
1833
//	public static void replErrorLog(String message) {
1834
//		try {
1835
//			FileOutputStream fos = new FileOutputStream(PropertyService
1836
//					.getProperty("replication.logdir")
1837
//					+ "/metacatreplicationerror.log", true);
1838
//			PrintWriter pw = new PrintWriter(fos);
1839
//			SimpleDateFormat formatter = new SimpleDateFormat("yy-MM-dd HH:mm:ss");
1840
//			java.util.Date localtime = new java.util.Date();
1841
//			String dateString = formatter.format(localtime);
1842
//			dateString += " :: " + message;
1843
//			//time stamp each entry
1844
//			pw.println(dateString);
1845
//			pw.flush();
1846
//		} catch (Exception e) {
1847
//			logReplication.error("error writing to replication error log from "
1848
//					+ "MetacatReplication.replErrorLog: " + e.getMessage());
1849
//			//e.printStackTrace(System.out);
1850
//		}
1851
//	}
1852

    
1853
	/**
1854
	 * Returns true if the replicate field for server in xml_replication is 1.
1855
	 * Returns false otherwise
1856
	 */
1857
	public static boolean replToServer(String server) {
1858
		DBConnection dbConn = null;
1859
		int serialNumber = -1;
1860
		PreparedStatement pstmt = null;
1861
		try {
1862
			dbConn = DBConnectionPool.getDBConnection("MetacatReplication.repltoServer");
1863
			serialNumber = dbConn.getCheckOutSerialNumber();
1864
			pstmt = dbConn.prepareStatement("select replicate from "
1865
					+ "xml_replication where server like '" + server + "'");
1866
			pstmt.execute();
1867
			ResultSet rs = pstmt.getResultSet();
1868
			boolean tablehasrows = rs.next();
1869
			if (tablehasrows) {
1870
				int i = rs.getInt(1);
1871
				if (i == 1) {
1872
					pstmt.close();
1873
					//conn.close();
1874
					return true;
1875
				} else {
1876
					pstmt.close();
1877
					//conn.close();
1878
					return false;
1879
				}
1880
			}
1881
		} catch (SQLException sqle) {
1882
			logMetacat.error("ReplicationService.replToServer - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1883
			logReplication.error("ReplicationService.replToServer - SQL error in MetacatReplication.replToServer: "
1884
					+ sqle.getMessage());
1885
		} finally {
1886
			try {
1887
				pstmt.close();
1888
				//conn.close();
1889
			}//try
1890
			catch (Exception ee) {
1891
				logMetacat.error("ReplicationService.replToServer - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1892
				logReplication.error("ReplicationService.replToServer - Error in MetacatReplication.replToServer: "
1893
						+ ee.getMessage());
1894
			}//catch
1895
			finally {
1896
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1897
			}//finally
1898
		}//finally
1899
		return false;
1900
		//the default if this server does not exist is to not replicate to it.
1901
	}
1902

    
1903
}
(6-6/7)