    001    package 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
    024    import java.util.ArrayList;
    025    import java.util.Collection;
    026    import java.util.Hashtable;
    027    import java.util.Iterator;
    028    import java.util.Map;
    029    import javax.servlet.http.HttpSession;
    030
    031    import org.apache.turbine.om.security.User;
    032    import 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     */
    056    public 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    }