1 package org.apache.turbine.services.session;
2
3
4 /*
5 * Licensed to the Apache Software Foundation (ASF) under one
6 * or more contributor license agreements. See the NOTICE file
7 * distributed with this work for additional information
8 * regarding copyright ownership. The ASF licenses this file
9 * to you under the Apache License, Version 2.0 (the
10 * "License"); you may not use this file except in compliance
11 * with the License. You may obtain a copy of the License at
12 *
13 * http://www.apache.org/licenses/LICENSE-2.0
14 *
15 * Unless required by applicable law or agreed to in writing,
16 * software distributed under the License is distributed on an
17 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
18 * KIND, either express or implied. See the License for the
19 * specific language governing permissions and limitations
20 * under the License.
21 */
22
23
24 import java.util.ArrayList;
25 import java.util.Collection;
26 import java.util.Hashtable;
27 import java.util.Iterator;
28 import java.util.Map;
29 import javax.servlet.http.HttpSession;
30
31 import org.apache.turbine.om.security.User;
32 import org.apache.turbine.services.TurbineBaseService;
33
34 /**
35 * The SessionService allows thread-safe access to the current
36 * sessions of the current context. The session objects that are
37 * cached by this service are obtained through a listener, which must
38 * be configured via your web application's <code>web.xml</code>
39 * deployement descriptor as follows:
40 *
41 * <blockquote><code><pre>
42 * <listener>
43 * <listener-class>
44 * org.apache.turbine.session.SessionListener
45 * </listener-class>
46 * </listener>
47 * </pre></code></blockquote>
48 *
49 * @author <a href="mailto:quintonm@bellsouth.net">Quinton McCombs</a>
50 * @author <a href="mailto:dlr@collab.net">Daniel Rall</a>
51 * @since 2.3
52 * @version $Id: TurbineSessionService.java 1066925 2011-02-03 19:44:37Z ludwig $
53 * @see org.apache.turbine.services.session.TurbineSession
54 * @see org.apache.turbine.services.session.SessionListener
55 */
56 public class TurbineSessionService
57 extends TurbineBaseService
58 implements SessionService
59 {
60 /** Map of active sessions */
61 private Map<String, HttpSession> activeSessions;
62
63 /**
64 * Gets a list of the active sessions.
65 *
66 * @return A copy of the list of <code>HttpSession</code> objects.
67 */
68 public Collection<HttpSession> getActiveSessions()
69 {
70 // Sync externally to allow ArrayList's ctor to iterate
71 // activeSessions' values in a thread-safe fashion.
72 synchronized (activeSessions)
73 {
74 return new ArrayList<HttpSession>(activeSessions.values());
75 }
76 }
77
78 /**
79 * Adds a session to the current list. This method should only be
80 * called by the listener.
81 *
82 * @param session Session to add
83 */
84 public void addSession(HttpSession session)
85 {
86 activeSessions.put(session.getId(), session);
87 }
88
89 /**
90 * Removes a session from the current list. This method should only be
91 * called by the listener.
92 *
93 * @param session Session to remove
94 */
95 public void removeSession(HttpSession session)
96 {
97 activeSessions.remove(session.getId());
98 }
99
100 /**
101 * Determines if a given user is currently logged in. The actual
102 * implementation of the User object must implement the equals()
103 * method. By default, Torque based objects (liek TurbineUser)
104 * have an implementation of equals() that will compare the
105 * result of getPrimaryKey().
106 *
107 * @param user User to check for
108 * @return true if the user is logged in on one of the
109 * active sessions.
110 */
111 public boolean isUserLoggedIn(User user)
112 {
113 return getActiveUsers().contains(user);
114 }
115
116 /**
117 * Gets a collection of all user objects representing the users currently
118 * logged in. This will exclude any instances of anonymous user that
119 * Turbine will use before the user actually logs on.
120 *
121 * @return A set of {@link org.apache.turbine.om.security.User} objects.
122 */
123 public Collection<User> getActiveUsers()
124 {
125 Collection<User> users;
126 synchronized (activeSessions)
127 {
128 // Pre-allocate a list which won't need expansion more
129 // than once.
130 users = new ArrayList<User>((int) (activeSessions.size() * 0.7));
131 for (Iterator<HttpSession> i = activeSessions.values().iterator(); i.hasNext();)
132 {
133 User u = getUserFromSession(i.next());
134 if (u != null && u.hasLoggedIn())
135 {
136 users.add(u);
137 }
138 }
139 }
140
141 return users;
142 }
143
144 /**
145 * Gets the User object of the the specified HttpSession.
146 *
147 * @param session The session from which to extract a user.
148 * @return The Turbine User object.
149 */
150 public User getUserFromSession(HttpSession session)
151 {
152 // Not sure of other containers, but Tomcat 5.0.28 sometimes returns
153 // invalid sessions which will result in IllegalStateException when
154 // session.getAttribute() is invoked below.
155 try
156 {
157 return (User) session.getAttribute(User.SESSION_KEY);
158 }
159 catch (IllegalStateException e)
160 {
161 return null;
162 }
163 }
164
165 /**
166 * Gets the HttpSession by the session identifier
167 *
168 * @param sessionId The unique session identifier.
169 * @return The session keyed by the specified identifier.
170 */
171 public HttpSession getSession(String sessionId)
172 {
173 return this.activeSessions.get(sessionId);
174 }
175
176 /**
177 * Get a collection of all session on which the given user
178 * is logged in.
179 *
180 * @param user the user
181 * @return Collection of HtttSession objects
182 */
183 public Collection<HttpSession> getSessionsForUser(User user)
184 {
185 Collection<HttpSession> sessions = new ArrayList<HttpSession>();
186 synchronized (activeSessions)
187 {
188 for (Iterator<HttpSession> i = activeSessions.values().iterator(); i.hasNext();)
189 {
190 HttpSession session = i.next();
191 User u = this.getUserFromSession(session);
192 if (user.equals(u))
193 {
194 sessions.add(session);
195 }
196 }
197 }
198
199 return sessions;
200 }
201
202
203 // ---- Service initilization ------------------------------------------
204
205 /**
206 * Initializes the service
207 */
208 @Override
209 public void init()
210 {
211 this.activeSessions = new Hashtable<String, HttpSession>();
212
213 setInit(true);
214 }
215
216 /**
217 * Returns to uninitialized state.
218 */
219 @Override
220 public void shutdown()
221 {
222 this.activeSessions = null;
223
224 setInit(false);
225 }
226
227 }