Coverage Report - org.apache.shiro.session.mgt.AbstractNativeSessionManager
 
Classes in this File Line Coverage Branch Coverage Complexity
AbstractNativeSessionManager
76%
70/92
59%
13/22
1.471
 
 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.authz.AuthorizationException;
 22  
 import org.apache.shiro.session.*;
 23  
 import org.apache.shiro.util.CollectionUtils;
 24  
 import org.slf4j.Logger;
 25  
 import org.slf4j.LoggerFactory;
 26  
 
 27  
 import java.util.ArrayList;
 28  
 import java.util.Collection;
 29  
 import java.util.Collections;
 30  
 import java.util.Date;
 31  
 
 32  
 /**
 33  
  * Abstract implementation supporting the {@link NativeSessionManager NativeSessionManager} interface, supporting
 34  
  * {@link SessionListener SessionListener}s and application of the
 35  
  * {@link #getGlobalSessionTimeout() globalSessionTimeout}.
 36  
  *
 37  
  * @since 1.0
 38  
  */
 39  
 public abstract class AbstractNativeSessionManager extends AbstractSessionManager implements NativeSessionManager {
 40  
 
 41  2
     private static final Logger log = LoggerFactory.getLogger(AbstractSessionManager.class);
 42  
 
 43  
     private Collection<SessionListener> listeners;
 44  
 
 45  90
     public AbstractNativeSessionManager() {
 46  90
         this.listeners = new ArrayList<SessionListener>();
 47  90
     }
 48  
 
 49  
     public void setSessionListeners(Collection<SessionListener> listeners) {
 50  4
         this.listeners = listeners != null ? listeners : new ArrayList<SessionListener>();
 51  4
     }
 52  
 
 53  
     @SuppressWarnings({"UnusedDeclaration"})
 54  
     public Collection<SessionListener> getSessionListeners() {
 55  8
         return this.listeners;
 56  
     }
 57  
 
 58  
     public Session start(SessionContext context) {
 59  56
         Session session = createSession(context);
 60  56
         applyGlobalSessionTimeout(session);
 61  56
         onStart(session, context);
 62  56
         notifyStart(session);
 63  
         //Don't expose the EIS-tier Session object to the client-tier:
 64  56
         return createExposedSession(session, context);
 65  
     }
 66  
 
 67  
     /**
 68  
      * Creates a new {@code Session Session} instance based on the specified (possibly {@code null})
 69  
      * initialization data.  Implementing classes must manage the persistent state of the returned session such that it
 70  
      * could later be acquired via the {@link #getSession(SessionKey)} method.
 71  
      *
 72  
      * @param context the initialization data that can be used by the implementation or underlying
 73  
      *                {@link SessionFactory} when instantiating the internal {@code Session} instance.
 74  
      * @return the new {@code Session} instance.
 75  
      * @throws org.apache.shiro.authz.HostUnauthorizedException
 76  
      *                                if the system access control policy restricts access based
 77  
      *                                on client location/IP and the specified hostAddress hasn't been enabled.
 78  
      * @throws AuthorizationException if the system access control policy does not allow the currently executing
 79  
      *                                caller to start sessions.
 80  
      */
 81  
     protected abstract Session createSession(SessionContext context) throws AuthorizationException;
 82  
 
 83  
     protected void applyGlobalSessionTimeout(Session session) {
 84  56
         session.setTimeout(getGlobalSessionTimeout());
 85  56
         onChange(session);
 86  56
     }
 87  
 
 88  
     /**
 89  
      * Template method that allows subclasses to react to a new session being created.
 90  
      * <p/>
 91  
      * This method is invoked <em>before</em> any session listeners are notified.
 92  
      *
 93  
      * @param session the session that was just {@link #createSession created}.
 94  
      * @param context the {@link SessionContext SessionContext} that was used to start the session.
 95  
      */
 96  
     protected void onStart(Session session, SessionContext context) {
 97  56
     }
 98  
 
 99  
     public Session getSession(SessionKey key) throws SessionException {
 100  0
         Session session = lookupSession(key);
 101  0
         return session != null ? createExposedSession(session, key) : null;
 102  
     }
 103  
 
 104  
     private Session lookupSession(SessionKey key) throws SessionException {
 105  406
         if (key == null) {
 106  0
             throw new NullPointerException("SessionKey argument cannot be null.");
 107  
         }
 108  406
         return doGetSession(key);
 109  
     }
 110  
 
 111  
     private Session lookupRequiredSession(SessionKey key) throws SessionException {
 112  406
         Session session = lookupSession(key);
 113  398
         if (session == null) {
 114  0
             String msg = "Unable to locate required Session instance based on SessionKey [" + key + "].";
 115  0
             throw new UnknownSessionException(msg);
 116  
         }
 117  398
         return session;
 118  
     }
 119  
 
 120  
     protected abstract Session doGetSession(SessionKey key) throws InvalidSessionException;
 121  
 
 122  
     protected Session createExposedSession(Session session, SessionContext context) {
 123  56
         return new DelegatingSession(this, new DefaultSessionKey(session.getId()));
 124  
     }
 125  
 
 126  
     protected Session createExposedSession(Session session, SessionKey key) {
 127  0
         return new DelegatingSession(this, new DefaultSessionKey(session.getId()));
 128  
     }
 129  
 
 130  
     /**
 131  
      * Returns the session instance to use to pass to registered {@code SessionListener}s for notification
 132  
      * that the session has been invalidated (stopped or expired).
 133  
      * <p/>
 134  
      * The default implementation returns an {@link ImmutableProxiedSession ImmutableProxiedSession} instance to ensure
 135  
      * that the specified {@code session} argument is not modified by any listeners.
 136  
      *
 137  
      * @param session the {@code Session} object being invalidated.
 138  
      * @return the {@code Session} instance to use to pass to registered {@code SessionListener}s for notification.
 139  
      */
 140  
     protected Session beforeInvalidNotification(Session session) {
 141  36
         return new ImmutableProxiedSession(session);
 142  
     }
 143  
 
 144  
     /**
 145  
      * Notifies any interested {@link SessionListener}s that a Session has started.  This method is invoked
 146  
      * <em>after</em> the {@link #onStart onStart} method is called.
 147  
      *
 148  
      * @param session the session that has just started that will be delivered to any
 149  
      *                {@link #setSessionListeners(java.util.Collection) registered} session listeners.
 150  
      * @see SessionListener#onStart(org.apache.shiro.session.Session)
 151  
      */
 152  
     protected void notifyStart(Session session) {
 153  56
         for (SessionListener listener : this.listeners) {
 154  10
             listener.onStart(session);
 155  10
         }
 156  56
     }
 157  
 
 158  
     protected void notifyStop(Session session) {
 159  24
         Session forNotification = beforeInvalidNotification(session);
 160  24
         for (SessionListener listener : this.listeners) {
 161  4
             listener.onStop(forNotification);
 162  4
         }
 163  24
     }
 164  
 
 165  
     protected void notifyExpiration(Session session) {
 166  12
         Session forNotification = beforeInvalidNotification(session);
 167  12
         for (SessionListener listener : this.listeners) {
 168  6
             listener.onExpiration(forNotification);
 169  4
         }
 170  10
     }
 171  
 
 172  
     public Date getStartTimestamp(SessionKey key) {
 173  0
         return lookupRequiredSession(key).getStartTimestamp();
 174  
     }
 175  
 
 176  
     public Date getLastAccessTime(SessionKey key) {
 177  0
         return lookupRequiredSession(key).getLastAccessTime();
 178  
     }
 179  
 
 180  
     public long getTimeout(SessionKey key) throws InvalidSessionException {
 181  10
         return lookupRequiredSession(key).getTimeout();
 182  
     }
 183  
 
 184  
     public void setTimeout(SessionKey key, long maxIdleTimeInMillis) throws InvalidSessionException {
 185  10
         Session s = lookupRequiredSession(key);
 186  8
         s.setTimeout(maxIdleTimeInMillis);
 187  8
         onChange(s);
 188  8
     }
 189  
 
 190  
     public void touch(SessionKey key) throws InvalidSessionException {
 191  2
         Session s = lookupRequiredSession(key);
 192  2
         s.touch();
 193  2
         onChange(s);
 194  2
     }
 195  
 
 196  
     public String getHost(SessionKey key) {
 197  0
         return lookupRequiredSession(key).getHost();
 198  
     }
 199  
 
 200  
     public Collection<Object> getAttributeKeys(SessionKey key) {
 201  0
         Collection<Object> c = lookupRequiredSession(key).getAttributeKeys();
 202  0
         if (!CollectionUtils.isEmpty(c)) {
 203  0
             return Collections.unmodifiableCollection(c);
 204  
         }
 205  0
         return Collections.emptySet();
 206  
     }
 207  
 
 208  
     public Object getAttribute(SessionKey sessionKey, Object attributeKey) throws InvalidSessionException {
 209  214
         return lookupRequiredSession(sessionKey).getAttribute(attributeKey);
 210  
     }
 211  
 
 212  
     public void setAttribute(SessionKey sessionKey, Object attributeKey, Object value) throws InvalidSessionException {
 213  88
         if (value == null) {
 214  0
             removeAttribute(sessionKey, attributeKey);
 215  
         } else {
 216  88
             Session s = lookupRequiredSession(sessionKey);
 217  88
             s.setAttribute(attributeKey, value);
 218  88
             onChange(s);
 219  
         }
 220  88
     }
 221  
 
 222  
     public Object removeAttribute(SessionKey sessionKey, Object attributeKey) throws InvalidSessionException {
 223  56
         Session s = lookupRequiredSession(sessionKey);
 224  56
         Object removed = s.removeAttribute(attributeKey);
 225  56
         if (removed != null) {
 226  34
             onChange(s);
 227  
         }
 228  56
         return removed;
 229  
     }
 230  
 
 231  
     public boolean isValid(SessionKey key) {
 232  
         try {
 233  0
             checkValid(key);
 234  0
             return true;
 235  0
         } catch (InvalidSessionException e) {
 236  0
             return false;
 237  
         }
 238  
     }
 239  
 
 240  
     public void stop(SessionKey key) throws InvalidSessionException {
 241  24
         Session session = lookupRequiredSession(key);
 242  
         try {
 243  24
             if (log.isDebugEnabled()) {
 244  24
                 log.debug("Stopping session with id [" + session.getId() + "]");
 245  
             }
 246  24
             session.stop();
 247  24
             onStop(session, key);
 248  24
             notifyStop(session);
 249  
         } finally {
 250  24
             afterStopped(session);
 251  24
         }
 252  24
     }
 253  
 
 254  
     protected void onStop(Session session, SessionKey key) {
 255  24
         onStop(session);
 256  24
     }
 257  
 
 258  
     protected void onStop(Session session) {
 259  0
         onChange(session);
 260  0
     }
 261  
 
 262  
     protected void afterStopped(Session session) {
 263  0
     }
 264  
 
 265  
     public void checkValid(SessionKey key) throws InvalidSessionException {
 266  
         //just try to acquire it.  If there is a problem, an exception will be thrown:
 267  2
         lookupRequiredSession(key);
 268  0
     }
 269  
 
 270  
     protected void onChange(Session s) {
 271  2
     }
 272  
 }