Project

General

Profile

1 4080 daigle
/**
2
 *  '$RCSfile$'
3
 *    Purpose: A Class that implements session utility methods
4
 *  Copyright: 2008 Regents of the University of California and the
5
 *             National Center for Ecological Analysis and Synthesis
6
 *    Authors: Michael Daigle
7
 *
8
 *   '$Author$'
9
 *     '$Date$'
10
 * '$Revision$'
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.service;
28
29 8588 leinfelder
import java.io.IOException;
30
import java.io.Writer;
31 5041 daigle
import java.util.Calendar;
32 5311 daigle
import java.util.Enumeration;
33 4080 daigle
import java.util.Hashtable;
34
35 5041 daigle
import javax.servlet.http.HttpServletResponse;
36
37 4080 daigle
import org.apache.log4j.Logger;
38
39 5041 daigle
import edu.ucsb.nceas.metacat.properties.PropertyService;
40 5015 daigle
import edu.ucsb.nceas.metacat.shared.BaseService;
41
import edu.ucsb.nceas.metacat.shared.ServiceException;
42 4080 daigle
import edu.ucsb.nceas.metacat.util.SessionData;
43 5041 daigle
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
44 4080 daigle
45 4442 daigle
public class SessionService extends BaseService {
46 4080 daigle
47
	private static SessionService sessionService = null;
48 5041 daigle
	private static int sessionTimeoutMinutes;
49 4080 daigle
50
	private static Logger logMetacat = Logger.getLogger(SessionService.class);
51
	private static Hashtable<String, SessionData> sessionHash = null;
52
53 4297 daigle
	private static final String PUBLIC_SESSION_ID = "0";
54 5311 daigle
55
	private static Object lockObj = new Object();
56 4080 daigle
57
	/**
58
	 * private constructor since this is a singleton
59
	 */
60 5015 daigle
	private SessionService() throws ServiceException {
61
		_serviceName = "SessionService";
62
63 5041 daigle
		String sessionTimeoutStr = null;
64
		try {
65
			sessionHash = new Hashtable<String, SessionData>();
66
			sessionTimeoutStr = PropertyService.getProperty("session.timeoutMinutes");
67
			sessionTimeoutMinutes = Integer.parseInt(sessionTimeoutStr);
68
69
			logMetacat.debug("SessionService() - Registering public session id: " +
70
					PUBLIC_SESSION_ID);
71 5070 daigle
			registerSession(PUBLIC_SESSION_ID, "public", null, null, "Public User");
72 5041 daigle
		} catch (PropertyNotFoundException pnfe) {
73
			throw new ServiceException("SessionService() - Error getting property: " +
74
					pnfe.getMessage());
75
		} catch (NumberFormatException nfe) {
76
			throw new ServiceException("SessionService() - Error parsing session timeout minutes: " +
77
					sessionTimeoutStr);
78
		}
79 4080 daigle
	}
80
81
	/**
82 4429 daigle
	 * Get the single instance of SessionService.
83 4080 daigle
	 *
84 4429 daigle
	 * @return the single instance of SessionService
85 4080 daigle
	 */
86 5374 berkley
	public static SessionService getInstance() {
87
	    try
88
	    {
89
	        if (sessionService == null) {
90
	            sessionService = new SessionService();
91
	        }
92
	        return sessionService;
93
	    }
94
	    catch(ServiceException se)
95
	    {
96
	        logMetacat.error("SessionService.getInstance - could not get " +
97
	                "an instance of SessionService: " + se.getMessage());
98
	    }
99
		return null;
100 4080 daigle
	}
101 4297 daigle
102 4442 daigle
	public boolean refreshable() {
103
		return false;
104
	}
105
106 4981 daigle
	public void doRefresh() throws ServiceException {
107 4442 daigle
		return;
108
	}
109
110 4981 daigle
	public void stop() throws ServiceException {
111
		return;
112
	}
113
114 4297 daigle
	/**
115
	 * Register a session in the session hash table.  This uses
116
	 * the parameters passed in to create a SessionData object.
117
	 *
118
	 * @param sessionId
119
	 *            the ID of the session to register
120
	 * @param userName
121
	 *            the user name of the session
122
	 * @param groupNames
123
	 *            the group names for the session
124
	 * @param password
125
	 *            the password for the session
126
	 */
