001package org.apache.turbine.services.session; 002 003 004/* 005 * Licensed to the Apache Software Foundation (ASF) under one 006 * or more contributor license agreements. See the NOTICE file 007 * distributed with this work for additional information 008 * regarding copyright ownership. The ASF licenses this file 009 * to you under the Apache License, Version 2.0 (the 010 * "License"); you may not use this file except in compliance 011 * with the License. You may obtain a copy of the License at 012 * 013 * http://www.apache.org/licenses/LICENSE-2.0 014 * 015 * Unless required by applicable law or agreed to in writing, 016 * software distributed under the License is distributed on an 017 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 018 * KIND, either express or implied. See the License for the 019 * specific language governing permissions and limitations 020 * under the License. 021 */ 022 023 024import java.util.ArrayList; 025import java.util.Collection; 026import java.util.Hashtable; 027import java.util.Iterator; 028import java.util.Map; 029import javax.servlet.http.HttpSession; 030 031import org.apache.turbine.om.security.User; 032import org.apache.turbine.services.TurbineBaseService; 033 034/** 035 * The SessionService allows thread-safe access to the current 036 * sessions of the current context. The session objects that are 037 * cached by this service are obtained through a listener, which must 038 * be configured via your web application's <code>web.xml</code> 039 * deployement descriptor as follows: 040 * 041 * <blockquote><code><pre> 042 * <listener> 043 * <listener-class> 044 * org.apache.turbine.session.SessionListener 045 * </listener-class> 046 * </listener> 047 * </pre></code></blockquote> 048 * 049 * @author <a href="mailto:quintonm@bellsouth.net">Quinton McCombs</a> 050 * @author <a href="mailto:dlr@collab.net">Daniel Rall</a> 051 * @since 2.3 052 * @version $Id: TurbineSessionService.java 1066925 2011-02-03 19:44:37Z ludwig $ 053 * @see org.apache.turbine.services.session.TurbineSession 054 * @see org.apache.turbine.services.session.SessionListener 055 */ 056public class TurbineSessionService 057 extends TurbineBaseService 058 implements SessionService 059{ 060 /** Map of active sessions */ 061 private Map<String, HttpSession> activeSessions; 062 063 /** 064 * Gets a list of the active sessions. 065 * 066 * @return A copy of the list of <code>HttpSession</code> objects. 067 */ 068 public Collection<HttpSession> getActiveSessions() 069 { 070 // Sync externally to allow ArrayList's ctor to iterate 071 // activeSessions' values in a thread-safe fashion. 072 synchronized (activeSessions) 073 { 074 return new ArrayList<HttpSession>(activeSessions.values()); 075 } 076 } 077 078 /** 079 * Adds a session to the current list. This method should only be 080 * called by the listener. 081 * 082 * @param session Session to add 083 */ 084 public void addSession(HttpSession session) 085 { 086 activeSessions.put(session.getId(), session); 087 } 088 089 /** 090 * Removes a session from the current list. This method should only be 091 * called by the listener. 092 * 093 * @param session Session to remove 094 */ 095 public void removeSession(HttpSession session) 096 { 097 activeSessions.remove(session.getId()); 098 } 099 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}