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: leinfelder $'
9
 *     '$Date: 2014-02-10 16:17:30 -0800 (Mon, 10 Feb 2014) $'
10
 * '$Revision: 8588 $'
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.IOException;
30
import java.io.Writer;
31
import java.util.Calendar;
32
import java.util.Enumeration;
33
import java.util.Hashtable;
34

    
35
import javax.servlet.http.HttpServletResponse;
36

    
37
import org.apache.log4j.Logger;
38

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

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

    
57
	/**
58
	 * private constructor since this is a singleton
59
	 */
60
	private SessionService() throws ServiceException {		
61
		_serviceName = "SessionService";
62
		
63
		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
			registerSession(PUBLIC_SESSION_ID, "public", null, null, "Public User");
72
		} 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
	}
80
	
81
	/**
82
	 * Get the single instance of SessionService.
83
	 * 
84
	 * @return the single instance of SessionService
85
	 */
86
	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
	}
101
	
102
	public boolean refreshable() {
103
		return false;
104
	}
105
	
106
	public void doRefresh() throws ServiceException {
107
		return;
108
	}
109
	
110
	public void stop() throws ServiceException {
111
		return;
112
	}
113
	
114
	/**
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
	public void registerSession(String sessionId, String userName,
128
			String[] groupNames, String password, String name) throws ServiceException {
129
		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
		}
139
	}
140
	
141
	/**
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
	public void registerSession(SessionData sessionData) throws ServiceException {
148
		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
		}
157
	}
158
	
159
	/**
160
	 * Unregister a session from the session hash table.
161
	 * 
162
	 * @param sessionId
163
	 *            the id of the session to remove.
164
	 */
165
	public void unRegisterSession(String sessionId) {
166
		synchronized(lockObj) {
167
			if (sessionId == null) {
168
				logMetacat.error("SessionService.unRegisterSession - trying to " + 
169
					"unregister a session with null id");
170
				return;
171
			}
172
			if (sessionId.equals(PUBLIC_SESSION_ID)) {
173
				logMetacat.error("SessionService.unRegisterSession - cannot unregister public session, " +
174
					"sessionId=" + sessionId);
175
				return;
176
			}
177
		
178
			logMetacat.info("SessionService.unRegisterSession - unRegistering session: " + sessionId);
179
			sessionHash.remove(sessionId);
180
		}
181
	}
182
	
183
	/**
184
	 * 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
	public void unRegisterAllSessions() {
190
		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
	 * 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
	public boolean isSessionRegistered(String sessionId) {		
209
		if (sessionId == null) {
210
			logMetacat.error("SessionService.isSessionRegistered - trying to check if a " + 
211
					"session with null id is registered");
212
			return false;
213
		}
214
		
215
		checkTimeout(sessionId);
216
		
217
		return sessionHash.containsKey(sessionId);
218
	}
219
	
220
	/**
221
	 * 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
	 * @throws IOException 
229
	 */
230
	public void validateSession(Writer out, HttpServletResponse response, 
231
			String sessionId) throws IOException {		
232
		boolean needSessionInfo = false;
233
		response.setContentType("text/xml");
234
		out.write("<?xml version=\"1.0\"?>");
235
		out.write("<validateSession><status>");
236
		if (validateSession(sessionId)) {
237
			out.write("valid");
238
			needSessionInfo = true;
239
		} else {
240
			out.write("invalid");
241
		}
242
		out.write("</status>");
243
		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
		}
257
		out.write("<sessionId>" + sessionId + "</sessionId></validateSession>");				
258
	}
259
	
260
	/**
261
	 * 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
	public boolean validateSession(String sessionId) {				
268
		if (sessionId != null && !sessionId.equals(PUBLIC_SESSION_ID) && isSessionRegistered(sessionId)) {
269
			return true;
270
		} else {
271
			return false;
272
		}			
273
	}
274
	
275
	/**
276
	 * 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
	public SessionData getRegisteredSession(String sessionId) {
283
		if (sessionId == null) {
284
			logMetacat.error("SessionService.getRegisteredSession - trying to get a session with null id");
285
			return null;
286
		}
287
		checkTimeout(sessionId);
288
		
289
		return sessionHash.get(sessionId);
290
	}
291
	
292
	/**
293
	 * Get the public session from the session hash table. 
294
	 */
295
	public SessionData getPublicSession() {
296
		return sessionHash.get(PUBLIC_SESSION_ID);
297
	}
298
	
299
	/**
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
	public synchronized void touchSession(String sessionId) {
306
		if (sessionId == null) {
307
			logMetacat.error("SessionService.touchSession - trying to touch a session with null id");
308
		} else if (isSessionRegistered(sessionId)) {
309
			synchronized(lockObj) {
310
				SessionData sessionData = getRegisteredSession(sessionId);
311
				sessionData.setLastAccessedTime();
312
			}
313
		}
314
	}
315
	
316
	private void checkTimeout (String sessionId) {
317
		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
		}		
326
	}
327
	
328
	/*
329
	 * Add user's groups information into the response
330
	 */
331
	private void appendGroupsInformation(SessionData sessionData, Writer out ) throws IOException {
332
	  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

    
345
}
(2-2/7)