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: 2011-11-02 20:40:12 -0700 (Wed, 02 Nov 2011) $'
10
 * '$Revision: 6595 $'
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.io.BufferedInputStream;
30
import java.io.BufferedOutputStream;
31
import java.io.ByteArrayInputStream;
32
import java.io.ByteArrayOutputStream;
33
import java.io.File;
34
import java.io.FileInputStream;
35
import java.io.FileNotFoundException;
36
import java.io.FileOutputStream;
37
import java.io.IOException;
38
import java.io.InputStream;
39
import java.io.InputStreamReader;
40
import java.io.OutputStream;
41
import java.io.StringReader;
42
import java.io.Writer;
43
import java.net.MalformedURLException;
44
import java.net.URL;
45
import java.security.PrivateKey;
46
import java.security.cert.X509Certificate;
47
import java.sql.PreparedStatement;
48
import java.sql.ResultSet;
49
import java.sql.SQLException;
50
import java.sql.Timestamp;
51
import java.text.SimpleDateFormat;
52
import java.util.Calendar;
53
import java.util.Date;
54
import java.util.Hashtable;
55
import java.util.List;
56
import java.util.Timer;
57
import java.util.Vector;
58

    
59
import javax.servlet.http.HttpServletRequest;
60
import javax.servlet.http.HttpServletResponse;
61
import javax.xml.bind.DatatypeConverter;
62

    
63
import org.apache.http.HttpResponse;
64
import org.apache.http.conn.scheme.Scheme;
65
import org.apache.http.conn.ssl.SSLSocketFactory;
66
import org.apache.log4j.Logger;
67
import org.dataone.client.RestClient;
68
import org.dataone.client.auth.CertificateManager;
69
import org.dataone.service.types.v1.Session;
70
import org.dataone.service.types.v1.SystemMetadata;
71
import org.dataone.service.util.TypeMarshaller;
72
import org.xml.sax.InputSource;
73
import org.xml.sax.SAXException;
74
import org.xml.sax.XMLReader;
75

    
76
import edu.ucsb.nceas.metacat.DocInfoHandler;
77
import edu.ucsb.nceas.metacat.DocumentImpl;
78
import edu.ucsb.nceas.metacat.DocumentImplWrapper;
79
import edu.ucsb.nceas.metacat.EventLog;
80
import edu.ucsb.nceas.metacat.IdentifierManager;
81
import edu.ucsb.nceas.metacat.McdbDocNotFoundException;
82
import edu.ucsb.nceas.metacat.McdbException;
83
import edu.ucsb.nceas.metacat.accesscontrol.AccessControlException;
84
import edu.ucsb.nceas.metacat.accesscontrol.AccessControlForSingleFile;
85
import edu.ucsb.nceas.metacat.accesscontrol.PermOrderException;
86
import edu.ucsb.nceas.metacat.accesscontrol.XMLAccessDAO;
87
import edu.ucsb.nceas.metacat.client.InsufficientKarmaException;
88
import edu.ucsb.nceas.metacat.database.DBConnection;
89
import edu.ucsb.nceas.metacat.database.DBConnectionPool;
90
import edu.ucsb.nceas.metacat.database.DatabaseService;
91
import edu.ucsb.nceas.metacat.dataone.hazelcast.HazelcastService;
92
import edu.ucsb.nceas.metacat.properties.PropertyService;
93
import edu.ucsb.nceas.metacat.shared.BaseService;
94
import edu.ucsb.nceas.metacat.shared.HandlerException;
95
import edu.ucsb.nceas.metacat.shared.ServiceException;
96
import edu.ucsb.nceas.metacat.util.DocumentUtil;
97
import edu.ucsb.nceas.metacat.util.MetacatUtil;
98
import edu.ucsb.nceas.metacat.util.ReplicationUtil;
99
import edu.ucsb.nceas.metacat.util.SystemUtil;
100
import edu.ucsb.nceas.utilities.FileUtil;
101
import edu.ucsb.nceas.utilities.GeneralPropertyException;
102
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
103

    
104
public class ReplicationService extends BaseService {
105

    
106
	private static ReplicationService replicationService = null;
107

    
108
	private long timeInterval;
109
	private Date firstTime;
110
	private boolean timedReplicationIsOn = false;
111
	Timer replicationDaemon;
112
	private static Vector<String> fileLocks = new Vector<String>();
113
//	private Thread lockThread = null;
114
	public static final String FORCEREPLICATEDELETE = "forcereplicatedelete";
115
	private static String TIMEREPLICATION = "replication.timedreplication";
116
	private static String TIMEREPLICATIONINTERVAl ="replication.timedreplicationinterval";
117
	private static String FIRSTTIME = "replication.firsttimedreplication";
118
	private static final int TIMEINTERVALLIMIT = 7200000;
119
	public static final String REPLICATIONUSER = "replication";
120

    
121
	public static final String REPLICATION_LOG_FILE_NAME = "metacatreplication.log";
122
	public static String METACAT_REPL_ERROR_MSG = null;
123
	private static Logger logReplication = Logger.getLogger("ReplicationLogging");
124
	private static Logger logMetacat = Logger.getLogger(ReplicationService.class);
125

    
126
	private ReplicationService() throws ServiceException {
127
		_serviceName = "ReplicationService";
128
		
129
		initialize();
130
	}
131
	
132
	private void initialize() throws ServiceException {
133
				
134
		// initialize db connections to handle any update requests
135
		// deltaT = util.getProperty("replication.deltaT");
136
		// the default deltaT can be set from metacat.properties
137
		// create a thread to do the delta-T check but don't execute it yet
138
		replicationDaemon = new Timer(true);
139
		try {
140
			String replLogFile = PropertyService.getProperty("replication.logdir")
141
				+ FileUtil.getFS() + REPLICATION_LOG_FILE_NAME;
142
			METACAT_REPL_ERROR_MSG = "An error occurred in replication.  Please see the " +
143
				"replication log at: " + replLogFile;
144
			
145
			String timedRepIsOnStr = 
146
				PropertyService.getProperty("replication.timedreplication");
147
			timedReplicationIsOn = (new Boolean(timedRepIsOnStr)).booleanValue();
148
			logReplication.info("ReplicationService.initialize - The timed replication on is" + timedReplicationIsOn);
149

    
150
			String timeIntervalStr = 
151
				PropertyService.getProperty("replication.timedreplicationinterval");
152
			timeInterval = (new Long(timeIntervalStr)).longValue();
153
			logReplication.info("ReplicationService.initialize - The timed replication time Interval is " + timeInterval);
154

    
155
			String firstTimeStr = 
156
				PropertyService.getProperty("replication.firsttimedreplication");
157
			logReplication.info("ReplicationService.initialize - first replication time form property is " + firstTimeStr);
158
			firstTime = ReplicationHandler.combinateCurrentDateAndGivenTime(firstTimeStr);
159

    
160
			logReplication.info("ReplicationService.initialize - After combine current time, the real first time is "
161
					+ firstTime.toString() + " minisec");
162

    
163
			// set up time replication if it is on
164
			if (timedReplicationIsOn) {
165
				replicationDaemon.scheduleAtFixedRate(new ReplicationHandler(),
166
						firstTime, timeInterval);
167
				logReplication.info("ReplicationService.initialize - deltaT handler started with rate="
168
						+ timeInterval + " mini seconds at " + firstTime.toString());
169
			}
170

    
171
		} catch (PropertyNotFoundException pnfe) {
172
			throw new ServiceException(
173
					"ReplicationService.initialize - Property error while instantiating "
174
							+ "replication service: " + pnfe.getMessage());
175
		} catch (HandlerException he) {
176
			throw new ServiceException(
177
					"ReplicationService.initialize - Handler error while instantiating "
178
							+ "replication service" + he.getMessage());
179
		} 
180
	}
181

    
182
	/**
183
	 * Get the single instance of SessionService.
184
	 * 
185
	 * @return the single instance of SessionService
186
	 */
187
	public static ReplicationService getInstance() throws ServiceException {
188
		if (replicationService == null) {
189
			replicationService = new ReplicationService();
190
		}
191
		return replicationService;
192
	}
193

    
194
	public boolean refreshable() {
195
		return true;
196
	}
197

    
198
	protected void doRefresh() throws ServiceException {
199
		return;
200
	}
201
	
202
	public void stop() throws ServiceException{
203
		
204
	}
205

    
206
	public void stopReplication() throws ServiceException {
207
	      //stop the replication server
208
	      replicationDaemon.cancel();
209
	      replicationDaemon = new Timer(true);
210
	      timedReplicationIsOn = false;
211
	      try {
212
	    	  PropertyService.setProperty("replication.timedreplication", (new Boolean(timedReplicationIsOn)).toString());
213
	      } catch (GeneralPropertyException gpe) {
214
	    	  logReplication.warn("ReplicationService.stopReplication - Could not set replication.timedreplication property: " + gpe.getMessage());
215
	      }
216

    
217
	      logReplication.info("ReplicationService.stopReplication - deltaT handler stopped");
218
		return;
219
	}
220
	
221
	protected void startReplication(Hashtable<String, String[]> params) throws ServiceException {
222

    
223
	       String firstTimeStr = "";
224
	      //start the replication server
225
	       if ( params.containsKey("rate") ) {
226
	        timeInterval = new Long(
227
	               new String(((String[])params.get("rate"))[0])).longValue();
228
	        if(timeInterval < TIMEINTERVALLIMIT) {
229
	            //deltaT<30 is a timing mess!
230
	            timeInterval = TIMEINTERVALLIMIT;
231
	            throw new ServiceException("Replication deltaT rate cannot be less than "+
232
	                    TIMEINTERVALLIMIT + " millisecs and system automatically setup the rate to "+TIMEINTERVALLIMIT);
233
	        }
234
	      } else {
235
	        timeInterval = TIMEINTERVALLIMIT ;
236
	      }
237
	      logReplication.info("ReplicationService.startReplication - New rate is: " + timeInterval + " mini seconds.");
238
	      if ( params.containsKey("firsttime"))
239
	      {
240
	         firstTimeStr = ((String[])params.get("firsttime"))[0];
241
	         try
242
	         {
243
	           firstTime = ReplicationHandler.combinateCurrentDateAndGivenTime(firstTimeStr);
244
	           logReplication.info("ReplicationService.startReplication - The first time setting is "+firstTime.toString());
245
	         }
246
	         catch (HandlerException e)
247
	         {
248
	            throw new ServiceException(e.getMessage());
249
	         }
250
	         logReplication.warn("After combine current time, the real first time is "
251
	                                  +firstTime.toString()+" minisec");
252
	      }
253
	      else
254
	      {
255
	    	  logMetacat.error("ReplicationService.startReplication - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
256
	          logReplication.error("ReplicationService.startReplication - You should specify the first time " +
257
	                                  "to start a time replication");
258
	          return;
259
	      }
260
	      
261
	      timedReplicationIsOn = true;
262
	      try {
263
	      // save settings to property file
264
	      PropertyService.setProperty(TIMEREPLICATION, (new Boolean(timedReplicationIsOn)).toString());
265
	      // note we couldn't use firstTime object because it has date info
266
	      // we only need time info such as 10:00 PM
267
	      PropertyService.setProperty(FIRSTTIME, firstTimeStr);
268
	      PropertyService.setProperty(TIMEREPLICATIONINTERVAl, (new Long(timeInterval)).toString());
269
	      } catch (GeneralPropertyException gpe) {
270
	    	  logReplication.warn("ReplicationService.startReplication - Could not set property: " + gpe.getMessage());
271
	      }
272
	      replicationDaemon.cancel();
273
	      replicationDaemon = new Timer(true);
274
	      replicationDaemon.scheduleAtFixedRate(new ReplicationHandler(), firstTime,
275
	                                            timeInterval);
276
	      
277
	      logReplication.info("ReplicationService.startReplication - deltaT handler started with rate=" +
278
	                                    timeInterval + " milliseconds at " +firstTime.toString());
279

    
280
	}
281
	
282
	public void runOnce() throws ServiceException {
283
	      //updates this server exactly once
284
	      replicationDaemon.schedule(new ReplicationHandler(), 0);
285
	}
286

    
287
	/**
288
	 * This method can add, delete and list the servers currently included in
289
	 * xml_replication.
290
	 * action           subaction            other needed params
291
	 * ---------------------------------------------------------
292
	 * servercontrol    add                  server
293
	 * servercontrol    delete               server
294
	 * servercontrol    list
295
	 */
296
	protected static void handleServerControlRequest(
297
			Hashtable<String, String[]> params, HttpServletResponse response) {
298
		String subaction = ((String[]) params.get("subaction"))[0];
299
		DBConnection dbConn = null;
300
		int serialNumber = -1;
301
		PreparedStatement pstmt = null;
302
		String replicate = null;
303
		String server = null;
304
		String dataReplicate = null;
305
		String systemMetadataReplicate = null;
306
		String hub = null;
307
		Writer out = null;
308
		try {
309
			response.setContentType("text/xml");
310
			out = response.getWriter();
311
			
312
			//conn = util.openDBConnection();
313
			dbConn = DBConnectionPool
314
					.getDBConnection("MetacatReplication.handleServerControlRequest");
315
			serialNumber = dbConn.getCheckOutSerialNumber();
316

    
317
			// add server to server list
318
			if (subaction.equals("add")) {
319
				replicate = ((String[]) params.get("replicate"))[0];
320
				server = ((String[]) params.get("server"))[0];
321

    
322
				//Get data replication value
323
				dataReplicate = ((String[]) params.get("datareplicate"))[0];
324
				//Get system metadata replication value
325
				systemMetadataReplicate = ((String[]) params.get("systemmetadatareplicate"))[0];
326
				//Get hub value
327
				hub = ((String[]) params.get("hub"))[0];
328

    
329
				Calendar cal = Calendar.getInstance();
330
                cal.set(1980, 1, 1);
331
				String sql = "INSERT INTO xml_replication "
332
						+ "(server, last_checked, replicate, datareplicate, systemmetadatareplicate, hub) "
333
						+ "VALUES (?,?,?,?,?,?)";
334
				
335
				pstmt = dbConn.prepareStatement(sql);
336
						
337
				pstmt.setString(1, server);
338
				pstmt.setTimestamp(2, new Timestamp(cal.getTimeInMillis()));
339
				pstmt.setInt(3, Integer.parseInt(replicate));
340
				pstmt.setInt(4, Integer.parseInt(dataReplicate));
341
				pstmt.setInt(5, Integer.parseInt(systemMetadataReplicate));
342
				pstmt.setInt(6, Integer.parseInt(hub));
343
				
344
				String sqlReport = "XMLAccessAccess.getXMLAccessForDoc - SQL: " + sql;
345
				sqlReport += " [" + server + "," + replicate + 
346
					"," + dataReplicate + "," + hub + "]";
347
				
348
				logMetacat.info(sqlReport);
349
				
350
				pstmt.execute();
351
				pstmt.close();
352
				dbConn.commit();
353
				out.write("Server " + server + " added");
354
				response.setContentType("text/html");
355
				out.write("<html><body><table border=\"1\">");
356
				out.write("<tr><td><b>server</b></td>");
357
				out.write("<td><b>last_checked</b></td>");
358
				out.write("<td><b>replicate</b></td>");
359
				out.write("<td><b>datareplicate</b></td>");
360
				out.write("<td><b>systemmetadatareplicate</b></td>");
361
				out.write("<td><b>hub</b></td></tr>");
362
				pstmt = dbConn.prepareStatement("SELECT serverid, server, last_checked, replicate, datareplicate, systemmetadatareplicate, hub FROM xml_replication");
363
				//increase dbconnection usage
364
				dbConn.increaseUsageCount(1);
365

    
366
				pstmt.execute();
367
				ResultSet rs = pstmt.getResultSet();
368
				boolean tablehasrows = rs.next();
369
				while (tablehasrows) {
370
					out.write("<tr><td>" + rs.getString(2) + "</td><td>");
371
					out.write(rs.getString(3) + "</td><td>");
372
					out.write(rs.getString(4) + "</td><td>");
373
					out.write(rs.getString(5) + "</td><td>");
374
					out.write(rs.getString(6) + "</td><td>");
375
					out.write(rs.getString(7) + "</td></tr>");
376

    
377
					tablehasrows = rs.next();
378
				}
379
				out.write("</table></body></html>");
380

    
381
				// download certificate with the public key on this server
382
				// and import it as a trusted certificate
383
				String certURL = ((String[]) params.get("certificate"))[0];
384
				if (certURL != null && !certURL.equals("")) {
385
					downloadCertificate(certURL);
386
				}
387

    
388
				// delete server from server list
389
			} else if (subaction.equals("delete")) {
390
				server = ((String[]) params.get("server"))[0];
391
				pstmt = dbConn.prepareStatement("DELETE FROM xml_replication "
392
						+ "WHERE server LIKE ?");
393
				pstmt.setString(1, server);
394
				pstmt.execute();
395
				pstmt.close();
396
				dbConn.commit();
397
				out.write("Server " + server + " deleted");
398
				response.setContentType("text/html");
399
				out.write("<html><body><table border=\"1\">");
400
				out.write("<tr><td><b>server</b></td>");
401
				out.write("<td><b>last_checked</b></td>");
402
				out.write("<td><b>replicate</b></td>");
403
				out.write("<td><b>datareplicate</b></td>");
404
				out.write("<td><b>systemmetadatareplicate</b></td>");
405
				out.write("<td><b>hub</b></td></tr>");
406

    
407
				pstmt = dbConn.prepareStatement("SELECT serverid, server, last_checked, replicate, datareplicate, systemmetadatareplicate, hub FROM xml_replication");
408
				//increase dbconnection usage
409
				dbConn.increaseUsageCount(1);
410
				pstmt.execute();
411
				ResultSet rs = pstmt.getResultSet();
412
				boolean tablehasrows = rs.next();
413
				while (tablehasrows) {
414
					out.write("<tr><td>" + rs.getString(2) + "</td><td>");
415
					out.write(rs.getString(3) + "</td><td>");
416
					out.write(rs.getString(4) + "</td><td>");
417
					out.write(rs.getString(5) + "</td><td>");
418
					out.write(rs.getString(6) + "</td><td>");
419
					out.write(rs.getString(7) + "</td></tr>");
420
					tablehasrows = rs.next();
421
				}
422
				out.write("</table></body></html>");
423

    
424
				// list servers in server list
425
			} else if (subaction.equals("list")) {
426
				response.setContentType("text/html");
427
				out.write("<html><body><table border=\"1\">");
428
				out.write("<tr><td><b>server</b></td>");
429
				out.write("<td><b>last_checked</b></td>");
430
				out.write("<td><b>replicate</b></td>");
431
				out.write("<td><b>datareplicate</b></td>");
432
				out.write("<td><b>systemmetadatareplicate</b></td>");
433
				out.write("<td><b>hub</b></td></tr>");
434
				pstmt = dbConn.prepareStatement("SELECT serverid, server, last_checked, replicate, datareplicate, systemmetadatareplicate, hub FROM xml_replication");
435
				pstmt.execute();
436
				ResultSet rs = pstmt.getResultSet();
437
				boolean tablehasrows = rs.next();
438
				while (tablehasrows) {
439
					out.write("<tr><td>" + rs.getString(2) + "</td><td>");
440
					out.write(rs.getString(3) + "</td><td>");
441
					out.write(rs.getString(4) + "</td><td>");
442
					out.write(rs.getString(5) + "</td><td>");
443
					out.write(rs.getString(6) + "</td><td>");
444
					out.write(rs.getString(7) + "</td></tr>");
445

    
446
					tablehasrows = rs.next();
447
				}
448
				out.write("</table></body></html>");
449
			} else {
450

    
451
				out.write("<error>Unkonwn subaction</error>");
452

    
453
			}
454
			pstmt.close();
455
			//conn.close();
456

    
457
		} catch (Exception e) {
458
			logMetacat.error("ReplicationService.handleServerControlRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
459
			logReplication.error("ReplicationService.handleServerControlRequest - Error in "
460
					+ "MetacatReplication.handleServerControlRequest " + e.getMessage());
461
			e.printStackTrace(System.out);
462
		} finally {
463
			try {
464
				pstmt.close();
465
			}//try
466
			catch (SQLException ee) {
467
				logMetacat.error("ReplicationService.handleServerControlRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
468
				logReplication.error("ReplicationService.handleServerControlRequest - Error in MetacatReplication.handleServerControlRequest to close pstmt "
469
						+ ee.getMessage());
470
			}//catch
471
			finally {
472
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
473
			}//finally
474
			if (out != null) {
475
				try {
476
					out.close();
477
				} catch (IOException e) {
478
					logMetacat.error(e.getMessage(), e);
479
				}
480
			}
481
		}//finally
482

    
483
	}
484

    
485
	// download certificate with the public key from certURL and
486
	// upload it onto this server; it then must be imported as a
487
	// trusted certificate
488
	private static void downloadCertificate(String certURL) throws FileNotFoundException,
489
			IOException, MalformedURLException, PropertyNotFoundException {
490

    
491
		// the path to be uploaded to
492
		String certPath = SystemUtil.getContextDir();
493

    
494
		// get filename from the URL of the certificate
495
		String filename = certURL;
496
		int slash = Math.max(filename.lastIndexOf('/'), filename.lastIndexOf('\\'));
497
		if (slash > -1) {
498
			filename = filename.substring(slash + 1);
499
		}
500

    
501
		// open file output strem to write the input into it
502
		File f = new File(certPath, filename);
503
		synchronized (f) {
504
			try {
505
				if (f.exists()) {
506
					throw new IOException("File already exist: " + f.getCanonicalFile());
507
					// if ( f.exists() && !f.canWrite() ) {
508
					// throw new IOException("Not writable: " +
509
					// f.getCanonicalFile());
510
				}
511
			} catch (SecurityException se) {
512
				// if a security manager exists,
513
				// its checkRead method is called for f.exist()
514
				// or checkWrite method is called for f.canWrite()
515
				throw se;
516
			}
517

    
518
			// create a buffered byte output stream
519
			// that uses a default-sized output buffer
520
			FileOutputStream fos = new FileOutputStream(f);
521
			BufferedOutputStream out = new BufferedOutputStream(fos);
522

    
523
			// this should be http url
524
			URL url = new URL(certURL);
525
			BufferedInputStream bis = null;
526
			try {
527
				bis = new BufferedInputStream(url.openStream());
528
				byte[] buf = new byte[4 * 1024]; // 4K buffer
529
				int b = bis.read(buf);
530
				while (b != -1) {
531
					out.write(buf, 0, b);
532
					b = bis.read(buf);
533
				}
534
			} finally {
535
				if (bis != null)
536
					bis.close();
537
			}
538
			// the input and the output streams must be closed
539
			bis.close();
540
			out.flush();
541
			out.close();
542
			fos.close();
543
		} // end of synchronized(f)
544
	}
545

    
546
	/**
547
	 * when a forcereplication request comes in, local host sends a read request
548
	 * to the requesting server (remote server) for the specified docid. Then
549
	 * store it in local database.
550
	 */
551
	protected static void handleForceReplicateRequest(
552
			Hashtable<String, String[]> params, HttpServletResponse response,
553
			HttpServletRequest request) {
554
		String server = ((String[]) params.get("server"))[0]; // the server that
555
		String docid = ((String[]) params.get("docid"))[0]; // sent the document
556
		String dbaction = "UPDATE"; // the default action is UPDATE
557
		//    boolean override = false;
558
		//    int serverCode = 1;
559
		DBConnection dbConn = null;
560
		int serialNumber = -1;
561
		String docName = null;
562

    
563
		try {
564
			//if the url contains a dbaction then the default action is overridden
565
			if (params.containsKey("dbaction")) {
566
				dbaction = ((String[]) params.get("dbaction"))[0];
567
				//serverCode = MetacatReplication.getServerCode(server);
568
				//override = true; //we are now overriding the default action
569
			}
570
			logReplication.info("ReplicationService.handleForceReplicateRequest - Force replication request from: " + server);
571
			logReplication.info("ReplicationService.handleForceReplicateRequest - Force replication docid: " + docid);
572
			logReplication.info("ReplicationService.handleForceReplicateRequest - Force replication action: " + dbaction);
573
			// sending back read request to remote server
574
			URL u = new URL("https://" + server + "?server="
575
					+ MetacatUtil.getLocalReplicationServerName() + "&action=read&docid="
576
					+ docid);
577
			String xmldoc = ReplicationService.getURLContent(u);
578

    
579
			// get the document info from server
580
			URL docinfourl = new URL("https://" + server + "?server="
581
					+ MetacatUtil.getLocalReplicationServerName()
582
					+ "&action=getdocumentinfo&docid=" + docid);
583
			
584

    
585
			String docInfoStr = ReplicationService.getURLContent(docinfourl);
586
			// strip out the system metadata portion
587
			String systemMetadataXML = ReplicationUtil.getSystemMetadataContent(docInfoStr);
588
			docInfoStr = ReplicationUtil.getContentWithoutSystemMetadata(docInfoStr);
589
		   	  
590
			//dih is the parser for the docinfo xml format
591
			DocInfoHandler dih = new DocInfoHandler();
592
			XMLReader docinfoParser = ReplicationHandler.initParser(dih);
593
			docinfoParser.parse(new InputSource(new StringReader(docInfoStr)));
594
			//      Hashtable<String,Vector<AccessControlForSingleFile>> docinfoHash = dih.getDocInfo();
595
			Hashtable<String, String> docinfoHash = dih.getDocInfo();
596
			
597
			// Get home server of this docid
598
			String homeServer = (String) docinfoHash.get("home_server");
599
			
600
			// process system metadata
601
			if (systemMetadataXML != null) {
602
				SystemMetadata sysMeta = 
603
					TypeMarshaller.unmarshalTypeFromStream(
604
							SystemMetadata.class,
605
							new ByteArrayInputStream(systemMetadataXML.getBytes("UTF-8")));
606
				// need the guid-to-docid mapping
607
				IdentifierManager.getInstance().createMapping(sysMeta.getIdentifier().getValue(), docid);
608
			}
609
      
610
			// dates
611
			String createdDateString = docinfoHash.get("date_created");
612
			String updatedDateString = docinfoHash.get("date_updated");
613
			Date createdDate = DatatypeConverter.parseDateTime(createdDateString).getTime();
614
			Date updatedDate = DatatypeConverter.parseDateTime(updatedDateString).getTime();
615
		      
616
			logReplication.info("ReplicationService.handleForceReplicateRequest - homeServer: " + homeServer);
617
			// Get Document type
618
			String docType = (String) docinfoHash.get("doctype");
619
			logReplication.info("ReplicationService.handleForceReplicateRequest - docType: " + docType);
620
			String parserBase = null;
621
			// this for eml2 and we need user eml2 parser
622
			if (docType != null
623
					&& (docType.trim()).equals(DocumentImpl.EML2_0_0NAMESPACE)) {
624
				logReplication.warn("ReplicationService.handleForceReplicateRequest - This is an eml200 document!");
625
				parserBase = DocumentImpl.EML200;
626
			} else if (docType != null
627
					&& (docType.trim()).equals(DocumentImpl.EML2_0_1NAMESPACE)) {
628
				logReplication.warn("ReplicationService.handleForceReplicateRequest - This is an eml2.0.1 document!");
629
				parserBase = DocumentImpl.EML200;
630
			} else if (docType != null
631
					&& (docType.trim()).equals(DocumentImpl.EML2_1_0NAMESPACE)) {
632
				logReplication.warn("ReplicationService.handleForceReplicateRequest - This is an eml2.1.0 document!");
633
				parserBase = DocumentImpl.EML210;
634
			} else if (docType != null
635
					&& (docType.trim()).equals(DocumentImpl.EML2_1_1NAMESPACE)) {
636
				logReplication.warn("ReplicationService.handleForceReplicateRequest - This is an eml2.1.1 document!");
637
				parserBase = DocumentImpl.EML210;
638
			}
639
			logReplication.warn("ReplicationService.handleForceReplicateRequest - The parserBase is: " + parserBase);
640

    
641
			// Get DBConnection from pool
642
			dbConn = DBConnectionPool
643
					.getDBConnection("MetacatReplication.handleForceReplicateRequest");
644
			serialNumber = dbConn.getCheckOutSerialNumber();
645
			// write the document to local database
646
			DocumentImplWrapper wrapper = new DocumentImplWrapper(parserBase, false);
647
			//try this independently so we can set access even if the update action is invalid (i.e docid has not changed)
648
			try {
649
				wrapper.writeReplication(dbConn, xmldoc, null, null,
650
						dbaction, docid, null, null, homeServer, server, createdDate,
651
						updatedDate);
652
			} finally {
653

    
654
				//process extra access rules before dealing with the write exception (doc exist already)			
655
		        Vector<XMLAccessDAO> accessControlList = dih.getAccessControlList();
656
		        if (accessControlList != null) {
657
		        	AccessControlForSingleFile acfsf = new AccessControlForSingleFile(docid);
658
		        	for (XMLAccessDAO xmlAccessDAO : accessControlList) {
659
		        		if (!acfsf.accessControlExists(xmlAccessDAO)) {
660
		        			acfsf.insertPermissions(xmlAccessDAO);
661
							logReplication.info("ReplicationService.handleForceReplicateRequest - document " + docid
662
									+ " permissions added to DB");
663
		        		}
664
		            }
665
		        }
666
		        
667
		        // process the real owner and updater
668
				String user = (String) docinfoHash.get("user_owner");
669
				String updated = (String) docinfoHash.get("user_updated");
670
		        updateUserOwner(dbConn, docid, user, updated);
671

    
672
				logReplication.info("ReplicationService.handleForceReplicateRequest - document " + docid + " added to DB with "
673
						+ "action " + dbaction);
674
				
675
				EventLog.getInstance().log(request.getRemoteAddr(), request.getHeader("User-Agent"), REPLICATIONUSER, docid, dbaction);
676
			}
677
		} catch (SQLException sqle) {
678
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
679
			logReplication.error("ReplicationService.handleForceReplicateRequest - SQL error when adding doc " + docid + 
680
					" to DB with action " + dbaction + ": " + sqle.getMessage());
681
		} catch (MalformedURLException mue) {
682
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
683
			logReplication.error("ReplicationService.handleForceReplicateRequest - URL error when adding doc " + docid + 
684
					" to DB with action " + dbaction + ": " + mue.getMessage());
685
		} catch (SAXException se) {
686
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
687
			logReplication.error("ReplicationService.handleForceReplicateRequest - SAX parsing error when adding doc " + docid + 
688
					" to DB with action " + dbaction + ": " + se.getMessage());
689
		} catch (HandlerException he) {
690
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
691
			logReplication.error("ReplicationService.handleForceReplicateRequest - Handler error when adding doc " + docid + 
692
					" to DB with action " + dbaction + ": " + he.getMessage());
693
		} catch (IOException ioe) {
694
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
695
			logReplication.error("ReplicationService.handleForceReplicateRequest - I/O error when adding doc " + docid + 
696
					" to DB with action " + dbaction + ": " + ioe.getMessage());
697
		} catch (PermOrderException poe) {
698
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
699
			logReplication.error("ReplicationService.handleForceReplicateRequest - Permissions order error when adding doc " + docid + 
700
					" to DB with action " + dbaction + ": " + poe.getMessage());
701
		} catch (AccessControlException ace) {
702
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
703
			logReplication.error("ReplicationService.handleForceReplicateRequest - Permissions order error when adding doc " + docid + 
704
					" to DB with action " + dbaction + ": " + ace.getMessage());
705
		} catch (Exception e) {
706
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
707
			logReplication.error("ReplicationService.handleForceReplicateRequest - General error when adding doc " + docid + 
708
					" to DB with action " + dbaction + ": " + e.getMessage());
709
		} finally {
710
			// Return the checked out DBConnection
711
			DBConnectionPool.returnDBConnection(dbConn, serialNumber);
712
		}//finally
713
	}
714

    
715
	/*
716
	 * when a forcereplication delete request comes in, local host will delete this
717
	 * document
718
	 */
719
	protected static void handleForceReplicateDeleteRequest(
720
			Hashtable<String, String[]> params, HttpServletResponse response,
721
			HttpServletRequest request) {
722
		String server = ((String[]) params.get("server"))[0]; // the server that
723
		String docid = ((String[]) params.get("docid"))[0]; // sent the document
724
		try {
725
			logReplication.info("ReplicationService.handleForceReplicateDeleteRequest - force replication delete request from " + server);
726
			logReplication.info("ReplicationService.handleForceReplicateDeleteRequest - force replication delete docid " + docid);
727
			logReplication.info("ReplicationService.handleForceReplicateDeleteRequest - Force replication delete request from: " + server);
728
			logReplication.info("ReplicationService.handleForceReplicateDeleteRequest - Force replication delete docid: " + docid);
729
			DocumentImpl.delete(docid, null, null, server);
730
			logReplication.info("ReplicationService.handleForceReplicateDeleteRequest - document " + docid + " was successfully deleted ");
731
			EventLog.getInstance().log(request.getRemoteAddr(), request.getHeader("User-Agent"), REPLICATIONUSER, docid,
732
					"delete");
733
			logReplication.info("ReplicationService.handleForceReplicateDeleteRequest - document " + docid + " was successfully deleted ");
734
		} catch (McdbDocNotFoundException e) {
735
			logMetacat.error("ReplicationService.handleForceReplicateDeleteRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
736
			logReplication.error("document " + docid
737
					+ " failed to delete because " + e.getMessage());
738
			logReplication.error("ReplicationService.handleForceReplicateDeleteRequest - error: " + e.getMessage());
739
		} catch (InsufficientKarmaException e) {
740
			logMetacat.error("ReplicationService.handleForceReplicateDeleteRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
741
			logReplication.error("document " + docid
742
					+ " failed to delete because " + e.getMessage());
743
			logReplication.error("ReplicationService.handleForceReplicateDeleteRequest - error: " + e.getMessage());
744
		} catch (SQLException e) {
745
			logMetacat.error("ReplicationService.handleForceReplicateDeleteRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
746
			logReplication.error("document " + docid
747
					+ " failed to delete because " + e.getMessage());
748
			logReplication.error("ReplicationService.handleForceReplicateDeleteRequest - error: " + e.getMessage());
749
		} catch (Exception e) {
750
			logMetacat.error("ReplicationService.handleForceReplicateDeleteRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
751
			logReplication.error("document " + docid
752
					+ " failed to delete because " + e.getMessage());
753
			logReplication.error("ReplicationService.handleForceReplicateDeleteRequest - error: " + e.getMessage());
754

    
755
		}//catch
756

    
757
	}
758

    
759
	/**
760
	 * when a forcereplication data file request comes in, local host sends a
761
	 * readdata request to the requesting server (remote server) for the specified
762
	 * docid. Then store it in local database and file system
763
	 */
764
	protected static void handleForceReplicateDataFileRequest(Hashtable<String, String[]> params,
765
			HttpServletRequest request) {
766

    
767
		//make sure there is some parameters
768
		if (params.isEmpty()) {
769
			return;
770
		}
771
		// Get remote server
772
		String server = ((String[]) params.get("server"))[0];
773
		// the docid should include rev number
774
		String docid = ((String[]) params.get("docid"))[0];
775
		// Make sure there is a docid and server
776
		if (docid == null || server == null || server.equals("")) {
777
			logMetacat.error("ReplicationService.handleForceReplicateDataFileRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
778
			logReplication.error("ReplicationService.handleForceReplicateDataFileRequest - Didn't specify docid or server for replication");
779
			return;
780
		}
781

    
782
		// Overide or not
783
		//    boolean override = false;
784
		// dbaction - update or insert
785
		String dbaction = null;
786

    
787
		try {
788
			//docid was switch to two parts uinque code and rev
789
			//String uniqueCode=MetacatUtil.getDocIdFromString(docid);
790
			//int rev=MetacatUtil.getVersionFromString(docid);
791
			if (params.containsKey("dbaction")) {
792
				dbaction = ((String[]) params.get("dbaction"))[0];
793
			} else//default value is update
794
			{
795
				dbaction = "update";
796
			}
797

    
798
			logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - Force replication request from: " + server);
799
			logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - Force replication docid: " + docid);
800
			logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - Force replication action: " + dbaction);
801
			// get the document info from server
802
			URL docinfourl = new URL("https://" + server + "?server="
803
					+ MetacatUtil.getLocalReplicationServerName()
804
					+ "&action=getdocumentinfo&docid=" + docid);
805

    
806
			String docInfoStr = ReplicationService.getURLContent(docinfourl);
807
			
808
			// strip out the system metadata portion
809
		    String systemMetadataXML = ReplicationUtil.getSystemMetadataContent(docInfoStr);
810
		   	docInfoStr = ReplicationUtil.getContentWithoutSystemMetadata(docInfoStr);
811

    
812
			//dih is the parser for the docinfo xml format
813
			DocInfoHandler dih = new DocInfoHandler();
814
			XMLReader docinfoParser = ReplicationHandler.initParser(dih);
815
			docinfoParser.parse(new InputSource(new StringReader(docInfoStr)));
816
			Hashtable<String, String> docinfoHash = dih.getDocInfo();
817
			
818
			String docName = (String) docinfoHash.get("docname");
819

    
820
			String docType = (String) docinfoHash.get("doctype");
821

    
822
			String docHomeServer = (String) docinfoHash.get("home_server");
823
			
824
			String createdDateString = docinfoHash.get("date_created");
825
			String updatedDateString = docinfoHash.get("date_updated");
826
			
827
			Date createdDate = DatatypeConverter.parseDateTime(createdDateString).getTime();
828
			Date updatedDate = DatatypeConverter.parseDateTime(updatedDateString).getTime();
829
			
830
			logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - docHomeServer of datafile: " + docHomeServer);
831

    
832
			if (dbaction.equals("insert") || dbaction.equals("update")) {
833
				//Get data file and store it into local file system.
834
				// sending back readdata request to server
835
				URL url = new URL("https://" + server + "?server="
836
						+ MetacatUtil.getLocalReplicationServerName()
837
						+ "&action=readdata&docid=" + docid);
838
				String datafilePath = PropertyService
839
						.getProperty("application.datafilepath");
840

    
841
				Exception writeException = null;
842
				//register data file into xml_documents table and wite data file
843
				//into file system
844
				try {
845
					DocumentImpl.writeDataFileInReplication(url.openStream(),
846
							datafilePath, docName, docType, docid, null, docHomeServer,
847
							server, DocumentImpl.DOCUMENTTABLE, false, createdDate,
848
							updatedDate);
849
				} catch (Exception e) {
850
					writeException = e;
851
				}
852
				
853
				// process the real owner and updater
854
				DBConnection dbConn = DBConnectionPool.getDBConnection("ReplicationService.handleForceDataFileRequest");
855
		        int serialNumber = dbConn.getCheckOutSerialNumber();
856
		        dbConn.setAutoCommit(false);
857
				String user = (String) docinfoHash.get("user_owner");
858
				String updated = (String) docinfoHash.get("user_updated");
859
		        updateUserOwner(dbConn, docid, user, updated);
860
		        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
861
		        
862
		        Vector<XMLAccessDAO> accessControlList = dih.getAccessControlList();
863
		        if (accessControlList != null) {
864
		        	AccessControlForSingleFile acfsf = new AccessControlForSingleFile(docid);
865
		        	for (XMLAccessDAO xmlAccessDAO : accessControlList) {
866
		        		if (!acfsf.accessControlExists(xmlAccessDAO)) {
867
		        			acfsf.insertPermissions(xmlAccessDAO);
868
							logReplication.info("ReplicationService.handleForceReplicateRequest - document " + docid
869
									+ " permissions added to DB");
870
		        		}
871
		            }
872
		        }
873
		        
874
		        // process system metadata
875
		        if (systemMetadataXML != null) {
876
		      	  SystemMetadata sysMeta = 
877
		      		TypeMarshaller.unmarshalTypeFromStream(
878
		      				  SystemMetadata.class, 
879
		      				  new ByteArrayInputStream(systemMetadataXML.getBytes("UTF-8")));
880
		      	  // need the guid-to-docid mapping
881
		      	  IdentifierManager.getInstance().createMapping(sysMeta.getIdentifier().getValue(), docid);
882
		        }
883

    
884
				if (writeException != null) {
885
					throw writeException;
886
				}
887

    
888
				logReplication.info("ReplicationService.handleForceReplicateDataFileRequest - datafile " + docid + " added to DB with "
889
						+ "action " + dbaction);
890
				EventLog.getInstance().log(request.getRemoteAddr(), request.getHeader("User-Agent"), REPLICATIONUSER,
891
						docid, dbaction);
892
			}
893

    
894
		} catch (Exception e) {
895
			logMetacat.error("ReplicationService.handleForceReplicateDataFileRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
896
			logReplication.error("ReplicationService.handleForceReplicateDataFileRequest - Datafile " + docid
897
					+ " failed to added to DB with " + "action " + dbaction + " because "
898
					+ e.getMessage());
899
			logReplication.error("ReplicationService.handleForceReplicateDataFileRequest - ERROR in MetacatReplication.handleForceDataFileReplicate"
900
					+ "Request(): " + e.getMessage());
901
		}
902
	}
903

    
904
	/**
905
	 * Grants or denies a lock to a requesting host.
906
	 * The servlet parameters of interrest are:
907
	 * docid: the docid of the file the lock is being requested for
908
	 * currentdate: the timestamp of the document on the remote server
909
	 *
910
	 */
911
	protected static void handleGetLockRequest(
912
			Hashtable<String, String[]> params, HttpServletResponse response) {
913

    
914
		try {
915

    
916
			String docid = ((String[]) params.get("docid"))[0];
917
			String remoteRev = ((String[]) params.get("updaterev"))[0];
918
			DocumentImpl requestDoc = new DocumentImpl(docid);
919
			logReplication.info("ReplicationService.handleGetLockRequest - lock request for " + docid);
920
			int localRevInt = requestDoc.getRev();
921
			int remoteRevInt = Integer.parseInt(remoteRev);
922

    
923
			// get a writer for sending back to response
924
			response.setContentType("text/xml");
925
			Writer out = response.getWriter();
926
			
927
			if (remoteRevInt >= localRevInt) {
928
				if (!fileLocks.contains(docid)) { //grant the lock if it is not already locked
929
					fileLocks.add(0, docid); //insert at the beginning of the queue Vector
930
					//send a message back to the the remote host authorizing the insert
931
					out.write("<lockgranted><docid>" + docid
932
									+ "</docid></lockgranted>");
933
					//          lockThread = new Thread(this);
934
					//          lockThread.setPriority(Thread.MIN_PRIORITY);
935
					//          lockThread.start();
936
					logReplication.info("ReplicationService.handleGetLockRequest - lock granted for " + docid);
937
				} else { //deny the lock
938
					out.write("<filelocked><docid>" + docid + "</docid></filelocked>");
939
					logReplication.info("ReplicationService.handleGetLockRequest - lock denied for " + docid
940
							+ "reason: file already locked");
941
				}
942
			} else {//deny the lock.
943
				out.write("<outdatedfile><docid>" + docid + "</docid></filelocked>");
944
				logReplication.info("ReplicationService.handleGetLockRequest - lock denied for " + docid
945
						+ "reason: client has outdated file");
946
			}
947
			out.close();
948
			//conn.close();
949
		} catch (Exception e) {
950
			logMetacat.error("ReplicationService.handleGetLockRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
951
			logReplication.error("ReplicationService.handleGetLockRequest - error requesting file lock from MetacatReplication."
952
					+ "handleGetLockRequest: " + e.getMessage());
953
			e.printStackTrace(System.out);
954
		}
955
	}
956

    
957
	/**
958
	 * Sends all of the xml_documents information encoded in xml to a requestor
959
	 * the format is:
960
	 * <!ELEMENT documentinfo (docid, docname, doctype, doctitle, user_owner,
961
	 *                  user_updated, home_server, public_access, rev)/>
962
	 * all of the subelements of document info are #PCDATA
963
	 */
964
	protected static void handleGetDocumentInfoRequest(
965
			Hashtable<String, String[]> params, HttpServletResponse response) {
966
		String docid = ((String[]) (params.get("docid")))[0];
967
		StringBuffer sb = new StringBuffer();
968

    
969
		try {
970
			DocumentImpl doc = new DocumentImpl(docid);
971
			sb.append("<documentinfo><docid>").append(docid);
972
			sb.append("</docid>");
973
			
974
			try {
975
				// serialize the System Metadata as XML for docinfo
976
				String guid = IdentifierManager.getInstance().getGUID(doc.getDocID(), doc.getRev());
977
				SystemMetadata systemMetadata = IdentifierManager.getInstance().getSystemMetadata(guid);
978
				ByteArrayOutputStream baos = new ByteArrayOutputStream();
979
				TypeMarshaller.marshalTypeToOutputStream(systemMetadata, baos);
980
				String systemMetadataXML = baos.toString("UTF-8");
981
				sb.append("<systemMetadata>");
982
				sb.append(systemMetadataXML);
983
				sb.append("</systemMetadata>");
984
			} catch(McdbDocNotFoundException e) {
985
			  logMetacat.warn("No SystemMetadata found for: " + docid);
986
			}
987
			
988
			Calendar created = Calendar.getInstance();
989
			created.setTime(doc.getCreateDate());
990
			Calendar updated = Calendar.getInstance();
991
			updated.setTime(doc.getUpdateDate());
992
			
993
			sb.append("<docname>").append(doc.getDocname());
994
			sb.append("</docname><doctype>").append(doc.getDoctype());
995
			sb.append("</doctype>");
996
			sb.append("<user_owner>").append(doc.getUserowner());
997
			sb.append("</user_owner><user_updated>").append(doc.getUserupdated());
998
			sb.append("</user_updated>");
999
			sb.append("<date_created>");
1000
			sb.append(DatatypeConverter.printDateTime(created));
1001
			sb.append("</date_created>");
1002
			sb.append("<date_updated>");
1003
			sb.append(DatatypeConverter.printDateTime(updated));
1004
			sb.append("</date_updated>");
1005
			sb.append("<home_server>");
1006
			sb.append(doc.getDocHomeServer());
1007
			sb.append("</home_server>");
1008
			sb.append("<public_access>").append(doc.getPublicaccess());
1009
			sb.append("</public_access><rev>").append(doc.getRev());
1010
			sb.append("</rev>");
1011

    
1012
			sb.append("<accessControl>");
1013

    
1014
			AccessControlForSingleFile acfsf = new AccessControlForSingleFile(docid); 
1015
			sb.append(acfsf.getAccessString());
1016
			
1017
			sb.append("</accessControl>");
1018

    
1019
			sb.append("</documentinfo>");
1020
			// get a writer for sending back to response
1021
			response.setContentType("text/xml");
1022
			Writer out = response.getWriter();
1023
			out.write(sb.toString());
1024
			out.close();
1025

    
1026
		} catch (Exception e) {
1027
			logMetacat.error("ReplicationService.handleGetDocumentInfoRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1028
			logReplication.error("ReplicationService.handleGetDocumentInfoRequest - error in metacatReplication.handlegetdocumentinforequest "
1029
					+ "for doc: " + docid + " : " + e.getMessage());
1030
		}
1031

    
1032
	}
1033
	
1034
	/**
1035
	 * Sends System Metadata as XML
1036
	 */
1037
	protected static void handleGetSystemMetadataRequest(
1038
			Hashtable<String, String[]> params, HttpServletResponse response) {
1039
		String guid = ((String[]) (params.get("guid")))[0];
1040
		String systemMetadataXML = null;
1041
		try {
1042
			
1043
			// serialize the System Metadata as XML 
1044
			SystemMetadata systemMetadata = IdentifierManager.getInstance().getSystemMetadata(guid);
1045
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
1046
			TypeMarshaller.marshalTypeToOutputStream(systemMetadata, baos);
1047
			systemMetadataXML = baos.toString("UTF-8");
1048
				
1049
			// get a writer for sending back to response
1050
			response.setContentType("text/xml");
1051
			Writer out = response.getWriter();
1052
			out.write(systemMetadataXML);
1053
			out.close();
1054

    
1055
		} catch (Exception e) {
1056
			String msg = "ReplicationService.handleGetSystemMetadataRequest for guid: " + guid + " : " + e.getMessage();
1057
			logMetacat.error(msg);                         
1058
			logReplication.error(msg);
1059
		}
1060

    
1061
	}
1062
	
1063
	/**
1064
	 * when a forcereplication request comes in, local host sends a read request
1065
	 * to the requesting server (remote server) for the specified docid. Then
1066
	 * store it in local database.
1067
	 */
1068
	protected static void handleForceReplicateSystemMetadataRequest(
1069
			Hashtable<String, String[]> params, HttpServletResponse response,
1070
			HttpServletRequest request) {
1071
		String server = ((String[]) params.get("server"))[0]; // the server that
1072
		String guid = ((String[]) params.get("guid"))[0]; // sent the document
1073
		
1074
		try {
1075
			logReplication.info("ReplicationService.handleForceReplicateSystemMetadataRequest - Force replication system metadata request from: " + server);
1076
			// get the system metadata from server
1077
			URL docinfourl = new URL("https://" + server + "?server="
1078
					+ MetacatUtil.getLocalReplicationServerName()
1079
					+ "&action=getsystemmetadata&guid=" + guid);
1080
			
1081
			String systemMetadataXML = ReplicationService.getURLContent(docinfourl);
1082
						
1083
			// process system metadata
1084
			if (systemMetadataXML != null) {
1085
				SystemMetadata sysMeta = 
1086
					TypeMarshaller.unmarshalTypeFromStream(
1087
							SystemMetadata.class,
1088
							new ByteArrayInputStream(systemMetadataXML.getBytes("UTF-8")));
1089
				HazelcastService.getInstance().getSystemMetadataMap().put(sysMeta.getIdentifier(), sysMeta);
1090
			}
1091
      
1092
			logReplication.info("ReplicationService.handleForceReplicateSystemMetadataRequest - processed guid: " + guid);
1093
			EventLog.getInstance().log(request.getRemoteAddr(), request.getHeader("User-Agent"), REPLICATIONUSER, guid, "systemMetadata");
1094

    
1095
		} catch (Exception e) {
1096
			logMetacat.error("ReplicationService.handleForceReplicateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG, e);                         
1097
			logReplication.error("ReplicationService.handleForceReplicateRequest - General error when processing guid: " + guid, e);
1098
		}
1099
	}
1100

    
1101
	/**
1102
	 * Sends a datafile to a remote host
1103
	 */
1104
	protected static void handleGetDataFileRequest(OutputStream outPut,
1105
			Hashtable<String, String[]> params, HttpServletResponse response)
1106

    
1107
	{
1108
		// File path for data file
1109
		String filepath;
1110
		// Request docid
1111
		String docId = ((String[]) (params.get("docid")))[0];
1112
		//check if the doicd is null
1113
		if (docId == null) {
1114
			logMetacat.error("ReplicationService.handleGetDataFileRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1115
			logReplication.error("ReplicationService.handleGetDataFileRequest - Didn't specify docid for replication");
1116
			return;
1117
		}
1118

    
1119
		//try to open a https stream to test if the request server's public key
1120
		//in the key store, this is security issue
1121
		try {
1122
			filepath = PropertyService.getProperty("application.datafilepath");
1123
			String server = params.get("server")[0];
1124
			URL u = new URL("https://" + server + "?server="
1125
					+ MetacatUtil.getLocalReplicationServerName() + "&action=test");
1126
			String test = ReplicationService.getURLContent(u);
1127
			//couldn't pass the test
1128
			if (test.indexOf("successfully") == -1) {
1129
				//response.setContentType("text/xml");
1130
				//outPut.println("<error>Couldn't pass the trust test</error>");
1131
				logMetacat.error("ReplicationService.handleGetDataFileRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1132
				logReplication.error("ReplicationService.handleGetDataFileRequest - Couldn't pass the trust test");
1133
				return;
1134
			}
1135
		}//try
1136
		catch (Exception ee) {
1137
			return;
1138
		}//catch
1139

    
1140
		if (!filepath.endsWith("/")) {
1141
			filepath += "/";
1142
		}
1143
		// Get file aboslute file name
1144
		String filename = filepath + docId;
1145

    
1146
		//MIME type
1147
		String contentType = null;
1148
		if (filename.endsWith(".xml")) {
1149
			contentType = "text/xml";
1150
		} else if (filename.endsWith(".css")) {
1151
			contentType = "text/css";
1152
		} else if (filename.endsWith(".dtd")) {
1153
			contentType = "text/plain";
1154
		} else if (filename.endsWith(".xsd")) {
1155
			contentType = "text/xml";
1156
		} else if (filename.endsWith("/")) {
1157
			contentType = "text/html";
1158
		} else {
1159
			File f = new File(filename);
1160
			if (f.isDirectory()) {
1161
				contentType = "text/html";
1162
			} else {
1163
				contentType = "application/octet-stream";
1164
			}
1165
		}
1166

    
1167
		// Set the mime type
1168
		response.setContentType(contentType);
1169

    
1170
		// Get the content of the file
1171
		FileInputStream fin = null;
1172
		try {
1173
			// FileInputStream to metacat
1174
			fin = new FileInputStream(filename);
1175
			// 4K buffer
1176
			byte[] buf = new byte[4 * 1024];
1177
			// Read data from file input stream to byte array
1178
			int b = fin.read(buf);
1179
			// Write to outStream from byte array
1180
			while (b != -1) {
1181
				outPut.write(buf, 0, b);
1182
				b = fin.read(buf);
1183
			}
1184
			// close file input stream
1185
			fin.close();
1186

    
1187
		}//try
1188
		catch (Exception e) {
1189
			logMetacat.error("ReplicationService.handleGetDataFileRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1190
			logReplication.error("ReplicationService.handleGetDataFileRequest - error getting data file from MetacatReplication."
1191
					+ "handlGetDataFileRequest " + e.getMessage());
1192
			e.printStackTrace(System.out);
1193
		}//catch
1194

    
1195
	}
1196

    
1197
	/**
1198
	 * Sends a document to a remote host
1199
	 */
1200
	protected static void handleGetDocumentRequest(
1201
			Hashtable<String, String[]> params, HttpServletResponse response) {
1202

    
1203
		String urlString = null;
1204
		String documentPath = null;
1205
		String errorMsg = null;
1206
		try {
1207
			// try to open a https stream to test if the request server's public
1208
			// key
1209
			// in the key store, this is security issue
1210
			String server = params.get("server")[0];
1211
			urlString = "https://" + server + "?server="
1212
					+ MetacatUtil.getLocalReplicationServerName() + "&action=test";
1213
			URL u = new URL(urlString);
1214
			String test = ReplicationService.getURLContent(u);
1215
			// couldn't pass the test
1216
			if (test.indexOf("successfully") == -1) {
1217
				response.setContentType("text/xml");
1218
				Writer out = response.getWriter();
1219
				out.write("<error>Couldn't pass the trust test " + test + " </error>");
1220
				out.close();
1221
				return;
1222
			}
1223

    
1224
			String docid = params.get("docid")[0];
1225
			logReplication.debug("ReplicationService.handleGetDocumentRequest - MetacatReplication.handleGetDocumentRequest for docid: "
1226
					+ docid);
1227
			DocumentImpl di = new DocumentImpl(docid);
1228

    
1229
			String documentDir = PropertyService
1230
					.getProperty("application.documentfilepath");
1231
			documentPath = documentDir + FileUtil.getFS() + docid;
1232

    
1233
			// if the document does not exist on disk, read it from db and write
1234
			// it to disk.
1235
			if (FileUtil.getFileStatus(documentPath) == FileUtil.DOES_NOT_EXIST
1236
					|| FileUtil.getFileSize(documentPath) == 0) {
1237
				FileOutputStream fos = new FileOutputStream(documentPath);
1238
				di.toXml(fos, null, null, true);
1239
			}
1240

    
1241
			// read the file from disk and send it to outputstream
1242
			OutputStream outputStream = response.getOutputStream();
1243
			di.readFromFileSystem(outputStream, null, null, documentPath);
1244

    
1245
			logReplication.info("ReplicationService.handleGetDocumentRequest - document " + docid + " sent");
1246

    
1247
			// return to avoid continuing to the error reporting section at the end
1248
			return;
1249
			
1250
		} catch (MalformedURLException mue) {
1251
			logMetacat.error("ReplicationService.handleGetDocumentRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1252
			logReplication.error("ReplicationService.handleGetDocumentRequest - Url error when getting document from MetacatReplication."
1253
					+ "handlGetDocumentRequest for url: " + urlString + " : "
1254
					+ mue.getMessage());
1255
			// e.printStackTrace(System.out);
1256
			
1257
		} catch (IOException ioe) {
1258
			logMetacat.error("ReplicationService.handleGetDocumentRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1259
			logReplication.error("ReplicationService.handleGetDocumentRequest - I/O error when getting document from MetacatReplication."
1260
					+ "handlGetDocumentRequest for file: " + documentPath + " : "
1261
					+ ioe.getMessage());
1262
			errorMsg = ioe.getMessage();
1263
		} catch (PropertyNotFoundException pnfe) {
1264
			logMetacat.error("ReplicationService.handleGetDocumentRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1265
			logReplication
1266
					.error("ReplicationService.handleGetDocumentRequest - Error getting property when getting document from MetacatReplication."
1267
							+ "handlGetDocumentRequest for file: "
1268
							+ documentPath
1269
							+ " : "
1270
							+ pnfe.getMessage());
1271
			// e.printStackTrace(System.out);
1272
			errorMsg = pnfe.getMessage();
1273
		} catch (McdbException me) {
1274
			logReplication
1275
					.error("ReplicationService.handleGetDocumentRequest - Document implementation error  getting property when getting document from MetacatReplication."
1276
							+ "handlGetDocumentRequest for file: "
1277
							+ documentPath
1278
							+ " : "
1279
							+ me.getMessage());
1280
			// e.printStackTrace(System.out);
1281
			errorMsg = me.getMessage();
1282
		}
1283
		
1284
		// report any errors if we got here
1285
		response.setContentType("text/xml");
1286
		Writer out = null;
1287
		try {
1288
			response.getWriter();
1289
			out = response.getWriter();
1290
			out.write("<error>" + errorMsg + "</error>");
1291
		} catch (Exception e) {
1292
			logMetacat.error(e.getMessage(), e);
1293
		} finally {
1294
			try {
1295
				out.close();
1296
			} catch (IOException e) {
1297
				logMetacat.error(e.getMessage(), e);
1298
			}
1299
		}
1300
		
1301

    
1302
	}
1303

    
1304
	/**
1305
	 * Sends a list of all of the documents on this sever along with their
1306
	 * revision numbers. The format is: <!ELEMENT replication (server, updates)>
1307
	 * <!ELEMENT server (#PCDATA)> <!ELEMENT updates ((updatedDocument |
1308
	 * deleteDocument | revisionDocument)*)> <!ELEMENT updatedDocument (docid,
1309
	 * rev, datafile*)> <!ELEMENT deletedDocument (docid, rev)> <!ELEMENT
1310
	 * revisionDocument (docid, rev, datafile*)> <!ELEMENT docid (#PCDATA)>
1311
	 * <!ELEMENT rev (#PCDATA)> <!ELEMENT datafile (#PCDATA)> note that the rev
1312
	 * in deletedDocument is always empty. I just left it in there to make the
1313
	 * parser implementation easier.
1314
	 */
1315
	protected static void handleUpdateRequest(Hashtable<String, String[]> params,
1316
			HttpServletResponse response) {
1317
		// Checked out DBConnection
1318
		DBConnection dbConn = null;
1319
		// DBConenction serial number when checked it out
1320
		int serialNumber = -1;
1321
		PreparedStatement pstmt = null;
1322
		// Server list to store server info of xml_replication table
1323
		ReplicationServerList serverList = null;
1324
		
1325
		// a writer for response
1326
		Writer out = null;
1327

    
1328
		try {
1329
			// get writer, TODO: encoding?
1330
			response.setContentType("text/xml");
1331
			out = response.getWriter();
1332
			
1333
			// Check out a DBConnection from pool
1334
			dbConn = DBConnectionPool
1335
					.getDBConnection("MetacatReplication.handleUpdateRequest");
1336
			serialNumber = dbConn.getCheckOutSerialNumber();
1337
			// Create a server list from xml_replication table
1338
			serverList = new ReplicationServerList();
1339

    
1340
			// Get remote server name from param
1341
			String server = ((String[]) params.get("server"))[0];
1342
			// If no servr name in param, return a error
1343
			if (server == null || server.equals("")) {
1344
				out.write("<error>Request didn't specify server name</error>");
1345
				out.close();
1346
				return;
1347
			}//if
1348

    
1349
			//try to open a https stream to test if the request server's public key
1350
			//in the key store, this is security issue
1351
			String testUrl = "https://" + server + "?server="
1352
            + MetacatUtil.getLocalReplicationServerName() + "&action=test";
1353
			logReplication.info("Running trust test: " + testUrl);
1354
			URL u = new URL(testUrl);
1355
			String test = ReplicationService.getURLContent(u);
1356
			logReplication.info("Ouput from test is '" + test + "'");
1357
			//couldn't pass the test
1358
			if (test.indexOf("successfully") == -1) {
1359
			    logReplication.error("Trust test failed.");
1360
				out.write("<error>Couldn't pass the trust test</error>");
1361
				out.close();
1362
				return;
1363
			}
1364
			logReplication.info("Trust test succeeded.");
1365

    
1366
			// Check if local host configure to replicate xml documents to remote
1367
			// server. If not send back a error message
1368
			if (!serverList.getReplicationValue(server)) {
1369
				out.write("<error>Configuration not allow to replicate document to you</error>");
1370
				out.close();
1371
				return;
1372
			}//if
1373

    
1374
			// Store the sql command
1375
			StringBuffer docsql = new StringBuffer();
1376
			StringBuffer revisionSql = new StringBuffer();
1377
			// Stroe the docid list
1378
			StringBuffer doclist = new StringBuffer();
1379
			// Store the deleted docid list
1380
			StringBuffer delsql = new StringBuffer();
1381
			// Store the data set file
1382
			Vector<Vector<String>> packageFiles = new Vector<Vector<String>>();
1383

    
1384
			// Append local server's name and replication servlet to doclist
1385
			doclist.append("<?xml version=\"1.0\"?><replication>");
1386
			doclist.append("<server>")
1387
					.append(MetacatUtil.getLocalReplicationServerName());
1388
			//doclist.append(util.getProperty("replicationpath"));
1389
			doclist.append("</server><updates>");
1390

    
1391
			// Get correct docid that reside on this server according the requesting
1392
			// server's replicate and data replicate value in xml_replication table
1393
			docsql.append(DatabaseService.getInstance().getDBAdapter().getReplicationDocumentListSQL());
1394
			//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)) ");
1395
			revisionSql.append("select docid, rev, doctype from xml_revisions ");
1396
			// If the localhost is not a hub to the remote server, only replicate
1397
			// the docid' which home server is local host (server_location =1)
1398
			if (!serverList.getHubValue(server)) {
1399
				String serverLocationDoc = " and a.server_location = 1";
1400
				String serverLocationRev = "where server_location = 1";
1401
				docsql.append(serverLocationDoc);
1402
				revisionSql.append(serverLocationRev);
1403
			}
1404
			logReplication.info("ReplicationService.handleUpdateRequest - Doc sql: " + docsql.toString());
1405

    
1406
			// Get any deleted documents
1407
			delsql.append("select distinct docid from ");
1408
			delsql.append("xml_revisions where docid not in (select docid from ");
1409
			delsql.append("xml_documents) ");
1410
			// If the localhost is not a hub to the remote server, only replicate
1411
			// the docid' which home server is local host (server_location =1)
1412
			if (!serverList.getHubValue(server)) {
1413
				delsql.append("and server_location = 1");
1414
			}
1415
			logReplication.info("ReplicationService.handleUpdateRequest - Deleted sql: " + delsql.toString());
1416

    
1417
			// Get docid list of local host
1418
			pstmt = dbConn.prepareStatement(docsql.toString());
1419
			pstmt.execute();
1420
			ResultSet rs = pstmt.getResultSet();
1421
			boolean tablehasrows = rs.next();
1422
			//If metacat configed to replicate data file
1423
			//if ((util.getProperty("replicationsenddata")).equals("on"))
1424
			boolean replicateData = serverList.getDataReplicationValue(server);
1425
			if (replicateData) {
1426
				while (tablehasrows) {
1427
					String recordDoctype = rs.getString(3);
1428
					Vector<String> packagedoctypes = MetacatUtil
1429
							.getOptionList(PropertyService
1430
									.getProperty("xml.packagedoctype"));
1431
					//if this is a package file, put it at the end
1432
					//because if a package file is read before all of the files it
1433
					//refers to are loaded then there is an error
1434
					if (recordDoctype != null && !packagedoctypes.contains(recordDoctype)) {
1435
						//If this is not data file
1436
						if (!recordDoctype.equals("BIN")) {
1437
							//for non-data file document
1438
							doclist.append("<updatedDocument>");
1439
							doclist.append("<docid>").append(rs.getString(1));
1440
							doclist.append("</docid><rev>").append(rs.getInt(2));
1441
							doclist.append("</rev>");
1442
							doclist.append("</updatedDocument>");
1443
						}//if
1444
						else {
1445
							//for data file document, in datafile attributes
1446
							//we put "datafile" value there
1447
							doclist.append("<updatedDocument>");
1448
							doclist.append("<docid>").append(rs.getString(1));
1449
							doclist.append("</docid><rev>").append(rs.getInt(2));
1450
							doclist.append("</rev>");
1451
							doclist.append("<datafile>");
1452
							doclist.append(PropertyService
1453
									.getProperty("replication.datafileflag"));
1454
							doclist.append("</datafile>");
1455
							doclist.append("</updatedDocument>");
1456
						}//else
1457
					}//if packagedoctpes
1458
					else { //the package files are saved to be put into the xml later.
1459
						Vector<String> v = new Vector<String>();
1460
						v.add(rs.getString(1));
1461
						v.add(String.valueOf(rs.getInt(2)));
1462
						packageFiles.add(v);
1463
					}//esle
1464
					tablehasrows = rs.next();
1465
				}//while
1466
			}//if
1467
			else //metacat was configured not to send data file
1468
			{
1469
				while (tablehasrows) {
1470
					String recordDoctype = rs.getString(3);
1471
					if (!recordDoctype.equals("BIN")) { //don't replicate data files
1472
						Vector<String> packagedoctypes = MetacatUtil
1473
								.getOptionList(PropertyService
1474
										.getProperty("xml.packagedoctype"));
1475
						if (recordDoctype != null
1476
								&& !packagedoctypes.contains(recordDoctype)) { //if this is a package file, put it at the end
1477
							//because if a package file is read before all of the files it
1478
							//refers to are loaded then there is an error
1479
							doclist.append("<updatedDocument>");
1480
							doclist.append("<docid>").append(rs.getString(1));
1481
							doclist.append("</docid><rev>").append(rs.getInt(2));
1482
							doclist.append("</rev>");
1483
							doclist.append("</updatedDocument>");
1484
						} else { //the package files are saved to be put into the xml later.
1485
							Vector<String> v = new Vector<String>();
1486
							v.add(rs.getString(1));
1487
							v.add(String.valueOf(rs.getInt(2)));
1488
							packageFiles.add(v);
1489
						}
1490
					}//if
1491
					tablehasrows = rs.next();
1492
				}//while
1493
			}//else
1494

    
1495
			pstmt = dbConn.prepareStatement(delsql.toString());
1496
			//usage count should increas 1
1497
			dbConn.increaseUsageCount(1);
1498

    
1499
			pstmt.execute();
1500
			rs = pstmt.getResultSet();
1501
			tablehasrows = rs.next();
1502
			while (tablehasrows) { //handle the deleted documents
1503
				doclist.append("<deletedDocument><docid>").append(rs.getString(1));
1504
				doclist.append("</docid><rev></rev></deletedDocument>");
1505
				//note that rev is always empty for deleted docs
1506
				tablehasrows = rs.next();
1507
			}
1508

    
1509
			//now we can put the package files into the xml results
1510
			for (int i = 0; i < packageFiles.size(); i++) {
1511
				Vector<String> v = packageFiles.elementAt(i);
1512
				doclist.append("<updatedDocument>");
1513
				doclist.append("<docid>").append(v.elementAt(0));
1514
				doclist.append("</docid><rev>");
1515
				doclist.append(v.elementAt(1));
1516
				doclist.append("</rev>");
1517
				doclist.append("</updatedDocument>");
1518
			}
1519
			// add revision doc list  
1520
			doclist.append(prepareRevisionDoc(dbConn, revisionSql.toString(),
1521
					replicateData));
1522
			
1523
			// add the system metadata entries if configured to replicate them
1524
			boolean replicateSystemMetadata = serverList.getSystemMetadataReplicationValue(server);
1525
			if (replicateSystemMetadata) {
1526
				Date since = new Date(System.currentTimeMillis());
1527
				since = serverList.getLastCheckedDate(server);
1528
				List<String> systemMetadataEntries = 
1529
					IdentifierManager.getInstance().getUpdatedSystemMetadataIds(since);
1530
				for (int i = 0; i < systemMetadataEntries.size(); i++) {
1531
					String guid = systemMetadataEntries.get(i);
1532
					doclist.append("<updatedSystemMetadata>");
1533
					doclist.append("<guid>");
1534
					doclist.append(guid);
1535
					doclist.append("</guid>");
1536
					doclist.append("</updatedSystemMetadata>");
1537
				}
1538
			}
1539

    
1540
			doclist.append("</updates></replication>");
1541
			logReplication.info("ReplicationService.handleUpdateRequest - doclist: " + doclist.toString());
1542
			pstmt.close();
1543
			//conn.close();
1544
			out.write(doclist.toString());
1545

    
1546
		} catch (Exception e) {
1547
			logMetacat.error("ReplicationService.handleUpdateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1548
			logReplication.error("ReplicationService.handleUpdateRequest - error in MetacatReplication." + "handleupdaterequest: "
1549
					+ e.getMessage());
1550
			//e.printStackTrace(System.out);
1551
			try {
1552
				out.write("<error>" + e.getMessage() + "</error>");
1553
			} catch (IOException e1) {
1554
				logMetacat.error(e1.getMessage(), e1);
1555
			}
1556
		} finally {
1557
			try {
1558
				pstmt.close();
1559
			}//try
1560
			catch (SQLException ee) {
1561
				logMetacat.error("ReplicationService.handleUpdateRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1562
				logReplication.error("ReplicationService.handleUpdateRequest - Error in MetacatReplication."
1563
						+ "handleUpdaterequest to close pstmt: " + ee.getMessage());
1564
			}//catch
1565
			finally {
1566
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1567
			}//finally
1568
			try {
1569
				out.close();
1570
			} catch (IOException e) {
1571
				logMetacat.error(e.getMessage(), e);
1572
			}
1573
		}//finally
1574

    
1575
	}//handlUpdateRequest
1576

    
1577
	/**
1578
	 * 
1579
	 * @param dbConn connection for doing the update
1580
	 * @param docid the document id to update
1581
	 * @param owner the user_owner
1582
	 * @param updater the user_updated
1583
	 * @throws SQLException
1584
	 */
1585
	public static void updateUserOwner(DBConnection dbConn, String docid, String owner, String updater) throws SQLException {
1586
	
1587
		String sql = 
1588
			"UPDATE xml_documents " +
1589
			"SET user_owner = ?, " +
1590
			"user_updated = ? " +
1591
			"WHERE docid = ?;";
1592
		PreparedStatement pstmt = dbConn.prepareStatement(sql);
1593
		//usage count should increas 1
1594
		dbConn.increaseUsageCount(1);
1595

    
1596
		docid = DocumentUtil.getSmartDocId(docid);
1597
		pstmt.setString(1, owner);
1598
		pstmt.setString(2, updater);
1599
		pstmt.setString(3, docid);
1600
		pstmt.execute();
1601
		pstmt.close();
1602
		
1603
		dbConn.commit();
1604
	}
1605
	
1606
	/*
1607
	 * This method will get the xml string for document in xml_revision
1608
	 * The schema look like <!ELEMENT revisionDocument (docid, rev, datafile*)>
1609
	 */
1610
	private static String prepareRevisionDoc(DBConnection dbConn, String revSql,
1611
			boolean replicateData) throws Exception {
1612
		logReplication.warn("ReplicationService.prepareRevisionDoc - The revision document sql is " + revSql);
1613
		StringBuffer revDocList = new StringBuffer();
1614
		PreparedStatement pstmt = dbConn.prepareStatement(revSql);
1615
		//usage count should increas 1
1616
		dbConn.increaseUsageCount(1);
1617

    
1618
		pstmt.execute();
1619
		ResultSet rs = pstmt.getResultSet();
1620
		boolean tablehasrows = rs.next();
1621
		while (tablehasrows) {
1622
			String recordDoctype = rs.getString(3);
1623

    
1624
			//If this is data file and it isn't configured to replicate data
1625
			if (recordDoctype.equals("BIN") && !replicateData) {
1626
				// do nothing
1627
				continue;
1628
			} else {
1629

    
1630
				revDocList.append("<revisionDocument>");
1631
				revDocList.append("<docid>").append(rs.getString(1));
1632
				revDocList.append("</docid><rev>").append(rs.getInt(2));
1633
				revDocList.append("</rev>");
1634
				// data file
1635
				if (recordDoctype.equals("BIN")) {
1636
					revDocList.append("<datafile>");
1637
					revDocList.append(PropertyService
1638
							.getProperty("replication.datafileflag"));
1639
					revDocList.append("</datafile>");
1640
				}
1641
				revDocList.append("</revisionDocument>");
1642

    
1643
			}//else
1644
			tablehasrows = rs.next();
1645
		}
1646
		//System.out.println("The revision list is"+ revDocList.toString());
1647
		return revDocList.toString();
1648
	}
1649

    
1650
	/**
1651
	 * Returns the xml_catalog table encoded in xml
1652
	 */
1653
	public static String getCatalogXML() {
1654
		return handleGetCatalogRequest(null, null, false);
1655
	}
1656

    
1657
	/**
1658
	 * Sends the contents of the xml_catalog table encoded in xml
1659
	 * The xml format is:
1660
	 * <!ELEMENT xml_catalog (row*)>
1661
	 * <!ELEMENT row (entry_type, source_doctype, target_doctype, public_id,
1662
	 *                system_id)>
1663
	 * All of the sub elements of row are #PCDATA
1664

    
1665
	 * If printFlag == false then do not print to out.
1666
	 */
1667
	protected static String handleGetCatalogRequest(
1668
			Hashtable<String, String[]> params, HttpServletResponse response,
1669
			boolean printFlag) {
1670
		DBConnection dbConn = null;
1671
		int serialNumber = -1;
1672
		PreparedStatement pstmt = null;
1673
		Writer out = null;
1674
		try {
1675
			// get writer, TODO: encoding?
1676
		    if(printFlag)
1677
		    {
1678
		        response.setContentType("text/xml");
1679
		        out = response.getWriter();
1680
		    }
1681
			/*conn = MetacatReplication.getDBConnection("MetacatReplication." +
1682
			                                          "handleGetCatalogRequest");*/
1683
			dbConn = DBConnectionPool
1684
					.getDBConnection("MetacatReplication.handleGetCatalogRequest");
1685
			serialNumber = dbConn.getCheckOutSerialNumber();
1686
			pstmt = dbConn.prepareStatement("select entry_type, "
1687
					+ "source_doctype, target_doctype, public_id, "
1688
					+ "system_id from xml_catalog");
1689
			pstmt.execute();
1690
			ResultSet rs = pstmt.getResultSet();
1691
			boolean tablehasrows = rs.next();
1692
			StringBuffer sb = new StringBuffer();
1693
			sb.append("<?xml version=\"1.0\"?><xml_catalog>");
1694
			while (tablehasrows) {
1695
				sb.append("<row><entry_type>").append(rs.getString(1));
1696
				sb.append("</entry_type><source_doctype>").append(rs.getString(2));
1697
				sb.append("</source_doctype><target_doctype>").append(rs.getString(3));
1698
				sb.append("</target_doctype><public_id>").append(rs.getString(4));
1699
				// system id may not have server url on front.  Add it if not.
1700
				String systemID = rs.getString(5);
1701
				if (!systemID.startsWith("http://")) {
1702
					systemID = SystemUtil.getContextURL() + systemID;
1703
				}
1704
				sb.append("</public_id><system_id>").append(systemID);
1705
				sb.append("</system_id></row>");
1706

    
1707
				tablehasrows = rs.next();
1708
			}
1709
			sb.append("</xml_catalog>");
1710
			//conn.close();
1711
			if (printFlag) {
1712
				response.setContentType("text/xml");
1713
				out.write(sb.toString());
1714
			}
1715
			pstmt.close();
1716
			return sb.toString();
1717
		} catch (Exception e) {
1718
			logMetacat.error("ReplicationService.handleGetCatalogRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1719
			logReplication.error("ReplicationService.handleGetCatalogRequest - error in MetacatReplication.handleGetCatalogRequest:"
1720
					+ e.getMessage());
1721
			e.printStackTrace(System.out);
1722
			if (printFlag) {
1723
				try {
1724
					out.write("<error>" + e.getMessage() + "</error>");
1725
				} catch (IOException e1) {
1726
					logMetacat.error(e1.getMessage(), e1);
1727
				}
1728
			}
1729
		} finally {
1730
			try {
1731
				pstmt.close();
1732
			}//try
1733
			catch (SQLException ee) {
1734
				logMetacat.error("ReplicationService.handleGetCatalogRequest - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1735
				logReplication.error("ReplicationService.handleGetCatalogRequest - Error in MetacatReplication.handleGetCatalogRequest: "
1736
						+ ee.getMessage());
1737
			}//catch
1738
			finally {
1739
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1740
			}//finally
1741
			if (out != null) {
1742
				try {
1743
					out.close();
1744
				} catch (IOException e1) {
1745
					logMetacat.error(e1.getMessage(), e1);
1746
				}
1747
			}
1748
		}//finally
1749

    
1750
		return null;
1751
	}
1752

    
1753
	/**
1754
	 * Sends the current system date to the remote server.  Using this action
1755
	 * for replication gets rid of any problems with syncronizing clocks
1756
	 * because a time specific to a document is always kept on its home server.
1757
	 */
1758
	protected static void handleGetTimeRequest(
1759
			Hashtable<String, String[]> params, HttpServletResponse response) {
1760
		
1761
		// use standard ISO format -- the receiving end wants this too
1762
		String dateString = DatatypeConverter.printDateTime(Calendar.getInstance());
1763
		
1764
		// get a writer for sending back to response
1765
		response.setContentType("text/xml");
1766
		Writer out = null;
1767
		try {
1768
			out = response.getWriter();
1769
			out.write("<timestamp>" + dateString + "</timestamp>");
1770
			out.close();
1771
		} catch (IOException e) {
1772
			logMetacat.error(e.getMessage(), e);
1773
		}
1774
		
1775
	}
1776

    
1777
	/**
1778
	 * this method handles the timeout for a file lock.  when a lock is
1779
	 * granted it is granted for 30 seconds.  When this thread runs out
1780
	 * it deletes the docid from the queue, thus eliminating the lock.
1781
	 */
1782
	public void run() {
1783
		try {
1784
			logReplication.info("ReplicationService.run - thread started for docid: "
1785
					+ (String) fileLocks.elementAt(0));
1786

    
1787
			Thread.sleep(30000); //the lock will expire in 30 seconds
1788
			logReplication.info("thread for docid: "
1789
					+ (String) fileLocks.elementAt(fileLocks.size() - 1) + " exiting.");
1790

    
1791
			fileLocks.remove(fileLocks.size() - 1);
1792
			//fileLocks is treated as a FIFO queue.  If there are more than one lock
1793
			//in the vector, the first one inserted will be removed.
1794
		} catch (Exception e) {
1795
			logMetacat.error("ReplicationService.run - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1796
			logReplication.error("ReplicationService.run - error in file lock thread from "
1797
					+ "MetacatReplication.run: " + e.getMessage());
1798
		}
1799
	}
1800

    
1801
	/**
1802
	 * Returns the name of a server given a serverCode
1803
	 * @param serverCode the serverid of the server
1804
	 * @return the servername or null if the specified serverCode does not
1805
	 *         exist.
1806
	 */
1807
	public static String getServerNameForServerCode(int serverCode) {
1808
		//System.out.println("serverid: " + serverCode);
1809
		DBConnection dbConn = null;
1810
		int serialNumber = -1;
1811
		PreparedStatement pstmt = null;
1812
		try {
1813
			dbConn = DBConnectionPool.getDBConnection("MetacatReplication.getServer");
1814
			serialNumber = dbConn.getCheckOutSerialNumber();
1815
			String sql = new String("select server from "
1816
					+ "xml_replication where serverid = ?");
1817
			pstmt = dbConn.prepareStatement(sql);
1818
			pstmt.setInt(1, serverCode);
1819
			//System.out.println("getserver sql: " + sql);
1820
			pstmt.execute();
1821
			ResultSet rs = pstmt.getResultSet();
1822
			boolean tablehasrows = rs.next();
1823
			if (tablehasrows) {
1824
				//System.out.println("server: " + rs.getString(1));
1825
				return rs.getString(1);
1826
			}
1827

    
1828
			//conn.close();
1829
		} catch (Exception e) {
1830
			logMetacat.error("ReplicationService.getServerNameForServerCode - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1831
			logReplication.error("ReplicationService.getServerNameForServerCode - Error in MetacatReplication.getServer: " + e.getMessage());
1832
		} finally {
1833
			try {
1834
				pstmt.close();
1835
			}//try
1836
			catch (SQLException ee) {
1837
				logMetacat.error("ReplicationService.getServerNameForServerCode - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1838
				logReplication.error("ReplicationService.getServerNameForServerCode - Error in MetacactReplication.getserver: "
1839
						+ ee.getMessage());
1840
			}//catch
1841
			finally {
1842
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1843
			}//fianlly
1844
		}//finally
1845

    
1846
		return null;
1847
		//return null if the server does not exist
1848
	}
1849

    
1850
	/**
1851
	 * Returns a server code given a server name
1852
	 * @param server the name of the server
1853
	 * @return integer > 0 representing the code of the server, 0 if the server
1854
	 *  does not exist.
1855
	 */
1856
	public static int getServerCodeForServerName(String server) throws ServiceException {
1857
		DBConnection dbConn = null;
1858
		int serialNumber = -1;
1859
		PreparedStatement pstmt = null;
1860
		int serverCode = 0;
1861

    
1862
		try {
1863

    
1864
			//conn = util.openDBConnection();
1865
			dbConn = DBConnectionPool.getDBConnection("MetacatReplication.getServerCode");
1866
			serialNumber = dbConn.getCheckOutSerialNumber();
1867
			pstmt = dbConn.prepareStatement("SELECT serverid FROM xml_replication "
1868
					+ "WHERE server LIKE ?");
1869
			pstmt.setString(1, server);
1870
			pstmt.execute();
1871
			ResultSet rs = pstmt.getResultSet();
1872
			boolean tablehasrows = rs.next();
1873
			if (tablehasrows) {
1874
				serverCode = rs.getInt(1);
1875
				pstmt.close();
1876
				//conn.close();
1877
				return serverCode;
1878
			}
1879

    
1880
		} catch (SQLException sqle) {
1881
			throw new ServiceException("ReplicationService.getServerCodeForServerName - " 
1882
					+ "SQL error when getting server code: " + sqle.getMessage());
1883

    
1884
		} finally {
1885
			try {
1886
				pstmt.close();
1887
				//conn.close();
1888
			}//try
1889
			catch (Exception ee) {
1890
				logMetacat.error("ReplicationService.getServerCodeForServerName - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1891
				logReplication.error("ReplicationService.getServerNameForServerCode - Error in MetacatReplicatio.getServerCode: "
1892
						+ ee.getMessage());
1893

    
1894
			}//catch
1895
			finally {
1896
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1897
			}//finally
1898
		}//finally
1899

    
1900
		return serverCode;
1901
	}
1902

    
1903
	/**
1904
	 * Method to get a host server information for given docid
1905
	 * @param conn a connection to the database
1906
	 */
1907
	public static Hashtable<String, String> getHomeServerInfoForDocId(String docId) {
1908
		Hashtable<String, String> sl = new Hashtable<String, String>();
1909
		DBConnection dbConn = null;
1910
		int serialNumber = -1;
1911
		docId = DocumentUtil.getDocIdFromString(docId);
1912
		PreparedStatement pstmt = null;
1913
		int serverLocation;
1914
		try {
1915
			//get conection
1916
			dbConn = DBConnectionPool.getDBConnection("ReplicationHandler.getHomeServer");
1917
			serialNumber = dbConn.getCheckOutSerialNumber();
1918
			//get a server location from xml_document table
1919
			pstmt = dbConn.prepareStatement("select server_location from xml_documents "
1920
					+ "where docid = ?");
1921
			pstmt.setString(1, docId);
1922
			pstmt.execute();
1923
			ResultSet serverName = pstmt.getResultSet();
1924
			//get a server location
1925
			if (serverName.next()) {
1926
				serverLocation = serverName.getInt(1);
1927
				pstmt.close();
1928
			} else {
1929
				pstmt.close();
1930
				//ut.returnConnection(conn);
1931
				return null;
1932
			}
1933
			pstmt = dbConn.prepareStatement("select server, last_checked, replicate "
1934
					+ "from xml_replication where serverid = ?");
1935
			//increase usage count
1936
			dbConn.increaseUsageCount(1);
1937
			pstmt.setInt(1, serverLocation);
1938
			pstmt.execute();
1939
			ResultSet rs = pstmt.getResultSet();
1940
			boolean tableHasRows = rs.next();
1941
			if (tableHasRows) {
1942

    
1943
				String server = rs.getString(1);
1944
				String last_checked = rs.getString(2);
1945
				if (!server.equals("localhost")) {
1946
					sl.put(server, last_checked);
1947
				}
1948

    
1949
			} else {
1950
				pstmt.close();
1951
				//ut.returnConnection(conn);
1952
				return null;
1953
			}
1954
			pstmt.close();
1955
		} catch (Exception e) {
1956
			logMetacat.error("ReplicationService.getHomeServerInfoForDocId - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1957
			logReplication.error("ReplicationService.getHomeServerInfoForDocId - error in replicationHandler.getHomeServer(): "
1958
					+ e.getMessage());
1959
		} finally {
1960
			try {
1961
				pstmt.close();
1962
				//ut.returnConnection(conn);
1963
			} catch (Exception ee) {
1964
				logMetacat.error("ReplicationService.getHomeServerInfoForDocId - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1965
				logReplication.error("ReplicationService.getHomeServerInfoForDocId - Eror irn rplicationHandler.getHomeServer() "
1966
						+ "to close pstmt: " + ee.getMessage());
1967
			} finally {
1968
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1969
			}
1970

    
1971
		}//finally
1972
		return sl;
1973
	}
1974

    
1975
	/**
1976
	 * Returns a home server location  given a accnum
1977
	 * @param accNum , given accNum for a document
1978
	 *
1979
	 */
1980
	public static int getHomeServerCodeForDocId(String accNum) throws ServiceException {
1981
		DBConnection dbConn = null;
1982
		int serialNumber = -1;
1983
		PreparedStatement pstmt = null;
1984
		int serverCode = 1;
1985
		String docId = DocumentUtil.getDocIdFromString(accNum);
1986

    
1987
		try {
1988

    
1989
			// Get DBConnection
1990
			dbConn = DBConnectionPool
1991
					.getDBConnection("ReplicationHandler.getServerLocation");
1992
			serialNumber = dbConn.getCheckOutSerialNumber();
1993
			pstmt = dbConn.prepareStatement("SELECT server_location FROM xml_documents "
1994
					+ "WHERE docid LIKE ? ");
1995
			pstmt.setString(1, docId);
1996
			pstmt.execute();
1997
			ResultSet rs = pstmt.getResultSet();
1998
			boolean tablehasrows = rs.next();
1999
			//If a document is find, return the server location for it
2000
			if (tablehasrows) {
2001
				serverCode = rs.getInt(1);
2002
				pstmt.close();
2003
				//conn.close();
2004
				return serverCode;
2005
			}
2006
			//if couldn't find in xml_documents table, we think server code is 1
2007
			//(this is new document)
2008
			else {
2009
				pstmt.close();
2010
				//conn.close();
2011
				return serverCode;
2012
			}
2013

    
2014
		} catch (SQLException sqle) {
2015
			throw new ServiceException("ReplicationService.getHomeServerCodeForDocId - " 
2016
					+ "SQL error when getting home server code for docid: " + docId + " : " 
2017
					+ sqle.getMessage());
2018

    
2019
		} finally {
2020
			try {
2021
				pstmt.close();
2022
				//conn.close();
2023

    
2024
			} catch (SQLException sqle) {
2025
				logMetacat.error("ReplicationService.getHomeServerCodeForDocId - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
2026
				logReplication.error("ReplicationService.getHomeServerCodeForDocId - ReplicationService.getHomeServerCodeForDocId - " 
2027
						+ "SQL error when getting home server code for docid: " + docId + " : " 
2028
						+ sqle.getMessage());
2029
			} finally {
2030
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
2031
			}//finally
2032
		}//finally
2033
		//return serverCode;
2034
	}
2035

    
2036
	/**
2037
	 * This method returns the content of a url
2038
	 * @param u the url to return the content from
2039
	 * @return a string representing the content of the url
2040
	 * @throws java.io.IOException
2041
	 */
2042
	public static String getURLContent(URL u) throws java.io.IOException {
2043
	    logReplication.info("Getting url content from " + u.toString());
2044
		char istreamChar;
2045
		int istreamInt;
2046
		logReplication.info("ReplicationService.getURLContent - Before sending request to: " + u.toString());
2047
		// use httpclient to set up SSL
2048
		RestClient client = getSSLClient();
2049
		HttpResponse response = client.doGetRequest(u.toString());
2050
		// get the response content
2051
		InputStream input = response.getEntity().getContent();
2052
		logReplication.info("ReplicationService.getURLContent - After getting response from: " + u.toString());
2053
		InputStreamReader istream = new InputStreamReader(input);
2054
		StringBuffer serverResponse = new StringBuffer();
2055
		while ((istreamInt = istream.read()) != -1) {
2056
			istreamChar = (char) istreamInt;
2057
			serverResponse.append(istreamChar);
2058
		}
2059
		istream.close();
2060
		input.close();
2061

    
2062
		return serverResponse.toString();
2063
	}
2064
	
2065
	/**
2066
	 * Sets up an HttpClient with SSL connection.
2067
	 * Sends client certificate to the server when doing the request.
2068
	 * @return
2069
	 */
2070
	private static RestClient getSSLClient() {
2071
		RestClient client = new RestClient();
2072
		
2073
		// set up this server's client identity
2074
		String subject = null;
2075
		try {
2076
			X509Certificate certificate = CertificateManager.getInstance().loadCertificateFromFile(PropertyService.getProperty("replication.certificate.file"));
2077
			PrivateKey key = CertificateManager.getInstance().loadPrivateKeyFromFile(PropertyService.getProperty("replication.privatekey.file"));
2078
			subject = CertificateManager.getInstance().getSubjectDN(certificate);
2079
			CertificateManager.getInstance().registerCertificate(subject, certificate, key);
2080
		} catch (Exception e) {
2081
			// this is pretty much required for replication communication
2082
			logReplication.warn("Could find server's client certificate/private key: " + e.getMessage());
2083
		}
2084
		SSLSocketFactory socketFactory = null;
2085
		try {
2086
			socketFactory = CertificateManager.getInstance().getSSLSocketFactory(subject);
2087
		} catch (FileNotFoundException e) {
2088
			// these are somewhat expected for anonymous client use
2089
			logReplication.warn("Could not set up SSL connection for client - likely because the certificate could not be located: " + e.getMessage());
2090
		} catch (Exception e) {
2091
			// this is likely more severe
2092
			logReplication.warn("Funky SSL going on: " + e.getClass() + ":: " + e.getMessage());
2093
		}
2094
		try {
2095
			//443 is the default port, this value is overridden if explicitly set in the URL
2096
			Scheme sch = new Scheme("https", 443, socketFactory);
2097
			client.getHttpClient().getConnectionManager().getSchemeRegistry().register(sch);
2098
		} catch (Exception e) {
2099
			// this is likely more severe
2100
			logReplication.error("Failed to set up SSL connection for client. Continuing. " + e.getClass() + ":: " + e.getMessage(), e);
2101
		}
2102
		return client;
2103
	}
2104
	
2105

    
2106
//	/**
2107
//	 * Method for writing replication messages to a log file specified in
2108
//	 * metacat.properties
2109
//	 */
2110
//	public static void replLog(String message) {
2111
//		try {
2112
//			FileOutputStream fos = new FileOutputStream(PropertyService
2113
//					.getProperty("replication.logdir")
2114
//					+ "/metacatreplication.log", true);
2115
//			PrintWriter pw = new PrintWriter(fos);
2116
//			SimpleDateFormat formatter = new SimpleDateFormat("yy-MM-dd HH:mm:ss");
2117
//			java.util.Date localtime = new java.util.Date();
2118
//			String dateString = formatter.format(localtime);
2119
//			dateString += " :: " + message;
2120
//			// time stamp each entry
2121
//			pw.println(dateString);
2122
//			pw.flush();
2123
//		} catch (Exception e) {
2124
//			logReplication.error("error writing to replication log from "
2125
//					+ "MetacatReplication.replLog: " + e.getMessage());
2126
//			// e.printStackTrace(System.out);
2127
//		}
2128
//	}
2129

    
2130
//	/**
2131
//	 * Method for writing replication messages to a log file specified in
2132
//	 * metacat.properties
2133
//	 */
2134
//	public static void replErrorLog(String message) {
2135
//		try {
2136
//			FileOutputStream fos = new FileOutputStream(PropertyService
2137
//					.getProperty("replication.logdir")
2138
//					+ "/metacatreplicationerror.log", true);
2139
//			PrintWriter pw = new PrintWriter(fos);
2140
//			SimpleDateFormat formatter = new SimpleDateFormat("yy-MM-dd HH:mm:ss");
2141
//			java.util.Date localtime = new java.util.Date();
2142
//			String dateString = formatter.format(localtime);
2143
//			dateString += " :: " + message;
2144
//			//time stamp each entry
2145
//			pw.println(dateString);
2146
//			pw.flush();
2147
//		} catch (Exception e) {
2148
//			logReplication.error("error writing to replication error log from "
2149
//					+ "MetacatReplication.replErrorLog: " + e.getMessage());
2150
//			//e.printStackTrace(System.out);
2151
//		}
2152
//	}
2153

    
2154
	/**
2155
	 * Returns true if the replicate field for server in xml_replication is 1.
2156
	 * Returns false otherwise
2157
	 */
2158
	public static boolean replToServer(String server) {
2159
		DBConnection dbConn = null;
2160
		int serialNumber = -1;
2161
		PreparedStatement pstmt = null;
2162
		try {
2163
			dbConn = DBConnectionPool.getDBConnection("MetacatReplication.repltoServer");
2164
			serialNumber = dbConn.getCheckOutSerialNumber();
2165
			pstmt = dbConn.prepareStatement("select replicate from "
2166
					+ "xml_replication where server like ? ");
2167
			pstmt.setString(1, server);
2168
			pstmt.execute();
2169
			ResultSet rs = pstmt.getResultSet();
2170
			boolean tablehasrows = rs.next();
2171
			if (tablehasrows) {
2172
				int i = rs.getInt(1);
2173
				if (i == 1) {
2174
					pstmt.close();
2175
					//conn.close();
2176
					return true;
2177
				} else {
2178
					pstmt.close();
2179
					//conn.close();
2180
					return false;
2181
				}
2182
			}
2183
		} catch (SQLException sqle) {
2184
			logMetacat.error("ReplicationService.replToServer - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
2185
			logReplication.error("ReplicationService.replToServer - SQL error in MetacatReplication.replToServer: "
2186
					+ sqle.getMessage());
2187
		} finally {
2188
			try {
2189
				pstmt.close();
2190
				//conn.close();
2191
			}//try
2192
			catch (Exception ee) {
2193
				logMetacat.error("ReplicationService.replToServer - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
2194
				logReplication.error("ReplicationService.replToServer - Error in MetacatReplication.replToServer: "
2195
						+ ee.getMessage());
2196
			}//catch
2197
			finally {
2198
				DBConnectionPool.returnDBConnection(dbConn, serialNumber);
2199
			}//finally
2200
		}//finally
2201
		return false;
2202
		//the default if this server does not exist is to not replicate to it.
2203
	}
2204

    
2205
}
(7-7/8)