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: leinfelder $'
9
 *     '$Date: 2010-12-21 14:26:06 -0800 (Tue, 21 Dec 2010) $'
10
 * '$Revision: 5752 $'
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.ServletOutputStream;
37
import javax.servlet.http.*;
38

    
39
import edu.ucsb.nceas.metacat.DocInfoHandler;
40
import edu.ucsb.nceas.metacat.DocumentImpl;
41
import edu.ucsb.nceas.metacat.DocumentImplWrapper;
42
import edu.ucsb.nceas.metacat.EventLog;
43
import edu.ucsb.nceas.metacat.McdbException;
44
import edu.ucsb.nceas.metacat.accesscontrol.AccessControlException;
45
import edu.ucsb.nceas.metacat.accesscontrol.AccessControlForSingleFile;
46
import edu.ucsb.nceas.metacat.accesscontrol.PermOrderException;
47
import edu.ucsb.nceas.metacat.accesscontrol.XMLAccessDAO;
48
import edu.ucsb.nceas.metacat.database.DBConnection;
49
import edu.ucsb.nceas.metacat.database.DBConnectionPool;
50
import edu.ucsb.nceas.metacat.database.DatabaseService;
51
import edu.ucsb.nceas.metacat.properties.PropertyService;
52
import edu.ucsb.nceas.metacat.shared.BaseService;
53
import edu.ucsb.nceas.metacat.shared.HandlerException;
54
import edu.ucsb.nceas.metacat.shared.ServiceException;
55
import edu.ucsb.nceas.metacat.util.DocumentUtil;
56
import edu.ucsb.nceas.metacat.util.MetacatUtil;
57
import edu.ucsb.nceas.metacat.util.SystemUtil;
58
import edu.ucsb.nceas.metacat.IdentifierManager;
59
import edu.ucsb.nceas.metacat.McdbDocNotFoundException;
60
import edu.ucsb.nceas.utilities.FileUtil;
61
import edu.ucsb.nceas.utilities.GeneralPropertyException;
62
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
63

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

    
67
public class ReplicationService extends BaseService {
68

    
69
	private static ReplicationService replicationService = null;
70

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
418
	}
419

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

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

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

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

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

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

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

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

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

    
520
			String docInfoStr = ReplicationService.getURLContent(docinfourl);
521

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

    
529
			// Get user owner of this docid
530
			String user = (String) docinfoHash.get("user_owner");
531
			// Get home server of this docid
532
			String homeServer = (String) docinfoHash.get("home_server");
533
			String guid = (String) docinfoHash.get("guid");
534
			logReplication.info("XXXXXXXXXXXXXXXX GUID found in dociinfoHash: " + guid);
535
			
536
			logReplication.info("Processing guid " + guid + 
537
			  " information from handleForceReplicationRequest: " + 
538
			  docinfoHash.toString());
539
      IdentifierManager idman = IdentifierManager.getInstance();
540
      if(guid != null)
541
      { //if the guid was passed in, put it in the identifiers table
542
        logReplication.info("YYYYYYYYYYYYYY Creating guid/docid mapping for docid " + 
543
          docinfoHash.get("docid") + " and guid: " + guid);
544
        
545
        docName = (String) docinfoHash.get("docname");
546
        logReplication.info("ZZZZZZZZZZZZ docName: " + docName);
547
        if(docName.trim().equals("systemMetadata"))
548
        {
549
            logReplication.info("creating mapping for systemMetadata: guid: " + guid + " localId: " + docinfoHash.get("docid"));
550
            idman.createSystemMetadataMapping(guid, docinfoHash.get("docid"));
551
        }
552
        else
553
        {
554
            logReplication.info("creating mapping: guid: " + guid + " localId: " + docinfoHash.get("docid"));
555
            idman.createMapping(guid, docinfoHash.get("docid"));
556
        }
557
      }
558
      else
559
      {
560
        logReplication.debug("No guid information was included with the replicated document");
561
      }
562
      
563
			String createdDate = (String) docinfoHash.get("date_created");
564
			String updatedDate = (String) docinfoHash.get("date_updated");
565
			logReplication.info("ReplicationService.handleForceReplicateRequest - homeServer: " + homeServer);
566
			// Get Document type
567
			String docType = (String) docinfoHash.get("doctype");
568
			logReplication.info("ReplicationService.handleForceReplicateRequest - docType: " + docType);
569
			String parserBase = null;
570
			// this for eml2 and we need user eml2 parser
571
			if (docType != null
572
					&& (docType.trim()).equals(DocumentImpl.EML2_0_0NAMESPACE)) {
573
				logReplication.warn("ReplicationService.handleForceReplicateRequest - This is an eml200 document!");
574
				parserBase = DocumentImpl.EML200;
575
			} else if (docType != null
576
					&& (docType.trim()).equals(DocumentImpl.EML2_0_1NAMESPACE)) {
577
				logReplication.warn("ReplicationService.handleForceReplicateRequest - This is an eml2.0.1 document!");
578
				parserBase = DocumentImpl.EML200;
579
			} else if (docType != null
580
					&& (docType.trim()).equals(DocumentImpl.EML2_1_0NAMESPACE)) {
581
				logReplication.warn("ReplicationService.handleForceReplicateRequest - This is an eml2.1.0 document!");
582
				parserBase = DocumentImpl.EML210;
583
			} else if (docType != null
584
					&& (docType.trim()).equals(DocumentImpl.EML2_1_1NAMESPACE)) {
585
				logReplication.warn("ReplicationService.handleForceReplicateRequest - This is an eml2.1.1 document!");
586
				parserBase = DocumentImpl.EML210;
587
			}
588
			logReplication.warn("ReplicationService.handleForceReplicateRequest - The parserBase is: " + parserBase);
589

    
590
			// Get DBConnection from pool
591
			dbConn = DBConnectionPool
592
					.getDBConnection("MetacatReplication.handleForceReplicateRequest");
593
			serialNumber = dbConn.getCheckOutSerialNumber();
594
			// write the document to local database
595
			DocumentImplWrapper wrapper = new DocumentImplWrapper(parserBase, false);
596
			//try this independently so we can set
597
//			Exception writeException = null;
598
			try {
599
				wrapper.writeReplication(dbConn, xmldoc, null, null,
600
						dbaction, docid, user, null, homeServer, server, createdDate,
601
						updatedDate);
602
			} finally {
603
//				writeException = e;
604

    
605
				//process extra access rules before dealing with the write exception (doc exist already)			
606
		        Vector<XMLAccessDAO> accessControlList = dih.getAccessControlList();
607
		        if (accessControlList != null) {
608
		        	AccessControlForSingleFile acfsf = new AccessControlForSingleFile(docid);
609
		        	for (XMLAccessDAO xmlAccessDAO : accessControlList) {
610
		        		if (!acfsf.accessControlExists(xmlAccessDAO)) {
611
		        			acfsf.insertPermissions(xmlAccessDAO);
612
							logReplication.info("ReplicationService.handleForceReplicateRequest - document " + docid
613
									+ " permissions added to DB");
614
		        		}
615
		            }
616
		        }
617
//				if (accessControlList != null) {
618
//					for (int i = 0; i < accessControlList.size(); i++) {
619
//						AccessControlForSingleFile acfsf = (AccessControlForSingleFile) accessControlList
620
//								.get(i);
621
//						if (!acfsf.accessControlExists()) {
622
//							acfsf.insertPermissions();
623
//							logReplication.info("ReplicationService.handleForceReplicateRequest - document " + docid
624
//									+ " permissions added to DB");
625
//						}
626
//					}
627
//				}
628

    
629
//				if (writeException != null) {
630
//					throw writeException;
631
//				}
632

    
633
				logReplication.info("ReplicationService.handleForceReplicateRequest - document " + docid + " added to DB with "
634
						+ "action " + dbaction);
635
				
636
				if(guid != null)
637
                {
638
                    if(!docName.trim().equals("systemMetadata"))
639
                    {
640
                        logReplication.info("replicate D1GUID:" + guid + ":D1SCIMETADATA:" + 
641
                                docid + ":");
642
                    }
643
                    else
644
                    {
645
                        logReplication.info("replicate D1GUID:" + guid + ":D1SYSMETADATA:" + 
646
                                docid + ":");
647
                    }
648
                }
649
				EventLog.getInstance().log(request.getRemoteAddr(), REPLICATIONUSER, docid,
650
						dbaction);
651
			}
