Project

General

Profile

1
/**
2
 *  '$RCSfile$'
3
 *    Purpose: A Class that implements replication for metacat
4
 *  Copyright: 2000 Regents of the University of California and the
5
 *             National Center for Ecological Analysis and Synthesis
6
 *    Authors: Chad Berkley
7
 *
8
 *   '$Author: daigle $'
9
 *     '$Date: 2009-10-16 11:10:05 -0700 (Fri, 16 Oct 2009) $'
10
 * '$Revision: 5089 $'
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.PermissionController;
44
import edu.ucsb.nceas.metacat.accesscontrol.AccessControlForSingleFile;
45
import edu.ucsb.nceas.metacat.database.DBConnection;
46
import edu.ucsb.nceas.metacat.database.DBConnectionPool;
47
import edu.ucsb.nceas.metacat.database.DatabaseService;
48
import edu.ucsb.nceas.metacat.properties.PropertyService;
49
import edu.ucsb.nceas.metacat.shared.BaseService;
50
import edu.ucsb.nceas.metacat.shared.HandlerException;
51
import edu.ucsb.nceas.metacat.shared.ServiceException;
52
import edu.ucsb.nceas.metacat.util.DocumentUtil;
53
import edu.ucsb.nceas.metacat.util.MetacatUtil;
54
import edu.ucsb.nceas.metacat.util.SystemUtil;
55
import edu.ucsb.nceas.utilities.FileUtil;
56
import edu.ucsb.nceas.utilities.GeneralPropertyException;
57
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
58

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

    
62
public class ReplicationService extends BaseService {
63

    
64
	private static ReplicationService replicationService = null;
65

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
408
	}
409

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
576
			if (writeException != null) {
577
				throw writeException;
578
			}
579

    
580
			logReplication.info("ReplicationService.handleForceReplicateRequest - document " + docid + " added to DB with "
581
					+ "action " + dbaction);
582
			EventLog.getInstance().log(request.getRemoteAddr(), REPLICATIONUSER, docid,
583
					dbaction);
584
		}//try
585
		catch (Exception e) {
586
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
587
			logReplication.error("document " + docid
588
					+ " failed to added to DB with " + "action " + dbaction + " because "
589
					+ e.getMessage());
590
			logReplication.error("ReplicationService.handleForceReplicateRequest - "
591
					+ "error: " + e.getMessage());
592

    
593
		}//catch
594
		finally {
595
			// Return the checked out DBConnection
596
			DBConnectionPool.returnDBConnection(dbConn, serialNumber);
597
		}//finally
598
	}
599

    
600
	/*
601
	 * when a forcereplication delete request comes in, local host will delete this
602
	 * document
603
	 */
