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