Coverage Report - org.apache.shiro.session.mgt.DefaultSessionManager
 
Classes in this File Line Coverage Branch Coverage Complexity
DefaultSessionManager
90%
59/65
58%
14/24
1.636
 
 1  
 /*
 2  
  * Licensed to the Apache Software Foundation (ASF) under one
 3  
  * or more contributor license agreements.  See the NOTICE file
 4  
  * distributed with this work for additional information
 5  
  * regarding copyright ownership.  The ASF licenses this file
 6  
  * to you under the Apache License, Version 2.0 (the
 7  
  * "License"); you may not use this file except in compliance
 8  
  * with the License.  You may obtain a copy of the License at
 9  
  *
 10  
  *     http://www.apache.org/licenses/LICENSE-2.0
 11  
  *
 12  
  * Unless required by applicable law or agreed to in writing,
 13  
  * software distributed under the License is distributed on an
 14  
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 15  
  * KIND, either express or implied.  See the License for the
 16  
  * specific language governing permissions and limitations
 17  
  * under the License.
 18  
  */
 19  
 package org.apache.shiro.session.mgt;
 20  
 
 21  
 import org.apache.shiro.cache.CacheManager;
 22  
 import org.apache.shiro.cache.CacheManagerAware;
 23  
 import org.apache.shiro.session.Session;
 24  
 import org.apache.shiro.session.UnknownSessionException;
 25  
 import org.apache.shiro.session.mgt.eis.MemorySessionDAO;
 26  
 import org.apache.shiro.session.mgt.eis.SessionDAO;
 27  
 import org.slf4j.Logger;
 28  
 import org.slf4j.LoggerFactory;
 29  
 
 30  
 import java.io.Serializable;
 31  
 import java.util.Collection;
 32  
 import java.util.Collections;
 33  
 import java.util.Date;
 34  
 
 35  
 /**
 36  
  * Default business-tier implementation of a {@link ValidatingSessionManager}.  All session CRUD operations are
 37  
  * delegated to an internal {@link SessionDAO}.
 38  
  *
 39  
  * @since 0.1
 40  
  */
 41  
 public class DefaultSessionManager extends AbstractValidatingSessionManager implements CacheManagerAware {
 42  
 
 43  
     //TODO - complete JavaDoc
 44  
 
 45  1
     private static final Logger log = LoggerFactory.getLogger(DefaultSessionManager.class);
 46  
 
 47  
     private SessionFactory sessionFactory;
 48  
 
 49  
     protected SessionDAO sessionDAO;  //todo - move SessionDAO up to AbstractValidatingSessionManager?
 50  
 
 51  
     private CacheManager cacheManager;
 52  
 
 53  
     private boolean deleteInvalidSessions;
 54  
 
 55  44
     public DefaultSessionManager() {
 56  44
         this.deleteInvalidSessions = true;
 57  44
         this.sessionFactory = new SimpleSessionFactory();
 58  44
         this.sessionDAO = new MemorySessionDAO();
 59  44
     }
 60  
 
 61  
     public void setSessionDAO(SessionDAO sessionDAO) {
 62  2
         this.sessionDAO = sessionDAO;
 63  2
         applyCacheManagerToSessionDAO();
 64  2
     }
 65  
 
 66  
     public SessionDAO getSessionDAO() {
 67  1
         return this.sessionDAO;
 68  
     }
 69  
 
 70  
     /**
 71  
      * Returns the {@code SessionFactory} used to generate new {@link Session} instances.  The default instance
 72  
      * is a {@link SimpleSessionFactory}.
 73  
      *
 74  
      * @return the {@code SessionFactory} used to generate new {@link Session} instances.
 75  
      * @since 1.0
 76  
      */
 77  
     public SessionFactory getSessionFactory() {
 78  28
         return sessionFactory;
 79  
     }
 80  
 
 81  
     /**
 82  
      * Sets the {@code SessionFactory} used to generate new {@link Session} instances.  The default instance
 83  
      * is a {@link SimpleSessionFactory}.
 84  
      *
 85  
      * @param sessionFactory the {@code SessionFactory} used to generate new {@link Session} instances.
 86  
      * @since 1.0
 87  
      */
 88  
     public void setSessionFactory(SessionFactory sessionFactory) {
 89  1
         this.sessionFactory = sessionFactory;
 90  1
     }
 91  
 
 92  
     /**
 93  
      * Returns {@code true} if sessions should be automatically deleted after they are discovered to be invalid,
 94  
      * {@code false} if invalid sessions will be manually deleted by some process external to Shiro's control.  The
 95  
      * default is {@code true} to ensure no orphans exist in the underlying data store.
 96  
      * <h4>Usage</h4>
 97  
      * It is ok to set this to {@code false} <b><em>ONLY</em></b> if you have some other process that you manage yourself
 98  
      * that periodically deletes invalid sessions from the backing data store over time, such as via a Quartz or Cron
 99  
      * job.  If you do not do this, the invalid sessions will become 'orphans' and fill up the data store over time.
 100  
      * <p/>
 101  
      * This property is provided because some systems need the ability to perform querying/reporting against sessions in
 102  
      * the data store, even after they have stopped or expired.  Setting this attribute to {@code false} will allow
 103  
      * such querying, but with the caveat that the application developer/configurer deletes the sessions themselves by
 104  
      * some other means (cron, quartz, etc).
 105  
      *
 106  
      * @return {@code true} if sessions should be automatically deleted after they are discovered to be invalid,
 107  
      *         {@code false} if invalid sessions will be manually deleted by some process external to Shiro's control.
 108  
      * @since 1.0
 109  
      */
 110  
     public boolean isDeleteInvalidSessions() {
 111  17
         return deleteInvalidSessions;
 112  
     }
 113  
 
 114  
     /**
 115  
      * Sets whether or not sessions should be automatically deleted after they are discovered to be invalid.  Default
 116  
      * value is {@code true} to ensure no orphans will exist in the underlying data store.
 117  
      * <h4>WARNING</h4>
 118  
      * Only set this value to {@code false} if you are manually going to delete sessions yourself by some process
 119  
      * (quartz, cron, etc) external to Shiro's control.  See the
 120  
      * {@link #isDeleteInvalidSessions() isDeleteInvalidSessions()} JavaDoc for more.
 121  
      *
 122  
      * @param deleteInvalidSessions whether or not sessions should be automatically deleted after they are discovered
 123  
      *                              to be invalid.
 124  
      * @since 1.0
 125  
      */
 126  
     @SuppressWarnings({"UnusedDeclaration"})
 127  
     public void setDeleteInvalidSessions(boolean deleteInvalidSessions) {
 128  0
         this.deleteInvalidSessions = deleteInvalidSessions;
 129  0
     }
 130  
 
 131  
     public void setCacheManager(CacheManager cacheManager) {
 132  38
         this.cacheManager = cacheManager;
 133  38
         applyCacheManagerToSessionDAO();
 134  38
     }
 135  
 
 136  
     /**
 137  
      * Sets the internal {@code CacheManager} on the {@code SessionDAO} if it implements the
 138  
      * {@link org.apache.shiro.cache.CacheManagerAware CacheManagerAware} interface.
 139  
      * <p/>
 140  
      * This method is called after setting a cacheManager via the
 141  
      * {@link #setCacheManager(org.apache.shiro.cache.CacheManager) setCacheManager} method <em>em</em> when
 142  
      * setting a {@code SessionDAO} via the {@link #setSessionDAO} method to allow it to be propagated
 143  
      * in either case.
 144  
      *
 145  
      * @since 1.0
 146  
      */
 147  
     private void applyCacheManagerToSessionDAO() {
 148  40
         if (this.cacheManager != null && this.sessionDAO != null && this.sessionDAO instanceof CacheManagerAware) {
 149  1
             ((CacheManagerAware) this.sessionDAO).setCacheManager(this.cacheManager);
 150  
         }
 151  40
     }
 152  
 
 153  
     protected Session doCreateSession(SessionContext context) {
 154  28
         Session s = newSessionInstance(context);
 155  28
         if (log.isTraceEnabled()) {
 156  28
             log.trace("Creating session for host {}", s.getHost());
 157  
         }
 158  28
         create(s);
 159  28
         return s;
 160  
     }
 161  
 
 162  
     protected Session newSessionInstance(SessionContext context) {
 163  28
         return getSessionFactory().createSession(context);
 164  
     }
 165  
 
 166  
     /**
 167  
      * Persists the given session instance to an underlying EIS (Enterprise Information System).  This implementation
 168  
      * delegates and calls
 169  
      * <code>this.{@link SessionDAO sessionDAO}.{@link SessionDAO#create(org.apache.shiro.session.Session) create}(session);<code>
 170  
      *
 171  
      * @param session the Session instance to persist to the underlying EIS.
 172  
      */
 173  
     protected void create(Session session) {
 174  28
         if (log.isDebugEnabled()) {
 175  28
             log.debug("Creating new EIS record for new session instance [" + session + "]");
 176  
         }
 177  28
         sessionDAO.create(session);
 178  28
     }
 179  
 
 180  
     @Override
 181  
     protected void onStop(Session session) {
 182  12
         if (session instanceof SimpleSession) {
 183  12
             SimpleSession ss = (SimpleSession) session;
 184  12
             Date stopTs = ss.getStopTimestamp();
 185  12
             ss.setLastAccessTime(stopTs);
 186  
         }
 187  12
         onChange(session);
 188  12
     }
 189  
 
 190  
     @Override
 191  
     protected void afterStopped(Session session) {
 192  12
         if (isDeleteInvalidSessions()) {
 193  12
             delete(session);
 194  
         }
 195  12
     }
 196  
 
 197  
     protected void onExpiration(Session session) {
 198  5
         if (session instanceof SimpleSession) {
 199  5
             ((SimpleSession) session).setExpired(true);
 200  
         }
 201  5
         onChange(session);
 202  5
     }
 203  
 
 204  
     @Override
 205  
     protected void afterExpired(Session session) {
 206  5
         if (isDeleteInvalidSessions()) {
 207  5
             delete(session);
 208  
         }
 209  5
     }
 210  
 
 211  
     protected void onChange(Session session) {
 212  111
         sessionDAO.update(session);
 213  111
     }
 214  
 
 215  
     protected Session retrieveSession(SessionKey sessionKey) throws UnknownSessionException {
 216  203
         Serializable sessionId = getSessionId(sessionKey);
 217  203
         if (sessionId == null) {
 218  0
             log.debug("Unable to resolve session ID from SessionKey [{}].  Returning null to indicate a " +
 219  
                     "session could not be found.", sessionKey);
 220  0
             return null;
 221  
         }
 222  203
         Session s = retrieveSessionFromDataSource(sessionId);
 223  203
         if (s == null) {
 224  
             //session ID was provided, meaning one is expected to be found, but we couldn't find one:
 225  0
             String msg = "Could not find session with ID [" + sessionId + "]";
 226  0
             throw new UnknownSessionException(msg);
 227  
         }
 228  203
         return s;
 229  
     }
 230  
 
 231  
     protected Serializable getSessionId(SessionKey sessionKey) {
 232  203
         return sessionKey.getSessionId();
 233  
     }
 234  
 
 235  
     protected Session retrieveSessionFromDataSource(Serializable sessionId) throws UnknownSessionException {
 236  203
         return sessionDAO.readSession(sessionId);
 237  
     }
 238  
 
 239  
     protected void delete(Session session) {
 240  17
         sessionDAO.delete(session);
 241  17
     }
 242  
 
 243  
     protected Collection<Session> getActiveSessions() {
 244  3
         Collection<Session> active = sessionDAO.getActiveSessions();
 245  3
         return active != null ? active : Collections.<Session>emptySet();
 246  
     }
 247  
 
 248  
 }