Project

General

Profile

1 522 berkley
/**
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$'
9
 *     '$Date$'
10
 * '$Revision$'
11 669 jones
 *
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 522 berkley
 */
26
27 5014 daigle
package edu.ucsb.nceas.metacat.replication;
28 522 berkley
29
import java.util.*;
30 2572 tao
import java.util.Date;
31 522 berkley
import java.io.*;
32
import java.sql.*;
33
import java.net.*;
34
import java.text.*;
35 4080 daigle
36 522 berkley
import javax.servlet.http.*;
37 574 berkley
38 5014 daigle
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 5195 daigle
import edu.ucsb.nceas.metacat.accesscontrol.AccessControlException;
44 5089 daigle
import edu.ucsb.nceas.metacat.accesscontrol.AccessControlForSingleFile;
45 5195 daigle
import edu.ucsb.nceas.metacat.accesscontrol.PermOrderException;
46 5098 daigle
import edu.ucsb.nceas.metacat.accesscontrol.XMLAccessDAO;
47 5014 daigle
import edu.ucsb.nceas.metacat.database.DBConnection;
48
import edu.ucsb.nceas.metacat.database.DBConnectionPool;
49
import edu.ucsb.nceas.metacat.database.DatabaseService;
50 5030 daigle
import edu.ucsb.nceas.metacat.properties.PropertyService;
51 5014 daigle
import edu.ucsb.nceas.metacat.shared.BaseService;
52
import edu.ucsb.nceas.metacat.shared.HandlerException;
53
import edu.ucsb.nceas.metacat.shared.ServiceException;
54 5027 daigle
import edu.ucsb.nceas.metacat.util.DocumentUtil;
55 4698 daigle
import edu.ucsb.nceas.metacat.util.MetacatUtil;
56 4080 daigle
import edu.ucsb.nceas.metacat.util.SystemUtil;
57 5322 berkley
import edu.ucsb.nceas.metacat.IdentifierManager;
58
import edu.ucsb.nceas.metacat.McdbDocNotFoundException;
59 4488 daigle
import edu.ucsb.nceas.utilities.FileUtil;
60 4087 daigle
import edu.ucsb.nceas.utilities.GeneralPropertyException;
61 4080 daigle
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
62
63 2663 sgarg
import org.apache.log4j.Logger;
64 522 berkley
import org.xml.sax.*;
65
66 5014 daigle
public class ReplicationService extends BaseService {
67 4335 daigle
68 5014 daigle
	private static ReplicationService replicationService = null;
69 2663 sgarg
70 5014 daigle
	private long timeInterval;
71
	private Date firstTime;
72
	private boolean timedReplicationIsOn = false;
73
	Timer replicationDaemon;
74
	private static Vector<String> fileLocks = new Vector<String>();
75
//	private Thread lockThread = null;
76
	public static final String FORCEREPLICATEDELETE = "forcereplicatedelete";
77
	private static String TIMEREPLICATION = "replication.timedreplication";
78
	private static String TIMEREPLICATIONINTERVAl ="replication.timedreplicationinterval";
79
	private static String FIRSTTIME = "replication.firsttimedreplication";
80
	private static final int TIMEINTERVALLIMIT = 7200000;
81
	public static final String REPLICATIONUSER = "replication";
82 2286 tao
83 5014 daigle
	public static final String REPLICATION_LOG_FILE_NAME = "metacatreplication.log";
84
	public static String METACAT_REPL_ERROR_MSG = null;
85
	private static Logger logReplication = Logger.getLogger("ReplicationLogging");
86
	private static Logger logMetacat = Logger.getLogger(ReplicationService.class);
87 2286 tao
88 5014 daigle
	private ReplicationService() throws ServiceException {
89
		_serviceName = "ReplicationService";
90
91
		initialize();
92
	}
93
94
	private void initialize() throws ServiceException {
95
96
		// initialize db connections to handle any update requests
97
		// deltaT = util.getProperty("replication.deltaT");
98
		// the default deltaT can be set from metacat.properties
99
		// create a thread to do the delta-T check but don't execute it yet
100
		replicationDaemon = new Timer(true);
101
		try {
102
			String replLogFile = PropertyService.getProperty("replication.logdir")
103
				+ FileUtil.getFS() + REPLICATION_LOG_FILE_NAME;
104
			METACAT_REPL_ERROR_MSG = "An error occurred in replication.  Please see the " +
105
				"replication log at: " + replLogFile;
106
107
			String timedRepIsOnStr =
108
				PropertyService.getProperty("replication.timedreplication");
109
			timedReplicationIsOn = (new Boolean(timedRepIsOnStr)).booleanValue();
110
			logReplication.info("ReplicationService.initialize - The timed replication on is" + timedReplicationIsOn);
111 522 berkley
112 5014 daigle
			String timeIntervalStr =
113
				PropertyService.getProperty("replication.timedreplicationinterval");
114
			timeInterval = (new Long(timeIntervalStr)).longValue();
115
			logReplication.info("ReplicationService.initialize - The timed replication time Interval is " + timeInterval);
116 2286 tao
117 5014 daigle
			String firstTimeStr =
118
				PropertyService.getProperty("replication.firsttimedreplication");
119
			logReplication.info("ReplicationService.initialize - first replication time form property is " + firstTimeStr);
120
			firstTime = ReplicationHandler.combinateCurrentDateAndGivenTime(firstTimeStr);
121 2286 tao
122 5014 daigle
			logReplication.info("ReplicationService.initialize - After combine current time, the real first time is "
123
					+ firstTime.toString() + " minisec");
124 2286 tao
125 5014 daigle
			// set up time replication if it is on
126
			if (timedReplicationIsOn) {
127
				replicationDaemon.scheduleAtFixedRate(new ReplicationHandler(),
128
						firstTime, timeInterval);
129
				logReplication.info("ReplicationService.initialize - deltaT handler started with rate="
130
						+ timeInterval + " mini seconds at " + firstTime.toString());
131
			}
132 2286 tao
133 5014 daigle
		} catch (PropertyNotFoundException pnfe) {
134
			throw new ServiceException(
135
					"ReplicationService.initialize - Property error while instantiating "
136
							+ "replication service: " + pnfe.getMessage());
137
		} catch (HandlerException he) {
138
			throw new ServiceException(
139
					"ReplicationService.initialize - Handler error while instantiating "
140
							+ "replication service" + he.getMessage());
141
		}
142
	}
143 2286 tao
144 5014 daigle
	/**
145
	 * Get the single instance of SessionService.
146
	 *
147
	 * @return the single instance of SessionService
148
	 */
149
	public static ReplicationService getInstance() throws ServiceException {
150
		if (replicationService == null) {
151
			replicationService = new ReplicationService();
152
		}
153
		return replicationService;
154
	}
155 2286 tao
156 5014 daigle
	public boolean refreshable() {
157
		return true;
158
	}
159 2286 tao
160 5014 daigle
	protected void doRefresh() throws ServiceException {
161
		return;
162
	}
163
164
	public void stop() throws ServiceException{
165
166
	}
167 840 bojilova
168 5014 daigle
	public void stopReplication() throws ServiceException {
169
	      //stop the replication server
170
	      replicationDaemon.cancel();
171
	      replicationDaemon = new Timer(true);
172
	      timedReplicationIsOn = false;
173
	      try {
174
	    	  PropertyService.setProperty("replication.timedreplication", (new Boolean(timedReplicationIsOn)).toString());
175
	      } catch (GeneralPropertyException gpe) {
176
	    	  logReplication.warn("ReplicationService.stopReplication - Could not set replication.timedreplication property: " + gpe.getMessage());
177
	      }
178 4080 daigle
179 5014 daigle
	      logReplication.info("ReplicationService.stopReplication - deltaT handler stopped");
180
		return;
181
	}
182
183
	protected void startReplication(Hashtable<String, String[]> params) throws ServiceException {
184 2286 tao
185 5014 daigle
	       String firstTimeStr = "";
186
	      //start the replication server
187
	       if ( params.containsKey("rate") ) {
188
	        timeInterval = new Long(
189
	               new String(((String[])params.get("rate"))[0])).longValue();
190
	        if(timeInterval < TIMEINTERVALLIMIT) {
191
	            //deltaT<30 is a timing mess!
192
	            timeInterval = TIMEINTERVALLIMIT;
193
	            throw new ServiceException("Replication deltaT rate cannot be less than "+
194
	                    TIMEINTERVALLIMIT + " millisecs and system automatically setup the rate to "+TIMEINTERVALLIMIT);
195
	        }
196
	      } else {
197
	        timeInterval = TIMEINTERVALLIMIT ;
198
	      }
199
	      logReplication.info("ReplicationService.startReplication - New rate is: " + timeInterval + " mini seconds.");
200
	      if ( params.containsKey("firsttime"))
201
	      {
202
	         firstTimeStr = ((String[])params.get("firsttime"))[0];
203
	         try
204
	         {
205
	           firstTime = ReplicationHandler.combinateCurrentDateAndGivenTime(firstTimeStr);
206
	           logReplication.info("ReplicationService.startReplication - The first time setting is "+firstTime.toString());
207
	         }
208
	         catch (HandlerException e)
209
	         {
210
	            throw new ServiceException(e.getMessage());
211
	         }
212
	         logReplication.warn("After combine current time, the real first time is "
213
	                                  +firstTime.toString()+" minisec");
214
	      }
215
	      else
216
	      {
217
	    	  logMetacat.error("ReplicationService.startReplication - " + ReplicationService.METACAT_REPL_ERROR_MSG);
218
	          logReplication.error("ReplicationService.startReplication - You should specify the first time " +
219
	                                  "to start a time replication");
220
	          return;
221
	      }
222
223
	      timedReplicationIsOn = true;
224
	      try {
225
	      // save settings to property file
226
	      PropertyService.setProperty(TIMEREPLICATION, (new Boolean(timedReplicationIsOn)).toString());
227
	      // note we couldn't use firstTime object because it has date info
228
	      // we only need time info such as 10:00 PM
229
	      PropertyService.setProperty(FIRSTTIME, firstTimeStr);
230
	      PropertyService.setProperty(TIMEREPLICATIONINTERVAl, (new Long(timeInterval)).toString());
231
	      } catch (GeneralPropertyException gpe) {
232
	    	  logReplication.warn("ReplicationService.startReplication - Could not set property: " + gpe.getMessage());
233
	      }
234
	      replicationDaemon.cancel();
235
	      replicationDaemon = new Timer(true);
236
	      replicationDaemon.scheduleAtFixedRate(new ReplicationHandler(), firstTime,
237
	                                            timeInterval);
238
239
	      logReplication.info("ReplicationService.startReplication - deltaT handler started with rate=" +
240
	                                    timeInterval + " milliseconds at " +firstTime.toString());
241 837 bojilova
242 5014 daigle
	}
243
244
	public void runOnce() throws ServiceException {
245
	      //updates this server exactly once
246
	      replicationDaemon.schedule(new ReplicationHandler(), 0);
247
	}
248 2286 tao
249 5014 daigle
	/**
250
	 * This method can add, delete and list the servers currently included in
251
	 * xml_replication.
252
	 * action           subaction            other needed params
253
	 * ---------------------------------------------------------
254
	 * servercontrol    add                  server
255
	 * servercontrol    delete               server
256
	 * servercontrol    list
257
	 */
258
	protected static void handleServerControlRequest(PrintWriter out,
259
			Hashtable<String, String[]> params, HttpServletResponse response) {
260
		String subaction = ((String[]) params.get("subaction"))[0];
261
		DBConnection dbConn = null;
262
		int serialNumber = -1;
263
		PreparedStatement pstmt = null;
264
		String replicate = null;
265
		String server = null;
266
		String dataReplicate = null;
267
		String hub = null;
268
		try {
269
			//conn = util.openDBConnection();
270
			dbConn = DBConnectionPool
271
					.getDBConnection("MetacatReplication.handleServerControlRequest");
272
			serialNumber = dbConn.getCheckOutSerialNumber();
273 837 bojilova
274 5014 daigle
			// add server to server list
275
			if (subaction.equals("add")) {
276
				replicate = ((String[]) params.get("replicate"))[0];
277
				server = ((String[]) params.get("server"))[0];
278 2286 tao
279 5014 daigle
				//Get data replication value
280
				dataReplicate = ((String[]) params.get("datareplicate"))[0];
281
				//Get hub value
282
				hub = ((String[]) params.get("hub"))[0];
283 837 bojilova
284 5319 jones
				String toDateSql = DatabaseService.getInstance().getDBAdapter().toDate("01/01/1980","MM/DD/YYYY");
285 5151 daigle
				String sql = "INSERT INTO xml_replication "
286 5014 daigle
						+ "(server, last_checked, replicate, datareplicate, hub) "
287 5151 daigle
						+ "VALUES (?," + toDateSql + ",?,?,?)";
288
289
				pstmt = dbConn.prepareStatement(sql);
290
291
				pstmt.setString(1, server);
292
				pstmt.setInt(2, Integer.parseInt(replicate));
293
				pstmt.setInt(3, Integer.parseInt(dataReplicate));
294
				pstmt.setInt(4, Integer.parseInt(hub));
295
296
				String sqlReport = "XMLAccessAccess.getXMLAccessForDoc - SQL: " + sql;
297
				sqlReport += " [" + server + "," + replicate +
298
					"," + dataReplicate + "," + hub + "]";
299
300
				logMetacat.info(sqlReport);
301
302 5014 daigle
				pstmt.execute();
303
				pstmt.close();
304
				dbConn.commit();
305
				out.println("Server " + server + " added");
306
				response.setContentType("text/html");
307
				out.println("<html><body><table border=\"1\">");
308
				out.println("<tr><td><b>server</b></td><td><b>last_checked</b></td><td>");
309
				out.println("<b>replicate</b></td>");
310
				out.println("<td><b>datareplicate</b></td>");
311
				out.println("<td><b>hub</b></td></tr>");
312
				pstmt = dbConn.prepareStatement("SELECT * FROM xml_replication");
313
				//increase dbconnection usage
314
				dbConn.increaseUsageCount(1);
315 2298 tao
316 5014 daigle
				pstmt.execute();
317
				ResultSet rs = pstmt.getResultSet();
318
				boolean tablehasrows = rs.next();
319
				while (tablehasrows) {
320
					out.println("<tr><td>" + rs.getString(2) + "</td><td>");
321
					out.println(rs.getString(3) + "</td><td>");
322
					out.println(rs.getString(4) + "</td><td>");
323
					out.println(rs.getString(5) + "</td><td>");
324
					out.println(rs.getString(6) + "</td></tr>");
325 837 bojilova
326 5014 daigle
					tablehasrows = rs.next();
327
				}
328
				out.println("</table></body></html>");
329 837 bojilova
330 5014 daigle
				// download certificate with the public key on this server
331
				// and import it as a trusted certificate
332
				String certURL = ((String[]) params.get("certificate"))[0];
333 5151 daigle
				if (certURL != null && !certURL.equals("")) {
334
					downloadCertificate(certURL);
335
				}
336 837 bojilova
337 5014 daigle
				// delete server from server list
338
			} else if (subaction.equals("delete")) {
339
				server = ((String[]) params.get("server"))[0];
340
				pstmt = dbConn.prepareStatement("DELETE FROM xml_replication "
341
						+ "WHERE server LIKE '" + server + "'");
342
				pstmt.execute();
343
				pstmt.close();
344
				dbConn.commit();
345
				out.println("Server " + server + " deleted");
346
				response.setContentType("text/html");
347
				out.println("<html><body><table border=\"1\">");
348
				out.println("<tr><td><b>server</b></td><td><b>last_checked</b></td><td>");
349
				out.println("<b>replicate</b></td>");
350
				out.println("<td><b>datareplicate</b></td>");
351
				out.println("<td><b>hub</b></td></tr>");
352 837 bojilova
353 5014 daigle
				pstmt = dbConn.prepareStatement("SELECT * FROM xml_replication");
354
				//increase dbconnection usage
355
				dbConn.increaseUsageCount(1);
356
				pstmt.execute();
357
				ResultSet rs = pstmt.getResultSet();
358
				boolean tablehasrows = rs.next();
359
				while (tablehasrows) {
360
					out.println("<tr><td>" + rs.getString(2) + "</td><td>");
361
					out.println(rs.getString(3) + "</td><td>");
362
					out.println(rs.getString(4) + "</td><td>");
363
					out.println(rs.getString(5) + "</td><td>");
364
					out.println(rs.getString(6) + "</td></tr>");
365
					tablehasrows = rs.next();
366
				}
367
				out.println("</table></body></html>");
368 837 bojilova
369 5014 daigle
				// list servers in server list
370
			} else if (subaction.equals("list")) {
371
				response.setContentType("text/html");
372
				out.println("<html><body><table border=\"1\">");
373
				out.println("<tr><td><b>server</b></td><td><b>last_checked</b></td><td>");
374
				out.println("<b>replicate</b></td>");
375
				out.println("<td><b>datareplicate</b></td>");
376
				out.println("<td><b>hub</b></td></tr>");
377
				pstmt = dbConn.prepareStatement("SELECT * FROM xml_replication");
378
				pstmt.execute();
379
				ResultSet rs = pstmt.getResultSet();
380
				boolean tablehasrows = rs.next();
381
				while (tablehasrows) {
382
					out.println("<tr><td>" + rs.getString(2) + "</td><td>");
383
					out.println(rs.getString(3) + "</td><td>");
384
					out.println(rs.getString(4) + "</td><td>");
385
					out.println(rs.getString(5) + "</td><td>");
386
					out.println(rs.getString(6) + "</td></tr>");
387
					tablehasrows = rs.next();
388
				}
389
				out.println("</table></body></html>");
390
			} else {
391 2286 tao
392 5014 daigle
				out.println("<error>Unkonwn subaction</error>");
393 2286 tao
394 5014 daigle
			}
395
			pstmt.close();
396
			//conn.close();
397 2286 tao
398 5014 daigle
		} catch (Exception e) {
399
			logMetacat.error("ReplicationService.handleServerControlRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);
400
			logReplication.error("ReplicationService.handleServerControlRequest - Error in "
401
					+ "MetacatReplication.handleServerControlRequest " + e.getMessage());
402
			e.printStackTrace(System.out);
403
		} finally {
404
			try {
405
				pstmt.close();
406
			}//try
407
			catch (SQLException ee) {
408
				logMetacat.error("ReplicationService.handleServerControlRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);
409
				logReplication.error("ReplicationService.handleServerControlRequest - Error in MetacatReplication.handleServerControlRequest to close pstmt "
410
						+ ee.getMessage());
411
			}//catch
412
			finally {
413
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
414
			}//finally
415
		}//finally
416 2286 tao
417 5014 daigle
	}
418 2286 tao
419 5014 daigle
	// download certificate with the public key from certURL and
420 4080 daigle
	// upload it onto this server; it then must be imported as a
421
	// trusted certificate
422 5014 daigle
	private static void downloadCertificate(String certURL) throws FileNotFoundException,
423 4080 daigle
			IOException, MalformedURLException, PropertyNotFoundException {
424 5014 daigle
425 4080 daigle
		// the path to be uploaded to
426 5014 daigle
		String certPath = SystemUtil.getContextDir();
427 2286 tao
428 4080 daigle
		// get filename from the URL of the certificate
429
		String filename = certURL;
430
		int slash = Math.max(filename.lastIndexOf('/'), filename.lastIndexOf('\\'));
431
		if (slash > -1) {
432
			filename = filename.substring(slash + 1);
433
		}
434 2286 tao
435 4080 daigle
		// open file output strem to write the input into it
436
		File f = new File(certPath, filename);
437
		synchronized (f) {
438
			try {
439
				if (f.exists()) {
440
					throw new IOException("File already exist: " + f.getCanonicalFile());
441
					// if ( f.exists() && !f.canWrite() ) {
442
					// throw new IOException("Not writable: " +
443
					// f.getCanonicalFile());
444
				}
445
			} catch (SecurityException se) {
446
				// if a security manager exists,
447
				// its checkRead method is called for f.exist()
448
				// or checkWrite method is called for f.canWrite()
449
				throw se;
450
			}
451 2286 tao
452 4080 daigle
			// create a buffered byte output stream
453
			// that uses a default-sized output buffer
454
			FileOutputStream fos = new FileOutputStream(f);
455
			BufferedOutputStream out = new BufferedOutputStream(fos);
456 840 bojilova
457 4080 daigle
			// this should be http url
458
			URL url = new URL(certURL);
459
			BufferedInputStream bis = null;
460
			try {
461
				bis = new BufferedInputStream(url.openStream());
462
				byte[] buf = new byte[4 * 1024]; // 4K buffer
463
				int b = bis.read(buf);
464
				while (b != -1) {
465
					out.write(buf, 0, b);
466
					b = bis.read(buf);
467
				}
468
			} finally {
469
				if (bis != null)
470
					bis.close();
471
			}
472
			// the input and the output streams must be closed
473
			bis.close();
474
			out.flush();
475
			out.close();
476
			fos.close();
477
		} // end of synchronized(f)
478
	}
479 2286 tao
480 5014 daigle
	/**
481 4080 daigle
	 * when a forcereplication request comes in, local host sends a read request
482
	 * to the requesting server (remote server) for the specified docid. Then
483
	 * store it in local database.
484
	 */
485 5014 daigle
	protected static void handleForceReplicateRequest(PrintWriter out,
486
			Hashtable<String, String[]> params, HttpServletResponse response,
487
			HttpServletRequest request) {
488
		String server = ((String[]) params.get("server"))[0]; // the server that
489
		String docid = ((String[]) params.get("docid"))[0]; // sent the document
490
		String dbaction = "UPDATE"; // the default action is UPDATE
491
		//    boolean override = false;
492
		//    int serverCode = 1;
493
		DBConnection dbConn = null;
494
		int serialNumber = -1;
495 5459 berkley
		String docName = null;
496 2286 tao
497 5014 daigle
		try {
498
			//if the url contains a dbaction then the default action is overridden
499
			if (params.containsKey("dbaction")) {
500
				dbaction = ((String[]) params.get("dbaction"))[0];
501
				//serverCode = MetacatReplication.getServerCode(server);
502
				//override = true; //we are now overriding the default action
503
			}
504
			logReplication.info("ReplicationService.handleForceReplicateRequest - Force replication request from: " + server);
505
			logReplication.info("ReplicationService.handleForceReplicateRequest - Force replication docid: " + docid);
506
			logReplication.info("ReplicationService.handleForceReplicateRequest - Force replication action: " + dbaction);
507
			// sending back read request to remote server
508
			URL u = new URL("https://" + server + "?server="
509
					+ MetacatUtil.getLocalReplicationServerName() + "&action=read&docid="
510
					+ docid);
511
			String xmldoc = ReplicationService.getURLContent(u);
512 2286 tao
513 5014 daigle
			// get the document info from server
514
			URL docinfourl = new URL("https://" + server + "?server="
515
					+ MetacatUtil.getLocalReplicationServerName()
516
					+ "&action=getdocumentinfo&docid=" + docid);
517 5440 berkley
518 2286 tao
519 5014 daigle
			String docInfoStr = ReplicationService.getURLContent(docinfourl);
520 2286 tao
521 5014 daigle
			//dih is the parser for the docinfo xml format
522
			DocInfoHandler dih = new DocInfoHandler();
523
			XMLReader docinfoParser = ReplicationHandler.initParser(dih);
524
			docinfoParser.parse(new InputSource(new StringReader(docInfoStr)));
525
			//      Hashtable<String,Vector<AccessControlForSingleFile>> docinfoHash = dih.getDocInfo();
526
			Hashtable<String, String> docinfoHash = dih.getDocInfo();
527 2286 tao
528 5014 daigle
			// Get user owner of this docid
529
			String user = (String) docinfoHash.get("user_owner");
530
			// Get home server of this docid
531
			String homeServer = (String) docinfoHash.get("home_server");
532 5322 berkley
			String guid = (String) docinfoHash.get("guid");
533 5440 berkley
			logReplication.info("XXXXXXXXXXXXXXXX GUID found in dociinfoHash: " + guid);
534 5324 berkley
535 5451 berkley
			logReplication.info("Processing guid " + guid +
536 5324 berkley
			  " information from handleForceReplicationRequest: " +
537
			  docinfoHash.toString());
538
      IdentifierManager idman = IdentifierManager.getInstance();
539 5455 berkley
      if(guid != null)
540 5324 berkley
      { //if the guid was passed in, put it in the identifiers table
541 5451 berkley
        logReplication.info("YYYYYYYYYYYYYY Creating guid/docid mapping for docid " +
542 5324 berkley
          docinfoHash.get("docid") + " and guid: " + guid);
543 5451 berkley
544 5459 berkley
        docName = (String) docinfoHash.get("docname");
545 5451 berkley
        logReplication.info("ZZZZZZZZZZZZ docName: " + docName);
546
        if(docName.trim().equals("systemMetadata"))
547
        {
548
            logReplication.info("creating mapping for systemMetadata: guid: " + guid + " localId: " + docinfoHash.get("docid"));
549
            idman.createSystemMetadataMapping(guid, docinfoHash.get("docid"));
550
        }
551
        else
552
        {
553
            logReplication.info("creating mapping: guid: " + guid + " localId: " + docinfoHash.get("docid"));
554
            idman.createMapping(guid, docinfoHash.get("docid"));
555
        }
556 5324 berkley
      }
557
      else
558
      {
559
        logReplication.debug("No guid information was included with the replicated document");
560
      }
561
562 5014 daigle
			String createdDate = (String) docinfoHash.get("date_created");
563
			String updatedDate = (String) docinfoHash.get("date_updated");
564
			logReplication.info("ReplicationService.handleForceReplicateRequest - homeServer: " + homeServer);
565
			// Get Document type
566
			String docType = (String) docinfoHash.get("doctype");
567
			logReplication.info("ReplicationService.handleForceReplicateRequest - docType: " + docType);
568
			String parserBase = null;
569
			// this for eml2 and we need user eml2 parser
570
			if (docType != null
571
					&& (docType.trim()).equals(DocumentImpl.EML2_0_0NAMESPACE)) {
572
				logReplication.warn("ReplicationService.handleForceReplicateRequest - This is an eml200 document!");
573
				parserBase = DocumentImpl.EML200;
574
			} else if (docType != null
575
					&& (docType.trim()).equals(DocumentImpl.EML2_0_1NAMESPACE)) {
576
				logReplication.warn("ReplicationService.handleForceReplicateRequest - This is an eml2.0.1 document!");
577
				parserBase = DocumentImpl.EML200;
578
			} else if (docType != null
579
					&& (docType.trim()).equals(DocumentImpl.EML2_1_0NAMESPACE)) {
580
				logReplication.warn("ReplicationService.handleForceReplicateRequest - This is an eml2.1.0 document!");
581
				parserBase = DocumentImpl.EML210;
582 5709 leinfelder
			} else if (docType != null
583
					&& (docType.trim()).equals(DocumentImpl.EML2_1_1NAMESPACE)) {
584
				logReplication.warn("ReplicationService.handleForceReplicateRequest - This is an eml2.1.1 document!");
585
				parserBase = DocumentImpl.EML210;
586 5014 daigle
			}
587
			logReplication.warn("ReplicationService.handleForceReplicateRequest - The parserBase is: " + parserBase);
588 2286 tao
589 5014 daigle
			// Get DBConnection from pool
590
			dbConn = DBConnectionPool
591
					.getDBConnection("MetacatReplication.handleForceReplicateRequest");
592
			serialNumber = dbConn.getCheckOutSerialNumber();
593
			// write the document to local database
594
			DocumentImplWrapper wrapper = new DocumentImplWrapper(parserBase, false);
595
			//try this independently so we can set
596 5195 daigle
//			Exception writeException = null;
597 5014 daigle
			try {
598 5195 daigle
				wrapper.writeReplication(dbConn, xmldoc, null, null,
599 5014 daigle
						dbaction, docid, user, null, homeServer, server, createdDate,
600
						updatedDate);
601 5195 daigle
			} finally {
602
//				writeException = e;
603 3230 tao
604 5195 daigle
				//process extra access rules before dealing with the write exception (doc exist already)
605
		        Vector<XMLAccessDAO> accessControlList = dih.getAccessControlList();
606
		        if (accessControlList != null) {
607
		        	AccessControlForSingleFile acfsf = new AccessControlForSingleFile(docid);
608
		        	for (XMLAccessDAO xmlAccessDAO : accessControlList) {
609
		        		if (!acfsf.accessControlExists(xmlAccessDAO)) {
610
		        			acfsf.insertPermissions(xmlAccessDAO);
611
							logReplication.info("ReplicationService.handleForceReplicateRequest - document " + docid
612
									+ " permissions added to DB");
613
		        		}
614
		            }
615
		        }
616
//				if (accessControlList != null) {
617
//					for (int i = 0; i < accessControlList.size(); i++) {
618
//						AccessControlForSingleFile acfsf = (AccessControlForSingleFile) accessControlList
619
//								.get(i);
620
//						if (!acfsf.accessControlExists()) {
621
//							acfsf.insertPermissions();
622
//							logReplication.info("ReplicationService.handleForceReplicateRequest - document " + docid
623
//									+ " permissions added to DB");
624
//						}
625 5098 daigle
//					}
626
//				}
627 2286 tao
628 5195 daigle
//				if (writeException != null) {
629
//					throw writeException;
630
//				}
631
632
				logReplication.info("ReplicationService.handleForceReplicateRequest - document " + docid + " added to DB with "
633
						+ "action " + dbaction);
634 5458 berkley
635
				if(guid != null)
636
                {
637 5459 berkley
                    if(!docName.trim().equals("systemMetadata"))
638
                    {
639
                        logReplication.info("replicate D1GUID:" + guid + ":D1SCIMETADATA:" +
640
                                docid + ":");
641
                    }
642
                    else
643
                    {
644
                        logReplication.info("replicate D1GUID:" + guid + ":D1SYSMETADATA:" +
645
                                docid + ":");
646
                    }
647 5458 berkley
                }
648 5195 daigle
				EventLog.getInstance().log(request.getRemoteAddr(), REPLICATIONUSER, docid,
649
						dbaction);
650 5014 daigle
			}
651 5195 daigle
		} catch (SQLException sqle) {
652 5014 daigle
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);
653 5195 daigle
			logReplication.error("ReplicationService.handleForceReplicateRequest - SQL error when adding doc " + docid +
654
					" to DB with action " + dbaction + ": " + sqle.getMessage());
655
		} catch (MalformedURLException mue) {
656
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);
657
			logReplication.error("ReplicationService.handleForceReplicateRequest - URL error when adding doc " + docid +
658
					" to DB with action " + dbaction + ": " + mue.getMessage());
659
		} catch (SAXException se) {
660
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);
661
			logReplication.error("ReplicationService.handleForceReplicateRequest - SAX parsing error when adding doc " + docid +
662
					" to DB with action " + dbaction + ": " + se.getMessage());
663
		} catch (HandlerException he) {
664
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);
665
			logReplication.error("ReplicationService.handleForceReplicateRequest - Handler error when adding doc " + docid +
666
					" to DB with action " + dbaction + ": " + he.getMessage());
667
		} catch (IOException ioe) {
668
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);
669
			logReplication.error("ReplicationService.handleForceReplicateRequest - I/O error when adding doc " + docid +
670
					" to DB with action " + dbaction + ": " + ioe.getMessage());
