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 module hunt.shiro.mgt.SessionsSecurityManager;
20 
21 import hunt.shiro.mgt.AuthorizingSecurityManager;
22 
23 import hunt.shiro.Exceptions;
24 import hunt.shiro.cache.CacheManagerAware;
25 import hunt.shiro.event.EventBus;
26 import hunt.shiro.event.EventBusAware;
27 import hunt.shiro.session.Session;
28 
29 import hunt.shiro.session.mgt.DefaultSessionManager;
30 import hunt.shiro.session.mgt.SessionContext;
31 import hunt.shiro.session.mgt.SessionKey;
32 import hunt.shiro.session.mgt.SessionManager;
33 import hunt.shiro.util.LifecycleUtils;
34 
35 /**
36  * Shiro support of a {@link SecurityManager} class hierarchy that delegates all
37  * {@link hunt.shiro.session.Session session} operations to a wrapped
38  * {@link hunt.shiro.session.mgt.SessionManager SessionManager} instance.  That is, this class implements the
39  * methods in the {@link SessionManager SessionManager} interface, but in reality, those methods are merely
40  * passthrough calls to the underlying 'real' {@code SessionManager} instance.
41  * <p/>
42  * The remaining {@code SecurityManager} methods not implemented by this class or its parents are left to be
43  * implemented by subclasses.
44  * <p/>
45  * In keeping with the other classes in this hierarchy and Shiro's desire to minimize configuration whenever
46  * possible, suitable default instances for all dependencies will be created upon instantiation.
47  *
48  */
49 abstract class SessionsSecurityManager : AuthorizingSecurityManager {
50 
51     /**
52      * The internal delegate <code>SessionManager</code> used by this security manager that manages all the
53      * application's {@link Session Session}s.
54      */
55     private SessionManager sessionManager;
56 
57     /**
58      * Default no-arg constructor, internally creates a suitable default {@link SessionManager SessionManager} delegate
59      * instance.
60      */
61     this() {
62         super();
63         this.sessionManager = new DefaultSessionManager();
64         applyCacheManagerToSessionManager();
65     }
66 
67     /**
68      * Sets the underlying delegate {@link SessionManager} instance that will be used to support this implementation's
69      * <tt>SessionManager</tt> method calls.
70      * <p/>
71      * This <tt>SecurityManager</tt> implementation does not provide logic to support the inherited
72      * <tt>SessionManager</tt> interface, but instead delegates these calls to an internal
73      * <tt>SessionManager</tt> instance.
74      * <p/>
75      * If a <tt>SessionManager</tt> instance is not set, a default one will be automatically created and
76      * initialized appropriately for the the existing runtime environment.
77      *
78      * @param sessionManager delegate instance to use to support this manager's <tt>SessionManager</tt> method calls.
79      */
80     void setSessionManager(SessionManager sessionManager) {
81         this.sessionManager = sessionManager;
82         afterSessionManagerSet();
83     }
84 
85     protected void afterSessionManagerSet() {
86         applyCacheManagerToSessionManager();
87         applyEventBusToSessionManager();
88     }
89 
90     /**
91      * Returns this security manager's internal delegate {@link SessionManager SessionManager}.
92      *
93      * @return this security manager's internal delegate {@link SessionManager SessionManager}.
94      * @see #setSessionManager(hunt.shiro.session.mgt.SessionManager) setSessionManager
95      */
96     SessionManager getSessionManager() {
97         return this.sessionManager;
98     }
99 
100     /**
101      * Calls {@link hunt.shiro.mgt.AuthorizingSecurityManager#afterCacheManagerSet() super.afterCacheManagerSet()} and then immediately calls
102      * {@link #applyCacheManagerToSessionManager() applyCacheManagerToSessionManager()} to ensure the
103      * <code>CacheManager</code> is applied to the SessionManager as necessary.
104      */
105     override protected void afterCacheManagerSet() {
106         super.afterCacheManagerSet();
107         applyCacheManagerToSessionManager();
108     }
109 
110     /**
111      * Sets any configured EventBus on the SessionManager if necessary.
112      *
113      */
114     override protected void afterEventBusSet() {
115         super.afterEventBusSet();
116         applyEventBusToSessionManager();
117     }
118 
119     /**
120      * Ensures the internal delegate <code>SessionManager</code> is injected with the newly set
121      * {@link #setCacheManager CacheManager} so it may use it for its internal caching needs.
122      * <p/>
123      * Note:  This implementation only injects the CacheManager into the SessionManager if the SessionManager
124      * instance implements the {@link CacheManagerAware CacheManagerAware} interface.
125      */
126     protected void applyCacheManagerToSessionManager() {
127         CacheManagerAware cma = cast(CacheManagerAware) this.sessionManager;
128         if (cma !is null) {
129             cma.setCacheManager(getCacheManager());
130         }
131     }
132 
133     /**
134      * Ensures the internal delegate <code>SessionManager</code> is injected with the newly set
135      * {@link #setEventBus EventBus} so it may use it for its internal event needs.
136      * <p/>
137      * Note: This implementation only injects the EventBus into the SessionManager if the SessionManager
138      * instance implements the {@link EventBusAware EventBusAware} interface.
139      *
140      */
141     protected void applyEventBusToSessionManager() {
142         EventBus eventBus = getEventBus();
143         EventBusAware eba = cast(EventBusAware) this.sessionManager;
144         if (eventBus !is null && eba !is null) {
145             eba.setEventBus(eventBus);
146         }
147     }
148 
149     Session start(SessionContext context) {
150         return this.sessionManager.start(context);
151     }
152 
153     Session getSession(SessionKey key) {
154         return this.sessionManager.getSession(key);
155     }
156 
157     override void destroy() {
158         LifecycleUtils.destroy(cast(Object) getSessionManager());
159         this.sessionManager = null;
160         super.destroy();
161     }
162 }