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.concurrent.ConcurrentHashMap; 027import java.util.concurrent.ConcurrentMap; 028 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 * deployment descriptor as follows: 040 * 041 * <pre> 042 * <listener> 043 * <listener-class> 044 * org.apache.turbine.session.SessionListener 045 * </listener-class> 046 * </listener> 047 * </pre> 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$ 053 * @see org.apache.turbine.services.session.SessionListener 054 */ 055public class TurbineSessionService 056 extends TurbineBaseService 057 implements SessionService 058{ 059 /** Map of active sessions */ 060 private ConcurrentMap<String, HttpSession> activeSessions; 061 062 /** 063 * Gets a list of the active sessions. 064 * 065 * @return A copy of the list of <code>HttpSession</code> objects. 066 */ 067 @Override 068 public Collection<HttpSession> getActiveSessions() 069 { 070 return new ArrayList<>(activeSessions.values()); 071 } 072 073 /** 074 * Adds a session to the current list. This method should only be 075 * called by the listener. 076 * 077 * @param session Session to add 078 */ 079 @Override 080 public void addSession(HttpSession session) 081 { 082 activeSessions.put(session.getId(), session); 083 } 084 085 /** 086 * Removes a session from the current list. This method should only be 087 * called by the listener. 088 * 089 * @param session Session to remove 090 */ 091 @Override 092 public void removeSession(HttpSession session) 093 { 094 activeSessions.remove(session.getId()); 095 } 096 097 /** 098 * Determines if a given user is currently logged in. The actual 099 * implementation of the User object must implement the equals() 100 * method. By default, Torque based objects (liek TurbineUser) 101 * have an implementation of equals() that will compare the 102 * result of getPrimaryKey(). 103 * 104 * @param user User to check for 105 * @return true if the user is logged in on one of the 106 * active sessions. 107 */ 108 @Override 109 public boolean isUserLoggedIn(User user) 110 { 111 return getActiveUsers().contains(user); 112 } 113 114 /** 115 * Gets a collection of all user objects representing the users currently 116 * logged in. This will exclude any instances of anonymous user that 117 * Turbine will use before the user actually logs on. 118 * 119 * @return A set of {@link org.apache.turbine.om.security.User} objects. 120 */ 121 @Override 122 public Collection<User> getActiveUsers() 123 { 124 Collection<User> users; 125 // Pre-allocate a list which won't need expansion more 126 // than once. 127 users = new ArrayList<>((int) (activeSessions.size() * 0.7)); 128 for (HttpSession session : activeSessions.values()) 129 { 130 User u = getUserFromSession(session); 131 if (u != null && u.hasLoggedIn()) 132 { 133 users.add(u); 134 } 135 } 136 137 return users; 138 } 139 140 /** 141 * Gets the User object of the the specified HttpSession. 142 * 143 * @param session The session from which to extract a user. 144 * @return The Turbine User object. 145 */ 146 @Override 147 public User getUserFromSession(HttpSession session) 148 { 149 // Not sure of other containers, but Tomcat 5.0.28 sometimes returns 150 // invalid sessions which will result in IllegalStateException when 151 // session.getAttribute() is invoked below. 152 try 153 { 154 return (User) session.getAttribute(User.SESSION_KEY); 155 } 156 catch (IllegalStateException e) 157 { 158 return null; 159 } 160 } 161 162 /** 163 * Gets the HttpSession by the session identifier 164 * 165 * @param sessionId The unique session identifier. 166 * @return The session keyed by the specified identifier. 167 */ 168 @Override 169 public HttpSession getSession(String sessionId) 170 { 171 return this.activeSessions.get(sessionId); 172 } 173 174 /** 175 * Get a collection of all session on which the given user 176 * is logged in. 177 * 178 * @param user the user 179 * @return Collection of HtttSession objects 180 */ 181 @Override 182 public Collection<HttpSession> getSessionsForUser(User user) 183 { 184 Collection<HttpSession> sessions = new ArrayList<>(); 185 for (HttpSession session : activeSessions.values()) 186 { 187 User u = this.getUserFromSession(session); 188 if (user.equals(u)) 189 { 190 sessions.add(session); 191 } 192 } 193 194 return sessions; 195 } 196 197 198 // ---- Service initialization ------------------------------------------ 199 200 /** 201 * Initializes the service 202 */ 203 @Override 204 public void init() 205 { 206 this.activeSessions = new ConcurrentHashMap<>(); 207 208 setInit(true); 209 } 210 211 /** 212 * Returns to uninitialized state. 213 */ 214 @Override 215 public void shutdown() 216 { 217 this.activeSessions = null; 218 219 setInit(false); 220 } 221 222}