671
		} catch (PermOrderException poe) {
672
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);
673
			logReplication.error("ReplicationService.handleForceReplicateRequest - Permissions order error when adding doc " + docid +
674
					" to DB with action " + dbaction + ": " + poe.getMessage());
675
		} catch (AccessControlException ace) {
676
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);
677
			logReplication.error("ReplicationService.handleForceReplicateRequest - Permissions order error when adding doc " + docid +
678
					" to DB with action " + dbaction + ": " + ace.getMessage());
679
		} catch (Exception e) {
680
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);
681
			logReplication.error("ReplicationService.handleForceReplicateRequest - General error when adding doc " + docid +
682
					" to DB with action " + dbaction + ": " + e.getMessage());
683
		} finally {
684 5014 daigle
			// Return the checked out DBConnection
685
			DBConnectionPool.returnDBConnection(dbConn, serialNumber);
686
		}//finally
687
	}
688 2298 tao
689 5014 daigle
	/*
690
	 * when a forcereplication delete request comes in, local host will delete this
691
	 * document
692
	 */
693
	protected static void handleForceReplicateDeleteRequest(PrintWriter out,
694
			Hashtable<String, String[]> params, HttpServletResponse response,
695
			HttpServletRequest request) {
696
		String server = ((String[]) params.get("server"))[0]; // the server that
697
		String docid = ((String[]) params.get("docid"))[0]; // sent the document
698
		try {
699
			logReplication.info("ReplicationService.handleForceReplicateDeleteRequest - force replication delete request from " + server);
700
			logReplication.info("ReplicationService.handleForceReplicateDeleteRequest - force replication delete docid " + docid);
701
			logReplication.info("ReplicationService.handleForceReplicateDeleteRequest - Force replication delete request from: " + server);
702
			logReplication.info("ReplicationService.handleForceReplicateDeleteRequest - Force replication delete docid: " + docid);
703
			DocumentImpl.delete(docid, null, null, server);
704
			logReplication.info("ReplicationService.handleForceReplicateDeleteRequest - document " + docid + " was successfully deleted ");
705
			EventLog.getInstance().log(request.getRemoteAddr(), REPLICATIONUSER, docid,
706
					"delete");
707
			logReplication.info("ReplicationService.handleForceReplicateDeleteRequest - document " + docid + " was successfully deleted ");
708
		} catch (Exception e) {
709
			logMetacat.error("ReplicationService.handleForceReplicateDeleteRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);
710
			logReplication.error("document " + docid
711
					+ " failed to delete because " + e.getMessage());
712
			logReplication.error("ReplicationService.handleForceReplicateDeleteRequest - error: " + e.getMessage());
713 2298 tao
714 5014 daigle
		}//catch
715 2298 tao
716 5014 daigle
	}
717 2286 tao
718 5014 daigle
	/**
719
	 * when a forcereplication data file request comes in, local host sends a
720
	 * readdata request to the requesting server (remote server) for the specified
721
	 * docid. Then store it in local database and file system
722
	 */
723
	protected static void handleForceReplicateDataFileRequest(Hashtable<String, String[]> params,
724
			HttpServletRequest request) {
725 2286 tao
726 5014 daigle
		//make sure there is some parameters
727
		if (params.isEmpty()) {
728
			return;
729
		}
730
		// Get remote server
731
		String server = ((String[]) params.get("server"))[0];
732
		// the docid should include rev number
733
		String docid = ((String[]) params.get("docid"))[0];
734
		// Make sure there is a docid and server
735
		if (docid == null || server == null || server.equals("")) {
736
			logMetacat.error("ReplicationService.handleForceReplicateDataFileRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);
737
			logReplication.error("ReplicationService.handleForceReplicateDataFileRequest - Didn't specify docid or server for replication");
738
			return;
739
		}
740 2286 tao
741 5014 daigle
		// Overide or not
742
		//    boolean override = false;
743
		// dbaction - update or insert
744
		String dbaction = null;
745 2286 tao
746 5014 daigle
		try {
747
			//docid was switch to two parts uinque code and rev
748
			//String uniqueCode=MetacatUtil.getDocIdFromString(docid);
749
			//int rev=MetacatUtil.getVersionFromString(docid);
750
			if (params.containsKey("dbaction")) {
751
				dbaction = ((String[]) params.get("dbaction"))[0];
752
			} else//default value is update
753
			{
754
				dbaction = "update";
755
			}
756 2286 tao
757 5014 daigle
			logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - force replication request from " + server);
758
			logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - Force replication request from: " + server);
759
			logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - Force replication docid: " + docid);
760
			logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - Force replication action: " + dbaction);
761
			// get the document info from server
762
			URL docinfourl = new URL("https://" + server + "?server="
763
					+ MetacatUtil.getLocalReplicationServerName()
764
					+ "&action=getdocumentinfo&docid=" + docid);
765 1023 tao
766 5014 daigle
			String docInfoStr = ReplicationService.getURLContent(docinfourl);
767 2286 tao
768 5014 daigle
			//dih is the parser for the docinfo xml format
769
			DocInfoHandler dih = new DocInfoHandler();
770
			XMLReader docinfoParser = ReplicationHandler.initParser(dih);
771
			docinfoParser.parse(new InputSource(new StringReader(docInfoStr)));
772
			Hashtable<String, String> docinfoHash = dih.getDocInfo();
773
			String user = (String) docinfoHash.get("user_owner");
774 2286 tao
775 5014 daigle
			String docName = (String) docinfoHash.get("docname");
776 2286 tao
777 5014 daigle
			String docType = (String) docinfoHash.get("doctype");
778 2286 tao
779 5014 daigle
			String docHomeServer = (String) docinfoHash.get("home_server");
780 2286 tao
781 5014 daigle
			String createdDate = (String) docinfoHash.get("date_created");
782 2286 tao
783 5014 daigle
			String updatedDate = (String) docinfoHash.get("date_updated");
784
			logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - docHomeServer of datafile: " + docHomeServer);
785
786
			//if action is delete, we don't delete the data file. Just archieve
787
			//the xml_documents
788
			/*if (dbaction.equals("delete"))
789
			{
790
			  //conn = util.getConnection();
791
			  DocumentImpl.delete(docid,user,null);
792
			  //util.returnConnection(conn);
793
			}*/
794
			//To data file insert or update is same
795
			if (dbaction.equals("insert") || dbaction.equals("update")) {
796
				//Get data file and store it into local file system.
797
				// sending back readdata request to server
798
				URL url = new URL("https://" + server + "?server="
799
						+ MetacatUtil.getLocalReplicationServerName()
800
						+ "&action=readdata&docid=" + docid);
801
				String datafilePath = PropertyService
802
						.getProperty("application.datafilepath");
803
804
				Exception writeException = null;
805
				//register data file into xml_documents table and wite data file
806
				//into file system
807
				try {
808
					DocumentImpl.writeDataFileInReplication(url.openStream(),
809
							datafilePath, docName, docType, docid, user, docHomeServer,
810
							server, DocumentImpl.DOCUMENTTABLE, false, createdDate,
811
							updatedDate);
812
				} catch (Exception e) {
813
					writeException = e;
814
				}
815
				//process extra access rules
816 5098 daigle
//				Vector<AccessControlForSingleFile> accessControlList = dih
817
//						.getAccessControlList();
818
//				if (accessControlList != null) {
819
//					for (int i = 0; i < accessControlList.size(); i++) {
820
//						AccessControlForSingleFile acfsf = (AccessControlForSingleFile) accessControlList
821
//								.get(i);
822
//						if (!acfsf.accessControlExists()) {
823
//							acfsf.insertPermissions();
824
//							logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - datafile " + docid
825
//									+ " permissions added to DB");
826
//						}
827
//					}
828
//				}
829
830
		        Vector<XMLAccessDAO> accessControlList = dih.getAccessControlList();
831
		        if (accessControlList != null) {
832
		        	AccessControlForSingleFile acfsf = new AccessControlForSingleFile(docid);
833
		        	for (XMLAccessDAO xmlAccessDAO : accessControlList) {
834
		        		if (!acfsf.accessControlExists(xmlAccessDAO)) {
835
		        			acfsf.insertPermissions(xmlAccessDAO);
836
							logReplication.info("ReplicationService.handleForceReplicateRequest - document " + docid
837 5014 daigle
									+ " permissions added to DB");
838 5098 daigle
		        		}
839
		            }
840
		        }
841 5014 daigle
842
				if (writeException != null) {
843
					throw writeException;
844
				}
845
846
				//false means non-timed replication
847
				logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - datafile " + docid + " added to DB with "
848
						+ "action " + dbaction);
849
				EventLog.getInstance().log(request.getRemoteAddr(), REPLICATIONUSER,
850
						docid, dbaction);
851
			}
852
853
		} catch (Exception e) {
854
			logMetacat.error("ReplicationService.handleForceReplicateDataFileRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);
855
			logReplication.error("ReplicationService.handleForceReplicateDataFileRequest - Datafile " + docid
856
					+ " failed to added to DB with " + "action " + dbaction + " because "
857
					+ e.getMessage());
858
			logReplication.error("ReplicationService.handleForceReplicateDataFileRequest - ERROR in MetacatReplication.handleForceDataFileReplicate"
859
					+ "Request(): " + e.getMessage());
860 4449 leinfelder
		}
861 5014 daigle
	}
862 2286 tao
863 5014 daigle
	/**
864
	 * Grants or denies a lock to a requesting host.
865
	 * The servlet parameters of interrest are:
866
	 * docid: the docid of the file the lock is being requested for
867
	 * currentdate: the timestamp of the document on the remote server
868
	 *
869
	 */
870
	protected static void handleGetLockRequest(PrintWriter out,
871
			Hashtable<String, String[]> params, HttpServletResponse response) {
872 1292 tao
873 5014 daigle
		try {
874 2286 tao
875 5014 daigle
			String docid = ((String[]) params.get("docid"))[0];
876
			String remoteRev = ((String[]) params.get("updaterev"))[0];
877
			DocumentImpl requestDoc = new DocumentImpl(docid);
878
			logReplication.info("ReplicationService.handleGetLockRequest - lock request for " + docid);
879
			int localRevInt = requestDoc.getRev();
880
			int remoteRevInt = Integer.parseInt(remoteRev);
881 2286 tao
882 5014 daigle
			if (remoteRevInt >= localRevInt) {
883
				if (!fileLocks.contains(docid)) { //grant the lock if it is not already locked
884
					fileLocks.add(0, docid); //insert at the beginning of the queue Vector
885
					//send a message back to the the remote host authorizing the insert
886
					out
887
							.println("<lockgranted><docid>" + docid
888
									+ "</docid></lockgranted>");
889
					//          lockThread = new Thread(this);
890
					//          lockThread.setPriority(Thread.MIN_PRIORITY);
891
					//          lockThread.start();
892
					logReplication.info("ReplicationService.handleGetLockRequest - lock granted for " + docid);
893
				} else { //deny the lock
894
					out.println("<filelocked><docid>" + docid + "</docid></filelocked>");
895
					logReplication.info("ReplicationService.handleGetLockRequest - lock denied for " + docid
896
							+ "reason: file already locked");
897
				}
898
			} else {//deny the lock.
899
				out.println("<outdatedfile><docid>" + docid + "</docid></filelocked>");
900
				logReplication.info("ReplicationService.handleGetLockRequest - lock denied for " + docid
901
						+ "reason: client has outdated file");
902
			}
903
			//conn.close();
904
		} catch (Exception e) {
905
			logMetacat.error("ReplicationService.handleGetLockRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);
906
			logReplication.error("ReplicationService.handleGetLockRequest - error requesting file lock from MetacatReplication."
907
					+ "handleGetLockRequest: " + e.getMessage());
908
			e.printStackTrace(System.out);
909
		}
910
	}
911 2286 tao
912 5014 daigle
	/**
913
	 * Sends all of the xml_documents information encoded in xml to a requestor
914
	 * the format is:
915
	 * <!ELEMENT documentinfo (docid, docname, doctype, doctitle, user_owner,
916
	 *                  user_updated, home_server, public_access, rev)/>
917
	 * all of the subelements of document info are #PCDATA
918
	 */
919
	protected static void handleGetDocumentInfoRequest(PrintWriter out,
920
			Hashtable<String, String[]> params, HttpServletResponse response) {
921
		String docid = ((String[]) (params.get("docid")))[0];
922
		StringBuffer sb = new StringBuffer();
923 2286 tao
924 5014 daigle
		try {
925 5322 berkley
		  IdentifierManager idman = IdentifierManager.getInstance();
926 2286 tao
927 5014 daigle
			DocumentImpl doc = new DocumentImpl(docid);
928
			sb.append("<documentinfo><docid>").append(docid);
929 5322 berkley
			sb.append("</docid>");
930
			try
931
			{
932 5323 berkley
			  String guid = idman.getGUID(doc.getDocID(), doc.getRev());
933
			  sb.append("<guid>").append(guid).append("</guid>");
934 5454 berkley
			  String smLocalId = idman.getSystemMetadataLocalId(guid);
935
			  if(smLocalId != null && !smLocalId.trim().equals(""))
936
			  {
937
			      sb.append("<systemmetadatalocalid>").append(smLocalId).append("</systemmetadatalocalid>");
938
			  }
939 5322 berkley
			}
940
			catch(McdbDocNotFoundException e)
941
			{
942
			  //do nothing, there was no guid for this document
943
			}
944
			sb.append("<docname>").append(doc.getDocname());
945 5014 daigle
			sb.append("</docname><doctype>").append(doc.getDoctype());
946
			sb.append("</doctype>");
947
			sb.append("<user_owner>").append(doc.getUserowner());
948
			sb.append("</user_owner><user_updated>").append(doc.getUserupdated());
949
			sb.append("</user_updated>");
950
			sb.append("<date_created>");
951
			sb.append(doc.getCreateDate());
952
			sb.append("</date_created>");
953
			sb.append("<date_updated>");
954
			sb.append(doc.getUpdateDate());
955
			sb.append("</date_updated>");
956
			sb.append("<home_server>");
957
			sb.append(doc.getDocHomeServer());
958
			sb.append("</home_server>");
959
			sb.append("<public_access>").append(doc.getPublicaccess());
960
			sb.append("</public_access><rev>").append(doc.getRev());
961
			sb.append("</rev>");
962 2286 tao
963 5014 daigle
			sb.append("<accessControl>");
964 5098 daigle
965
			AccessControlForSingleFile acfsf = new AccessControlForSingleFile(docid);
966
			sb.append(acfsf.getAccessString());
967
968 5014 daigle
			sb.append("</accessControl>");
969 2286 tao
970 5014 daigle
			sb.append("</documentinfo>");
971
			response.setContentType("text/xml");
972
			out.println(sb.toString());
973 2286 tao
974 5014 daigle
		} catch (Exception e) {
975
			logMetacat.error("ReplicationService.handleGetDocumentInfoRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);
976
			logReplication.error("ReplicationService.handleGetDocumentInfoRequest - error in metacatReplication.handlegetdocumentinforequest "
977
					+ "for doc: " + docid + " : " + e.getMessage());
978
		}
979 2286 tao
980 5014 daigle
	}
981 2286 tao
982 5014 daigle
	/**
983
	 * Sends a datafile to a remote host
984
	 */
985
	protected static void handleGetDataFileRequest(OutputStream outPut,
986
			Hashtable<String, String[]> params, HttpServletResponse response)
987 2286 tao
988 5014 daigle
	{
989
		// File path for data file
990
		String filepath;
991
		// Request docid
992
		String docId = ((String[]) (params.get("docid")))[0];
993
		//check if the doicd is null
994
		if (docId == null) {
995
			logMetacat.error("ReplicationService.handleGetDataFileRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);
996
			logReplication.error("ReplicationService.handleGetDataFileRequest - Didn't specify docid for replication");
997
			return;
998
		}
999 2286 tao
1000 5014 daigle
		//try to open a https stream to test if the request server's public key
1001
		//in the key store, this is security issue
1002
		try {
1003
			filepath = PropertyService.getProperty("application.datafilepath");
1004
			String server = params.get("server")[0];
1005
			URL u = new URL("https://" + server + "?server="
1006
					+ MetacatUtil.getLocalReplicationServerName() + "&action=test");
1007
			String test = ReplicationService.getURLContent(u);
1008
			//couldn't pass the test
1009
			if (test.indexOf("successfully") == -1) {
1010
				//response.setContentType("text/xml");
1011
				//outPut.println("<error>Couldn't pass the trust test</error>");
1012
				logMetacat.error("ReplicationService.handleGetDataFileRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);
1013
				logReplication.error("ReplicationService.handleGetDataFileRequest - Couldn't pass the trust test");
1014
				return;
1015
			}
1016
		}//try
1017
		catch (Exception ee) {
1018
			return;
1019
		}//catch
1020 2286 tao
1021 5014 daigle
		if (!filepath.endsWith("/")) {
1022
			filepath += "/";
1023
		}
1024
		// Get file aboslute file name
1025
		String filename = filepath + docId;
1026 2286 tao
1027 5014 daigle
		//MIME type
1028
		String contentType = null;
1029
		if (filename.endsWith(".xml")) {
1030
			contentType = "text/xml";
1031
		} else if (filename.endsWith(".css")) {
1032
			contentType = "text/css";
1033
		} else if (filename.endsWith(".dtd")) {
1034
			contentType = "text/plain";
1035
		} else if (filename.endsWith(".xsd")) {
1036
			contentType = "text/xml";
1037
		} else if (filename.endsWith("/")) {
1038
			contentType = "text/html";
1039
		} else {
1040
			File f = new File(filename);
1041
			if (f.isDirectory()) {
1042
				contentType = "text/html";
1043
			} else {
1044
				contentType = "application/octet-stream";
1045
			}
1046
		}
1047 2286 tao
1048 5014 daigle
		// Set the mime type
1049
		response.setContentType(contentType);
1050 2286 tao
1051 5014 daigle
		// Get the content of the file
1052
		FileInputStream fin = null;
1053
		try {
1054
			// FileInputStream to metacat
1055
			fin = new FileInputStream(filename);
1056
			// 4K buffer
1057
			byte[] buf = new byte[4 * 1024];
1058
			// Read data from file input stream to byte array
1059
			int b = fin.read(buf);
1060
			// Write to outStream from byte array
1061
			while (b != -1) {
1062
				outPut.write(buf, 0, b);
1063
				b = fin.read(buf);
1064
			}
1065
			// close file input stream
1066
			fin.close();
1067 2286 tao
1068 5014 daigle
		}//try
1069
		catch (Exception e) {
1070
			logMetacat.error("ReplicationService.handleGetDataFileRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);
1071
			logReplication.error("ReplicationService.handleGetDataFileRequest - error getting data file from MetacatReplication."
1072
					+ "handlGetDataFileRequest " + e.getMessage());
1073
			e.printStackTrace(System.out);
1074
		}//catch
1075 2286 tao
1076 5014 daigle
	}
1077
1078
	/**
1079 4854 daigle
	 * Sends a document to a remote host
1080
	 */
1081 5014 daigle
	protected static void handleGetDocumentRequest(PrintWriter out,
1082 4854 daigle
			Hashtable<String, String[]> params, HttpServletResponse response) {
1083 2286 tao
1084 4854 daigle
		String urlString = null;
1085
		String documentPath = null;
1086
		try {
1087
			// try to open a https stream to test if the request server's public
1088
			// key
1089
			// in the key store, this is security issue
1090
			String server = params.get("server")[0];
1091
			urlString = "https://" + server + "?server="
1092
					+ MetacatUtil.getLocalReplicationServerName() + "&action=test";
1093
			URL u = new URL(urlString);
1094 5014 daigle
			String test = ReplicationService.getURLContent(u);
1095 4854 daigle
			// couldn't pass the test
1096
			if (test.indexOf("successfully") == -1) {
1097
				response.setContentType("text/xml");
1098
				out.println("<error>Couldn't pass the trust test " + test + " </error>");
1099
				out.close();
1100
				return;
1101
			}
1102 2286 tao
1103 4854 daigle
			String docid = params.get("docid")[0];
1104 5014 daigle
			logReplication.debug("ReplicationService.handleGetDocumentRequest - MetacatReplication.handleGetDocumentRequest for docid: "
1105
					+ docid);
1106 4854 daigle
			DocumentImpl di = new DocumentImpl(docid);
1107 2286 tao
1108 5014 daigle
			String documentDir = PropertyService
1109
					.getProperty("application.documentfilepath");
1110 4854 daigle
			documentPath = documentDir + FileUtil.getFS() + docid;
1111 4488 daigle
1112 4854 daigle
			// if the document does not exist on disk, read it from db and write
1113
			// it to disk.
1114
			if (FileUtil.getFileStatus(documentPath) == FileUtil.DOES_NOT_EXIST
1115
					|| FileUtil.getFileSize(documentPath) == 0) {
1116
				FileWriter fileWriter = new FileWriter(documentPath);
1117 4861 daigle
				di.toXml(fileWriter, null, null, true);
1118 4854 daigle
			}
1119 2286 tao
1120 4854 daigle
			// read the file from disk and sent it to PrintWriter
1121
			// PrintWriter out = new PrintWriter(streamOut);
1122 4861 daigle
			di.readFromFileSystem(out, null, null, documentPath);
1123 2286 tao
1124 4854 daigle
			// response.setContentType("text/xml");
1125
			// out.print(di.toString(null, null, true));
1126 2286 tao
1127 5014 daigle
			logReplication.info("ReplicationService.handleGetDocumentRequest - document " + docid + " sent");
1128 4854 daigle
1129
		} catch (MalformedURLException mue) {
1130 5014 daigle
			logMetacat.error("ReplicationService.handleGetDocumentRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);
1131
			logReplication.error("ReplicationService.handleGetDocumentRequest - Url error when getting document from MetacatReplication."
1132 4854 daigle
					+ "handlGetDocumentRequest for url: " + urlString + " : "
1133
					+ mue.getMessage());
1134
			// e.printStackTrace(System.out);
1135
			response.setContentType("text/xml");
1136
			out.println("<error>" + mue.getMessage() + "</error>");
1137
		} catch (IOException ioe) {
1138 5014 daigle
			logMetacat.error("ReplicationService.handleGetDocumentRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);
1139
			logReplication.error("ReplicationService.handleGetDocumentRequest - I/O error when getting document from MetacatReplication."
1140
					+ "handlGetDocumentRequest for file: " + documentPath + " : "
1141
					+ ioe.getMessage());
1142 4854 daigle
			// e.printStackTrace(System.out);
1143
			response.setContentType("text/xml");
1144
			out.println("<error>" + ioe.getMessage() + "</error>");
1145
		} catch (PropertyNotFoundException pnfe) {
1146 5014 daigle
			logMetacat.error("ReplicationService.handleGetDocumentRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);
1147
			logReplication
1148
					.error("ReplicationService.handleGetDocumentRequest - Error getting property when getting document from MetacatReplication."
1149
							+ "handlGetDocumentRequest for file: "
1150
							+ documentPath
1151
							+ " : "
1152
							+ pnfe.getMessage());
1153 4854 daigle
			// e.printStackTrace(System.out);
1154
			response.setContentType("text/xml");
1155
			out.println("<error>" + pnfe.getMessage() + "</error>");
1156
		} catch (McdbException me) {
1157 5014 daigle
			logReplication
1158
					.error("ReplicationService.handleGetDocumentRequest - Document implementation error  getting property when getting document from MetacatReplication."
1159
							+ "handlGetDocumentRequest for file: "
1160
							+ documentPath
1161
							+ " : "
1162
							+ me.getMessage());
1163 4854 daigle
			// e.printStackTrace(System.out);
1164
			response.setContentType("text/xml");
1165
			out.println("<error>" + me.getMessage() + "</error>");
1166
		}
1167
1168
	}
1169
1170 5014 daigle
	/**
1171 4854 daigle
	 * Sends a list of all of the documents on this sever along with their
1172
	 * revision numbers. The format is: <!ELEMENT replication (server, updates)>
1173
	 * <!ELEMENT server (#PCDATA)> <!ELEMENT updates ((updatedDocument |
1174
	 * deleteDocument | revisionDocument)*)> <!ELEMENT updatedDocument (docid,
1175
	 * rev, datafile*)> <!ELEMENT deletedDocument (docid, rev)> <!ELEMENT
1176
	 * revisionDocument (docid, rev, datafile*)> <!ELEMENT docid (#PCDATA)>
1177
	 * <!ELEMENT rev (#PCDATA)> <!ELEMENT datafile (#PCDATA)> note that the rev
1178
	 * in deletedDocument is always empty. I just left it in there to make the
1179
	 * parser implementation easier.
1180
	 */
1181 5014 daigle
	protected static void handleUpdateRequest(PrintWriter out, Hashtable<String, String[]> params,
1182
			HttpServletResponse response) {
1183
		// Checked out DBConnection
1184
		DBConnection dbConn = null;
1185
		// DBConenction serial number when checked it out
1186
		int serialNumber = -1;
1187
		PreparedStatement pstmt = null;
1188
		// Server list to store server info of xml_replication table
1189
		ReplicationServerList serverList = null;
1190 2286 tao
1191 5014 daigle
		try {
1192
			// Check out a DBConnection from pool
1193
			dbConn = DBConnectionPool
1194
					.getDBConnection("MetacatReplication.handleUpdateRequest");
1195
			serialNumber = dbConn.getCheckOutSerialNumber();
1196
			// Create a server list from xml_replication table
1197
			serverList = new ReplicationServerList();
1198 2286 tao
1199 5014 daigle
			// Get remote server name from param
1200
			String server = ((String[]) params.get("server"))[0];
1201
			// If no servr name in param, return a error
1202
			if (server == null || server.equals("")) {
1203
				response.setContentType("text/xml");
1204
				out.println("<error>Request didn't specify server name</error>");
1205
				out.close();
1206
				return;
1207
			}//if
1208 2286 tao
1209 5014 daigle
			//try to open a https stream to test if the request server's public key
1210
			//in the key store, this is security issue
1211 5440 berkley
			String testUrl = "https://" + server + "?server="
1212 5441 berkley
            + MetacatUtil.getLocalReplicationServerName() + "&action=test";
1213 5440 berkley
			logReplication.info("Running trust test: " + testUrl);
1214
			URL u = new URL(testUrl);
1215 5014 daigle
			String test = ReplicationService.getURLContent(u);
1216 5441 berkley
			logReplication.info("Ouput from test is '" + test + "'");
1217 5014 daigle
			//couldn't pass the test
1218
			if (test.indexOf("successfully") == -1) {
1219 5441 berkley
			    logReplication.error("Trust test failed.");
1220 5014 daigle
				response.setContentType("text/xml");
1221
				out.println("<error>Couldn't pass the trust test</error>");
1222
				out.close();
1223
				return;
1224
			}
1225 5441 berkley
			logReplication.info("Trust test succeeded.");
1226 2286 tao
1227 5014 daigle
			// Check if local host configure to replicate xml documents to remote
1228
			// server. If not send back a error message
1229
			if (!serverList.getReplicationValue(server)) {
1230
				response.setContentType("text/xml");
1231
				out
1232
						.println("<error>Configuration not allow to replicate document to you</error>");
1233
				out.close();
1234
				return;
1235
			}//if
1236 2286 tao
1237 5014 daigle
			// Store the sql command
1238
			StringBuffer docsql = new StringBuffer();
1239
			StringBuffer revisionSql = new StringBuffer();
1240
			// Stroe the docid list
1241
			StringBuffer doclist = new StringBuffer();
1242
			// Store the deleted docid list
1243
			StringBuffer delsql = new StringBuffer();
1244
			// Store the data set file
1245
			Vector<Vector<String>> packageFiles = new Vector<Vector<String>>();
1246 2286 tao
1247 5014 daigle
			// Append local server's name and replication servlet to doclist
1248
			doclist.append("<?xml version=\"1.0\"?><replication>");
1249
			doclist.append("<server>")
1250
					.append(MetacatUtil.getLocalReplicationServerName());
1251
			//doclist.append(util.getProperty("replicationpath"));
1252
			doclist.append("</server><updates>");
1253 2286 tao
1254 5014 daigle
			// Get correct docid that reside on this server according the requesting
1255
			// server's replicate and data replicate value in xml_replication table
1256 5319 jones
			docsql.append(DatabaseService.getInstance().getDBAdapter().getReplicationDocumentListSQL());
1257 5014 daigle
			//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)) ");
1258
			revisionSql.append("select docid, rev, doctype from xml_revisions ");
1259
			// If the localhost is not a hub to the remote server, only replicate
1260
			// the docid' which home server is local host (server_location =1)
1261
			if (!serverList.getHubValue(server)) {
1262
				String serverLocationDoc = " and a.server_location = 1";
1263
				String serverLocationRev = "where server_location = 1";
1264
				docsql.append(serverLocationDoc);
1265
				revisionSql.append(serverLocationRev);
1266
			}
1267
			logReplication.info("ReplicationService.handleUpdateRequest - Doc sql: " + docsql.toString());
1268 2286 tao
1269 5014 daigle
			// Get any deleted documents
1270
			delsql.append("select distinct docid from ");
1271
			delsql.append("xml_revisions where docid not in (select docid from ");
1272
			delsql.append("xml_documents) ");
1273
			// If the localhost is not a hub to the remote server, only replicate
1274
			// the docid' which home server is local host (server_location =1)
1275
			if (!serverList.getHubValue(server)) {
1276
				delsql.append("and server_location = 1");
1277
			}
1278
			logReplication.info("ReplicationService.handleUpdateRequest - Deleted sql: " + delsql.toString());
1279 2286 tao
1280 5014 daigle
			// Get docid list of local host
1281
			pstmt = dbConn.prepareStatement(docsql.toString());
1282
			pstmt.execute();
1283
			ResultSet rs = pstmt.getResultSet();
1284
			boolean tablehasrows = rs.next();
1285
			//If metacat configed to replicate data file
1286
			//if ((util.getProperty("replicationsenddata")).equals("on"))
1287
			boolean replicateData = serverList.getDataReplicationValue(server);
1288
			if (replicateData) {
1289
				while (tablehasrows) {
1290
					String recordDoctype = rs.getString(3);
1291
					Vector<String> packagedoctypes = MetacatUtil
1292
							.getOptionList(PropertyService
1293
									.getProperty("xml.packagedoctype"));
1294
					//if this is a package file, put it at the end
1295
					//because if a package file is read before all of the files it
1296
					//refers to are loaded then there is an error
1297
					if (recordDoctype != null && !packagedoctypes.contains(recordDoctype)) {
1298
						//If this is not data file
1299
						if (!recordDoctype.equals("BIN")) {
1300
							//for non-data file document
1301
							doclist.append("<updatedDocument>");
1302
							doclist.append("<docid>").append(rs.getString(1));
1303
							doclist.append("</docid><rev>").append(rs.getInt(2));
1304
							doclist.append("</rev>");
1305
							doclist.append("</updatedDocument>");
1306
						}//if
1307
						else {
1308
							//for data file document, in datafile attributes
1309
							//we put "datafile" value there
1310
							doclist.append("<updatedDocument>");
1311
							doclist.append("<docid>").append(rs.getString(1));
1312
							doclist.append("</docid><rev>").append(rs.getInt(2));
1313
							doclist.append("</rev>");
1314
							doclist.append("<datafile>");
1315
							doclist.append(PropertyService
1316
									.getProperty("replication.datafileflag"));
1317
							doclist.append("</datafile>");
1318
							doclist.append("</updatedDocument>");
1319
						}//else
1320
					}//if packagedoctpes
1321
					else { //the package files are saved to be put into the xml later.
1322
						Vector<String> v = new Vector<String>();
1323
						v.add(rs.getString(1));
1324
						v.add(String.valueOf(rs.getInt(2)));
1325
						packageFiles.add(v);
1326
					}//esle
1327
					tablehasrows = rs.next();
1328
				}//while
1329
			}//if
1330
			else //metacat was configured not to send data file
1331
			{
1332
				while (tablehasrows) {
1333
					String recordDoctype = rs.getString(3);
1334
					if (!recordDoctype.equals("BIN")) { //don't replicate data files
1335
						Vector<String> packagedoctypes = MetacatUtil
1336
								.getOptionList(PropertyService
1337
										.getProperty("xml.packagedoctype"));
1338
						if (recordDoctype != null
1339
								&& !packagedoctypes.contains(recordDoctype)) { //if this is a package file, put it at the end
1340
							//because if a package file is read before all of the files it
1341
							//refers to are loaded then there is an error
1342
							doclist.append("<updatedDocument>");
1343
							doclist.append("<docid>").append(rs.getString(1));
1344
							doclist.append("</docid><rev>").append(rs.getInt(2));
1345
							doclist.append("</rev>");
1346
							doclist.append("</updatedDocument>");
1347
						} else { //the package files are saved to be put into the xml later.
1348
							Vector<String> v = new Vector<String>();
1349
							v.add(rs.getString(1));
1350
							v.add(String.valueOf(rs.getInt(2)));
1351
							packageFiles.add(v);
1352
						}
1353
					}//if
1354
					tablehasrows = rs.next();
1355
				}//while
1356
			}//else
1357 2286 tao
1358 5014 daigle
			pstmt = dbConn.prepareStatement(delsql.toString());
1359
			//usage count should increas 1
1360
			dbConn.increaseUsageCount(1);
1361 2286 tao
1362 5014 daigle
			pstmt.execute();
1363
			rs = pstmt.getResultSet();
1364
			tablehasrows = rs.next();
1365
			while (tablehasrows) { //handle the deleted documents
1366
				doclist.append("<deletedDocument><docid>").append(rs.getString(1));
1367
				doclist.append("</docid><rev></rev></deletedDocument>");
1368
				//note that rev is always empty for deleted docs
1369
				tablehasrows = rs.next();
1370
			}
1371 2286 tao
1372 5014 daigle
			//now we can put the package files into the xml results
1373
			for (int i = 0; i < packageFiles.size(); i++) {
1374
				Vector<String> v = packageFiles.elementAt(i);
1375
				doclist.append("<updatedDocument>");
1376
				doclist.append("<docid>").append(v.elementAt(0));
1377
				doclist.append("</docid><rev>");
1378
				doclist.append(v.elementAt(1));
1379
				doclist.append("</rev>");
1380
				doclist.append("</updatedDocument>");
1381
			}
1382
			// add revision doc list
1383
			doclist.append(prepareRevisionDoc(dbConn, revisionSql.toString(),
1384
					replicateData));
1385 2286 tao
1386 5014 daigle
			doclist.append("</updates></replication>");
1387
			logReplication.info("ReplicationService.handleUpdateRequest - doclist: " + doclist.toString());
1388
			pstmt.close();
1389
			//conn.close();
1390
			response.setContentType("text/xml");
1391
			out.println(doclist.toString());
1392 2286 tao
1393 5014 daigle
		} catch (Exception e) {
1394
			logMetacat.error("ReplicationService.handleUpdateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);
1395
			logReplication.error("ReplicationService.handleUpdateRequest - error in MetacatReplication." + "handleupdaterequest: "
1396
					+ e.getMessage());
1397
			//e.printStackTrace(System.out);
1398
			response.setContentType("text/xml");
1399
			out.println("<error>" + e.getMessage() + "</error>");
1400
		} finally {
1401
			try {
1402
				pstmt.close();
1403
			}//try
1404
			catch (SQLException ee) {
1405
				logMetacat.error("ReplicationService.handleUpdateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);
1406
				logReplication.error("ReplicationService.handleUpdateRequest - Error in MetacatReplication."
1407
						+ "handleUpdaterequest to close pstmt: " + ee.getMessage());
1408
			}//catch
1409
			finally {
1410
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1411
			}//finally
1412
		}//finally
1413 2286 tao
1414 5014 daigle
	}//handlUpdateRequest
1415 2286 tao
1416 5014 daigle
	/*
1417
	 * This method will get the xml string for document in xml_revision
1418
	 * The schema look like <!ELEMENT revisionDocument (docid, rev, datafile*)>
1419
	 */
1420
	private static String prepareRevisionDoc(DBConnection dbConn, String revSql,
1421
			boolean replicateData) throws Exception {
1422
		logReplication.warn("ReplicationService.prepareRevisionDoc - The revision document sql is " + revSql);
1423
		StringBuffer revDocList = new StringBuffer();
1424
		PreparedStatement pstmt = dbConn.prepareStatement(revSql);
1425
		//usage count should increas 1
1426
		dbConn.increaseUsageCount(1);
1427 2286 tao
1428 5014 daigle
		pstmt.execute();
1429
		ResultSet rs = pstmt.getResultSet();
1430
		boolean tablehasrows = rs.next();
1431
		while (tablehasrows) {
1432
			String recordDoctype = rs.getString(3);
1433 2286 tao
1434 5014 daigle
			//If this is data file and it isn't configured to replicate data
1435
			if (recordDoctype.equals("BIN") && !replicateData) {
1436
				// do nothing
1437
				continue;
1438
			} else {
1439 2597 tao
1440 5014 daigle
				revDocList.append("<revisionDocument>");
1441
				revDocList.append("<docid>").append(rs.getString(1));
1442
				revDocList.append("</docid><rev>").append(rs.getInt(2));
1443
				revDocList.append("</rev>");
1444
				// data file
1445
				if (recordDoctype.equals("BIN")) {
1446
					revDocList.append("<datafile>");
1447
					revDocList.append(PropertyService
1448
							.getProperty("replication.datafileflag"));
1449
					revDocList.append("</datafile>");
1450
				}
1451
				revDocList.append("</revisionDocument>");
1452 2286 tao
1453 5014 daigle
			}//else
1454
			tablehasrows = rs.next();
1455
		}
1456
		//System.out.println("The revision list is"+ revDocList.toString());
1457
		return revDocList.toString();
1458
	}
1459 2286 tao
1460 5014 daigle
	/**
1461
	 * Returns the xml_catalog table encoded in xml
1462
	 */
1463
	public static String getCatalogXML() {
1464
		return handleGetCatalogRequest(null, null, null, false);
1465
	}
1466 2286 tao
1467 5014 daigle
	/**
1468
	 * Sends the contents of the xml_catalog table encoded in xml
1469
	 * The xml format is:
1470
	 * <!ELEMENT xml_catalog (row*)>
1471
	 * <!ELEMENT row (entry_type, source_doctype, target_doctype, public_id,
1472
	 *                system_id)>
1473
	 * All of the sub elements of row are #PCDATA
1474 2286 tao
1475 5014 daigle
	 * If printFlag == false then do not print to out.
1476
	 */
1477
	protected static String handleGetCatalogRequest(PrintWriter out,
1478
			Hashtable<String, String[]> params, HttpServletResponse response,
1479
			boolean printFlag) {
1480
		DBConnection dbConn = null;
1481
		int serialNumber = -1;
1482
		PreparedStatement pstmt = null;
1483
		try {
1484
			/*conn = MetacatReplication.getDBConnection("MetacatReplication." +
1485
			                                          "handleGetCatalogRequest");*/
1486
			dbConn = DBConnectionPool
1487
					.getDBConnection("MetacatReplication.handleGetCatalogRequest");
1488
			serialNumber = dbConn.getCheckOutSerialNumber();
1489
			pstmt = dbConn.prepareStatement("select entry_type, "
1490
					+ "source_doctype, target_doctype, public_id, "
1491
					+ "system_id from xml_catalog");
1492
			pstmt.execute();
1493
			ResultSet rs = pstmt.getResultSet();
1494
			boolean tablehasrows = rs.next();
1495
			StringBuffer sb = new StringBuffer();
1496
			sb.append("<?xml version=\"1.0\"?><xml_catalog>");
1497
			while (tablehasrows) {
1498
				sb.append("<row><entry_type>").append(rs.getString(1));
1499
				sb.append("</entry_type><source_doctype>").append(rs.getString(2));
1500
				sb.append("</source_doctype><target_doctype>").append(rs.getString(3));
1501
				sb.append("</target_doctype><public_id>").append(rs.getString(4));
1502
				// system id may not have server url on front.  Add it if not.
1503
				String systemID = rs.getString(5);
1504
				if (!systemID.startsWith("http://")) {
1505
					systemID = SystemUtil.getContextURL() + systemID;
1506
				}
1507
				sb.append("</public_id><system_id>").append(systemID);
1508
				sb.append("</system_id></row>");
1509 2286 tao
1510 5014 daigle
				tablehasrows = rs.next();
1511
			}
1512
			sb.append("</xml_catalog>");
1513
			//conn.close();
1514
			if (printFlag) {
1515
				response.setContentType("text/xml");
1516
				out.println(sb.toString());
1517
			}
1518
			pstmt.close();
1519
			return sb.toString();
1520
		} catch (Exception e) {
1521
			logMetacat.error("ReplicationService.handleGetCatalogRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);
1522
			logReplication.error("ReplicationService.handleGetCatalogRequest - error in MetacatReplication.handleGetCatalogRequest:"
1523
					+ e.getMessage());
1524
			e.printStackTrace(System.out);
1525
			if (printFlag) {
1526
				out.println("<error>" + e.getMessage() + "</error>");
1527
			}
1528
		} finally {
1529
			try {
1530
				pstmt.close();
1531
			}//try
1532
			catch (SQLException ee) {
1533
				logMetacat.error("ReplicationService.handleGetCatalogRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);
1534
				logReplication.error("ReplicationService.handleGetCatalogRequest - Error in MetacatReplication.handleGetCatalogRequest: "
1535
						+ ee.getMessage());
1536
			}//catch
1537
			finally {
1538
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1539
			}//finally
1540
		}//finally
1541 2286 tao
1542 5014 daigle
		return null;
1543
	}
1544 2286 tao
1545 5014 daigle
	/**
1546
	 * Sends the current system date to the remote server.  Using this action
1547
	 * for replication gets rid of any problems with syncronizing clocks
1548
	 * because a time specific to a document is always kept on its home server.
1549
	 */
1550
	protected static void handleGetTimeRequest(PrintWriter out,
1551
			Hashtable<String, String[]> params, HttpServletResponse response) {
1552
		SimpleDateFormat formatter = new SimpleDateFormat("MM/dd/yy HH:mm:ss");
1553
		java.util.Date localtime = new java.util.Date();
1554
		String dateString = formatter.format(localtime);
1555
		response.setContentType("text/xml");
1556 2286 tao
1557 5014 daigle
		out.println("<timestamp>" + dateString + "</timestamp>");
1558
	}
1559 2286 tao
1560 5014 daigle
	/**
1561
	 * this method handles the timeout for a file lock.  when a lock is
1562
	 * granted it is granted for 30 seconds.  When this thread runs out
1563
	 * it deletes the docid from the queue, thus eliminating the lock.
1564
	 */
1565
	public void run() {
1566
		try {
1567
			logReplication.info("ReplicationService.run - thread started for docid: "
1568
					+ (String) fileLocks.elementAt(0));
1569 2286 tao
1570 5014 daigle
			Thread.sleep(30000); //the lock will expire in 30 seconds
1571
			logReplication.info("thread for docid: "
1572
					+ (String) fileLocks.elementAt(fileLocks.size() - 1) + " exiting.");
1573 2286 tao
1574 5014 daigle
			fileLocks.remove(fileLocks.size() - 1);
1575
			//fileLocks is treated as a FIFO queue.  If there are more than one lock
1576
			//in the vector, the first one inserted will be removed.
1577
		} catch (Exception e) {
1578
			logMetacat.error("ReplicationService.run - " + ReplicationService.METACAT_REPL_ERROR_MSG);
1579
			logReplication.error("ReplicationService.run - error in file lock thread from "
1580
					+ "MetacatReplication.run: " + e.getMessage());
1581
		}
1582
	}
1583 2286 tao
1584 5014 daigle
	/**
1585
	 * Returns the name of a server given a serverCode
1586
	 * @param serverCode the serverid of the server
1587
	 * @return the servername or null if the specified serverCode does not
1588
	 *         exist.
1589
	 */
1590
	public static String getServerNameForServerCode(int serverCode) {
1591
		//System.out.println("serverid: " + serverCode);
1592
		DBConnection dbConn = null;
1593
		int serialNumber = -1;
1594
		PreparedStatement pstmt = null;
1595
		try {
1596
			dbConn = DBConnectionPool.getDBConnection("MetacatReplication.getServer");
1597
			serialNumber = dbConn.getCheckOutSerialNumber();
1598
			String sql = new String("select server from "
1599
					+ "xml_replication where serverid = " + serverCode);
1600
			pstmt = dbConn.prepareStatement(sql);
1601
			//System.out.println("getserver sql: " + sql);
1602
			pstmt.execute();
1603
			ResultSet rs = pstmt.getResultSet();
1604
			boolean tablehasrows = rs.next();
1605
			if (tablehasrows) {
1606
				//System.out.println("server: " + rs.getString(1));
1607
				return rs.getString(1);
1608
			}
1609 2286 tao
1610 5014 daigle
			//conn.close();
1611
		} catch (Exception e) {
1612
			logMetacat.error("ReplicationService.getServerNameForServerCode - " + ReplicationService.METACAT_REPL_ERROR_MSG);
1613
			logReplication.error("ReplicationService.getServerNameForServerCode - Error in MetacatReplication.getServer: " + e.getMessage());
1614
		} finally {
1615
			try {
1616
				pstmt.close();
1617
			}//try
1618
			catch (SQLException ee) {
1619
				logMetacat.error("ReplicationService.getServerNameForServerCode - " + ReplicationService.METACAT_REPL_ERROR_MSG);
1620
				logReplication.error("ReplicationService.getServerNameForServerCode - Error in MetacactReplication.getserver: "
1621
						+ ee.getMessage());
1622
			}//catch
1623
			finally {
1624
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1625
			}//fianlly
1626
		}//finally
1627 2286 tao
1628 5014 daigle
		return null;
1629
		//return null if the server does not exist
1630
	}
1631 2286 tao
1632 5014 daigle
	/**
1633
	 * Returns a server code given a server name
1634
	 * @param server the name of the server
1635
	 * @return integer > 0 representing the code of the server, 0 if the server
1636
	 *  does not exist.
1637
	 */
1638
	public static int getServerCodeForServerName(String server) throws ServiceException {
1639
		DBConnection dbConn = null;
1640
		int serialNumber = -1;
1641
		PreparedStatement pstmt = null;
1642
		int serverCode = 0;
1643 2286 tao
1644 5014 daigle
		try {
1645 837 bojilova
1646 5014 daigle
			//conn = util.openDBConnection();
1647
			dbConn = DBConnectionPool.getDBConnection("MetacatReplication.getServerCode");
1648
			serialNumber = dbConn.getCheckOutSerialNumber();
1649
			pstmt = dbConn.prepareStatement("SELECT serverid FROM xml_replication "
1650
					+ "WHERE server LIKE '" + server + "'");
1651
			pstmt.execute();
1652
			ResultSet rs = pstmt.getResultSet();
1653
			boolean tablehasrows = rs.next();
1654
			if (tablehasrows) {
1655
				serverCode = rs.getInt(1);
1656
				pstmt.close();
1657
				//conn.close();
1658
				return serverCode;
1659
			}
1660 837 bojilova
1661 5014 daigle
		} catch (SQLException sqle) {
1662
			throw new ServiceException("ReplicationService.getServerCodeForServerName - "
1663
					+ "SQL error when getting server code: " + sqle.getMessage());
1664 2286 tao
1665 5014 daigle
		} finally {
1666
			try {
1667
				pstmt.close();
1668
				//conn.close();
1669
			}//try
1670
			catch (Exception ee) {
1671
				logMetacat.error("ReplicationService.getServerCodeForServerName - " + ReplicationService.METACAT_REPL_ERROR_MSG);
1672
				logReplication.error("ReplicationService.getServerNameForServerCode - Error in MetacatReplicatio.getServerCode: "
1673
						+ ee.getMessage());
1674 837 bojilova
1675 5014 daigle
			}//catch
1676
			finally {
1677
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1678
			}//finally
1679
		}//finally
1680 2286 tao
1681 5014 daigle
		return serverCode;
1682
	}
1683 2286 tao
1684 5014 daigle
	/**
1685
	 * Method to get a host server information for given docid
1686
	 * @param conn a connection to the database
1687
	 */
1688
	public static Hashtable<String, String> getHomeServerInfoForDocId(String docId) {
1689
		Hashtable<String, String> sl = new Hashtable<String, String>();
1690
		DBConnection dbConn = null;
1691
		int serialNumber = -1;
1692 5027 daigle
		docId = DocumentUtil.getDocIdFromString(docId);
1693 5014 daigle
		PreparedStatement pstmt = null;
1694
		int serverLocation;
1695
		try {
1696
			//get conection
1697
			dbConn = DBConnectionPool.getDBConnection("ReplicationHandler.getHomeServer");
1698
			serialNumber = dbConn.getCheckOutSerialNumber();
1699
			//get a server location from xml_document table
1700
			pstmt = dbConn.prepareStatement("select server_location from xml_documents "
1701
					+ "where docid = ?");
1702
			pstmt.setString(1, docId);
1703
			pstmt.execute();
1704
			ResultSet serverName = pstmt.getResultSet();
1705
			//get a server location
1706
			if (serverName.next()) {
1707
				serverLocation = serverName.getInt(1);
1708
				pstmt.close();
1709
			} else {
1710
				pstmt.close();
1711
				//ut.returnConnection(conn);
1712
				return null;
1713
			}
1714
			pstmt = dbConn.prepareStatement("select server, last_checked, replicate "
1715
					+ "from xml_replication where serverid = ?");
1716
			//increase usage count
1717
			dbConn.increaseUsageCount(1);
1718
			pstmt.setInt(1, serverLocation);
1719
			pstmt.execute();
1720
			ResultSet rs = pstmt.getResultSet();
1721
			boolean tableHasRows = rs.next();
1722
			if (tableHasRows) {
1723 2286 tao
1724 5014 daigle
				String server = rs.getString(1);
1725
				String last_checked = rs.getString(2);
1726
				if (!server.equals("localhost")) {
1727
					sl.put(server, last_checked);
1728
				}
1729 2286 tao
1730 5014 daigle
			} else {
1731
				pstmt.close();
1732
				//ut.returnConnection(conn);
1733
				return null;
1734
			}
1735
			pstmt.close();
1736
		} catch (Exception e) {
1737
			logMetacat.error("ReplicationService.getHomeServerInfoForDocId - " + ReplicationService.METACAT_REPL_ERROR_MSG);
1738
			logReplication.error("ReplicationService.getHomeServerInfoForDocId - error in replicationHandler.getHomeServer(): "
1739
					+ e.getMessage());
1740
		} finally {
1741
			try {
1742
				pstmt.close();
1743
				//ut.returnConnection(conn);
1744
			} catch (Exception ee) {
1745
				logMetacat.error("ReplicationService.getHomeServerInfoForDocId - " + ReplicationService.METACAT_REPL_ERROR_MSG);
1746
				logReplication.error("ReplicationService.getHomeServerInfoForDocId - Eror irn rplicationHandler.getHomeServer() "
1747
						+ "to close pstmt: " + ee.getMessage());
1748
			} finally {
1749
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1750
			}
1751 2286 tao
1752 5014 daigle
		}//finally
1753
		return sl;
1754
	}
1755 2286 tao
1756 5014 daigle
	/**
1757
	 * Returns a home server location  given a accnum
1758
	 * @param accNum , given accNum for a document
1759
	 *
1760
	 */
1761
	public static int getHomeServerCodeForDocId(String accNum) throws ServiceException {
1762
		DBConnection dbConn = null;
1763
		int serialNumber = -1;
1764
		PreparedStatement pstmt = null;
1765
		int serverCode = 1;
1766 5027 daigle
		String docId = DocumentUtil.getDocIdFromString(accNum);
1767 2286 tao
1768 5014 daigle
		try {
1769 1292 tao
1770 5014 daigle
			// Get DBConnection
1771
			dbConn = DBConnectionPool
1772
					.getDBConnection("ReplicationHandler.getServerLocation");
1773
			serialNumber = dbConn.getCheckOutSerialNumber();
1774
			pstmt = dbConn.prepareStatement("SELECT server_location FROM xml_documents "
1775
					+ "WHERE docid LIKE '" + docId + "'");
1776
			pstmt.execute();
1777
			ResultSet rs = pstmt.getResultSet();
1778
			boolean tablehasrows = rs.next();
1779
			//If a document is find, return the server location for it
1780
			if (tablehasrows) {
1781
				serverCode = rs.getInt(1);
1782
				pstmt.close();
1783
				//conn.close();
1784
				return serverCode;
1785
			}
1786
			//if couldn't find in xml_documents table, we think server code is 1
1787
			//(this is new document)
1788
			else {
1789
				pstmt.close();
1790
				//conn.close();
1791
				return serverCode;
1792
			}
1793 1292 tao
1794 5014 daigle
		} catch (SQLException sqle) {
1795
			throw new ServiceException("ReplicationService.getHomeServerCodeForDocId - "
1796
					+ "SQL error when getting home server code for docid: " + docId + " : "
1797
					+ sqle.getMessage());
1798 2286 tao
1799 5014 daigle
		} finally {
1800
			try {
1801
				pstmt.close();
1802
				//conn.close();
1803 2286 tao
1804 5014 daigle
			} catch (SQLException sqle) {
1805
				logMetacat.error("ReplicationService.getHomeServerCodeForDocId - " + ReplicationService.METACAT_REPL_ERROR_MSG);
1806
				logReplication.error("ReplicationService.getHomeServerCodeForDocId - ReplicationService.getHomeServerCodeForDocId - "
1807
						+ "SQL error when getting home server code for docid: " + docId + " : "
1808
						+ sqle.getMessage());
1809
			} finally {
1810
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1811
			}//finally
1812
		}//finally
1813
		//return serverCode;
1814
	}
1815 1292 tao
1816 5014 daigle
	/**
1817
	 * This method returns the content of a url
1818
	 * @param u the url to return the content from
1819
	 * @return a string representing the content of the url
1820
	 * @throws java.io.IOException
1821
	 */
1822
	public static String getURLContent(URL u) throws java.io.IOException {
1823 5441 berkley
	    logReplication.info("Getting url content from " + u.toString());
1824 5014 daigle
		char istreamChar;
1825
		int istreamInt;
1826 5440 berkley
		logReplication.info("ReplicationService.getURLContent - Before open the stream" + u.toString());
1827 5014 daigle
		InputStream input = u.openStream();
1828 5440 berkley
		logReplication.info("ReplicationService.getURLContent - After open the stream" + u.toString());
1829 5014 daigle
		InputStreamReader istream = new InputStreamReader(input);
1830
		StringBuffer serverResponse = new StringBuffer();
1831
		while ((istreamInt = istream.read()) != -1) {
1832
			istreamChar = (char) istreamInt;
1833
			serverResponse.append(istreamChar);
1834
		}
1835
		istream.close();
1836
		input.close();
1837 2286 tao
1838 5014 daigle
		return serverResponse.toString();
1839
	}
1840 2286 tao
1841 5014 daigle
//	/**
1842
//	 * Method for writing replication messages to a log file specified in
1843
//	 * metacat.properties
1844
//	 */
1845
//	public static void replLog(String message) {
1846
//		try {
1847
//			FileOutputStream fos = new FileOutputStream(PropertyService
1848
//					.getProperty("replication.logdir")
1849
//					+ "/metacatreplication.log", true);
1850
//			PrintWriter pw = new PrintWriter(fos);
1851
//			SimpleDateFormat formatter = new SimpleDateFormat("yy-MM-dd HH:mm:ss");
1852
//			java.util.Date localtime = new java.util.Date();
1853
//			String dateString = formatter.format(localtime);
1854
//			dateString += " :: " + message;
1855
//			// time stamp each entry
1856
//			pw.println(dateString);
1857
//			pw.flush();
1858
//		} catch (Exception e) {
1859
//			logReplication.error("error writing to replication log from "
1860
//					+ "MetacatReplication.replLog: " + e.getMessage());
1861
//			// e.printStackTrace(System.out);
1862
//		}
1863
//	}
1864 2286 tao
1865 5014 daigle
//	/**
1866
//	 * Method for writing replication messages to a log file specified in
1867
//	 * metacat.properties
1868
//	 */
1869
//	public static void replErrorLog(String message) {
1870
//		try {
1871
//			FileOutputStream fos = new FileOutputStream(PropertyService
1872
//					.getProperty("replication.logdir")
1873
//					+ "/metacatreplicationerror.log", true);
1874
//			PrintWriter pw = new PrintWriter(fos);
1875
//			SimpleDateFormat formatter = new SimpleDateFormat("yy-MM-dd HH:mm:ss");
1876
//			java.util.Date localtime = new java.util.Date();
1877
//			String dateString = formatter.format(localtime);
1878
//			dateString += " :: " + message;
1879
//			//time stamp each entry
1880
//			pw.println(dateString);
1881
//			pw.flush();
1882
//		} catch (Exception e) {
1883
//			logReplication.error("error writing to replication error log from "
1884
//					+ "MetacatReplication.replErrorLog: " + e.getMessage());
1885
//			//e.printStackTrace(System.out);
1886
//		}
1887
//	}
1888 2286 tao
1889 5014 daigle
	/**
1890
	 * Returns true if the replicate field for server in xml_replication is 1.
1891
	 * Returns false otherwise
1892 4080 daigle
	 */
1893 5014 daigle
	public static boolean replToServer(String server) {
1894
		DBConnection dbConn = null;
1895
		int serialNumber = -1;
1896
		PreparedStatement pstmt = null;
1897 4080 daigle
		try {
1898 5014 daigle
			dbConn = DBConnectionPool.getDBConnection("MetacatReplication.repltoServer");
1899
			serialNumber = dbConn.getCheckOutSerialNumber();
1900
			pstmt = dbConn.prepareStatement("select replicate from "
1901
					+ "xml_replication where server like '" + server + "'");
1902
			pstmt.execute();
1903
			ResultSet rs = pstmt.getResultSet();
1904
			boolean tablehasrows = rs.next();
1905
			if (tablehasrows) {
1906
				int i = rs.getInt(1);
1907
				if (i == 1) {
1908
					pstmt.close();
1909
					//conn.close();
1910
					return true;
1911
				} else {
1912
					pstmt.close();
1913
					//conn.close();
1914
					return false;
1915
				}
1916
			}
1917
		} catch (SQLException sqle) {
1918
			logMetacat.error("ReplicationService.replToServer - " + ReplicationService.METACAT_REPL_ERROR_MSG);
1919
			logReplication.error("ReplicationService.replToServer - SQL error in MetacatReplication.replToServer: "
1920
					+ sqle.getMessage());
1921
		} finally {
1922
			try {
1923
				pstmt.close();
1924
				//conn.close();
1925
			}//try
1926
			catch (Exception ee) {
1927
				logMetacat.error("ReplicationService.replToServer - " + ReplicationService.METACAT_REPL_ERROR_MSG);
1928
				logReplication.error("ReplicationService.replToServer - Error in MetacatReplication.replToServer: "
1929
						+ ee.getMessage());
1930
			}//catch
1931
			finally {
1932
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1933
			}//finally
1934
		}//finally
1935
		return false;
1936
		//the default if this server does not exist is to not replicate to it.
1937 4080 daigle
	}
1938 2286 tao
1939 522 berkley
}