652
		} catch (SQLException sqle) {
653
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
654
			logReplication.error("ReplicationService.handleForceReplicateRequest - SQL error when adding doc " + docid + 
655
					" to DB with action " + dbaction + ": " + sqle.getMessage());
656
		} catch (MalformedURLException mue) {
657
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
658
			logReplication.error("ReplicationService.handleForceReplicateRequest - URL error when adding doc " + docid + 
659
					" to DB with action " + dbaction + ": " + mue.getMessage());
660
		} catch (SAXException se) {
661
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
662
			logReplication.error("ReplicationService.handleForceReplicateRequest - SAX parsing error when adding doc " + docid + 
663
					" to DB with action " + dbaction + ": " + se.getMessage());
664
		} catch (HandlerException he) {
665
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
666
			logReplication.error("ReplicationService.handleForceReplicateRequest - Handler error when adding doc " + docid + 
667
					" to DB with action " + dbaction + ": " + he.getMessage());
668
		} catch (IOException ioe) {
669
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
670
			logReplication.error("ReplicationService.handleForceReplicateRequest - I/O error when adding doc " + docid + 
671
					" to DB with action " + dbaction + ": " + ioe.getMessage());
672
		} catch (PermOrderException poe) {
673
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
674
			logReplication.error("ReplicationService.handleForceReplicateRequest - Permissions order error when adding doc " + docid + 
675
					" to DB with action " + dbaction + ": " + poe.getMessage());
676
		} catch (AccessControlException ace) {
677
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
678
			logReplication.error("ReplicationService.handleForceReplicateRequest - Permissions order error when adding doc " + docid + 
679
					" to DB with action " + dbaction + ": " + ace.getMessage());
680
		} catch (Exception e) {
681
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
682
			logReplication.error("ReplicationService.handleForceReplicateRequest - General error when adding doc " + docid + 
683
					" to DB with action " + dbaction + ": " + e.getMessage());
684
		} finally {
685
			// Return the checked out DBConnection
686
			DBConnectionPool.returnDBConnection(dbConn, serialNumber);
687
		}//finally
688
	}
689

    
690
	/*
691
	 * when a forcereplication delete request comes in, local host will delete this
692
	 * document
693
	 */
