Project

General

Profile

1
/**
2
 *  '$RCSfile$'
3
 *    Purpose: A Class that implements replication for metacat
4
 *  Copyright: 2000 Regents of the University of California and the
5
 *             National Center for Ecological Analysis and Synthesis
6
 *    Authors: Chad Berkley
7
 *
8
 *   '$Author: daigle $'
9
 *     '$Date: 2009-03-25 13:41:15 -0800 (Wed, 25 Mar 2009) $'
10
 * '$Revision: 4861 $'
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.FileInputStream;
30
import java.io.FileNotFoundException;
31
import java.io.IOException;
32
import java.io.InputStream;
33
import java.io.OutputStream;
34
import java.io.PrintWriter;
35
import java.security.KeyStore;
36
import java.security.KeyStoreException;
37
import java.security.NoSuchAlgorithmException;
38
import java.security.cert.CertificateException;
39
import java.security.cert.X509Certificate;
40
import java.util.Enumeration;
41
import java.util.Hashtable;
42

    
43
import javax.servlet.ServletConfig;
44
import javax.servlet.ServletException;
45
import javax.servlet.http.HttpServlet;
46
import javax.servlet.http.HttpServletRequest;
47
import javax.servlet.http.HttpServletResponse;
48
import javax.servlet.http.HttpSession;
49

    
50
import org.apache.log4j.Logger;
51
import org.dataone.client.auth.CertificateManager;
52

    
53
import edu.ucsb.nceas.metacat.properties.PropertyService;
54
import edu.ucsb.nceas.metacat.service.ServiceService;
55
import edu.ucsb.nceas.metacat.service.SessionService;
56
import edu.ucsb.nceas.metacat.shared.MetacatUtilException;
57
import edu.ucsb.nceas.metacat.shared.ServiceException;
58
import edu.ucsb.nceas.metacat.util.AuthUtil;
59
import edu.ucsb.nceas.metacat.util.SessionData;
60
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
61

    
62
public class ReplicationServlet extends HttpServlet {
63

    
64
	private static final long serialVersionUID = -2898600143193513155L;
65

    
66
	private static Logger logReplication = Logger.getLogger("ReplicationLogging");
67
	private static Logger logMetacat = Logger.getLogger(ReplicationServlet.class);
68

    
69
	/**
70
	 * Initialize the servlet by creating appropriate database connections
71
	 */