127 5374 berkley
	public void registerSession(String sessionId, String userName,
128 5070 daigle
			String[] groupNames, String password, String name) throws ServiceException {
129 5311 daigle
		synchronized(lockObj) {
130
			if (sessionId == null) {
131
				throw new ServiceException("SessionService.registerSession - " +
132
						"Cannot register a null session id");
133
			}
134
			logMetacat.debug("SessionService.registerSession - Registering session id: " + sessionId);
135
			SessionData sessionData = new SessionData(sessionId, userName, groupNames,
136
					password, name);
137
			sessionHash.put(sessionId, sessionData);
138 4780 daigle
		}
139 4080 daigle
	}
140
141 4297 daigle
	/**
142
	 * Register a session in the session hash table.
143
	 *
144
	 * @param sessionData
145
	 *            the session data object to add to the session hash
146
	 */
147 5374 berkley
	public void registerSession(SessionData sessionData) throws ServiceException {
148 5311 daigle
		synchronized(lockObj) {
149
			if (sessionData == null) {
150
				throw new ServiceException("SessionService.registerSession - " +
151
						"Cannot register null session data");
152
			}
153
			logMetacat.debug("SessionService.registerSession - Registering session " +
154
					"data with id: " + sessionData.getId());
155
			sessionHash.put(sessionData.getId(), sessionData);
156 4780 daigle
		}
157 4080 daigle
	}
158
159 4297 daigle
	/**
160
	 * Unregister a session from the session hash table.
161
	 *
162
	 * @param sessionId
163
	 *            the id of the session to remove.
164
	 */
165 5374 berkley
	public void unRegisterSession(String sessionId) {
166 5311 daigle
		synchronized(lockObj) {
167
			if (sessionId == null) {
168
				logMetacat.error("SessionService.unRegisterSession - trying to " +
169 5041 daigle
					"unregister a session with null id");
170 5505 leinfelder
				return;
171 5311 daigle
			}
172 5505 leinfelder
			if (sessionId.equals(PUBLIC_SESSION_ID)) {
173
				logMetacat.error("SessionService.unRegisterSession - cannot unregister public session, " +
174
					"sessionId=" + sessionId);
175
				return;
176
			}
177 5311 daigle
178
			logMetacat.info("SessionService.unRegisterSession - unRegistering session: " + sessionId);
179
			sessionHash.remove(sessionId);
180 4780 daigle
		}
181 4080 daigle
	}
182
183 4297 daigle
	/**
184 5311 daigle
	 * Unregister all sessions from the session hash table except the public session.
185
	 *
186
	 * @param sessionId
187
	 *            the id of the session to remove.
188
	 */
189 5374 berkley
	public void unRegisterAllSessions() {
190 5311 daigle
		synchronized(lockObj) {
191
			Enumeration<String> keyEnum = sessionHash.keys();
192
			while (keyEnum.hasMoreElements()) {
193
				String sessionId = keyEnum.nextElement();
194
				if (!sessionId.equals(PUBLIC_SESSION_ID)) {
195
					logMetacat.info("SessionService.unRegisterAllSessions - unRegistering session: " + sessionId);
196
					sessionHash.remove(sessionId);
197
				}
198
			}
199
		}
200
	}
201
202
	/**
203 4297 daigle
	 * Check if a session is registered in the session hash table.
204
	 *
205
	 * @param sessionId
206
	 *            the id of the session to look for.
207
	 */
208 5374 berkley
	public boolean isSessionRegistered(String sessionId) {
209 4780 daigle
		if (sessionId == null) {
210 5041 daigle
			logMetacat.error("SessionService.isSessionRegistered - trying to check if a " +
211
					"session with null id is registered");
212 4780 daigle
			return false;
213
		}
214 5041 daigle
215
		checkTimeout(sessionId);
216
217 4080 daigle
		return sessionHash.containsKey(sessionId);
218
	}
219
220 4297 daigle
	/**
221 5041 daigle
	 * Check if a session is registered in the session hash table. Write results
222
	 * in XML format to output.
223
	 *
224
	 * @param out
225
	 *            the output stream to write to.
226
	 * @param sessionId
227
	 *            the id of the session to look for.
228 8588 leinfelder
	 * @throws IOException
229 5041 daigle
	 */