604
	protected static void handleForceReplicateDeleteRequest(PrintWriter out,
605
			Hashtable<String, String[]> params, HttpServletResponse response,
606
			HttpServletRequest request) {
607
		String server = ((String[]) params.get("server"))[0]; // the server that
608
		String docid = ((String[]) params.get("docid"))[0]; // sent the document
609
		try {
610
			logReplication.info("ReplicationService.handleForceReplicateDeleteRequest - force replication delete request from " + server);
611
			logReplication.info("ReplicationService.handleForceReplicateDeleteRequest - force replication delete docid " + docid);
612
			logReplication.info("ReplicationService.handleForceReplicateDeleteRequest - Force replication delete request from: " + server);
613
			logReplication.info("ReplicationService.handleForceReplicateDeleteRequest - Force replication delete docid: " + docid);
614
			DocumentImpl.delete(docid, null, null, server);
615
			logReplication.info("ReplicationService.handleForceReplicateDeleteRequest - document " + docid + " was successfully deleted ");
616
			EventLog.getInstance().log(request.getRemoteAddr(), REPLICATIONUSER, docid,
617
					"delete");
618
			logReplication.info("ReplicationService.handleForceReplicateDeleteRequest - document " + docid + " was successfully deleted ");
619
		} catch (Exception e) {
620
			logMetacat.error("ReplicationService.handleForceReplicateDeleteRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
621
			logReplication.error("document " + docid
622
					+ " failed to delete because " + e.getMessage());
623
			logReplication.error("ReplicationService.handleForceReplicateDeleteRequest - error: " + e.getMessage());
624

    
625
		}//catch
626

    
627
	}
628

    
629
	/**
630
	 * when a forcereplication data file request comes in, local host sends a
631
	 * readdata request to the requesting server (remote server) for the specified
632
	 * docid. Then store it in local database and file system
633
	 */
634
	protected static void handleForceReplicateDataFileRequest(Hashtable<String, String[]> params,
635
			HttpServletRequest request) {
636

    
637
		//make sure there is some parameters
638
		if (params.isEmpty()) {
639
			return;
640
		}
641
		// Get remote server
642
		String server = ((String[]) params.get("server"))[0];
643
		// the docid should include rev number
644
		String docid = ((String[]) params.get("docid"))[0];
645
		// Make sure there is a docid and server
646
		if (docid == null || server == null || server.equals("")) {
647
			logMetacat.error("ReplicationService.handleForceReplicateDataFileRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
648
			logReplication.error("ReplicationService.handleForceReplicateDataFileRequest - Didn't specify docid or server for replication");
649
			return;
650
		}
651

    
652
		// Overide or not
653
		//    boolean override = false;
654
		// dbaction - update or insert
655
		String dbaction = null;
656

    
657
		try {
658
			//docid was switch to two parts uinque code and rev
659
			//String uniqueCode=MetacatUtil.getDocIdFromString(docid);
660
			//int rev=MetacatUtil.getVersionFromString(docid);
661
			if (params.containsKey("dbaction")) {
662
				dbaction = ((String[]) params.get("dbaction"))[0];
663
			} else//default value is update
664
			{
665
				dbaction = "update";
666
			}
667

    
668
			logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - force replication request from " + server);
669
			logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - Force replication request from: " + server);
670
			logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - Force replication docid: " + docid);
671
			logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - Force replication action: " + dbaction);
672
			// get the document info from server
673
			URL docinfourl = new URL("https://" + server + "?server="
674
					+ MetacatUtil.getLocalReplicationServerName()
675
					+ "&action=getdocumentinfo&docid=" + docid);
676

    
677
			String docInfoStr = ReplicationService.getURLContent(docinfourl);
678

    
679
			//dih is the parser for the docinfo xml format
680
			DocInfoHandler dih = new DocInfoHandler();
681
			XMLReader docinfoParser = ReplicationHandler.initParser(dih);
682
			docinfoParser.parse(new InputSource(new StringReader(docInfoStr)));
683
			Hashtable<String, String> docinfoHash = dih.getDocInfo();
684
			String user = (String) docinfoHash.get("user_owner");
685

    
686
			String docName = (String) docinfoHash.get("docname");
687

    
688
			String docType = (String) docinfoHash.get("doctype");
689

    
690
			String docHomeServer = (String) docinfoHash.get("home_server");
691

    
692
			String createdDate = (String) docinfoHash.get("date_created");
693

    
694
			String updatedDate = (String) docinfoHash.get("date_updated");
695
			logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - docHomeServer of datafile: " + docHomeServer);
696

    
697
			//if action is delete, we don't delete the data file. Just archieve
698
			//the xml_documents
699
			/*if (dbaction.equals("delete"))
700
			{
701
			  //conn = util.getConnection();
702
			  DocumentImpl.delete(docid,user,null);
703
			  //util.returnConnection(conn);
704
			}*/
705
			//To data file insert or update is same
706
			if (dbaction.equals("insert") || dbaction.equals("update")) {
707
				//Get data file and store it into local file system.
708
				// sending back readdata request to server
709
				URL url = new URL("https://" + server + "?server="
710
						+ MetacatUtil.getLocalReplicationServerName()
711
						+ "&action=readdata&docid=" + docid);
712
				String datafilePath = PropertyService
713
						.getProperty("application.datafilepath");
714

    
715
				Exception writeException = null;
716
				//register data file into xml_documents table and wite data file
717
				//into file system
718
				try {
719
					DocumentImpl.writeDataFileInReplication(url.openStream(),
720
							datafilePath, docName, docType, docid, user, docHomeServer,
721
							server, DocumentImpl.DOCUMENTTABLE, false, createdDate,
722
							updatedDate);
723
				} catch (Exception e) {
724
					writeException = e;
725
				}
726
				//process extra access rules
727
				Vector<AccessControlForSingleFile> accessControlList = dih
728
						.getAccessControlList();
729
				if (accessControlList != null) {
730
					for (int i = 0; i < accessControlList.size(); i++) {
731
						AccessControlForSingleFile acfsf = (AccessControlForSingleFile) accessControlList
732
								.get(i);
733
						if (!acfsf.accessControlExists()) {
734
							acfsf.insertPermissions();
735
							logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - datafile " + docid
736
									+ " permissions added to DB");
737
						}
738
					}
739
				}
740

    
741
				if (writeException != null) {
742
					throw writeException;
743
				}
744

    
745
				//false means non-timed replication
746
				logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - datafile " + docid + " added to DB with "
747
						+ "action " + dbaction);
748
				EventLog.getInstance().log(request.getRemoteAddr(), REPLICATIONUSER,
749
						docid, dbaction);
750
			}
751

    
752
		} catch (Exception e) {
753
			logMetacat.error("ReplicationService.handleForceReplicateDataFileRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
754
			logReplication.error("ReplicationService.handleForceReplicateDataFileRequest - Datafile " + docid
755
					+ " failed to added to DB with " + "action " + dbaction + " because "
756
					+ e.getMessage());
757
			logReplication.error("ReplicationService.handleForceReplicateDataFileRequest - ERROR in MetacatReplication.handleForceDataFileReplicate"
758
					+ "Request(): " + e.getMessage());
759
		}
760
	}
761

    
762
	/**
763
	 * Grants or denies a lock to a requesting host.
764
	 * The servlet parameters of interrest are:
765
	 * docid: the docid of the file the lock is being requested for
766
	 * currentdate: the timestamp of the document on the remote server
767
	 *
768
	 */
769
	protected static void handleGetLockRequest(PrintWriter out,
770
			Hashtable<String, String[]> params, HttpServletResponse response) {
771

    
772
		try {
773

    
774
			String docid = ((String[]) params.get("docid"))[0];
775
			String remoteRev = ((String[]) params.get("updaterev"))[0];
776
			DocumentImpl requestDoc = new DocumentImpl(docid);
777
			logReplication.info("ReplicationService.handleGetLockRequest - lock request for " + docid);
778
			int localRevInt = requestDoc.getRev();
779
			int remoteRevInt = Integer.parseInt(remoteRev);
780

    
781
			if (remoteRevInt >= localRevInt) {
782
				if (!fileLocks.contains(docid)) { //grant the lock if it is not already locked
783
					fileLocks.add(0, docid); //insert at the beginning of the queue Vector
784
					//send a message back to the the remote host authorizing the insert
785
					out
786
							.println("<lockgranted><docid>" + docid
787
									+ "</docid></lockgranted>");
788
					//          lockThread = new Thread(this);
789
					//          lockThread.setPriority(Thread.MIN_PRIORITY);
790
					//          lockThread.start();
791
					logReplication.info("ReplicationService.handleGetLockRequest - lock granted for " + docid);
792
				} else { //deny the lock
793
					out.println("<filelocked><docid>" + docid + "</docid></filelocked>");
794
					logReplication.info("ReplicationService.handleGetLockRequest - lock denied for " + docid
795
							+ "reason: file already locked");
796
				}
797
			} else {//deny the lock.
798
				out.println("<outdatedfile><docid>" + docid + "</docid></filelocked>");
799
				logReplication.info("ReplicationService.handleGetLockRequest - lock denied for " + docid
800
						+ "reason: client has outdated file");
801
			}
802
			//conn.close();
803
		} catch (Exception e) {
804
			logMetacat.error("ReplicationService.handleGetLockRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
805
			logReplication.error("ReplicationService.handleGetLockRequest - error requesting file lock from MetacatReplication."
806
					+ "handleGetLockRequest: " + e.getMessage());
807
			e.printStackTrace(System.out);
808
		}
809
	}
810

    
811
	/**
812
	 * Sends all of the xml_documents information encoded in xml to a requestor
813
	 * the format is:
814
	 * <!ELEMENT documentinfo (docid, docname, doctype, doctitle, user_owner,
815
	 *                  user_updated, home_server, public_access, rev)/>
816
	 * all of the subelements of document info are #PCDATA
817
	 */
818
	protected static void handleGetDocumentInfoRequest(PrintWriter out,
819
			Hashtable<String, String[]> params, HttpServletResponse response) {
820
		String docid = ((String[]) (params.get("docid")))[0];
821
		StringBuffer sb = new StringBuffer();
822

    
823
		try {
824

    
825
			DocumentImpl doc = new DocumentImpl(docid);
826
			sb.append("<documentinfo><docid>").append(docid);
827
			sb.append("</docid><docname>").append(doc.getDocname());
828
			sb.append("</docname><doctype>").append(doc.getDoctype());
829
			sb.append("</doctype>");
830
			sb.append("<user_owner>").append(doc.getUserowner());
831
			sb.append("</user_owner><user_updated>").append(doc.getUserupdated());
832
			sb.append("</user_updated>");
833
			sb.append("<date_created>");
834
			sb.append(doc.getCreateDate());
835
			sb.append("</date_created>");
836
			sb.append("<date_updated>");
837
			sb.append(doc.getUpdateDate());
838
			sb.append("</date_updated>");
839
			sb.append("<home_server>");
840
			sb.append(doc.getDocHomeServer());
841
			sb.append("</home_server>");
842
			sb.append("<public_access>").append(doc.getPublicaccess());
843
			sb.append("</public_access><rev>").append(doc.getRev());
844
			sb.append("</rev>");
845

    
846
			//permissions on the document
847
			PermissionController permController = new PermissionController(docid);
848
			Vector<AccessControlForSingleFile> accessControlList = permController
849
					.getAccessControl();
850
			sb.append("<accessControl>");
851
			for (int i = 0; i < accessControlList.size(); i++) {
852
				AccessControlForSingleFile acfsf = (AccessControlForSingleFile) accessControlList
853
						.get(i);
854
				sb.append(acfsf.getAccessString());
855
			}
856
			sb.append("</accessControl>");
857

    
858
			sb.append("</documentinfo>");
859
			response.setContentType("text/xml");
860
			out.println(sb.toString());
861

    
862
		} catch (Exception e) {
863
			logMetacat.error("ReplicationService.handleGetDocumentInfoRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
864
			logReplication.error("ReplicationService.handleGetDocumentInfoRequest - error in metacatReplication.handlegetdocumentinforequest "
865
					+ "for doc: " + docid + " : " + e.getMessage());
866
		}
867

    
868
	}
869

    
870
	/**
871
	 * Sends a datafile to a remote host
872
	 */
873
	protected static void handleGetDataFileRequest(OutputStream outPut,
874
			Hashtable<String, String[]> params, HttpServletResponse response)
875

    
876
	{
877
		// File path for data file
878
		String filepath;
879
		// Request docid
880
		String docId = ((String[]) (params.get("docid")))[0];
881
		//check if the doicd is null
882
		if (docId == null) {
883
			logMetacat.error("ReplicationService.handleGetDataFileRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
884
			logReplication.error("ReplicationService.handleGetDataFileRequest - Didn't specify docid for replication");
885
			return;
886
		}
887

    
888
		//try to open a https stream to test if the request server's public key
889
		//in the key store, this is security issue
890
		try {
891
			filepath = PropertyService.getProperty("application.datafilepath");
892
			String server = params.get("server")[0];
893
			URL u = new URL("https://" + server + "?server="
894
					+ MetacatUtil.getLocalReplicationServerName() + "&action=test");
895
			String test = ReplicationService.getURLContent(u);
896
			//couldn't pass the test
897
			if (test.indexOf("successfully") == -1) {
898
				//response.setContentType("text/xml");
899
				//outPut.println("<error>Couldn't pass the trust test</error>");
900
				logMetacat.error("ReplicationService.handleGetDataFileRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
901
				logReplication.error("ReplicationService.handleGetDataFileRequest - Couldn't pass the trust test");
902
				return;
903
			}
904
		}//try
905
		catch (Exception ee) {
906
			return;
907
		}//catch
908

    
909
		if (!filepath.endsWith("/")) {
910
			filepath += "/";
911
		}
912
		// Get file aboslute file name
913
		String filename = filepath + docId;
914

    
915
		//MIME type
916
		String contentType = null;
917
		if (filename.endsWith(".xml")) {
918
			contentType = "text/xml";
919
		} else if (filename.endsWith(".css")) {
920
			contentType = "text/css";
921
		} else if (filename.endsWith(".dtd")) {
922
			contentType = "text/plain";
923
		} else if (filename.endsWith(".xsd")) {
924
			contentType = "text/xml";
925
		} else if (filename.endsWith("/")) {
926
			contentType = "text/html";
927
		} else {
928
			File f = new File(filename);
929
			if (f.isDirectory()) {
930
				contentType = "text/html";
931
			} else {
932
				contentType = "application/octet-stream";
933
			}
934
		}
935

    
936
		// Set the mime type
937
		response.setContentType(contentType);
938

    
939
		// Get the content of the file
940
		FileInputStream fin = null;
941
		try {
942
			// FileInputStream to metacat
943
			fin = new FileInputStream(filename);
944
			// 4K buffer
945
			byte[] buf = new byte[4 * 1024];
946
			// Read data from file input stream to byte array
947
			int b = fin.read(buf);
948
			// Write to outStream from byte array
949
			while (b != -1) {
950
				outPut.write(buf, 0, b);
951
				b = fin.read(buf);
952
			}
953
			// close file input stream
954
			fin.close();
955

    
956
		}//try
957
		catch (Exception e) {
958
			logMetacat.error("ReplicationService.handleGetDataFileRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
959
			logReplication.error("ReplicationService.handleGetDataFileRequest - error getting data file from MetacatReplication."
960
					+ "handlGetDataFileRequest " + e.getMessage());
961
			e.printStackTrace(System.out);
962
		}//catch
963

    
964
	}
965

    
966
	/**
967
	 * Sends a document to a remote host
968
	 */
969
	protected static void handleGetDocumentRequest(PrintWriter out,
970
			Hashtable<String, String[]> params, HttpServletResponse response) {
971

    
972
		String urlString = null;
973
		String documentPath = null;
974
		try {
975
			// try to open a https stream to test if the request server's public
976
			// key
977
			// in the key store, this is security issue
978
			String server = params.get("server")[0];
979
			urlString = "https://" + server + "?server="
980
					+ MetacatUtil.getLocalReplicationServerName() + "&action=test";
981
			URL u = new URL(urlString);
982
			String test = ReplicationService.getURLContent(u);
983
			// couldn't pass the test
984
			if (test.indexOf("successfully") == -1) {
985
				response.setContentType("text/xml");
986
				out.println("<error>Couldn't pass the trust test " + test + " </error>");
987
				out.close();
988
				return;
989
			}
990

    
991
			String docid = params.get("docid")[0];
992
			logReplication.debug("ReplicationService.handleGetDocumentRequest - MetacatReplication.handleGetDocumentRequest for docid: "
993
					+ docid);
994
			DocumentImpl di = new DocumentImpl(docid);
995

    
996
			String documentDir = PropertyService
997
					.getProperty("application.documentfilepath");
998
			documentPath = documentDir + FileUtil.getFS() + docid;
999

    
1000
			// if the document does not exist on disk, read it from db and write
1001
			// it to disk.
1002
			if (FileUtil.getFileStatus(documentPath) == FileUtil.DOES_NOT_EXIST
1003
					|| FileUtil.getFileSize(documentPath) == 0) {
1004
				FileWriter fileWriter = new FileWriter(documentPath);
1005
				di.toXml(fileWriter, null, null, true);
1006
			}
1007

    
1008
			// read the file from disk and sent it to PrintWriter
1009
			// PrintWriter out = new PrintWriter(streamOut);
1010
			di.readFromFileSystem(out, null, null, documentPath);
1011

    
1012
			// response.setContentType("text/xml");
1013
			// out.print(di.toString(null, null, true));
1014

    
1015
			logReplication.info("ReplicationService.handleGetDocumentRequest - document " + docid + " sent");
1016

    
1017
		} catch (MalformedURLException mue) {
1018
			logMetacat.error("ReplicationService.handleGetDocumentRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1019
			logReplication.error("ReplicationService.handleGetDocumentRequest - Url error when getting document from MetacatReplication."
1020
					+ "handlGetDocumentRequest for url: " + urlString + " : "
1021
					+ mue.getMessage());
1022
			// e.printStackTrace(System.out);
1023
			response.setContentType("text/xml");
1024
			out.println("<error>" + mue.getMessage() + "</error>");
1025
		} catch (IOException ioe) {
1026
			logMetacat.error("ReplicationService.handleGetDocumentRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1027
			logReplication.error("ReplicationService.handleGetDocumentRequest - I/O error when getting document from MetacatReplication."
1028
					+ "handlGetDocumentRequest for file: " + documentPath + " : "
1029
					+ ioe.getMessage());
1030
			// e.printStackTrace(System.out);
1031
			response.setContentType("text/xml");
1032
			out.println("<error>" + ioe.getMessage() + "</error>");
1033
		} catch (PropertyNotFoundException pnfe) {
1034
			logMetacat.error("ReplicationService.handleGetDocumentRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1035
			logReplication
1036
					.error("ReplicationService.handleGetDocumentRequest - Error getting property when getting document from MetacatReplication."
1037
							+ "handlGetDocumentRequest for file: "
1038
							+ documentPath
1039
							+ " : "
1040
							+ pnfe.getMessage());
1041
			// e.printStackTrace(System.out);
1042
			response.setContentType("text/xml");
1043
			out.println("<error>" + pnfe.getMessage() + "</error>");
1044
		} catch (McdbException me) {
1045
			logReplication
1046
					.error("ReplicationService.handleGetDocumentRequest - Document implementation error  getting property when getting document from MetacatReplication."
1047
							+ "handlGetDocumentRequest for file: "
1048
							+ documentPath
1049
							+ " : "
1050
							+ me.getMessage());
1051
			// e.printStackTrace(System.out);
1052
			response.setContentType("text/xml");
1053
			out.println("<error>" + me.getMessage() + "</error>");
1054
		}
1055

    
1056
	}
1057

    
1058
	/**
1059
	 * Sends a list of all of the documents on this sever along with their
1060
	 * revision numbers. The format is: <!ELEMENT replication (server, updates)>
1061
	 * <!ELEMENT server (#PCDATA)> <!ELEMENT updates ((updatedDocument |
1062
	 * deleteDocument | revisionDocument)*)> <!ELEMENT updatedDocument (docid,
1063
	 * rev, datafile*)> <!ELEMENT deletedDocument (docid, rev)> <!ELEMENT
1064
	 * revisionDocument (docid, rev, datafile*)> <!ELEMENT docid (#PCDATA)>
1065
	 * <!ELEMENT rev (#PCDATA)> <!ELEMENT datafile (#PCDATA)> note that the rev
1066
	 * in deletedDocument is always empty. I just left it in there to make the
1067
	 * parser implementation easier.
1068
	 */
1069
	protected static void handleUpdateRequest(PrintWriter out, Hashtable<String, String[]> params,
1070
			HttpServletResponse response) {
1071
		// Checked out DBConnection
1072
		DBConnection dbConn = null;
1073
		// DBConenction serial number when checked it out
1074
		int serialNumber = -1;
1075
		PreparedStatement pstmt = null;
1076
		// Server list to store server info of xml_replication table
1077
		ReplicationServerList serverList = null;
1078

    
1079
		try {
1080
			// Check out a DBConnection from pool
1081
			dbConn = DBConnectionPool
1082
					.getDBConnection("MetacatReplication.handleUpdateRequest");
1083
			serialNumber = dbConn.getCheckOutSerialNumber();
1084
			// Create a server list from xml_replication table
1085
			serverList = new ReplicationServerList();
1086

    
1087
			// Get remote server name from param
1088
			String server = ((String[]) params.get("server"))[0];
1089
			// If no servr name in param, return a error
1090
			if (server == null || server.equals("")) {
1091
				response.setContentType("text/xml");
1092
				out.println("<error>Request didn't specify server name</error>");
1093
				out.close();
1094
				return;
1095
			}//if
1096

    
1097
			//try to open a https stream to test if the request server's public key
1098
			//in the key store, this is security issue
1099
			URL u = new URL("https://" + server + "?server="
1100
					+ MetacatUtil.getLocalReplicationServerName() + "&action=test");
1101
			String test = ReplicationService.getURLContent(u);
1102
			//couldn't pass the test
1103
			if (test.indexOf("successfully") == -1) {
1104
				response.setContentType("text/xml");
1105
				out.println("<error>Couldn't pass the trust test</error>");
1106
				out.close();
1107
				return;
1108
			}
1109

    
1110
			// Check if local host configure to replicate xml documents to remote
1111
			// server. If not send back a error message
1112
			if (!serverList.getReplicationValue(server)) {
1113
				response.setContentType("text/xml");
1114
				out
1115
						.println("<error>Configuration not allow to replicate document to you</error>");
1116
				out.close();
1117
				return;
1118
			}//if
1119

    
1120
			// Store the sql command
1121
			StringBuffer docsql = new StringBuffer();
1122
			StringBuffer revisionSql = new StringBuffer();
1123
			// Stroe the docid list
1124
			StringBuffer doclist = new StringBuffer();
1125
			// Store the deleted docid list
1126
			StringBuffer delsql = new StringBuffer();
1127
			// Store the data set file
1128
			Vector<Vector<String>> packageFiles = new Vector<Vector<String>>();
1129

    
1130
			// Append local server's name and replication servlet to doclist
1131
			doclist.append("<?xml version=\"1.0\"?><replication>");
1132
			doclist.append("<server>")
1133
					.append(MetacatUtil.getLocalReplicationServerName());
1134
			//doclist.append(util.getProperty("replicationpath"));
1135
			doclist.append("</server><updates>");
1136

    
1137
			// Get correct docid that reside on this server according the requesting
1138
			// server's replicate and data replicate value in xml_replication table
1139
			docsql.append(DatabaseService.getDBAdapter().getReplicationDocumentListSQL());
1140
			//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)) ");
1141
			revisionSql.append("select docid, rev, doctype from xml_revisions ");
1142
			// If the localhost is not a hub to the remote server, only replicate
1143
			// the docid' which home server is local host (server_location =1)
1144
			if (!serverList.getHubValue(server)) {
1145
				String serverLocationDoc = " and a.server_location = 1";
1146
				String serverLocationRev = "where server_location = 1";
1147
				docsql.append(serverLocationDoc);
1148
				revisionSql.append(serverLocationRev);
1149
			}
1150
			logReplication.info("ReplicationService.handleUpdateRequest - Doc sql: " + docsql.toString());
1151

    
1152
			// Get any deleted documents
1153
			delsql.append("select distinct docid from ");
1154
			delsql.append("xml_revisions where docid not in (select docid from ");
1155
			delsql.append("xml_documents) ");
1156
			// If the localhost is not a hub to the remote server, only replicate
1157
			// the docid' which home server is local host (server_location =1)
1158
			if (!serverList.getHubValue(server)) {
1159
				delsql.append("and server_location = 1");
1160
			}
1161
			logReplication.info("ReplicationService.handleUpdateRequest - Deleted sql: " + delsql.toString());
1162

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

    
1241
			pstmt = dbConn.prepareStatement(delsql.toString());
1242
			//usage count should increas 1
1243
			dbConn.increaseUsageCount(1);
1244

    
1245
			pstmt.execute();
1246
			rs = pstmt.getResultSet();
1247
			tablehasrows = rs.next();
1248
			while (tablehasrows) { //handle the deleted documents
1249
				doclist.append("<deletedDocument><docid>").append(rs.getString(1));
1250
				doclist.append("</docid><rev></rev></deletedDocument>");
1251
				//note that rev is always empty for deleted docs
1252
				tablehasrows = rs.next();
1253
			}
1254

    
1255
			//now we can put the package files into the xml results
1256
			for (int i = 0; i < packageFiles.size(); i++) {
1257
				Vector<String> v = packageFiles.elementAt(i);
1258
				doclist.append("<updatedDocument>");
1259
				doclist.append("<docid>").append(v.elementAt(0));
1260
				doclist.append("</docid><rev>");
1261
				doclist.append(v.elementAt(1));
1262
				doclist.append("</rev>");
1263
				doclist.append("</updatedDocument>");
1264
			}
1265
			// add revision doc list  
1266
			doclist.append(prepareRevisionDoc(dbConn, revisionSql.toString(),
1267
					replicateData));
1268

    
1269
			doclist.append("</updates></replication>");
1270
			logReplication.info("ReplicationService.handleUpdateRequest - doclist: " + doclist.toString());
1271
			pstmt.close();
1272
			//conn.close();
1273
			response.setContentType("text/xml");
1274
			out.println(doclist.toString());
1275

    
1276
		} catch (Exception e) {
1277
			logMetacat.error("ReplicationService.handleUpdateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1278
			logReplication.error("ReplicationService.handleUpdateRequest - error in MetacatReplication." + "handleupdaterequest: "
1279
					+ e.getMessage());
1280
			//e.printStackTrace(System.out);
1281
			response.setContentType("text/xml");
1282
			out.println("<error>" + e.getMessage() + "</error>");
1283
		} finally {
1284
			try {
1285
				pstmt.close();
1286
			}//try
1287
			catch (SQLException ee) {
1288
				logMetacat.error("ReplicationService.handleUpdateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1289
				logReplication.error("ReplicationService.handleUpdateRequest - Error in MetacatReplication."
1290
						+ "handleUpdaterequest to close pstmt: " + ee.getMessage());
1291
			}//catch
1292
			finally {
1293
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1294
			}//finally
1295
		}//finally
1296

    
1297
	}//handlUpdateRequest
1298

    
1299
	/*
1300
	 * This method will get the xml string for document in xml_revision
1301
	 * The schema look like <!ELEMENT revisionDocument (docid, rev, datafile*)>
1302
	 */
1303
	private static String prepareRevisionDoc(DBConnection dbConn, String revSql,
1304
			boolean replicateData) throws Exception {
1305
		logReplication.warn("ReplicationService.prepareRevisionDoc - The revision document sql is " + revSql);
1306
		StringBuffer revDocList = new StringBuffer();
1307
		PreparedStatement pstmt = dbConn.prepareStatement(revSql);
1308
		//usage count should increas 1
1309
		dbConn.increaseUsageCount(1);
1310

    
1311
		pstmt.execute();
1312
		ResultSet rs = pstmt.getResultSet();
1313
		boolean tablehasrows = rs.next();
1314
		while (tablehasrows) {
1315
			String recordDoctype = rs.getString(3);
1316

    
1317
			//If this is data file and it isn't configured to replicate data
1318
			if (recordDoctype.equals("BIN") && !replicateData) {
1319
				// do nothing
1320
				continue;
1321
			} else {
1322

    
1323
				revDocList.append("<revisionDocument>");
1324
				revDocList.append("<docid>").append(rs.getString(1));
1325
				revDocList.append("</docid><rev>").append(rs.getInt(2));
1326
				revDocList.append("</rev>");
1327
				// data file
1328
				if (recordDoctype.equals("BIN")) {
1329
					revDocList.append("<datafile>");
1330
					revDocList.append(PropertyService
1331
							.getProperty("replication.datafileflag"));
1332
					revDocList.append("</datafile>");
1333
				}
1334
				revDocList.append("</revisionDocument>");
1335

    
1336
			}//else
1337
			tablehasrows = rs.next();
1338
		}
1339
		//System.out.println("The revision list is"+ revDocList.toString());
1340
		return revDocList.toString();
1341
	}
1342

    
1343
	/**
1344
	 * Returns the xml_catalog table encoded in xml
1345
	 */
1346
	public static String getCatalogXML() {
1347
		return handleGetCatalogRequest(null, null, null, false);
1348
	}
1349

    
1350
	/**
1351
	 * Sends the contents of the xml_catalog table encoded in xml
1352
	 * The xml format is:
1353
	 * <!ELEMENT xml_catalog (row*)>
1354
	 * <!ELEMENT row (entry_type, source_doctype, target_doctype, public_id,
1355
	 *                system_id)>
1356
	 * All of the sub elements of row are #PCDATA
1357

    
1358
	 * If printFlag == false then do not print to out.
1359
	 */
1360
	protected static String handleGetCatalogRequest(PrintWriter out,
1361
			Hashtable<String, String[]> params, HttpServletResponse response,
1362
			boolean printFlag) {
1363
		DBConnection dbConn = null;
1364
		int serialNumber = -1;
1365
		PreparedStatement pstmt = null;
1366
		try {
1367
			/*conn = MetacatReplication.getDBConnection("MetacatReplication." +
1368
			                                          "handleGetCatalogRequest");*/
1369
			dbConn = DBConnectionPool
1370
					.getDBConnection("MetacatReplication.handleGetCatalogRequest");
1371
			serialNumber = dbConn.getCheckOutSerialNumber();
1372
			pstmt = dbConn.prepareStatement("select entry_type, "
1373
					+ "source_doctype, target_doctype, public_id, "
1374
					+ "system_id from xml_catalog");
1375
			pstmt.execute();
1376
			ResultSet rs = pstmt.getResultSet();
1377
			boolean tablehasrows = rs.next();
1378
			StringBuffer sb = new StringBuffer();
1379
			sb.append("<?xml version=\"1.0\"?><xml_catalog>");
1380
			while (tablehasrows) {
1381
				sb.append("<row><entry_type>").append(rs.getString(1));
1382
				sb.append("</entry_type><source_doctype>").append(rs.getString(2));
1383
				sb.append("</source_doctype><target_doctype>").append(rs.getString(3));
1384
				sb.append("</target_doctype><public_id>").append(rs.getString(4));
1385
				// system id may not have server url on front.  Add it if not.
1386
				String systemID = rs.getString(5);
1387
				if (!systemID.startsWith("http://")) {
1388
					systemID = SystemUtil.getContextURL() + systemID;
1389
				}
1390
				sb.append("</public_id><system_id>").append(systemID);
1391
				sb.append("</system_id></row>");
1392

    
1393
				tablehasrows = rs.next();
1394
			}
1395
			sb.append("</xml_catalog>");
1396
			//conn.close();
1397
			if (printFlag) {
1398
				response.setContentType("text/xml");
1399
				out.println(sb.toString());
1400
			}
1401
			pstmt.close();
1402
			return sb.toString();
1403
		} catch (Exception e) {
1404
			logMetacat.error("ReplicationService.handleGetCatalogRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1405
			logReplication.error("ReplicationService.handleGetCatalogRequest - error in MetacatReplication.handleGetCatalogRequest:"
1406
					+ e.getMessage());
1407
			e.printStackTrace(System.out);
1408
			if (printFlag) {
1409
				out.println("<error>" + e.getMessage() + "</error>");
1410
			}
1411
		} finally {
1412
			try {
1413
				pstmt.close();
1414
			}//try
1415
			catch (SQLException ee) {
1416
				logMetacat.error("ReplicationService.handleGetCatalogRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1417
				logReplication.error("ReplicationService.handleGetCatalogRequest - Error in MetacatReplication.handleGetCatalogRequest: "
1418
						+ ee.getMessage());
1419
			}//catch
1420
			finally {
1421
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1422
			}//finally
1423
		}//finally
1424

    
1425
		return null;
1426
	}
1427

    
1428
	/**
1429
	 * Sends the current system date to the remote server.  Using this action
1430
	 * for replication gets rid of any problems with syncronizing clocks
1431
	 * because a time specific to a document is always kept on its home server.
1432
	 */
1433
	protected static void handleGetTimeRequest(PrintWriter out,
1434
			Hashtable<String, String[]> params, HttpServletResponse response) {
1435
		SimpleDateFormat formatter = new SimpleDateFormat("MM/dd/yy HH:mm:ss");
1436
		java.util.Date localtime = new java.util.Date();
1437
		String dateString = formatter.format(localtime);
1438
		response.setContentType("text/xml");
1439

    
1440
		out.println("<timestamp>" + dateString + "</timestamp>");
1441
	}
1442

    
1443
	/**
1444
	 * this method handles the timeout for a file lock.  when a lock is
1445
	 * granted it is granted for 30 seconds.  When this thread runs out
1446
	 * it deletes the docid from the queue, thus eliminating the lock.
1447
	 */
1448
	public void run() {
1449
		try {
1450
			logReplication.info("ReplicationService.run - thread started for docid: "
1451
					+ (String) fileLocks.elementAt(0));
1452

    
1453
			Thread.sleep(30000); //the lock will expire in 30 seconds
1454
			logReplication.info("thread for docid: "
1455
					+ (String) fileLocks.elementAt(fileLocks.size() - 1) + " exiting.");
1456

    
1457
			fileLocks.remove(fileLocks.size() - 1);
1458
			//fileLocks is treated as a FIFO queue.  If there are more than one lock
1459
			//in the vector, the first one inserted will be removed.
1460
		} catch (Exception e) {
1461
			logMetacat.error("ReplicationService.run - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1462
			logReplication.error("ReplicationService.run - error in file lock thread from "
1463
					+ "MetacatReplication.run: " + e.getMessage());
1464
		}
1465
	}
1466

    
1467
	/**
1468
	 * Returns the name of a server given a serverCode
1469
	 * @param serverCode the serverid of the server
1470
	 * @return the servername or null if the specified serverCode does not
1471
	 *         exist.
1472
	 */
1473
	public static String getServerNameForServerCode(int serverCode) {
1474
		//System.out.println("serverid: " + serverCode);
1475
		DBConnection dbConn = null;
1476
		int serialNumber = -1;
1477
		PreparedStatement pstmt = null;
1478
		try {
1479
			dbConn = DBConnectionPool.getDBConnection("MetacatReplication.getServer");
1480
			serialNumber = dbConn.getCheckOutSerialNumber();
1481
			String sql = new String("select server from "
1482
					+ "xml_replication where serverid = " + serverCode);
1483
			pstmt = dbConn.prepareStatement(sql);
1484
			//System.out.println("getserver sql: " + sql);
1485
			pstmt.execute();
1486
			ResultSet rs = pstmt.getResultSet();
1487
			boolean tablehasrows = rs.next();
1488
			if (tablehasrows) {
1489
				//System.out.println("server: " + rs.getString(1));
1490
				return rs.getString(1);
1491
			}
1492

    
1493
			//conn.close();
1494
		} catch (Exception e) {
1495
			logMetacat.error("ReplicationService.getServerNameForServerCode - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1496
			logReplication.error("ReplicationService.getServerNameForServerCode - Error in MetacatReplication.getServer: " + e.getMessage());
1497
		} finally {
1498
			try {
1499
				pstmt.close();
1500
			}//try
1501
			catch (SQLException ee) {
1502
				logMetacat.error("ReplicationService.getServerNameForServerCode - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1503
				logReplication.error("ReplicationService.getServerNameForServerCode - Error in MetacactReplication.getserver: "
1504
						+ ee.getMessage());
1505
			}//catch
1506
			finally {
1507
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1508
			}//fianlly
1509
		}//finally
1510

    
1511
		return null;
1512
		//return null if the server does not exist
1513
	}
1514

    
1515
	/**
1516
	 * Returns a server code given a server name
1517
	 * @param server the name of the server
1518
	 * @return integer > 0 representing the code of the server, 0 if the server
1519
	 *  does not exist.
1520
	 */
1521
	public static int getServerCodeForServerName(String server) throws ServiceException {
1522
		DBConnection dbConn = null;
1523
		int serialNumber = -1;
1524
		PreparedStatement pstmt = null;
1525
		int serverCode = 0;
1526

    
1527
		try {
1528

    
1529
			//conn = util.openDBConnection();
1530
			dbConn = DBConnectionPool.getDBConnection("MetacatReplication.getServerCode");
1531
			serialNumber = dbConn.getCheckOutSerialNumber();
1532
			pstmt = dbConn.prepareStatement("SELECT serverid FROM xml_replication "
1533
					+ "WHERE server LIKE '" + server + "'");
1534
			pstmt.execute();
1535
			ResultSet rs = pstmt.getResultSet();
1536
			boolean tablehasrows = rs.next();
1537
			if (tablehasrows) {
1538
				serverCode = rs.getInt(1);
1539
				pstmt.close();
1540
				//conn.close();
1541
				return serverCode;
1542
			}
1543

    
1544
		} catch (SQLException sqle) {
1545
			throw new ServiceException("ReplicationService.getServerCodeForServerName - " 
1546
					+ "SQL error when getting server code: " + sqle.getMessage());
1547

    
1548
		} finally {
1549
			try {
1550
				pstmt.close();
1551
				//conn.close();
1552
			}//try
1553
			catch (Exception ee) {
1554
				logMetacat.error("ReplicationService.getServerCodeForServerName - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1555
				logReplication.error("ReplicationService.getServerNameForServerCode - Error in MetacatReplicatio.getServerCode: "
1556
						+ ee.getMessage());
1557

    
1558
			}//catch
1559
			finally {
1560
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1561
			}//finally
1562
		}//finally
1563

    
1564
		return serverCode;
1565
	}
1566

    
1567
	/**
1568
	 * Method to get a host server information for given docid
1569
	 * @param conn a connection to the database
1570
	 */
1571
	public static Hashtable<String, String> getHomeServerInfoForDocId(String docId) {
1572
		Hashtable<String, String> sl = new Hashtable<String, String>();
1573
		DBConnection dbConn = null;
1574
		int serialNumber = -1;
1575
		docId = DocumentUtil.getDocIdFromString(docId);
1576
		PreparedStatement pstmt = null;
1577
		int serverLocation;
1578
		try {
1579
			//get conection
1580
			dbConn = DBConnectionPool.getDBConnection("ReplicationHandler.getHomeServer");
1581
			serialNumber = dbConn.getCheckOutSerialNumber();
1582
			//get a server location from xml_document table
1583
			pstmt = dbConn.prepareStatement("select server_location from xml_documents "
1584
					+ "where docid = ?");
1585
			pstmt.setString(1, docId);
1586
			pstmt.execute();
1587
			ResultSet serverName = pstmt.getResultSet();
1588
			//get a server location
1589
			if (serverName.next()) {
1590
				serverLocation = serverName.getInt(1);
1591
				pstmt.close();
1592
			} else {
1593
				pstmt.close();
1594
				//ut.returnConnection(conn);
1595
				return null;
1596
			}
1597
			pstmt = dbConn.prepareStatement("select server, last_checked, replicate "
1598
					+ "from xml_replication where serverid = ?");
1599
			//increase usage count
1600
			dbConn.increaseUsageCount(1);
1601
			pstmt.setInt(1, serverLocation);
1602
			pstmt.execute();
1603
			ResultSet rs = pstmt.getResultSet();
1604
			boolean tableHasRows = rs.next();
1605
			if (tableHasRows) {
1606

    
1607
				String server = rs.getString(1);
1608
				String last_checked = rs.getString(2);
1609
				if (!server.equals("localhost")) {
1610
					sl.put(server, last_checked);
1611
				}
1612

    
1613
			} else {
1614
				pstmt.close();
1615
				//ut.returnConnection(conn);
1616
				return null;
1617
			}
1618
			pstmt.close();
1619
		} catch (Exception e) {
1620
			logMetacat.error("ReplicationService.getHomeServerInfoForDocId - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1621
			logReplication.error("ReplicationService.getHomeServerInfoForDocId - error in replicationHandler.getHomeServer(): "
1622
					+ e.getMessage());
1623
		} finally {
1624
			try {
1625
				pstmt.close();
1626
				//ut.returnConnection(conn);
1627
			} catch (Exception ee) {
1628
				logMetacat.error("ReplicationService.getHomeServerInfoForDocId - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1629
				logReplication.error("ReplicationService.getHomeServerInfoForDocId - Eror irn rplicationHandler.getHomeServer() "
1630
						+ "to close pstmt: " + ee.getMessage());
1631
			} finally {
1632
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1633
			}
1634

    
1635
		}//finally
1636
		return sl;
1637
	}
1638

    
1639
	/**
1640
	 * Returns a home server location  given a accnum
1641
	 * @param accNum , given accNum for a document
1642
	 *
1643
	 */
1644
	public static int getHomeServerCodeForDocId(String accNum) throws ServiceException {
1645
		DBConnection dbConn = null;
1646
		int serialNumber = -1;
1647
		PreparedStatement pstmt = null;
1648
		int serverCode = 1;
1649
		String docId = DocumentUtil.getDocIdFromString(accNum);
1650

    
1651
		try {
1652

    
1653
			// Get DBConnection
1654
			dbConn = DBConnectionPool
1655
					.getDBConnection("ReplicationHandler.getServerLocation");
1656
			serialNumber = dbConn.getCheckOutSerialNumber();
1657
			pstmt = dbConn.prepareStatement("SELECT server_location FROM xml_documents "
1658
					+ "WHERE docid LIKE '" + docId + "'");
1659
			pstmt.execute();
1660
			ResultSet rs = pstmt.getResultSet();
1661
			boolean tablehasrows = rs.next();
1662
			//If a document is find, return the server location for it
1663
			if (tablehasrows) {
1664
				serverCode = rs.getInt(1);
1665
				pstmt.close();
1666
				//conn.close();
1667
				return serverCode;
1668
			}
1669
			//if couldn't find in xml_documents table, we think server code is 1
1670
			//(this is new document)
1671
			else {
1672
				pstmt.close();
1673
				//conn.close();
1674
				return serverCode;
1675
			}
1676

    
1677
		} catch (SQLException sqle) {
1678
			throw new ServiceException("ReplicationService.getHomeServerCodeForDocId - " 
1679
					+ "SQL error when getting home server code for docid: " + docId + " : " 
1680
					+ sqle.getMessage());
1681

    
1682
		} finally {
1683
			try {
1684
				pstmt.close();
1685
				//conn.close();
1686

    
1687
			} catch (SQLException sqle) {
1688
				logMetacat.error("ReplicationService.getHomeServerCodeForDocId - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1689
				logReplication.error("ReplicationService.getHomeServerCodeForDocId - ReplicationService.getHomeServerCodeForDocId - " 
1690
						+ "SQL error when getting home server code for docid: " + docId + " : " 
1691
						+ sqle.getMessage());
1692
			} finally {
1693
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1694
			}//finally
1695
		}//finally
1696
		//return serverCode;
1697
	}
1698

    
1699
	/**
1700
	 * This method returns the content of a url
1701
	 * @param u the url to return the content from
1702
	 * @return a string representing the content of the url
1703
	 * @throws java.io.IOException
1704
	 */
1705
	public static String getURLContent(URL u) throws java.io.IOException {
1706
		char istreamChar;
1707
		int istreamInt;
1708
		logReplication.info("ReplicationService.getURLContent - Before open the stream" + u.toString());
1709
		InputStream input = u.openStream();
1710
		logReplication.info("ReplicationService.getURLContent - After open the stream" + u.toString());
1711
		InputStreamReader istream = new InputStreamReader(input);
1712
		StringBuffer serverResponse = new StringBuffer();
1713
		while ((istreamInt = istream.read()) != -1) {
1714
			istreamChar = (char) istreamInt;
1715
			serverResponse.append(istreamChar);
1716
		}
1717
		istream.close();
1718
		input.close();
1719

    
1720
		return serverResponse.toString();
1721
	}
1722

    
1723
//	/**
1724
//	 * Method for writing replication messages to a log file specified in
1725
//	 * metacat.properties
1726
//	 */
1727
//	public static void replLog(String message) {
1728
//		try {
1729
//			FileOutputStream fos = new FileOutputStream(PropertyService
1730
//					.getProperty("replication.logdir")
1731
//					+ "/metacatreplication.log", true);
1732
//			PrintWriter pw = new PrintWriter(fos);
1733
//			SimpleDateFormat formatter = new SimpleDateFormat("yy-MM-dd HH:mm:ss");
1734
//			java.util.Date localtime = new java.util.Date();
1735
//			String dateString = formatter.format(localtime);
1736
//			dateString += " :: " + message;
1737
//			// time stamp each entry
1738
//			pw.println(dateString);
1739
//			pw.flush();
1740
//		} catch (Exception e) {
1741
//			logReplication.error("error writing to replication log from "
1742
//					+ "MetacatReplication.replLog: " + e.getMessage());
1743
//			// e.printStackTrace(System.out);
1744
//		}
1745
//	}
1746

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

    
1771
	/**
1772
	 * Returns true if the replicate field for server in xml_replication is 1.
1773
	 * Returns false otherwise
1774
	 */
1775
	public static boolean replToServer(String server) {
1776
		DBConnection dbConn = null;
1777
		int serialNumber = -1;
1778
		PreparedStatement pstmt = null;
1779
		try {
1780
			dbConn = DBConnectionPool.getDBConnection("MetacatReplication.repltoServer");
1781
			serialNumber = dbConn.getCheckOutSerialNumber();
1782
			pstmt = dbConn.prepareStatement("select replicate from "
1783
					+ "xml_replication where server like '" + server + "'");
1784
			pstmt.execute();
1785
			ResultSet rs = pstmt.getResultSet();
1786
			boolean tablehasrows = rs.next();
1787
			if (tablehasrows) {
1788
				int i = rs.getInt(1);
1789
				if (i == 1) {
1790
					pstmt.close();
1791
					//conn.close();
1792
					return true;
1793
				} else {
1794
					pstmt.close();
1795
					//conn.close();
1796
					return false;
1797
				}
1798
			}
1799
		} catch (SQLException sqle) {
1800
			logMetacat.error("ReplicationService.replToServer - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1801
			logReplication.error("ReplicationService.replToServer - SQL error in MetacatReplication.replToServer: "
1802
					+ sqle.getMessage());
1803
		} finally {
1804
			try {
1805
				pstmt.close();
1806
				//conn.close();
1807
			}//try
1808
			catch (Exception ee) {
1809
				logMetacat.error("ReplicationService.replToServer - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1810
				logReplication.error("ReplicationService.replToServer - Error in MetacatReplication.replToServer: "
1811
						+ ee.getMessage());
1812
			}//catch
1813
			finally {
1814
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1815
			}//finally
1816
		}//finally
1817
		return false;
1818
		//the default if this server does not exist is to not replicate to it.
1819
	}
1820

    
1821
}
(6-6/7)