001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one
003     * or more contributor license agreements.  See the NOTICE file
004     * distributed with this work for additional information
005     * regarding copyright ownership.  The ASF licenses this file
006     * to you under the Apache License, Version 2.0 (the
007     * "License"); you may not use this file except in compliance
008     * with the License.  You may obtain a copy of the License at
009     *
010     *     http://www.apache.org/licenses/LICENSE-2.0
011     *
012     * Unless required by applicable law or agreed to in writing,
013     * software distributed under the License is distributed on an
014     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015     * KIND, either express or implied.  See the License for the
016     * specific language governing permissions and limitations
017     * under the License.
018     */
019    package org.apache.shiro.mgt;
020    
021    import org.apache.shiro.authz.AuthorizationException;
022    import org.apache.shiro.cache.CacheManagerAware;
023    import org.apache.shiro.session.Session;
024    import org.apache.shiro.session.SessionException;
025    import org.apache.shiro.session.mgt.DefaultSessionManager;
026    import org.apache.shiro.session.mgt.SessionContext;
027    import org.apache.shiro.session.mgt.SessionKey;
028    import org.apache.shiro.session.mgt.SessionManager;
029    import org.apache.shiro.util.LifecycleUtils;
030    
031    
032    /**
033     * Shiro support of a {@link SecurityManager} class hierarchy that delegates all
034     * {@link org.apache.shiro.session.Session session} operations to a wrapped
035     * {@link org.apache.shiro.session.mgt.SessionManager SessionManager} instance.  That is, this class implements the
036     * methods in the {@link SessionManager SessionManager} interface, but in reality, those methods are merely
037     * passthrough calls to the underlying 'real' {@code SessionManager} instance.
038     * <p/>
039     * The remaining {@code SecurityManager} methods not implemented by this class or its parents are left to be
040     * implemented by subclasses.
041     * <p/>
042     * In keeping with the other classes in this hierarchy and Shiro's desire to minimize configuration whenever
043     * possible, suitable default instances for all dependencies will be created upon instantiation.
044     *
045     * @author Les Hazlewood
046     * @since 0.9
047     */
048    public abstract class SessionsSecurityManager extends AuthorizingSecurityManager {
049    
050        /**
051         * The internal delegate <code>SessionManager</code> used by this security manager that manages all the
052         * application's {@link Session Session}s.
053         */
054        private SessionManager sessionManager;
055    
056        /**
057         * Default no-arg constructor, internally creates a suitable default {@link SessionManager SessionManager} delegate
058         * instance.
059         */
060        public SessionsSecurityManager() {
061            super();
062            this.sessionManager = new DefaultSessionManager();
063            applyCacheManagerToSessionManager();
064        }
065    
066        /**
067         * Sets the underlying delegate {@link SessionManager} instance that will be used to support this implementation's
068         * <tt>SessionManager</tt> method calls.
069         * <p/>
070         * This <tt>SecurityManager</tt> implementation does not provide logic to support the inherited
071         * <tt>SessionManager</tt> interface, but instead delegates these calls to an internal
072         * <tt>SessionManager</tt> instance.
073         * <p/>
074         * If a <tt>SessionManager</tt> instance is not set, a default one will be automatically created and
075         * initialized appropriately for the the existing runtime environment.
076         *
077         * @param sessionManager delegate instance to use to support this manager's <tt>SessionManager</tt> method calls.
078         */
079        public void setSessionManager(SessionManager sessionManager) {
080            this.sessionManager = sessionManager;
081            afterSessionManagerSet();
082        }
083    
084        protected void afterSessionManagerSet() {
085            applyCacheManagerToSessionManager();
086        }
087    
088        /**
089         * Returns this security manager's internal delegate {@link SessionManager SessionManager}.
090         *
091         * @return this security manager's internal delegate {@link SessionManager SessionManager}.
092         * @see #setSessionManager(org.apache.shiro.session.mgt.SessionManager) setSessionManager
093         */
094        public SessionManager getSessionManager() {
095            return this.sessionManager;
096        }
097    
098        /**
099         * Calls {@link org.apache.shiro.mgt.AuthorizingSecurityManager#afterCacheManagerSet() super.afterCacheManagerSet()} and then immediately calls
100         * {@link #applyCacheManagerToSessionManager() applyCacheManagerToSessionManager()} to ensure the
101         * <code>CacheManager</code> is applied to the SessionManager as necessary.
102         */
103        protected void afterCacheManagerSet() {
104            super.afterCacheManagerSet();
105            applyCacheManagerToSessionManager();
106        }
107    
108        /**
109         * Ensures the internal delegate <code>SessionManager</code> is injected with the newly set
110         * {@link #setCacheManager CacheManager} so it may use it for its internal caching needs.
111         * <p/>
112         * Note:  This implementation only injects the CacheManager into the SessionManager if the SessionManager
113         * instance implements the {@link CacheManagerAware CacheManagerAware} interface.
114         */
115        protected void applyCacheManagerToSessionManager() {
116            if (this.sessionManager instanceof CacheManagerAware) {
117                ((CacheManagerAware) this.sessionManager).setCacheManager(getCacheManager());
118            }
119        }
120    
121        public Session start(SessionContext context) throws AuthorizationException {
122            return this.sessionManager.start(context);
123        }
124    
125        public Session getSession(SessionKey key) throws SessionException {
126            return this.sessionManager.getSession(key);
127        }
128    
129        public void destroy() {
130            LifecycleUtils.destroy(getSessionManager());
131            this.sessionManager = null;
132        }
133    }