    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 * &lt;listener&gt;
    043 *   &lt;listener-class&gt;
    044 *     org.apache.turbine.session.SessionListener
    045 *   &lt;/listener-class&gt;
    046 * &lt;/listener&gt;
    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}