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.session.mgt.eis.CachingSessionDAO;
20 
21 // import hunt.shiro.cache.Cache;
22 // import hunt.shiro.cache.CacheManager;
23 // import hunt.shiro.cache.CacheManagerAware;
24 // import hunt.shiro.session.Session;
25 // import hunt.shiro.Exceptions;
26 // import hunt.shiro.session.mgt.ValidatingSession;
27 
28 // import hunt.util.Common;
29 // import hunt.collection;
30 // import hunt.collection.Collections;
31 
32 // /**
33 //  * An CachingSessionDAO is a SessionDAO that provides a transparent caching layer between the components that
34 //  * use it and the underlying EIS (Enterprise Information System) session backing store (for example, filesystem,
35 //  * database, enterprise grid/cloud, etc).
36 //  * <p/>
37 //  * This implementation caches all active sessions in a configured
38 //  * {@link #getActiveSessionsCache() activeSessionsCache}.  This property is {@code null} by default and if one is
39 //  * not explicitly set, a {@link #setCacheManager cacheManager} is expected to be configured which will in turn be used
40 //  * to acquire the {@code Cache} instance to use for the {@code activeSessionsCache}.
41 //  * <p/>
42 //  * All {@code SessionDAO} methods are implemented by this class to employ
43 //  * caching behavior and delegates the actual EIS operations to respective do* methods to be implemented by
44 //  * subclasses (doCreate, doRead, etc).
45 //  *
46 //  */
47 // abstract class CachingSessionDAO : AbstractSessionDAO, CacheManagerAware {
48 
49 //     /**
50 //      * The default active sessions cache name, equal to {@code shiro-activeSessionCache}.
51 //      */
52 //      enum string ACTIVE_SESSION_CACHE_NAME = "shiro-activeSessionCache";
53 
54 //     /**
55 //      * The CacheManager to use to acquire the Session cache.
56 //      */
57 //     private CacheManager cacheManager;
58 
59 //     /**
60 //      * The Cache instance responsible for caching Sessions.
61 //      */
62 //     private Cache!(Serializable, Session) activeSessions;
63 
64 //     /**
65 //      * The name of the session cache, defaults to {@link #ACTIVE_SESSION_CACHE_NAME}.
66 //      */
67 //     private string activeSessionsCacheName = ACTIVE_SESSION_CACHE_NAME;
68 
69 //     /**
70 //      * Default no-arg constructor.
71 //      */
72 //     this() {
73 //     }
74 
75 //     /**
76 //      * Sets the cacheManager to use for acquiring the {@link #getActiveSessionsCache() activeSessionsCache} if
77 //      * one is not configured.
78 //      *
79 //      * @param cacheManager the manager to use for constructing the session cache.
80 //      */
81 //      void setCacheManager(CacheManager cacheManager) {
82 //         this.cacheManager = cacheManager;
83 //     }
84 
85 //     /**
86 //      * Returns the CacheManager to use for acquiring the {@link #getActiveSessionsCache() activeSessionsCache} if
87 //      * one is not configured.  That is, the {@code CacheManager} will only be used if the
88 //      * {@link #getActiveSessionsCache() activeSessionsCache} property is {@code null}.
89 //      *
90 //      * @return the CacheManager used by the implementation that creates the activeSessions Cache.
91 //      */
92 //      CacheManager getCacheManager() {
93 //         return cacheManager;
94 //     }
95 
96 //     /**
97 //      * Returns the name of the actives sessions cache to be returned by the {@code CacheManager}.  Unless
98 //      * overridden by {@link #setActiveSessionsCacheName(string)}, defaults to {@link #ACTIVE_SESSION_CACHE_NAME}.
99 //      *
100 //      * @return the name of the active sessions cache.
101 //      */
102 //      string getActiveSessionsCacheName() {
103 //         return activeSessionsCacheName;
104 //     }
105 
106 //     /**
107 //      * Sets the name of the active sessions cache to be returned by the {@code CacheManager}.  Defaults to
108 //      * {@link #ACTIVE_SESSION_CACHE_NAME}.
109 //      *
110 //      * @param activeSessionsCacheName the name of the active sessions cache to be returned by the {@code CacheManager}.
111 //      */
112 //      void setActiveSessionsCacheName(string activeSessionsCacheName) {
113 //         this.activeSessionsCacheName = activeSessionsCacheName;
114 //     }
115 
116 //     /**
117 //      * Returns the cache instance to use for storing active sessions.  If one is not available (it is {@code null}),
118 //      * it will be {@link CacheManager#getCache(string) acquired} from the {@link #setCacheManager configured}
119 //      * {@code CacheManager} using the {@link #getActiveSessionsCacheName() activeSessionsCacheName}.
120 //      *
121 //      * @return the cache instance to use for storing active sessions or {@code null} if the {@code Cache} instance
122 //      *         should be retrieved from the
123 //      */
124 //      Cache!(Serializable, Session) getActiveSessionsCache() {
125 //         return this.activeSessions;
126 //     }
127 
128 //     /**
129 //      * Sets the cache instance to use for storing active sessions.  If one is not set (it remains {@code null}),
130 //      * it will be {@link CacheManager#getCache(string) acquired} from the {@link #setCacheManager configured}
131 //      * {@code CacheManager} using the {@link #getActiveSessionsCacheName() activeSessionsCacheName}.
132 //      *
133 //      * @param cache the cache instance to use for storing active sessions or {@code null} if the cache is to be
134 //      *              acquired from the {@link #setCacheManager configured} {@code CacheManager}.
135 //      */
136 //      void setActiveSessionsCache(Cache!(Serializable, Session) cache) {
137 //         this.activeSessions = cache;
138 //     }
139 
140 //     /**
141 //      * Returns the active sessions cache, but if that cache instance is null, first lazily creates the cache instance
142 //      * via the {@link #createActiveSessionsCache()} method and then returns the instance.
143 //      * <p/>
144 //      * Note that this method will only return a non-null value code if the {@code CacheManager} has been set.  If
145 //      * not set, there will be no cache.
146 //      *
147 //      * @return the active sessions cache instance.
148 //      */
149 //     private Cache!(Serializable, Session) getActiveSessionsCacheLazy() {
150 //         if (this.activeSessions  is null) {
151 //             this.activeSessions = createActiveSessionsCache();
152 //         }
153 //         return activeSessions;
154 //     }
155 
156 //     /**
157 //      * Creates a cache instance used to store active sessions.  Creation is done by first
158 //      * {@link #getCacheManager() acquiring} the {@code CacheManager}.  If the cache manager is not null, the
159 //      * cache returned is that resulting from the following call:
160 //      * <pre>       string name = {@link #getActiveSessionsCacheName() getActiveSessionsCacheName()};
161 //      * cacheManager.getCache(name);</pre>
162 //      *
163 //      * @return a cache instance used to store active sessions, or {@code null} if the {@code CacheManager} has
164 //      *         not been set.
165 //      */
166 //     protected Cache!(Serializable, Session) createActiveSessionsCache() {
167 //         Cache!(Serializable, Session) cache = null;
168 //         CacheManager mgr = getCacheManager();
169 //         if (mgr !is null) {
170 //             string name = getActiveSessionsCacheName();
171 //             cache = mgr.getCache(name);
172 //         }
173 //         return cache;
174 //     }
175 
176 //     /**
177 //      * Calls {@code super.create(session)}, then caches the session keyed by the returned {@code sessionId}, and then
178 //      * returns this {@code sessionId}.
179 //      *
180 //      * @param session Session object to create in the EIS and then cache.
181 //      */
182 //      Serializable create(Session session) {
183 //         Serializable sessionId = super.create(session);
184 //         cache(session, sessionId);
185 //         return sessionId;
186 //     }
187 
188 //     /**
189 //      * Returns the cached session with the corresponding {@code sessionId} or {@code null} if there is
190 //      * no session cached under that id (or if there is no Cache).
191 //      *
192 //      * @param sessionId the id of the cached session to acquire.
193 //      * @return the cached session with the corresponding {@code sessionId}, or {@code null} if the session
194 //      *         does not exist or is not cached.
195 //      */
196 //     protected Session getCachedSession(Serializable sessionId) {
197 //         Session cached = null;
198 //         if (sessionId !is null) {
199 //             Cache!(Serializable, Session) cache = getActiveSessionsCacheLazy();
200 //             if (cache !is null) {
201 //                 cached = getCachedSession(sessionId, cache);
202 //             }
203 //         }
204 //         return cached;
205 //     }
206 
207 //     /**
208 //      * Returns the Session with the specified id from the specified cache.  This method simply calls
209 //      * {@code cache.get(sessionId)} and can be overridden by subclasses for custom acquisition behavior.
210 //      *
211 //      * @param sessionId the id of the session to acquire.
212 //      * @param cache     the cache to acquire the session from
213 //      * @return the cached session, or {@code null} if the session wasn't in the cache.
214 //      */
215 //     protected Session getCachedSession(Serializable sessionId, Cache!(Serializable, Session) cache) {
216 //         return cache.get(sessionId);
217 //     }
218 
219 //     /**
220 //      * Caches the specified session under the cache entry key of {@code sessionId}.
221 //      *
222 //      * @param session   the session to cache
223 //      * @param sessionId the session id, to be used as the cache entry key.
224 //      */
225 //     protected void cache(Session session, Serializable sessionId) {
226 //         if (session  is null || sessionId  is null) {
227 //             return;
228 //         }
229 //         Cache!(Serializable, Session) cache = getActiveSessionsCacheLazy();
230 //         if (cache  is null) {
231 //             return;
232 //         }
233 //         cache(session, sessionId, cache);
234 //     }
235 
236 //     /**
237 //      * Caches the specified session in the given cache under the key of {@code sessionId}.  This implementation
238 //      * simply calls {@code cache.put(sessionId,session)} and can be overridden for custom behavior.
239 //      *
240 //      * @param session   the session to cache
241 //      * @param sessionId the id of the session, expected to be the cache key.
242 //      * @param cache     the cache to store the session
243 //      */
244 //     protected void cache(Session session, Serializable sessionId, Cache!(Serializable, Session) cache) {
245 //         cache.put(sessionId, session);
246 //     }
247 
248 //     /**
249 //      * Attempts to acquire the Session from the cache first using the session ID as the cache key.  If no session
250 //      * is found, {@code super.readSession(sessionId)} is called to perform the actual retrieval.
251 //      *
252 //      * @param sessionId the id of the session to retrieve from the EIS.
253 //      * @return the session identified by {@code sessionId} in the EIS.
254 //      * @throws UnknownSessionException if the id specified does not correspond to any session in the cache or EIS.
255 //      */
256 //      Session readSession(Serializable sessionId){
257 //         Session s = getCachedSession(sessionId);
258 //         if (s  is null) {
259 //             s = super.readSession(sessionId);
260 //         }
261 //         return s;
262 //     }
263 
264 //     /**
265 //      * Updates the state of the given session to the EIS by first delegating to
266 //      * {@link #doUpdate(hunt.shiro.session.Session)}.  If the session is a {@link ValidatingSession}, it will
267 //      * be added to the cache only if it is {@link ValidatingSession#isValid()} and if invalid, will be removed from the
268 //      * cache.  If it is not a {@code ValidatingSession} instance, it will be added to the cache in any event.
269 //      *
270 //      * @param session the session object to update in the EIS.
271 //      * @throws UnknownSessionException if no existing EIS session record exists with the
272 //      *                                 identifier of {@link Session#getId() session.getId()}
273 //      */
274 //      void update(Session session){
275 //         doUpdate(session);
276 //         ValidatingSession vs = cast(ValidatingSession) session;
277 //         if (vs !is null) {
278 //             if (vs.isValid()) {
279 //                 cache(session, session.getId());
280 //             } else {
281 //                 uncache(session);
282 //             }
283 //         } else {
284 //             cache(session, session.getId());
285 //         }
286 //     }
287 
288 //     /**
289 //      * Subclass implementation hook to actually persist the {@code Session}'s state to the underlying EIS.
290 //      *
291 //      * @param session the session object whose state will be propagated to the EIS.
292 //      */
293 //     protected abstract void doUpdate(Session session);
294 
295 //     /**
296 //      * Removes the specified session from any cache and then permanently deletes the session from the EIS by
297 //      * delegating to {@link #doDelete}.
298 //      *
299 //      * @param session the session to remove from caches and permanently remove from the EIS.
300 //      */
301 //      void remove(Session session) {
302 //         uncache(session);
303 //         doDelete(session);
304 //     }
305 
306 //     /**
307 //      * Subclass implementation hook to permanently remove the given Session from the underlying EIS.
308 //      *
309 //      * @param session the session instance to permanently remove from the EIS.
310 //      */
311 //     protected abstract void doDelete(Session session);
312 
313 //     /**
314 //      * Removes the specified Session from the cache.
315 //      *
316 //      * @param session the session to remove from the cache.
317 //      */
318 //     protected void uncache(Session session) {
319 //         if (session  is null) {
320 //             return;
321 //         }
322 //         Serializable id = session.getId();
323 //         if (id  is null) {
324 //             return;
325 //         }
326 //         Cache!(Serializable, Session) cache = getActiveSessionsCacheLazy();
327 //         if (cache !is null) {
328 //             cache.remove(id);
329 //         }
330 //     }
331 
332 //     /**
333 //      * Returns all active sessions in the system.
334 //      * <p/>
335 //      * <p>This implementation merely returns the sessions found in the activeSessions cache.  Subclass implementations
336 //      * may wish to override this method to retrieve them in a different way, perhaps by an RDBMS query or by other
337 //      * means.
338 //      *
339 //      * @return the sessions found in the activeSessions cache.
340 //      */
341 //      Collection!(Session) getActiveSessions() {
342 //         Cache!(Serializable, Session) cache = getActiveSessionsCacheLazy();
343 //         if (cache !is null) {
344 //             return cache.values();
345 //         } else {
346 //             return Collections.emptySet();
347 //         }
348 //     }
349 // }