| <?xml version="1.0" encoding="UTF-8"?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml" lang="en"><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/><link rel="stylesheet" href="../../jacoco-resources/report.css" type="text/css"/><link rel="shortcut icon" href="../../jacoco-resources/report.gif" type="image/gif"/><title>CachingSessionDAO.java</title><link rel="stylesheet" href="../../jacoco-resources/prettify.css" type="text/css"/><script type="text/javascript" src="../../jacoco-resources/prettify.js"></script></head><body onload="window['PR_TAB_WIDTH']=4;prettyPrint()"><div class="breadcrumb" id="breadcrumb"><span class="info"><a href="../../jacoco-sessions.html" class="el_session">Sessions</a></span><a href="../../index.html" class="el_report">Apache Shiro :: Test Coverage</a> > <a href="../index.html" class="el_bundle">shiro-core</a> > <a href="index.source.html" class="el_package">org.apache.shiro.session.mgt.eis</a> > <span class="el_source">CachingSessionDAO.java</span></div><h1>CachingSessionDAO.java</h1><pre class="source lang-java linenums">/* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| package org.apache.shiro.session.mgt.eis; |
| |
| import org.apache.shiro.cache.Cache; |
| import org.apache.shiro.cache.CacheManager; |
| import org.apache.shiro.cache.CacheManagerAware; |
| import org.apache.shiro.session.Session; |
| import org.apache.shiro.session.UnknownSessionException; |
| import org.apache.shiro.session.mgt.ValidatingSession; |
| |
| import java.io.Serializable; |
| import java.util.Collection; |
| import java.util.Collections; |
| |
| /** |
| * An CachingSessionDAO is a SessionDAO that provides a transparent caching layer between the components that |
| * use it and the underlying EIS (Enterprise Information System) session backing store (for example, filesystem, |
| * database, enterprise grid/cloud, etc). |
| * <p/> |
| * This implementation caches all active sessions in a configured |
| * {@link #getActiveSessionsCache() activeSessionsCache}. This property is {@code null} by default and if one is |
| * not explicitly set, a {@link #setCacheManager cacheManager} is expected to be configured which will in turn be used |
| * to acquire the {@code Cache} instance to use for the {@code activeSessionsCache}. |
| * <p/> |
| * All {@code SessionDAO} methods are implemented by this class to employ |
| * caching behavior and delegates the actual EIS operations to respective do* methods to be implemented by |
| * subclasses (doCreate, doRead, etc). |
| * |
| * @since 0.2 |
| */ |
| public abstract class CachingSessionDAO extends AbstractSessionDAO implements CacheManagerAware { |
| |
| /** |
| * The default active sessions cache name, equal to {@code shiro-activeSessionCache}. |
| */ |
| public static final String ACTIVE_SESSION_CACHE_NAME = "shiro-activeSessionCache"; |
| |
| /** |
| * The CacheManager to use to acquire the Session cache. |
| */ |
| private CacheManager cacheManager; |
| |
| /** |
| * The Cache instance responsible for caching Sessions. |
| */ |
| private Cache<Serializable, Session> activeSessions; |
| |
| /** |
| * The name of the session cache, defaults to {@link #ACTIVE_SESSION_CACHE_NAME}. |
| */ |
| <span class="fc" id="L68"> private String activeSessionsCacheName = ACTIVE_SESSION_CACHE_NAME;</span> |
| |
| /** |
| * Default no-arg constructor. |
| */ |
| <span class="fc" id="L73"> public CachingSessionDAO() {</span> |
| <span class="fc" id="L74"> }</span> |
| |
| /** |
| * Sets the cacheManager to use for acquiring the {@link #getActiveSessionsCache() activeSessionsCache} if |
| * one is not configured. |
| * |
| * @param cacheManager the manager to use for constructing the session cache. |
| */ |
| public void setCacheManager(CacheManager cacheManager) { |
| <span class="fc" id="L83"> this.cacheManager = cacheManager;</span> |
| <span class="fc" id="L84"> }</span> |
| |
| /** |
| * Returns the CacheManager to use for acquiring the {@link #getActiveSessionsCache() activeSessionsCache} if |
| * one is not configured. That is, the {@code CacheManager} will only be used if the |
| * {@link #getActiveSessionsCache() activeSessionsCache} property is {@code null}. |
| * |
| * @return the CacheManager used by the implementation that creates the activeSessions Cache. |
| */ |
| public CacheManager getCacheManager() { |
| <span class="fc" id="L94"> return cacheManager;</span> |
| } |
| |
| /** |
| * Returns the name of the actives sessions cache to be returned by the {@code CacheManager}. Unless |
| * overridden by {@link #setActiveSessionsCacheName(String)}, defaults to {@link #ACTIVE_SESSION_CACHE_NAME}. |
| * |
| * @return the name of the active sessions cache. |
| */ |
| public String getActiveSessionsCacheName() { |
| <span class="fc" id="L104"> return activeSessionsCacheName;</span> |
| } |
| |
| /** |
| * Sets the name of the active sessions cache to be returned by the {@code CacheManager}. Defaults to |
| * {@link #ACTIVE_SESSION_CACHE_NAME}. |
| * |
| * @param activeSessionsCacheName the name of the active sessions cache to be returned by the {@code CacheManager}. |
| */ |
| public void setActiveSessionsCacheName(String activeSessionsCacheName) { |
| <span class="nc" id="L114"> this.activeSessionsCacheName = activeSessionsCacheName;</span> |
| <span class="nc" id="L115"> }</span> |
| |
| /** |
| * Returns the cache instance to use for storing active sessions. If one is not available (it is {@code null}), |
| * it will be {@link CacheManager#getCache(String) acquired} from the {@link #setCacheManager configured} |
| * {@code CacheManager} using the {@link #getActiveSessionsCacheName() activeSessionsCacheName}. |
| * |
| * @return the cache instance to use for storing active sessions or {@code null} if the {@code Cache} instance |
| * should be retrieved from the |
| */ |
| public Cache<Serializable, Session> getActiveSessionsCache() { |
| <span class="fc" id="L126"> return this.activeSessions;</span> |
| } |
| |
| /** |
| * Sets the cache instance to use for storing active sessions. If one is not set (it remains {@code null}), |
| * it will be {@link CacheManager#getCache(String) acquired} from the {@link #setCacheManager configured} |
| * {@code CacheManager} using the {@link #getActiveSessionsCacheName() activeSessionsCacheName}. |
| * |
| * @param cache the cache instance to use for storing active sessions or {@code null} if the cache is to be |
| * acquired from the {@link #setCacheManager configured} {@code CacheManager}. |
| */ |
| public void setActiveSessionsCache(Cache<Serializable, Session> cache) { |
| <span class="nc" id="L138"> this.activeSessions = cache;</span> |
| <span class="nc" id="L139"> }</span> |
| |
| /** |
| * Returns the active sessions cache, but if that cache instance is null, first lazily creates the cache instance |
| * via the {@link #createActiveSessionsCache()} method and then returns the instance. |
| * <p/> |
| * Note that this method will only return a non-null value code if the {@code CacheManager} has been set. If |
| * not set, there will be no cache. |
| * |
| * @return the active sessions cache instance. |
| */ |
| private Cache<Serializable, Session> getActiveSessionsCacheLazy() { |
| <span class="fc bfc" id="L151" title="All 2 branches covered."> if (this.activeSessions == null) {</span> |
| <span class="fc" id="L152"> this.activeSessions = createActiveSessionsCache();</span> |
| } |
| <span class="fc" id="L154"> return activeSessions;</span> |
| } |
| |
| /** |
| * Creates a cache instance used to store active sessions. Creation is done by first |
| * {@link #getCacheManager() acquiring} the {@code CacheManager}. If the cache manager is not null, the |
| * cache returned is that resulting from the following call: |
| * <pre> String name = {@link #getActiveSessionsCacheName() getActiveSessionsCacheName()}; |
| * cacheManager.getCache(name);</pre> |
| * |
| * @return a cache instance used to store active sessions, or {@code null} if the {@code CacheManager} has |
| * not been set. |
| */ |
| protected Cache<Serializable, Session> createActiveSessionsCache() { |
| <span class="fc" id="L168"> Cache<Serializable, Session> cache = null;</span> |
| <span class="fc" id="L169"> CacheManager mgr = getCacheManager();</span> |
| <span class="pc bpc" id="L170" title="1 of 2 branches missed."> if (mgr != null) {</span> |
| <span class="fc" id="L171"> String name = getActiveSessionsCacheName();</span> |
| <span class="fc" id="L172"> cache = mgr.getCache(name);</span> |
| } |
| <span class="fc" id="L174"> return cache;</span> |
| } |
| |
| /** |
| * Calls {@code super.create(session)}, then caches the session keyed by the returned {@code sessionId}, and then |
| * returns this {@code sessionId}. |
| * |
| * @param session Session object to create in the EIS and then cache. |
| */ |
| public Serializable create(Session session) { |
| <span class="fc" id="L184"> Serializable sessionId = super.create(session);</span> |
| <span class="fc" id="L185"> cache(session, sessionId);</span> |
| <span class="fc" id="L186"> return sessionId;</span> |
| } |
| |
| /** |
| * Returns the cached session with the corresponding {@code sessionId} or {@code null} if there is |
| * no session cached under that id (or if there is no Cache). |
| * |
| * @param sessionId the id of the cached session to acquire. |
| * @return the cached session with the corresponding {@code sessionId}, or {@code null} if the session |
| * does not exist or is not cached. |
| */ |
| protected Session getCachedSession(Serializable sessionId) { |
| <span class="fc" id="L198"> Session cached = null;</span> |
| <span class="pc bpc" id="L199" title="1 of 2 branches missed."> if (sessionId != null) {</span> |
| <span class="fc" id="L200"> Cache<Serializable, Session> cache = getActiveSessionsCacheLazy();</span> |
| <span class="pc bpc" id="L201" title="1 of 2 branches missed."> if (cache != null) {</span> |
| <span class="fc" id="L202"> cached = getCachedSession(sessionId, cache);</span> |
| } |
| } |
| <span class="fc" id="L205"> return cached;</span> |
| } |
| |
| /** |
| * Returns the Session with the specified id from the specified cache. This method simply calls |
| * {@code cache.get(sessionId)} and can be overridden by subclasses for custom acquisition behavior. |
| * |
| * @param sessionId the id of the session to acquire. |
| * @param cache the cache to acquire the session from |
| * @return the cached session, or {@code null} if the session wasn't in the cache. |
| */ |
| protected Session getCachedSession(Serializable sessionId, Cache<Serializable, Session> cache) { |
| <span class="fc" id="L217"> return cache.get(sessionId);</span> |
| } |
| |
| /** |
| * Caches the specified session under the cache entry key of {@code sessionId}. |
| * |
| * @param session the session to cache |
| * @param sessionId the session id, to be used as the cache entry key. |
| * @since 1.0 |
| */ |
| protected void cache(Session session, Serializable sessionId) { |
| <span class="pc bpc" id="L228" title="2 of 4 branches missed."> if (session == null || sessionId == null) {</span> |
| <span class="nc" id="L229"> return;</span> |
| } |
| <span class="fc" id="L231"> Cache<Serializable, Session> cache = getActiveSessionsCacheLazy();</span> |
| <span class="pc bpc" id="L232" title="1 of 2 branches missed."> if (cache == null) {</span> |
| <span class="nc" id="L233"> return;</span> |
| } |
| <span class="fc" id="L235"> cache(session, sessionId, cache);</span> |
| <span class="fc" id="L236"> }</span> |
| |
| /** |
| * Caches the specified session in the given cache under the key of {@code sessionId}. This implementation |
| * simply calls {@code cache.put(sessionId,session)} and can be overridden for custom behavior. |
| * |
| * @param session the session to cache |
| * @param sessionId the id of the session, expected to be the cache key. |
| * @param cache the cache to store the session |
| */ |
| protected void cache(Session session, Serializable sessionId, Cache<Serializable, Session> cache) { |
| <span class="fc" id="L247"> cache.put(sessionId, session);</span> |
| <span class="fc" id="L248"> }</span> |
| |
| /** |
| * Attempts to acquire the Session from the cache first using the session ID as the cache key. If no session |
| * is found, {@code super.readSession(sessionId)} is called to perform the actual retrieval. |
| * |
| * @param sessionId the id of the session to retrieve from the EIS. |
| * @return the session identified by {@code sessionId} in the EIS. |
| * @throws UnknownSessionException if the id specified does not correspond to any session in the cache or EIS. |
| */ |
| public Session readSession(Serializable sessionId) throws UnknownSessionException { |
| <span class="fc" id="L259"> Session s = getCachedSession(sessionId);</span> |
| <span class="pc bpc" id="L260" title="1 of 2 branches missed."> if (s == null) {</span> |
| <span class="nc" id="L261"> s = super.readSession(sessionId);</span> |
| } |
| <span class="fc" id="L263"> return s;</span> |
| } |
| |
| /** |
| * Updates the state of the given session to the EIS by first delegating to |
| * {@link #doUpdate(org.apache.shiro.session.Session)}. If the session is a {@link ValidatingSession}, it will |
| * be added to the cache only if it is {@link ValidatingSession#isValid()} and if invalid, will be removed from the |
| * cache. If it is not a {@code ValidatingSession} instance, it will be added to the cache in any event. |
| * |
| * @param session the session object to update in the EIS. |
| * @throws UnknownSessionException if no existing EIS session record exists with the |
| * identifier of {@link Session#getId() session.getId()} |
| */ |
| public void update(Session session) throws UnknownSessionException { |
| <span class="fc" id="L277"> doUpdate(session);</span> |
| <span class="pc bpc" id="L278" title="1 of 2 branches missed."> if (session instanceof ValidatingSession) {</span> |
| <span class="pc bpc" id="L279" title="1 of 2 branches missed."> if (((ValidatingSession) session).isValid()) {</span> |
| <span class="fc" id="L280"> cache(session, session.getId());</span> |
| } else { |
| <span class="nc" id="L282"> uncache(session);</span> |
| } |
| } else { |
| <span class="nc" id="L285"> cache(session, session.getId());</span> |
| } |
| <span class="fc" id="L287"> }</span> |
| |
| /** |
| * Subclass implementation hook to actually persist the {@code Session}'s state to the underlying EIS. |
| * |
| * @param session the session object whose state will be propagated to the EIS. |
| */ |
| protected abstract void doUpdate(Session session); |
| |
| /** |
| * Removes the specified session from any cache and then permanently deletes the session from the EIS by |
| * delegating to {@link #doDelete}. |
| * |
| * @param session the session to remove from caches and permanently delete from the EIS. |
| */ |
| public void delete(Session session) { |
| <span class="nc" id="L303"> uncache(session);</span> |
| <span class="nc" id="L304"> doDelete(session);</span> |
| <span class="nc" id="L305"> }</span> |
| |
| /** |
| * Subclass implementation hook to permanently delete the given Session from the underlying EIS. |
| * |
| * @param session the session instance to permanently delete from the EIS. |
| */ |
| protected abstract void doDelete(Session session); |
| |
| /** |
| * Removes the specified Session from the cache. |
| * |
| * @param session the session to remove from the cache. |
| */ |
| protected void uncache(Session session) { |
| <span class="nc bnc" id="L320" title="All 2 branches missed."> if (session == null) {</span> |
| <span class="nc" id="L321"> return;</span> |
| } |
| <span class="nc" id="L323"> Serializable id = session.getId();</span> |
| <span class="nc bnc" id="L324" title="All 2 branches missed."> if (id == null) {</span> |
| <span class="nc" id="L325"> return;</span> |
| } |
| <span class="nc" id="L327"> Cache<Serializable, Session> cache = getActiveSessionsCacheLazy();</span> |
| <span class="nc bnc" id="L328" title="All 2 branches missed."> if (cache != null) {</span> |
| <span class="nc" id="L329"> cache.remove(id);</span> |
| } |
| <span class="nc" id="L331"> }</span> |
| |
| /** |
| * Returns all active sessions in the system. |
| * <p/> |
| * <p>This implementation merely returns the sessions found in the activeSessions cache. Subclass implementations |
| * may wish to override this method to retrieve them in a different way, perhaps by an RDBMS query or by other |
| * means. |
| * |
| * @return the sessions found in the activeSessions cache. |
| */ |
| public Collection<Session> getActiveSessions() { |
| <span class="nc" id="L343"> Cache<Serializable, Session> cache = getActiveSessionsCacheLazy();</span> |
| <span class="nc bnc" id="L344" title="All 2 branches missed."> if (cache != null) {</span> |
| <span class="nc" id="L345"> return cache.values();</span> |
| } else { |
| <span class="nc" id="L347"> return Collections.emptySet();</span> |
| } |
| } |
| } |
| </pre><div class="footer"><span class="right">Created with <a href="http://www.jacoco.org/jacoco">JaCoCo</a> 0.8.3.201901230119</span></div></body></html> |