72
	public void init(ServletConfig config) throws ServletException {
73

    
74
		try {
75
			// Register preliminary services
76
			ServiceService.registerService("ReplicationService", ReplicationService
77
					.getInstance());
78
			
79
		} catch (ServiceException se) {
80
			String errorMessage = "ReplicationServlet.init - Service problem while intializing Replication Servlet: "
81
					+ se.getMessage();
82
			logMetacat.error("ReplicationServlet.init - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
83
			logReplication.error(errorMessage);
84
			throw new ServletException(errorMessage);
85
		} 
86
	}
87

    
88
	public void destroy() {
89
		//ServiceService.
90
	}
91

    
92
	public void doGet(HttpServletRequest request, HttpServletResponse response)
93
			throws ServletException, IOException {
94
		// Process the data and send back the response
95
		handleGetOrPost(request, response);
96
	}
97

    
98
	public void doPost(HttpServletRequest request, HttpServletResponse response)
99
			throws ServletException, IOException {
100
		// Process the data and send back the response
101
		handleGetOrPost(request, response);
102
	}
103

    
104
	private void handleGetOrPost(HttpServletRequest request, HttpServletResponse response)
105
			throws ServletException, IOException {
106
		PrintWriter out = null;
107
		Hashtable<String, String[]> params = new Hashtable<String, String[]>();
108
		Enumeration<String> paramlist = request.getParameterNames();
109

    
110
		while (paramlist.hasMoreElements()) {
111
			String name = (String) paramlist.nextElement();
112
			String[] value = request.getParameterValues(name);
113
			params.put(name, value);
114
		}
115

    
116
		String action = "";
117
		if (!params.isEmpty() && params.get("action") != null) {
118
			action = ((String[]) params.get("action"))[0];
119
		}
120
		String server = null;
121

    
122
		try {
123
			// check if the server is included in the list of replicated servers
124
			if (!action.equals("servercontrol") && !action.equals("stop")
125
					&& !action.equals("start") && !action.equals("getall")) {
126

    
127
				// verify the client certificate on the request
128
				boolean isValid = false;
129
				String msg = "Client certificate is invalid";
130
				try {
131
					isValid = hasValidCertificate(request);
132
				} catch (Exception e) {
133
					msg = "Could not verify client certificate: " + e.getMessage();
134
					logMetacat.error(msg, e);
135
					logReplication.error(msg, e);
136
				}
137
				if (!isValid) {
138
					// send message to response
139
					out = response.getWriter();
140
					out.print("<error>");
141
					out.print(msg);
142
					out.print("</error>");
143
					out.close();
144
					return;
145
				}
146
				
147
				server = ((String[]) params.get("server"))[0];
148
				if (ReplicationService.getServerCodeForServerName(server) == 0) {
149
					logReplication.debug("ReplicationServlet.handleGetOrPost - Action \"" + action + "\" rejected for server: "
150
							+ server);
151
					return;
152
				} else {
153
					logReplication.debug("ReplicationServlet.handleGetOrPost - Action \"" + action + "\" accepted for server: "
154
							+ server);
155
				}
156
				
157
			} else {
158
				// start, stop, getall and servercontrol need to check if user is administor
159
				HttpSession sess = request.getSession(true);
160
				SessionData sessionData = null;
161
				String sess_id = "";
162
				String username = "";
163
				String[] groupnames = { "" };
164

    
165
				if (params.containsKey("sessionid")) {
166
					sess_id = ((String[]) params.get("sessionid"))[0];
167
					logReplication.info("ReplicationServlet.handleGetOrPost - in has sessionid " + sess_id);
168
					if (SessionService.getInstance().isSessionRegistered(sess_id)) {
169
						logReplication.info("ReplicationServlet.handleGetOrPost - find the id " + sess_id + " in hash table");
170
						sessionData = SessionService.getInstance().getRegisteredSession(sess_id);
171
					}
172
				}
173
				if (sessionData == null) {
174
					sessionData = new SessionData(sess.getId(), 
175
							(String) sess.getAttribute("username"), 
176
							(String[]) sess.getAttribute("groups"),
177
							(String) sess.getAttribute("password"), 
178
							(String) sess.getAttribute("name"));
179
				}
180

    
181
				username = sessionData.getUserName();
182
				logReplication.warn("ReplicationServlet.handleGetOrPost - The user name from session is: " + username);
183
				groupnames = sessionData.getGroupNames();
184
				if (!AuthUtil.isAdministrator(username, groupnames)) {
185
					out = response.getWriter();
186
					out.print("<error>");
187
					out.print("The user \"" + username
188
							+ "\" is not authorized for this action.");
189
					out.print("</error>");
190
					out.close();
191
					logReplication.warn("ReplicationServlet.handleGetOrPost - The user \"" + username
192
							+ "\" is not authorized for this action: " + action);
193
					return;
194
				}
195

    
196
			}// else
197

    
198
			if (action.equals("readdata")) {
199
				OutputStream outStream = response.getOutputStream();
200
				//to get the data file.
201
				ReplicationService.handleGetDataFileRequest(outStream, params, response);
202
				outStream.close();
203
			} else if (action.equals("forcereplicatedatafile")) {
204
				//read a specific docid from remote host, and store it into local host
205
				ReplicationService.handleForceReplicateDataFileRequest(params, request);
206
			} else if (action.equals("stop")) {
207
				// stop the replication server
208
				ReplicationService.getInstance().stopReplication();
209
				out = response.getWriter();
210
				out.println("Replication Handler Stopped");
211
			} else if (action.equals("start")) {
212
				ReplicationService.getInstance().startReplication(params);
213
				out = response.getWriter();
214
				out.println("Replication Handler Started");
215
			} else if (action.equals("getall")) {
216
				ReplicationService.getInstance().runOnce();
217
				response.setContentType("text/html");
218
				out = response.getWriter();
219
				out.println("<html><body>\"Get All\" Done</body></html>");
220
			} else if (action.equals("forcereplicate")) {
221
				// read a specific docid from remote host, and store it into
222
				// local host
223
				ReplicationService.handleForceReplicateRequest(params, response,
224
						request);
225
			} else if (action.equals("forcereplicatesystemmetadata")) {
226
				ReplicationService.handleForceReplicateSystemMetadataRequest(params, response,
227
						request);
228
			} else if (action.equals("forcereplicatedelete")) {
229
				// read a specific docid from remote host, and store it into
230
				// local host
231
				ReplicationService.handleForceReplicateDeleteRequest(params,
232
						response, request);
233
			} else if (action.equals("update")) {
234
				// request an update list from the server
235
				ReplicationService.handleUpdateRequest(params, response);
236
			} else if (action.equals("read")) {
237
				// request a specific document from the server
238
				// note that this could be replaced by a call to metacatServlet
239
				// handleGetDocumentAction().
240
				ReplicationService.handleGetDocumentRequest(params, response);				
241
			} else if (action.equals("getlock")) {
242
				ReplicationService.handleGetLockRequest(params, response);
243
			} else if (action.equals("getdocumentinfo")) {
244
				ReplicationService.handleGetDocumentInfoRequest(params, response);
245
			} else if (action.equals("getsystemmetadata")) {
246
				ReplicationService.handleGetSystemMetadataRequest(params, response);
247
			} else if (action.equals("gettime")) {
248
				ReplicationService.handleGetTimeRequest(params, response);
249
			} else if (action.equals("getcatalog")) {
250
				ReplicationService.handleGetCatalogRequest(params, response, true);
251
			} else if (action.equals("servercontrol")) {
252
				ReplicationService.handleServerControlRequest(params, response);
253
			} else if (action.equals("test")) {
254
				response.setContentType("text/html");
255
				out = response.getWriter();
256
				out.println("<html><body>Test successfully</body></html>");
257
			}
258

    
259
		} catch (ServiceException e) {
260
			logMetacat.error("ReplicationServlet.handleGetOrPost - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
261
			logReplication.error("ReplicationServlet.handleGetOrPost - Error in ReplicationServlet.handleGetOrPost: " + e.getMessage());
262
		} catch (MetacatUtilException mue) {
263
			logMetacat.error("ReplicationServlet.handleGetOrPost - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
264
			logReplication.error("ReplicationServlet.handleGetOrPost - Metacat utility error in ReplicationServlet.handleGetOrPost: "
265
							+ mue.getMessage());
266
		} finally {
267
			if (out != null) {
268
				out.close();
269
			}
270
		}
271
	}
272

    
273
	private boolean hasValidCertificate(HttpServletRequest request) throws KeyStoreException, PropertyNotFoundException, NoSuchAlgorithmException, CertificateException, IOException {
274
		// get the certificate from the request
275
		X509Certificate certificate = CertificateManager.getInstance().getCertificate(request);
276
		if (certificate != null) {
277
			// load the keystore
278
			KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
279
			InputStream is = new FileInputStream(PropertyService.getProperty("replication.keystore.filename"));
280
			String password = PropertyService.getProperty("replication.keystore.password");
281
			keyStore.load(is, password.toCharArray());
282
			// check that it contains our client's entry
283
			String alias = keyStore.getCertificateAlias(certificate);
284
			if (alias != null) {
285
				// TODO: more checking?
286
				return true;
287
			}
288
		}
289
 		return false;
290
	}
291
}
(8-8/8)