230 8588 leinfelder
	public void validateSession(Writer out, HttpServletResponse response,
231
			String sessionId) throws IOException {
232 7172 tao
		boolean needSessionInfo = false;
233 5041 daigle
		response.setContentType("text/xml");
234 8588 leinfelder
		out.write("<?xml version=\"1.0\"?>");
235 5041 daigle
		out.write("<validateSession><status>");
236 5070 daigle
		if (validateSession(sessionId)) {
237 5041 daigle
			out.write("valid");
238 7172 tao
			needSessionInfo = true;
239 5041 daigle
		} else {
240
			out.write("invalid");
241
		}
242
		out.write("</status>");
243 8075 leinfelder
		if (needSessionInfo) {
244
			SessionData sessionData = getRegisteredSession(sessionId);
245
		    if (sessionData != null) {
246
		      out.write("<userInformation>");
247
		      out.write("<name>");
248
		      out.write(sessionData.getUserName());
249
		      out.write("</name>");
250
		      out.write("<fullName>");
251
		      out.write(sessionData.getName());
252
		      out.write("</fullName>");
253
		      appendGroupsInformation(sessionData, out);
254
		      out.write("</userInformation>");
255
		    }
256 7172 tao
		}
257 5041 daigle
		out.write("<sessionId>" + sessionId + "</sessionId></validateSession>");
258
	}
259
260
	/**
261 5070 daigle
	 * Check if a session is registered in the session hash table. Return
262
	 * true if the session is valid and false otherwise.
263
	 *
264
	 * @param sessionId
265
	 *            the id of the session to look for.
266
	 */
267 5374 berkley
	public boolean validateSession(String sessionId) {
268 5070 daigle
		if (sessionId != null && !sessionId.equals(PUBLIC_SESSION_ID) && isSessionRegistered(sessionId)) {
269
			return true;
270
		} else {
271
			return false;
272
		}
273
	}
274
275
	/**
276 4297 daigle
	 * Get a registered session from the session hash table.
277
	 * TODO MCD need to time sessions out
278
	 *
279
	 * @param sessionId
280
	 *            the id of the session to retrieve.
281
	 */
282 5374 berkley
	public SessionData getRegisteredSession(String sessionId) {
283 4780 daigle
		if (sessionId == null) {
284 5041 daigle
			logMetacat.error("SessionService.getRegisteredSession - trying to get a session with null id");
285 4780 daigle
			return null;
286
		}
287 5041 daigle
		checkTimeout(sessionId);
288
289 4080 daigle
		return sessionHash.get(sessionId);
290
	}
291
292 4297 daigle
	/**
293
	 * Get the public session from the session hash table.
294
	 */
295 5374 berkley
	public SessionData getPublicSession() {
296 4297 daigle
		return sessionHash.get(PUBLIC_SESSION_ID);
297 4080 daigle
	}
298
299 4297 daigle
	/**
300
	 * Keep a session active by updating its last accessed time.
301
	 *
302
	 * @param sessionId
303
	 *            the id of the session to update.
304
	 */
305 5374 berkley
	public synchronized void touchSession(String sessionId) {
306 4780 daigle
		if (sessionId == null) {
307 5041 daigle
			logMetacat.error("SessionService.touchSession - trying to touch a session with null id");
308 4780 daigle
		} else if (isSessionRegistered(sessionId)) {
309 5311 daigle
			synchronized(lockObj) {
310
				SessionData sessionData = getRegisteredSession(sessionId);
311
				sessionData.setLastAccessedTime();
312
			}
313 4080 daigle
		}
314
	}
315 5041 daigle
316 5374 berkley
	private void checkTimeout (String sessionId) {
317 5041 daigle
		SessionData sessionData = null;
318
		if ((sessionData = sessionHash.get(sessionId)) != null) {
319
			Calendar expireTime = Calendar.getInstance();
320
			Calendar lastAccessedTime = sessionData.getLastAccessedTime();
321
			expireTime.add(Calendar.MINUTE, 0 - sessionTimeoutMinutes);
322
			if(lastAccessedTime.compareTo(expireTime) < 0 ) {
323
				unRegisterSession(sessionId);
324
			}
325 5311 daigle
		}
326 5041 daigle
	}
327 7172 tao
328
	/*
329
	 * Add user's groups information into the response
330
	 */
331 8588 leinfelder
	private void appendGroupsInformation(SessionData sessionData, Writer out ) throws IOException {
332 7172 tao
	  if(sessionData != null && out != null){
333
	    String[] groups = sessionData.getGroupNames();
334
	    if(groups != null) {
335
	      for(String groupName : groups) {
336
	        out.write("<group>");
337
	        out.write(groupName);
338
	        out.write("</group>");
339
	      }
340
	    }
341
	  }
342
343
	}
344 4080 daigle
345
}