694
	protected static void handleForceReplicateDeleteRequest(PrintWriter out,
695
			Hashtable<String, String[]> params, HttpServletResponse response,
696
			HttpServletRequest request) {
697
		String server = ((String[]) params.get("server"))[0]; // the server that
698
		String docid = ((String[]) params.get("docid"))[0]; // sent the document
699
		try {
700
			logReplication.info("ReplicationService.handleForceReplicateDeleteRequest - force replication delete request from " + server);
701
			logReplication.info("ReplicationService.handleForceReplicateDeleteRequest - force replication delete docid " + docid);
702
			logReplication.info("ReplicationService.handleForceReplicateDeleteRequest - Force replication delete request from: " + server);
703
			logReplication.info("ReplicationService.handleForceReplicateDeleteRequest - Force replication delete docid: " + docid);
704
			DocumentImpl.delete(docid, null, null, server);
705
			logReplication.info("ReplicationService.handleForceReplicateDeleteRequest - document " + docid + " was successfully deleted ");
706
			EventLog.getInstance().log(request.getRemoteAddr(), REPLICATIONUSER, docid,
707
					"delete");
708
			logReplication.info("ReplicationService.handleForceReplicateDeleteRequest - document " + docid + " was successfully deleted ");
709
		} catch (Exception e) {
710
			logMetacat.error("ReplicationService.handleForceReplicateDeleteRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
711
			logReplication.error("document " + docid
712
					+ " failed to delete because " + e.getMessage());
713
			logReplication.error("ReplicationService.handleForceReplicateDeleteRequest - error: " + e.getMessage());
714

    
715
		}//catch
716

    
717
	}
718

    
719
	/**
720
	 * when a forcereplication data file request comes in, local host sends a
721
	 * readdata request to the requesting server (remote server) for the specified
722
	 * docid. Then store it in local database and file system
723
	 */
724
	protected static void handleForceReplicateDataFileRequest(Hashtable<String, String[]> params,
725
			HttpServletRequest request) {
726

    
727
		//make sure there is some parameters
728
		if (params.isEmpty()) {
729
			return;
730
		}
731
		// Get remote server
732
		String server = ((String[]) params.get("server"))[0];
733
		// the docid should include rev number
734
		String docid = ((String[]) params.get("docid"))[0];
735
		// Make sure there is a docid and server
736
		if (docid == null || server == null || server.equals("")) {
737
			logMetacat.error("ReplicationService.handleForceReplicateDataFileRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
738
			logReplication.error("ReplicationService.handleForceReplicateDataFileRequest - Didn't specify docid or server for replication");
739
			return;
740
		}
741

    
742
		// Overide or not
743
		//    boolean override = false;
744
		// dbaction - update or insert
745
		String dbaction = null;
746

    
747
		try {
748
			//docid was switch to two parts uinque code and rev
749
			//String uniqueCode=MetacatUtil.getDocIdFromString(docid);
750
			//int rev=MetacatUtil.getVersionFromString(docid);
751
			if (params.containsKey("dbaction")) {
752
				dbaction = ((String[]) params.get("dbaction"))[0];
753
			} else//default value is update
754
			{
755
				dbaction = "update";
756
			}
757

    
758
			logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - force replication request from " + server);
759
			logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - Force replication request from: " + server);
760
			logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - Force replication docid: " + docid);
761
			logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - Force replication action: " + dbaction);
762
			// get the document info from server
763
			URL docinfourl = new URL("https://" + server + "?server="
764
					+ MetacatUtil.getLocalReplicationServerName()
765
					+ "&action=getdocumentinfo&docid=" + docid);
766

    
767
			String docInfoStr = ReplicationService.getURLContent(docinfourl);
768

    
769
			//dih is the parser for the docinfo xml format
770
			DocInfoHandler dih = new DocInfoHandler();
771
			XMLReader docinfoParser = ReplicationHandler.initParser(dih);
772
			docinfoParser.parse(new InputSource(new StringReader(docInfoStr)));
773
			Hashtable<String, String> docinfoHash = dih.getDocInfo();
774
			String user = (String) docinfoHash.get("user_owner");
775

    
776
			String docName = (String) docinfoHash.get("docname");
777

    
778
			String docType = (String) docinfoHash.get("doctype");
779

    
780
			String docHomeServer = (String) docinfoHash.get("home_server");
781

    
782
			String createdDate = (String) docinfoHash.get("date_created");
783

    
784
			String updatedDate = (String) docinfoHash.get("date_updated");
785
			logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - docHomeServer of datafile: " + docHomeServer);
786

    
787
			//if action is delete, we don't delete the data file. Just archieve
788
			//the xml_documents
789
			/*if (dbaction.equals("delete"))
790
			{
791
			  //conn = util.getConnection();
792
			  DocumentImpl.delete(docid,user,null);
793
			  //util.returnConnection(conn);
794
			}*/
795
			//To data file insert or update is same
796
			if (dbaction.equals("insert") || dbaction.equals("update")) {
797
				//Get data file and store it into local file system.
798
				// sending back readdata request to server
799
				URL url = new URL("https://" + server + "?server="
800
						+ MetacatUtil.getLocalReplicationServerName()
801
						+ "&action=readdata&docid=" + docid);
802
				String datafilePath = PropertyService
803
						.getProperty("application.datafilepath");
804

    
805
				Exception writeException = null;
806
				//register data file into xml_documents table and wite data file
807
				//into file system
808
				try {
809
					DocumentImpl.writeDataFileInReplication(url.openStream(),
810
							datafilePath, docName, docType, docid, user, docHomeServer,
811
							server, DocumentImpl.DOCUMENTTABLE, false, createdDate,
812
							updatedDate);
813
				} catch (Exception e) {
814
					writeException = e;
815
				}
816
				//process extra access rules
817
//				Vector<AccessControlForSingleFile> accessControlList = dih
818
//						.getAccessControlList();
819
//				if (accessControlList != null) {
820
//					for (int i = 0; i < accessControlList.size(); i++) {
821
//						AccessControlForSingleFile acfsf = (AccessControlForSingleFile) accessControlList
822
//								.get(i);
823
//						if (!acfsf.accessControlExists()) {
824
//							acfsf.insertPermissions();
825
//							logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - datafile " + docid
826
//									+ " permissions added to DB");
827
//						}
828
//					}
829
//				}
830
				
831
		        Vector<XMLAccessDAO> accessControlList = dih.getAccessControlList();
832
		        if (accessControlList != null) {
833
		        	AccessControlForSingleFile acfsf = new AccessControlForSingleFile(docid);
834
		        	for (XMLAccessDAO xmlAccessDAO : accessControlList) {
835
		        		if (!acfsf.accessControlExists(xmlAccessDAO)) {
836
		        			acfsf.insertPermissions(xmlAccessDAO);
837
							logReplication.info("ReplicationService.handleForceReplicateRequest - document " + docid
838
									+ " permissions added to DB");
839
		        		}
840
		            }
841
		        }
842

    
843
				if (writeException != null) {
844
					throw writeException;
845
				}
846

    
847
				//false means non-timed replication
848
				logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - datafile " + docid + " added to DB with "
849
						+ "action " + dbaction);
850
				EventLog.getInstance().log(request.getRemoteAddr(), REPLICATIONUSER,
851
						docid, dbaction);
852
			}
853

    
854
		} catch (Exception e) {
855
			logMetacat.error("ReplicationService.handleForceReplicateDataFileRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
856
			logReplication.error("ReplicationService.handleForceReplicateDataFileRequest - Datafile " + docid
857
					+ " failed to added to DB with " + "action " + dbaction + " because "
858
					+ e.getMessage());
859
			logReplication.error("ReplicationService.handleForceReplicateDataFileRequest - ERROR in MetacatReplication.handleForceDataFileReplicate"
860
					+ "Request(): " + e.getMessage());
861
		}
862
	}
863

    
864
	/**
865
	 * Grants or denies a lock to a requesting host.
866
	 * The servlet parameters of interrest are:
867
	 * docid: the docid of the file the lock is being requested for
868
	 * currentdate: the timestamp of the document on the remote server
869
	 *
870
	 */
871
	protected static void handleGetLockRequest(PrintWriter out,
872
			Hashtable<String, String[]> params, HttpServletResponse response) {
873

    
874
		try {
875

    
876
			String docid = ((String[]) params.get("docid"))[0];
877
			String remoteRev = ((String[]) params.get("updaterev"))[0];
878
			DocumentImpl requestDoc = new DocumentImpl(docid);
879
			logReplication.info("ReplicationService.handleGetLockRequest - lock request for " + docid);
880
			int localRevInt = requestDoc.getRev();
881
			int remoteRevInt = Integer.parseInt(remoteRev);
882

    
883
			if (remoteRevInt >= localRevInt) {
884
				if (!fileLocks.contains(docid)) { //grant the lock if it is not already locked
885
					fileLocks.add(0, docid); //insert at the beginning of the queue Vector
886
					//send a message back to the the remote host authorizing the insert
887
					out
888
							.println("<lockgranted><docid>" + docid
889
									+ "</docid></lockgranted>");
890
					//          lockThread = new Thread(this);
891
					//          lockThread.setPriority(Thread.MIN_PRIORITY);
892
					//          lockThread.start();
893
					logReplication.info("ReplicationService.handleGetLockRequest - lock granted for " + docid);
894
				} else { //deny the lock
895
					out.println("<filelocked><docid>" + docid + "</docid></filelocked>");
896
					logReplication.info("ReplicationService.handleGetLockRequest - lock denied for " + docid
897
							+ "reason: file already locked");
898
				}
899
			} else {//deny the lock.
900
				out.println("<outdatedfile><docid>" + docid + "</docid></filelocked>");
901
				logReplication.info("ReplicationService.handleGetLockRequest - lock denied for " + docid
902
						+ "reason: client has outdated file");
903
			}
904
			//conn.close();
905
		} catch (Exception e) {
906
			logMetacat.error("ReplicationService.handleGetLockRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
907
			logReplication.error("ReplicationService.handleGetLockRequest - error requesting file lock from MetacatReplication."
908
					+ "handleGetLockRequest: " + e.getMessage());
909
			e.printStackTrace(System.out);
910
		}
911
	}
912

    
913
	/**
914
	 * Sends all of the xml_documents information encoded in xml to a requestor
915
	 * the format is:
916
	 * <!ELEMENT documentinfo (docid, docname, doctype, doctitle, user_owner,
917
	 *                  user_updated, home_server, public_access, rev)/>
918
	 * all of the subelements of document info are #PCDATA
919
	 */
920
	protected static void handleGetDocumentInfoRequest(PrintWriter out,
921
			Hashtable<String, String[]> params, HttpServletResponse response) {
922
		String docid = ((String[]) (params.get("docid")))[0];
923
		StringBuffer sb = new StringBuffer();
924

    
925
		try {
926
		  IdentifierManager idman = IdentifierManager.getInstance();
927

    
928
			DocumentImpl doc = new DocumentImpl(docid);
929
			sb.append("<documentinfo><docid>").append(docid);
930
			sb.append("</docid>");
931
			try
932
			{
933
			  String guid = idman.getGUID(doc.getDocID(), doc.getRev());
934
			  sb.append("<guid>").append(guid).append("</guid>");
935
			  String smLocalId = idman.getSystemMetadataLocalId(guid);
936
			  if(smLocalId != null && !smLocalId.trim().equals(""))
937
			  {
938
			      sb.append("<systemmetadatalocalid>").append(smLocalId).append("</systemmetadatalocalid>");
939
			  }
940
			}
941
			catch(McdbDocNotFoundException e)
942
			{
943
			  //do nothing, there was no guid for this document
944
			}
945
			sb.append("<docname>").append(doc.getDocname());
946
			sb.append("</docname><doctype>").append(doc.getDoctype());
947
			sb.append("</doctype>");
948
			sb.append("<user_owner>").append(doc.getUserowner());
949
			sb.append("</user_owner><user_updated>").append(doc.getUserupdated());
950
			sb.append("</user_updated>");
951
			sb.append("<date_created>");
952
			sb.append(doc.getCreateDate());
953
			sb.append("</date_created>");
954
			sb.append("<date_updated>");
955
			sb.append(doc.getUpdateDate());
956
			sb.append("</date_updated>");
957
			sb.append("<home_server>");
958
			sb.append(doc.getDocHomeServer());
959
			sb.append("</home_server>");
960
			sb.append("<public_access>").append(doc.getPublicaccess());
961
			sb.append("</public_access><rev>").append(doc.getRev());
962
			sb.append("</rev>");
963

    
964
			sb.append("<accessControl>");
965

    
966
			AccessControlForSingleFile acfsf = new AccessControlForSingleFile(docid); 
967
			sb.append(acfsf.getAccessString());
968
			
969
			sb.append("</accessControl>");
970

    
971
			sb.append("</documentinfo>");
972
			response.setContentType("text/xml");
973
			out.println(sb.toString());
974

    
975
		} catch (Exception e) {
976
			logMetacat.error("ReplicationService.handleGetDocumentInfoRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
977
			logReplication.error("ReplicationService.handleGetDocumentInfoRequest - error in metacatReplication.handlegetdocumentinforequest "
978
					+ "for doc: " + docid + " : " + e.getMessage());
979
		}
980

    
981
	}
982

    
983
	/**
984
	 * Sends a datafile to a remote host
985
	 */
986
	protected static void handleGetDataFileRequest(OutputStream outPut,
987
			Hashtable<String, String[]> params, HttpServletResponse response)
988

    
989
	{
990
		// File path for data file
991
		String filepath;
992
		// Request docid
993
		String docId = ((String[]) (params.get("docid")))[0];
994
		//check if the doicd is null
995
		if (docId == null) {
996
			logMetacat.error("ReplicationService.handleGetDataFileRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
997
			logReplication.error("ReplicationService.handleGetDataFileRequest - Didn't specify docid for replication");
998
			return;
999
		}
1000

    
1001
		//try to open a https stream to test if the request server's public key
1002
		//in the key store, this is security issue
1003
		try {
1004
			filepath = PropertyService.getProperty("application.datafilepath");
1005
			String server = params.get("server")[0];
1006
			URL u = new URL("https://" + server + "?server="
1007
					+ MetacatUtil.getLocalReplicationServerName() + "&action=test");
1008
			String test = ReplicationService.getURLContent(u);
1009
			//couldn't pass the test
1010
			if (test.indexOf("successfully") == -1) {
1011
				//response.setContentType("text/xml");
1012
				//outPut.println("<error>Couldn't pass the trust test</error>");
1013
				logMetacat.error("ReplicationService.handleGetDataFileRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1014
				logReplication.error("ReplicationService.handleGetDataFileRequest - Couldn't pass the trust test");
1015
				return;
1016
			}
1017
		}//try
1018
		catch (Exception ee) {
1019
			return;
1020
		}//catch
1021

    
1022
		if (!filepath.endsWith("/")) {
1023
			filepath += "/";
1024
		}
1025
		// Get file aboslute file name
1026
		String filename = filepath + docId;
1027

    
1028
		//MIME type
1029
		String contentType = null;
1030
		if (filename.endsWith(".xml")) {
1031
			contentType = "text/xml";
1032
		} else if (filename.endsWith(".css")) {
1033
			contentType = "text/css";
1034
		} else if (filename.endsWith(".dtd")) {
1035
			contentType = "text/plain";
1036
		} else if (filename.endsWith(".xsd")) {
1037
			contentType = "text/xml";
1038
		} else if (filename.endsWith("/")) {
1039
			contentType = "text/html";
1040
		} else {
1041
			File f = new File(filename);
1042
			if (f.isDirectory()) {
1043
				contentType = "text/html";
1044
			} else {
1045
				contentType = "application/octet-stream";
1046
			}
1047
		}
1048

    
1049
		// Set the mime type
1050
		response.setContentType(contentType);
1051

    
1052
		// Get the content of the file
1053
		FileInputStream fin = null;
1054
		try {
1055
			// FileInputStream to metacat
1056
			fin = new FileInputStream(filename);
1057
			// 4K buffer
1058
			byte[] buf = new byte[4 * 1024];
1059
			// Read data from file input stream to byte array
1060
			int b = fin.read(buf);
1061
			// Write to outStream from byte array
1062
			while (b != -1) {
1063
				outPut.write(buf, 0, b);
1064
				b = fin.read(buf);
1065
			}
1066
			// close file input stream
1067
			fin.close();
1068

    
1069
		}//try
1070
		catch (Exception e) {
1071
			logMetacat.error("ReplicationService.handleGetDataFileRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1072
			logReplication.error("ReplicationService.handleGetDataFileRequest - error getting data file from MetacatReplication."
1073
					+ "handlGetDataFileRequest " + e.getMessage());
1074
			e.printStackTrace(System.out);
1075
		}//catch
1076

    
1077
	}
1078

    
1079
	/**
1080
	 * Sends a document to a remote host
1081
	 */
1082
	protected static void handleGetDocumentRequest(PrintWriter out,
1083
			Hashtable<String, String[]> params, HttpServletResponse response) {
1084

    
1085
		String urlString = null;
1086
		String documentPath = null;
1087
		try {
1088
			// try to open a https stream to test if the request server's public
1089
			// key
1090
			// in the key store, this is security issue
1091
			String server = params.get("server")[0];
1092
			urlString = "https://" + server + "?server="
1093
					+ MetacatUtil.getLocalReplicationServerName() + "&action=test";
1094
			URL u = new URL(urlString);
1095
			String test = ReplicationService.getURLContent(u);
1096
			// couldn't pass the test
1097
			if (test.indexOf("successfully") == -1) {
1098
				response.setContentType("text/xml");
1099
				out.println("<error>Couldn't pass the trust test " + test + " </error>");
1100
				out.close();
1101
				return;
1102
			}
1103

    
1104
			String docid = params.get("docid")[0];
1105
			logReplication.debug("ReplicationService.handleGetDocumentRequest - MetacatReplication.handleGetDocumentRequest for docid: "
1106
					+ docid);
1107
			DocumentImpl di = new DocumentImpl(docid);
1108

    
1109
			String documentDir = PropertyService
1110
					.getProperty("application.documentfilepath");
1111
			documentPath = documentDir + FileUtil.getFS() + docid;
1112

    
1113
			// if the document does not exist on disk, read it from db and write
1114
			// it to disk.
1115
			if (FileUtil.getFileStatus(documentPath) == FileUtil.DOES_NOT_EXIST
1116
					|| FileUtil.getFileSize(documentPath) == 0) {
1117
				FileOutputStream fos = new FileOutputStream(documentPath);
1118
				di.toXml(fos, null, null, true);
1119
			}
1120

    
1121
			// read the file from disk and send it to outputstream
1122
			OutputStream outputStream = response.getOutputStream();
1123
			di.readFromFileSystem(outputStream, null, null, documentPath);
1124

    
1125
			// response.setContentType("text/xml");
1126
			// out.print(di.toString(null, null, true));
1127

    
1128
			logReplication.info("ReplicationService.handleGetDocumentRequest - document " + docid + " sent");
1129

    
1130
		} catch (MalformedURLException mue) {
1131
			logMetacat.error("ReplicationService.handleGetDocumentRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1132
			logReplication.error("ReplicationService.handleGetDocumentRequest - Url error when getting document from MetacatReplication."
1133
					+ "handlGetDocumentRequest for url: " + urlString + " : "
1134
					+ mue.getMessage());
1135
			// e.printStackTrace(System.out);
1136
			response.setContentType("text/xml");
1137
			out.println("<error>" + mue.getMessage() + "</error>");
1138
		} catch (IOException ioe) {
1139
			logMetacat.error("ReplicationService.handleGetDocumentRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1140
			logReplication.error("ReplicationService.handleGetDocumentRequest - I/O error when getting document from MetacatReplication."
1141
					+ "handlGetDocumentRequest for file: " + documentPath + " : "
1142
					+ ioe.getMessage());
1143
			// e.printStackTrace(System.out);
1144
			response.setContentType("text/xml");
1145
			out.println("<error>" + ioe.getMessage() + "</error>");
1146
		} catch (PropertyNotFoundException pnfe) {
1147
			logMetacat.error("ReplicationService.handleGetDocumentRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1148
			logReplication
1149
					.error("ReplicationService.handleGetDocumentRequest - Error getting property when getting document from MetacatReplication."
1150
							+ "handlGetDocumentRequest for file: "
1151
							+ documentPath
1152
							+ " : "
1153
							+ pnfe.getMessage());
1154
			// e.printStackTrace(System.out);
1155
			response.setContentType("text/xml");
1156
			out.println("<error>" + pnfe.getMessage() + "</error>");
1157
		} catch (McdbException me) {
1158
			logReplication
1159
					.error("ReplicationService.handleGetDocumentRequest - Document implementation error  getting property when getting document from MetacatReplication."
1160
							+ "handlGetDocumentRequest for file: "
1161
							+ documentPath
1162
							+ " : "
1163
							+ me.getMessage());
1164
			// e.printStackTrace(System.out);
1165
			response.setContentType("text/xml");
1166
			out.println("<error>" + me.getMessage() + "</error>");
1167
		}
1168

    
1169
	}
1170

    
1171
	/**
1172
	 * Sends a list of all of the documents on this sever along with their
1173
	 * revision numbers. The format is: <!ELEMENT replication (server, updates)>
1174
	 * <!ELEMENT server (#PCDATA)> <!ELEMENT updates ((updatedDocument |
1175
	 * deleteDocument | revisionDocument)*)> <!ELEMENT updatedDocument (docid,
1176
	 * rev, datafile*)> <!ELEMENT deletedDocument (docid, rev)> <!ELEMENT
1177
	 * revisionDocument (docid, rev, datafile*)> <!ELEMENT docid (#PCDATA)>
1178
	 * <!ELEMENT rev (#PCDATA)> <!ELEMENT datafile (#PCDATA)> note that the rev
1179
	 * in deletedDocument is always empty. I just left it in there to make the
1180
	 * parser implementation easier.
1181
	 */
1182
	protected static void handleUpdateRequest(PrintWriter out, Hashtable<String, String[]> params,
1183
			HttpServletResponse response) {
1184
		// Checked out DBConnection
1185
		DBConnection dbConn = null;
1186
		// DBConenction serial number when checked it out
1187
		int serialNumber = -1;
1188
		PreparedStatement pstmt = null;
1189
		// Server list to store server info of xml_replication table
1190
		ReplicationServerList serverList = null;
1191

    
1192
		try {
1193
			// Check out a DBConnection from pool
1194
			dbConn = DBConnectionPool
1195
					.getDBConnection("MetacatReplication.handleUpdateRequest");
1196
			serialNumber = dbConn.getCheckOutSerialNumber();
1197
			// Create a server list from xml_replication table
1198
			serverList = new ReplicationServerList();
1199

    
1200
			// Get remote server name from param
1201
			String server = ((String[]) params.get("server"))[0];
1202
			// If no servr name in param, return a error
1203
			if (server == null || server.equals("")) {
1204
				response.setContentType("text/xml");
1205
				out.println("<error>Request didn't specify server name</error>");
1206
				out.close();
1207
				return;
1208
			}//if
1209

    
1210
			//try to open a https stream to test if the request server's public key
1211
			//in the key store, this is security issue
1212
			String testUrl = "https://" + server + "?server="
1213
            + MetacatUtil.getLocalReplicationServerName() + "&action=test";
1214
			logReplication.info("Running trust test: " + testUrl);
1215
			URL u = new URL(testUrl);
1216
			String test = ReplicationService.getURLContent(u);
1217
			logReplication.info("Ouput from test is '" + test + "'");
1218
			//couldn't pass the test
1219
			if (test.indexOf("successfully") == -1) {
1220
			    logReplication.error("Trust test failed.");
1221
				response.setContentType("text/xml");
1222
				out.println("<error>Couldn't pass the trust test</error>");
1223
				out.close();
1224
				return;
1225
			}
1226
			logReplication.info("Trust test succeeded.");
1227

    
1228
			// Check if local host configure to replicate xml documents to remote
1229
			// server. If not send back a error message
1230
			if (!serverList.getReplicationValue(server)) {
1231
				response.setContentType("text/xml");
1232
				out
1233
						.println("<error>Configuration not allow to replicate document to you</error>");
1234
				out.close();
1235
				return;
1236
			}//if
1237

    
1238
			// Store the sql command
1239
			StringBuffer docsql = new StringBuffer();
1240
			StringBuffer revisionSql = new StringBuffer();
1241
			// Stroe the docid list
1242
			StringBuffer doclist = new StringBuffer();
1243
			// Store the deleted docid list
1244
			StringBuffer delsql = new StringBuffer();
1245
			// Store the data set file
1246
			Vector<Vector<String>> packageFiles = new Vector<Vector<String>>();
1247

    
1248
			// Append local server's name and replication servlet to doclist
1249
			doclist.append("<?xml version=\"1.0\"?><replication>");
1250
			doclist.append("<server>")
1251
					.append(MetacatUtil.getLocalReplicationServerName());
1252
			//doclist.append(util.getProperty("replicationpath"));
1253
			doclist.append("</server><updates>");
1254

    
1255
			// Get correct docid that reside on this server according the requesting
1256
			// server's replicate and data replicate value in xml_replication table
1257
			docsql.append(DatabaseService.getInstance().getDBAdapter().getReplicationDocumentListSQL());
1258
			//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)) ");
1259
			revisionSql.append("select docid, rev, doctype from xml_revisions ");
1260
			// If the localhost is not a hub to the remote server, only replicate
1261
			// the docid' which home server is local host (server_location =1)
1262
			if (!serverList.getHubValue(server)) {
1263
				String serverLocationDoc = " and a.server_location = 1";
1264
				String serverLocationRev = "where server_location = 1";
1265
				docsql.append(serverLocationDoc);
1266
				revisionSql.append(serverLocationRev);
1267
			}
1268
			logReplication.info("ReplicationService.handleUpdateRequest - Doc sql: " + docsql.toString());
1269

    
1270
			// Get any deleted documents
1271
			delsql.append("select distinct docid from ");
1272
			delsql.append("xml_revisions where docid not in (select docid from ");
1273
			delsql.append("xml_documents) ");
1274
			// If the localhost is not a hub to the remote server, only replicate
1275
			// the docid' which home server is local host (server_location =1)
1276
			if (!serverList.getHubValue(server)) {
1277
				delsql.append("and server_location = 1");
1278
			}
1279
			logReplication.info("ReplicationService.handleUpdateRequest - Deleted sql: " + delsql.toString());
1280

    
1281
			// Get docid list of local host
1282
			pstmt = dbConn.prepareStatement(docsql.toString());
1283
			pstmt.execute();
1284
			ResultSet rs = pstmt.getResultSet();
1285
			boolean tablehasrows = rs.next();
1286
			//If metacat configed to replicate data file
1287
			//if ((util.getProperty("replicationsenddata")).equals("on"))
1288
			boolean replicateData = serverList.getDataReplicationValue(server);
1289
			if (replicateData) {
1290
				while (tablehasrows) {
1291
					String recordDoctype = rs.getString(3);
1292
					Vector<String> packagedoctypes = MetacatUtil
1293
							.getOptionList(PropertyService
1294
									.getProperty("xml.packagedoctype"));
1295
					//if this is a package file, put it at the end
1296
					//because if a package file is read before all of the files it
1297
					//refers to are loaded then there is an error
1298
					if (recordDoctype != null && !packagedoctypes.contains(recordDoctype)) {
1299
						//If this is not data file
1300
						if (!recordDoctype.equals("BIN")) {
1301
							//for non-data file document
1302
							doclist.append("<updatedDocument>");
1303
							doclist.append("<docid>").append(rs.getString(1));
1304
							doclist.append("</docid><rev>").append(rs.getInt(2));
1305
							doclist.append("</rev>");
1306
							doclist.append("</updatedDocument>");
1307
						}//if
1308
						else {
1309
							//for data file document, in datafile attributes
1310
							//we put "datafile" value there
1311
							doclist.append("<updatedDocument>");
1312
							doclist.append("<docid>").append(rs.getString(1));
1313
							doclist.append("</docid><rev>").append(rs.getInt(2));
1314
							doclist.append("</rev>");
1315
							doclist.append("<datafile>");
1316
							doclist.append(PropertyService
1317
									.getProperty("replication.datafileflag"));
1318
							doclist.append("</datafile>");
1319
							doclist.append("</updatedDocument>");
1320
						}//else
1321
					}//if packagedoctpes
1322
					else { //the package files are saved to be put into the xml later.
1323
						Vector<String> v = new Vector<String>();
1324
						v.add(rs.getString(1));
1325
						v.add(String.valueOf(rs.getInt(2)));
1326
						packageFiles.add(v);
1327
					}//esle
1328
					tablehasrows = rs.next();
1329
				}//while
1330
			}//if
1331
			else //metacat was configured not to send data file
1332
			{
1333
				while (tablehasrows) {
1334
					String recordDoctype = rs.getString(3);
1335
					if (!recordDoctype.equals("BIN")) { //don't replicate data files
1336
						Vector<String> packagedoctypes = MetacatUtil
1337
								.getOptionList(PropertyService
1338
										.getProperty("xml.packagedoctype"));
1339
						if (recordDoctype != null
1340
								&& !packagedoctypes.contains(recordDoctype)) { //if this is a package file, put it at the end
1341
							//because if a package file is read before all of the files it
1342
							//refers to are loaded then there is an error
1343
							doclist.append("<updatedDocument>");
1344
							doclist.append("<docid>").append(rs.getString(1));
1345
							doclist.append("</docid><rev>").append(rs.getInt(2));
1346
							doclist.append("</rev>");
1347
							doclist.append("</updatedDocument>");
1348
						} else { //the package files are saved to be put into the xml later.
1349
							Vector<String> v = new Vector<String>();
1350
							v.add(rs.getString(1));
1351
							v.add(String.valueOf(rs.getInt(2)));
1352
							packageFiles.add(v);
1353
						}
1354
					}//if
1355
					tablehasrows = rs.next();
1356
				}//while
1357
			}//else
1358

    
1359
			pstmt = dbConn.prepareStatement(delsql.toString());
1360
			//usage count should increas 1
1361
			dbConn.increaseUsageCount(1);
1362

    
1363
			pstmt.execute();
1364
			rs = pstmt.getResultSet();
1365
			tablehasrows = rs.next();
1366
			while (tablehasrows) { //handle the deleted documents
1367
				doclist.append("<deletedDocument><docid>").append(rs.getString(1));
1368
				doclist.append("</docid><rev></rev></deletedDocument>");
1369
				//note that rev is always empty for deleted docs
1370
				tablehasrows = rs.next();
1371
			}
1372

    
1373
			//now we can put the package files into the xml results
1374
			for (int i = 0; i < packageFiles.size(); i++) {
1375
				Vector<String> v = packageFiles.elementAt(i);
1376
				doclist.append("<updatedDocument>");
1377
				doclist.append("<docid>").append(v.elementAt(0));
1378
				doclist.append("</docid><rev>");
1379
				doclist.append(v.elementAt(1));
1380
				doclist.append("</rev>");
1381
				doclist.append("</updatedDocument>");
1382
			}
1383
			// add revision doc list  
1384
			doclist.append(prepareRevisionDoc(dbConn, revisionSql.toString(),
1385
					replicateData));
1386

    
1387
			doclist.append("</updates></replication>");
1388
			logReplication.info("ReplicationService.handleUpdateRequest - doclist: " + doclist.toString());
1389
			pstmt.close();
1390
			//conn.close();
1391
			response.setContentType("text/xml");
1392
			out.println(doclist.toString());
1393

    
1394
		} catch (Exception e) {
1395
			logMetacat.error("ReplicationService.handleUpdateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1396
			logReplication.error("ReplicationService.handleUpdateRequest - error in MetacatReplication." + "handleupdaterequest: "
1397
					+ e.getMessage());
1398
			//e.printStackTrace(System.out);
1399
			response.setContentType("text/xml");
1400
			out.println("<error>" + e.getMessage() + "</error>");
1401
		} finally {
1402
			try {
1403
				pstmt.close();
1404
			}//try
1405
			catch (SQLException ee) {
1406
				logMetacat.error("ReplicationService.handleUpdateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1407
				logReplication.error("ReplicationService.handleUpdateRequest - Error in MetacatReplication."
1408
						+ "handleUpdaterequest to close pstmt: " + ee.getMessage());
1409
			}//catch
1410
			finally {
1411
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1412
			}//finally
1413
		}//finally
1414

    
1415
	}//handlUpdateRequest
1416

    
1417
	/*
1418
	 * This method will get the xml string for document in xml_revision
1419
	 * The schema look like <!ELEMENT revisionDocument (docid, rev, datafile*)>
1420
	 */
1421
	private static String prepareRevisionDoc(DBConnection dbConn, String revSql,
1422
			boolean replicateData) throws Exception {
1423
		logReplication.warn("ReplicationService.prepareRevisionDoc - The revision document sql is " + revSql);
1424
		StringBuffer revDocList = new StringBuffer();
1425
		PreparedStatement pstmt = dbConn.prepareStatement(revSql);
1426
		//usage count should increas 1
1427
		dbConn.increaseUsageCount(1);
1428

    
1429
		pstmt.execute();
1430
		ResultSet rs = pstmt.getResultSet();
1431
		boolean tablehasrows = rs.next();
1432
		while (tablehasrows) {
1433
			String recordDoctype = rs.getString(3);
1434

    
1435
			//If this is data file and it isn't configured to replicate data
1436
			if (recordDoctype.equals("BIN") && !replicateData) {
1437
				// do nothing
1438
				continue;
1439
			} else {
1440

    
1441
				revDocList.append("<revisionDocument>");
1442
				revDocList.append("<docid>").append(rs.getString(1));
1443
				revDocList.append("</docid><rev>").append(rs.getInt(2));
1444
				revDocList.append("</rev>");
1445
				// data file
1446
				if (recordDoctype.equals("BIN")) {
1447
					revDocList.append("<datafile>");
1448
					revDocList.append(PropertyService
1449
							.getProperty("replication.datafileflag"));
1450
					revDocList.append("</datafile>");
1451
				}
1452
				revDocList.append("</revisionDocument>");
1453

    
1454
			}//else
1455
			tablehasrows = rs.next();
1456
		}
1457
		//System.out.println("The revision list is"+ revDocList.toString());
1458
		return revDocList.toString();
1459
	}
1460

    
1461
	/**
1462
	 * Returns the xml_catalog table encoded in xml
1463
	 */
1464
	public static String getCatalogXML() {
1465
		return handleGetCatalogRequest(null, null, null, false);
1466
	}
1467

    
1468
	/**
1469
	 * Sends the contents of the xml_catalog table encoded in xml
1470
	 * The xml format is:
1471
	 * <!ELEMENT xml_catalog (row*)>
1472
	 * <!ELEMENT row (entry_type, source_doctype, target_doctype, public_id,
1473
	 *                system_id)>
1474
	 * All of the sub elements of row are #PCDATA
1475

    
1476
	 * If printFlag == false then do not print to out.
1477
	 */
1478
	protected static String handleGetCatalogRequest(PrintWriter out,
1479
			Hashtable<String, String[]> params, HttpServletResponse response,
1480
			boolean printFlag) {
1481
		DBConnection dbConn = null;
1482
		int serialNumber = -1;
1483
		PreparedStatement pstmt = null;
1484
		try {
1485
			/*conn = MetacatReplication.getDBConnection("MetacatReplication." +
1486
			                                          "handleGetCatalogRequest");*/
1487
			dbConn = DBConnectionPool
1488
					.getDBConnection("MetacatReplication.handleGetCatalogRequest");
1489
			serialNumber = dbConn.getCheckOutSerialNumber();
1490
			pstmt = dbConn.prepareStatement("select entry_type, "
1491
					+ "source_doctype, target_doctype, public_id, "
1492
					+ "system_id from xml_catalog");
1493
			pstmt.execute();
1494
			ResultSet rs = pstmt.getResultSet();
1495
			boolean tablehasrows = rs.next();
1496
			StringBuffer sb = new StringBuffer();
1497
			sb.append("<?xml version=\"1.0\"?><xml_catalog>");
1498
			while (tablehasrows) {
1499
				sb.append("<row><entry_type>").append(rs.getString(1));
1500
				sb.append("</entry_type><source_doctype>").append(rs.getString(2));
1501
				sb.append("</source_doctype><target_doctype>").append(rs.getString(3));
1502
				sb.append("</target_doctype><public_id>").append(rs.getString(4));
1503
				// system id may not have server url on front.  Add it if not.
1504
				String systemID = rs.getString(5);
1505
				if (!systemID.startsWith("http://")) {
1506
					systemID = SystemUtil.getContextURL() + systemID;
1507
				}
1508
				sb.append("</public_id><system_id>").append(systemID);
1509
				sb.append("</system_id></row>");
1510

    
1511
				tablehasrows = rs.next();
1512
			}
1513
			sb.append("</xml_catalog>");
1514
			//conn.close();
1515
			if (printFlag) {
1516
				response.setContentType("text/xml");
1517
				out.println(sb.toString());
1518
			}
1519
			pstmt.close();
1520
			return sb.toString();
1521
		} catch (Exception e) {
1522
			logMetacat.error("ReplicationService.handleGetCatalogRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1523
			logReplication.error("ReplicationService.handleGetCatalogRequest - error in MetacatReplication.handleGetCatalogRequest:"
1524
					+ e.getMessage());
1525
			e.printStackTrace(System.out);
1526
			if (printFlag) {
1527
				out.println("<error>" + e.getMessage() + "</error>");
1528
			}
1529
		} finally {
1530
			try {
1531
				pstmt.close();
1532
			}//try
1533
			catch (SQLException ee) {
1534
				logMetacat.error("ReplicationService.handleGetCatalogRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1535
				logReplication.error("ReplicationService.handleGetCatalogRequest - Error in MetacatReplication.handleGetCatalogRequest: "
1536
						+ ee.getMessage());
1537
			}//catch
1538
			finally {
1539
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1540
			}//finally
1541
		}//finally
1542

    
1543
		return null;
1544
	}
1545

    
1546
	/**
1547
	 * Sends the current system date to the remote server.  Using this action
1548
	 * for replication gets rid of any problems with syncronizing clocks
1549
	 * because a time specific to a document is always kept on its home server.
1550
	 */
1551
	protected static void handleGetTimeRequest(PrintWriter out,
1552
			Hashtable<String, String[]> params, HttpServletResponse response) {
1553
		SimpleDateFormat formatter = new SimpleDateFormat("MM/dd/yy HH:mm:ss");
1554
		java.util.Date localtime = new java.util.Date();
1555
		String dateString = formatter.format(localtime);
1556
		response.setContentType("text/xml");
1557

    
1558
		out.println("<timestamp>" + dateString + "</timestamp>");
1559
	}
1560

    
1561
	/**
1562
	 * this method handles the timeout for a file lock.  when a lock is
1563
	 * granted it is granted for 30 seconds.  When this thread runs out
1564
	 * it deletes the docid from the queue, thus eliminating the lock.
1565
	 */
1566
	public void run() {
1567
		try {
1568
			logReplication.info("ReplicationService.run - thread started for docid: "
1569
					+ (String) fileLocks.elementAt(0));
1570

    
1571
			Thread.sleep(30000); //the lock will expire in 30 seconds
1572
			logReplication.info("thread for docid: "
1573
					+ (String) fileLocks.elementAt(fileLocks.size() - 1) + " exiting.");
1574

    
1575
			fileLocks.remove(fileLocks.size() - 1);
1576
			//fileLocks is treated as a FIFO queue.  If there are more than one lock
1577
			//in the vector, the first one inserted will be removed.
1578
		} catch (Exception e) {
1579
			logMetacat.error("ReplicationService.run - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1580
			logReplication.error("ReplicationService.run - error in file lock thread from "
1581
					+ "MetacatReplication.run: " + e.getMessage());
1582
		}
1583
	}
1584

    
1585
	/**
1586
	 * Returns the name of a server given a serverCode
1587
	 * @param serverCode the serverid of the server
1588
	 * @return the servername or null if the specified serverCode does not
1589
	 *         exist.
1590
	 */
1591
	public static String getServerNameForServerCode(int serverCode) {
1592
		//System.out.println("serverid: " + serverCode);
1593
		DBConnection dbConn = null;
1594
		int serialNumber = -1;
1595
		PreparedStatement pstmt = null;
1596
		try {
1597
			dbConn = DBConnectionPool.getDBConnection("MetacatReplication.getServer");
1598
			serialNumber = dbConn.getCheckOutSerialNumber();
1599
			String sql = new String("select server from "
1600
					+ "xml_replication where serverid = " + serverCode);
1601
			pstmt = dbConn.prepareStatement(sql);
1602
			//System.out.println("getserver sql: " + sql);
1603
			pstmt.execute();
1604
			ResultSet rs = pstmt.getResultSet();
1605
			boolean tablehasrows = rs.next();
1606
			if (tablehasrows) {
1607
				//System.out.println("server: " + rs.getString(1));
1608
				return rs.getString(1);
1609
			}
1610

    
1611
			//conn.close();
1612
		} catch (Exception e) {
1613
			logMetacat.error("ReplicationService.getServerNameForServerCode - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1614
			logReplication.error("ReplicationService.getServerNameForServerCode - Error in MetacatReplication.getServer: " + e.getMessage());
1615
		} finally {
1616
			try {
1617
				pstmt.close();
1618
			}//try
1619
			catch (SQLException ee) {
1620
				logMetacat.error("ReplicationService.getServerNameForServerCode - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1621
				logReplication.error("ReplicationService.getServerNameForServerCode - Error in MetacactReplication.getserver: "
1622
						+ ee.getMessage());
1623
			}//catch
1624
			finally {
1625
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1626
			}//fianlly
1627
		}//finally
1628

    
1629
		return null;
1630
		//return null if the server does not exist
1631
	}
1632

    
1633
	/**
1634
	 * Returns a server code given a server name
1635
	 * @param server the name of the server
1636
	 * @return integer > 0 representing the code of the server, 0 if the server
1637
	 *  does not exist.
1638
	 */
1639
	public static int getServerCodeForServerName(String server) throws ServiceException {
1640
		DBConnection dbConn = null;
1641
		int serialNumber = -1;
1642
		PreparedStatement pstmt = null;
1643
		int serverCode = 0;
1644

    
1645
		try {
1646

    
1647
			//conn = util.openDBConnection();
1648
			dbConn = DBConnectionPool.getDBConnection("MetacatReplication.getServerCode");
1649
			serialNumber = dbConn.getCheckOutSerialNumber();
1650
			pstmt = dbConn.prepareStatement("SELECT serverid FROM xml_replication "
1651
					+ "WHERE server LIKE '" + server + "'");
1652
			pstmt.execute();
1653
			ResultSet rs = pstmt.getResultSet();
1654
			boolean tablehasrows = rs.next();
1655
			if (tablehasrows) {
1656
				serverCode = rs.getInt(1);
1657
				pstmt.close();
1658
				//conn.close();
1659
				return serverCode;
1660
			}
1661

    
1662
		} catch (SQLException sqle) {
1663
			throw new ServiceException("ReplicationService.getServerCodeForServerName - " 
1664
					+ "SQL error when getting server code: " + sqle.getMessage());
1665

    
1666
		} finally {
1667
			try {
1668
				pstmt.close();
1669
				//conn.close();
1670
			}//try
1671
			catch (Exception ee) {
1672
				logMetacat.error("ReplicationService.getServerCodeForServerName - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1673
				logReplication.error("ReplicationService.getServerNameForServerCode - Error in MetacatReplicatio.getServerCode: "
1674
						+ ee.getMessage());
1675

    
1676
			}//catch
1677
			finally {
1678
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1679
			}//finally
1680
		}//finally
1681

    
1682
		return serverCode;
1683
	}
1684

    
1685
	/**
1686
	 * Method to get a host server information for given docid
1687
	 * @param conn a connection to the database
1688
	 */
1689
	public static Hashtable<String, String> getHomeServerInfoForDocId(String docId) {
1690
		Hashtable<String, String> sl = new Hashtable<String, String>();
1691
		DBConnection dbConn = null;
1692
		int serialNumber = -1;
1693
		docId = DocumentUtil.getDocIdFromString(docId);
1694
		PreparedStatement pstmt = null;
1695
		int serverLocation;
1696
		try {
1697
			//get conection
1698
			dbConn = DBConnectionPool.getDBConnection("ReplicationHandler.getHomeServer");
1699
			serialNumber = dbConn.getCheckOutSerialNumber();
1700
			//get a server location from xml_document table
1701
			pstmt = dbConn.prepareStatement("select server_location from xml_documents "
1702
					+ "where docid = ?");
1703
			pstmt.setString(1, docId);
1704
			pstmt.execute();
1705
			ResultSet serverName = pstmt.getResultSet();
1706
			//get a server location
1707
			if (serverName.next()) {
1708
				serverLocation = serverName.getInt(1);
1709
				pstmt.close();
1710
			} else {
1711
				pstmt.close();
1712
				//ut.returnConnection(conn);
1713
				return null;
1714
			}
1715
			pstmt = dbConn.prepareStatement("select server, last_checked, replicate "
1716
					+ "from xml_replication where serverid = ?");
1717
			//increase usage count
1718
			dbConn.increaseUsageCount(1);
1719
			pstmt.setInt(1, serverLocation);
1720
			pstmt.execute();
1721
			ResultSet rs = pstmt.getResultSet();
1722
			boolean tableHasRows = rs.next();
1723
			if (tableHasRows) {
1724

    
1725
				String server = rs.getString(1);
1726
				String last_checked = rs.getString(2);
1727
				if (!server.equals("localhost")) {
1728
					sl.put(server, last_checked);
1729
				}
1730

    
1731
			} else {
1732
				pstmt.close();
1733
				//ut.returnConnection(conn);
1734
				return null;
1735
			}
1736
			pstmt.close();
1737
		} catch (Exception e) {
1738
			logMetacat.error("ReplicationService.getHomeServerInfoForDocId - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1739
			logReplication.error("ReplicationService.getHomeServerInfoForDocId - error in replicationHandler.getHomeServer(): "
1740
					+ e.getMessage());
1741
		} finally {
1742
			try {
1743
				pstmt.close();
1744
				//ut.returnConnection(conn);
1745
			} catch (Exception ee) {
1746
				logMetacat.error("ReplicationService.getHomeServerInfoForDocId - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1747
				logReplication.error("ReplicationService.getHomeServerInfoForDocId - Eror irn rplicationHandler.getHomeServer() "
1748
						+ "to close pstmt: " + ee.getMessage());
1749
			} finally {
1750
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1751
			}
1752

    
1753
		}//finally
1754
		return sl;
1755
	}
1756

    
1757
	/**
1758
	 * Returns a home server location  given a accnum
1759
	 * @param accNum , given accNum for a document
1760
	 *
1761
	 */
1762
	public static int getHomeServerCodeForDocId(String accNum) throws ServiceException {
1763
		DBConnection dbConn = null;
1764
		int serialNumber = -1;
1765
		PreparedStatement pstmt = null;
1766
		int serverCode = 1;
1767
		String docId = DocumentUtil.getDocIdFromString(accNum);
1768

    
1769
		try {
1770

    
1771
			// Get DBConnection
1772
			dbConn = DBConnectionPool
1773
					.getDBConnection("ReplicationHandler.getServerLocation");
1774
			serialNumber = dbConn.getCheckOutSerialNumber();
1775
			pstmt = dbConn.prepareStatement("SELECT server_location FROM xml_documents "
1776
					+ "WHERE docid LIKE '" + docId + "'");
1777
			pstmt.execute();
1778
			ResultSet rs = pstmt.getResultSet();
1779
			boolean tablehasrows = rs.next();
1780
			//If a document is find, return the server location for it
1781
			if (tablehasrows) {
1782
				serverCode = rs.getInt(1);
1783
				pstmt.close();
1784
				//conn.close();
1785
				return serverCode;
1786
			}
1787
			//if couldn't find in xml_documents table, we think server code is 1
1788
			//(this is new document)
1789
			else {
1790
				pstmt.close();
1791
				//conn.close();
1792
				return serverCode;
1793
			}
1794

    
1795
		} catch (SQLException sqle) {
1796
			throw new ServiceException("ReplicationService.getHomeServerCodeForDocId - " 
1797
					+ "SQL error when getting home server code for docid: " + docId + " : " 
1798
					+ sqle.getMessage());
1799

    
1800
		} finally {
1801
			try {
1802
				pstmt.close();
1803
				//conn.close();
1804

    
1805
			} catch (SQLException sqle) {
1806
				logMetacat.error("ReplicationService.getHomeServerCodeForDocId - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1807
				logReplication.error("ReplicationService.getHomeServerCodeForDocId - ReplicationService.getHomeServerCodeForDocId - " 
1808
						+ "SQL error when getting home server code for docid: " + docId + " : " 
1809
						+ sqle.getMessage());
1810
			} finally {
1811
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1812
			}//finally
1813
		}//finally
1814
		//return serverCode;
1815
	}
1816

    
1817
	/**
1818
	 * This method returns the content of a url
1819
	 * @param u the url to return the content from
1820
	 * @return a string representing the content of the url
1821
	 * @throws java.io.IOException
1822
	 */
1823
	public static String getURLContent(URL u) throws java.io.IOException {
1824
	    logReplication.info("Getting url content from " + u.toString());
1825
		char istreamChar;
1826
		int istreamInt;
1827
		logReplication.info("ReplicationService.getURLContent - Before open the stream" + u.toString());
1828
		InputStream input = u.openStream();
1829
		logReplication.info("ReplicationService.getURLContent - After open the stream" + u.toString());
1830
		InputStreamReader istream = new InputStreamReader(input);
1831
		StringBuffer serverResponse = new StringBuffer();
1832
		while ((istreamInt = istream.read()) != -1) {
1833
			istreamChar = (char) istreamInt;
1834
			serverResponse.append(istreamChar);
1835
		}
1836
		istream.close();
1837
		input.close();
1838

    
1839
		return serverResponse.toString();
1840
	}
1841

    
1842
//	/**
1843
//	 * Method for writing replication messages to a log file specified in
1844
//	 * metacat.properties
1845
//	 */
1846
//	public static void replLog(String message) {
1847
//		try {
1848
//			FileOutputStream fos = new FileOutputStream(PropertyService
1849
//					.getProperty("replication.logdir")
1850
//					+ "/metacatreplication.log", true);
1851
//			PrintWriter pw = new PrintWriter(fos);
1852
//			SimpleDateFormat formatter = new SimpleDateFormat("yy-MM-dd HH:mm:ss");
1853
//			java.util.Date localtime = new java.util.Date();
1854
//			String dateString = formatter.format(localtime);
1855
//			dateString += " :: " + message;
1856
//			// time stamp each entry
1857
//			pw.println(dateString);
1858
//			pw.flush();
1859
//		} catch (Exception e) {
1860
//			logReplication.error("error writing to replication log from "
1861
//					+ "MetacatReplication.replLog: " + e.getMessage());
1862
//			// e.printStackTrace(System.out);
1863
//		}
1864
//	}
1865

    
1866
//	/**
1867
//	 * Method for writing replication messages to a log file specified in
1868
//	 * metacat.properties
1869
//	 */
1870
//	public static void replErrorLog(String message) {
1871
//		try {
1872
//			FileOutputStream fos = new FileOutputStream(PropertyService
1873
//					.getProperty("replication.logdir")
1874
//					+ "/metacatreplicationerror.log", true);
1875
//			PrintWriter pw = new PrintWriter(fos);
1876
//			SimpleDateFormat formatter = new SimpleDateFormat("yy-MM-dd HH:mm:ss");
1877
//			java.util.Date localtime = new java.util.Date();
1878
//			String dateString = formatter.format(localtime);
1879
//			dateString += " :: " + message;
1880
//			//time stamp each entry
1881
//			pw.println(dateString);
1882
//			pw.flush();
1883
//		} catch (Exception e) {
1884
//			logReplication.error("error writing to replication error log from "
1885
//					+ "MetacatReplication.replErrorLog: " + e.getMessage());
1886
//			//e.printStackTrace(System.out);
1887
//		}
1888
//	}
1889

    
1890
	/**
1891
	 * Returns true if the replicate field for server in xml_replication is 1.
1892
	 * Returns false otherwise
1893
	 */
1894
	public static boolean replToServer(String server) {
1895
		DBConnection dbConn = null;
1896
		int serialNumber = -1;
1897
		PreparedStatement pstmt = null;
1898
		try {
1899
			dbConn = DBConnectionPool.getDBConnection("MetacatReplication.repltoServer");
1900
			serialNumber = dbConn.getCheckOutSerialNumber();
1901
			pstmt = dbConn.prepareStatement("select replicate from "
1902
					+ "xml_replication where server like '" + server + "'");
1903
			pstmt.execute();
1904
			ResultSet rs = pstmt.getResultSet();
1905
			boolean tablehasrows = rs.next();
1906
			if (tablehasrows) {
1907
				int i = rs.getInt(1);
1908
				if (i == 1) {
1909
					pstmt.close();
1910
					//conn.close();
1911
					return true;
1912
				} else {
1913
					pstmt.close();
1914
					//conn.close();
1915
					return false;
1916
				}
1917
			}
1918
		} catch (SQLException sqle) {
1919
			logMetacat.error("ReplicationService.replToServer - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1920
			logReplication.error("ReplicationService.replToServer - SQL error in MetacatReplication.replToServer: "
1921
					+ sqle.getMessage());
1922
		} finally {
1923
			try {
1924
				pstmt.close();
1925
				//conn.close();
1926
			}//try
1927
			catch (Exception ee) {
1928
				logMetacat.error("ReplicationService.replToServer - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1929
				logReplication.error("ReplicationService.replToServer - Error in MetacatReplication.replToServer: "
1930
						+ ee.getMessage());
1931
			}//catch
1932
			finally {
1933
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1934
			}//finally
1935
		}//finally
1936
		return false;
1937
		//the default if this server does not exist is to not replicate to it.
1938
	}
1939

    
1940
}
(6-6/7)