Project

General

Profile

1
/**
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: berkley $'
9
 *     '$Date: 2010-06-08 12:34:30 -0700 (Tue, 08 Jun 2010) $'
10
 * '$Revision: 5374 $'
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
import java.io.PrintWriter;
30
import java.util.Calendar;
31
import java.util.Enumeration;
32
import java.util.Hashtable;
33

    
34
import javax.servlet.http.HttpServletResponse;
35

    
36
import org.apache.log4j.Logger;
37

    
38
import edu.ucsb.nceas.metacat.properties.PropertyService;
39
import edu.ucsb.nceas.metacat.shared.BaseService;
40
import edu.ucsb.nceas.metacat.shared.ServiceException;
41
import edu.ucsb.nceas.metacat.util.SessionData;
42
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
43

    
44
public class SessionService extends BaseService {
45
	
46
	private static SessionService sessionService = null;
47
	private static int sessionTimeoutMinutes;
48
	
49
	private static Logger logMetacat = Logger.getLogger(SessionService.class);
50
	private static Hashtable<String, SessionData> sessionHash = null;
51
	
52
	private static final String PUBLIC_SESSION_ID = "0";
53
	
54
	private static Object lockObj = new Object();
55

    
56
	/**
57
	 * private constructor since this is a singleton
58
	 */
59
	private SessionService() throws ServiceException {		
60
		_serviceName = "SessionService";
61
		
62
		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
			registerSession(PUBLIC_SESSION_ID, "public", null, null, "Public User");
71
		} 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
	}
79
	
80
	/**
81
	 * Get the single instance of SessionService.
82
	 * 
83
	 * @return the single instance of SessionService
84
	 */
85
	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
	}
100
	
101
	public boolean refreshable() {
102
		return false;
103
	}
104
	
105
	public void doRefresh() throws ServiceException {
106
		return;
107
	}
108
	
109
	public void stop() throws ServiceException {
110
		return;
111
	}
112
	
113
	/**
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
	public void registerSession(String sessionId, String userName,
127
			String[] groupNames, String password, String name) throws ServiceException {
128
		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
		}
138
	}
139
	
140
	/**
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
	public void registerSession(SessionData sessionData) throws ServiceException {
147
		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
		}
156
	}
157
	
158
	/**
159
	 * Unregister a session from the session hash table.
160
	 * 
161
	 * @param sessionId
162
	 *            the id of the session to remove.
163
	 */
164
	public void unRegisterSession(String sessionId) {
165
		synchronized(lockObj) {
166
			if (sessionId == null) {
167
				logMetacat.error("SessionService.unRegisterSession - trying to " + 
168
					"unregister a session with null id");
169
			}
170
		
171
			logMetacat.info("SessionService.unRegisterSession - unRegistering session: " + sessionId);
172
			sessionHash.remove(sessionId);
173
		}
174
	}
175
	
176
	/**
177
	 * Unregister all sessions from the session hash table except the public session.
178
	 * 
179
	 * @param sessionId
180
	 *            the id of the session to remove.
181
	 */
182
	public void unRegisterAllSessions() {
183
		synchronized(lockObj) {
184
			Enumeration<String> keyEnum = sessionHash.keys();
185
			while (keyEnum.hasMoreElements()) {
186
				String sessionId = keyEnum.nextElement();
187
				if (!sessionId.equals(PUBLIC_SESSION_ID)) {
188
					logMetacat.info("SessionService.unRegisterAllSessions - unRegistering session: " + sessionId);
189
					sessionHash.remove(sessionId);
190
				}
191
			}
192
		}
193
	}
194
	
195
	/**
196
	 * Check if a session is registered in the session hash table. 
197
	 * 
198
	 * @param sessionId
199
	 *            the id of the session to look for.
200
	 */
201
	public boolean isSessionRegistered(String sessionId) {		
202
		if (sessionId == null) {
203
			logMetacat.error("SessionService.isSessionRegistered - trying to check if a " + 
204
					"session with null id is registered");
205
			return false;
206
		}
207
		
208
		checkTimeout(sessionId);
209
		
210
		return sessionHash.containsKey(sessionId);
211
	}
212
	
213
	/**
214
	 * Check if a session is registered in the session hash table. Write results
215
	 * in XML format to output.
216
	 * 
217
	 * @param out
218
	 *            the output stream to write to.
219
	 * @param sessionId
220
	 *            the id of the session to look for.
221
	 */
222
	public void validateSession(PrintWriter out, HttpServletResponse response, 
223
			String sessionId) {		
224
		
225
		response.setContentType("text/xml");
226
		out.println("<?xml version=\"1.0\"?>");
227
		out.write("<validateSession><status>");
228
		if (validateSession(sessionId)) {
229
			out.write("valid");
230
		} else {
231
			out.write("invalid");
232
		}
233
		out.write("</status>");
234
		out.write("<sessionId>" + sessionId + "</sessionId></validateSession>");				
235
	}
236
	
237
	/**
238
	 * Check if a session is registered in the session hash table. Return
239
	 * true if the session is valid and false otherwise.
240
	 * 
241
	 * @param sessionId
242
	 *            the id of the session to look for.
243
	 */
244
	public boolean validateSession(String sessionId) {				
245
		if (sessionId != null && !sessionId.equals(PUBLIC_SESSION_ID) && isSessionRegistered(sessionId)) {
246
			return true;
247
		} else {
248
			return false;
249
		}			
250
	}
251
	
252
	/**
253
	 * Get a registered session from the session hash table. 
254
	 * TODO MCD need to time sessions out
255
	 * 
256
	 * @param sessionId
257
	 *            the id of the session to retrieve.
258
	 */
259
	public SessionData getRegisteredSession(String sessionId) {
260
		if (sessionId == null) {
261
			logMetacat.error("SessionService.getRegisteredSession - trying to get a session with null id");
262
			return null;
263
		}
264
		checkTimeout(sessionId);
265
		
266
		return sessionHash.get(sessionId);
267
	}
268
	
269
	/**
270
	 * Get the public session from the session hash table. 
271
	 */
272
	public SessionData getPublicSession() {
273
		return sessionHash.get(PUBLIC_SESSION_ID);
274
	}
275
	
276
	/**
277
	 * Keep a session active by updating its last accessed time. 
278
	 * 
279
	 * @param sessionId
280
	 *            the id of the session to update.
281
	 */
282
	public synchronized void touchSession(String sessionId) {
283
		if (sessionId == null) {
284
			logMetacat.error("SessionService.touchSession - trying to touch a session with null id");
285
		} else if (isSessionRegistered(sessionId)) {
286
			synchronized(lockObj) {
287
				SessionData sessionData = getRegisteredSession(sessionId);
288
				sessionData.setLastAccessedTime();
289
			}
290
		}
291
	}
292
	
293
	private void checkTimeout (String sessionId) {
294
		SessionData sessionData = null;
295
		if ((sessionData = sessionHash.get(sessionId)) != null) {
296
			Calendar expireTime = Calendar.getInstance();
297
			Calendar lastAccessedTime = sessionData.getLastAccessedTime();
298
			expireTime.add(Calendar.MINUTE, 0 - sessionTimeoutMinutes);
299
			if(lastAccessedTime.compareTo(expireTime) < 0 ) {
300
				unRegisterSession(sessionId);
301
			}
302
		}		
303
	}
304

    
305
}
(2-2/4)