blob: 9f60fd95c30507c0de10206a2beeb44622802303 [file] [log] [blame]
<?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>AbstractValidatingSessionManager.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> &gt; <a href="../index.html" class="el_bundle">shiro-core</a> &gt; <a href="index.source.html" class="el_package">org.apache.shiro.session.mgt</a> &gt; <span class="el_source">AbstractValidatingSessionManager.java</span></div><h1>AbstractValidatingSessionManager.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
* &quot;License&quot;); 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
* &quot;AS IS&quot; 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;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.session.ExpiredSessionException;
import org.apache.shiro.session.InvalidSessionException;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.UnknownSessionException;
import org.apache.shiro.util.Destroyable;
import org.apache.shiro.util.LifecycleUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Collection;
/**
* Default business-tier implementation of the {@link ValidatingSessionManager} interface.
*
* @since 0.1
*/
public abstract class AbstractValidatingSessionManager extends AbstractNativeSessionManager
implements ValidatingSessionManager, Destroyable {
//TODO - complete JavaDoc
<span class="fc" id="L44"> private static final Logger log = LoggerFactory.getLogger(AbstractValidatingSessionManager.class);</span>
/**
* The default interval at which sessions will be validated (1 hour);
* This can be overridden by calling {@link #setSessionValidationInterval(long)}
*/
public static final long DEFAULT_SESSION_VALIDATION_INTERVAL = MILLIS_PER_HOUR;
protected boolean sessionValidationSchedulerEnabled;
/**
* Scheduler used to validate sessions on a regular basis.
*/
protected SessionValidationScheduler sessionValidationScheduler;
protected long sessionValidationInterval;
<span class="fc" id="L61"> public AbstractValidatingSessionManager() {</span>
<span class="fc" id="L62"> this.sessionValidationSchedulerEnabled = true;</span>
<span class="fc" id="L63"> this.sessionValidationInterval = DEFAULT_SESSION_VALIDATION_INTERVAL;</span>
<span class="fc" id="L64"> }</span>
public boolean isSessionValidationSchedulerEnabled() {
<span class="fc" id="L67"> return sessionValidationSchedulerEnabled;</span>
}
@SuppressWarnings({&quot;UnusedDeclaration&quot;})
public void setSessionValidationSchedulerEnabled(boolean sessionValidationSchedulerEnabled) {
<span class="fc" id="L72"> this.sessionValidationSchedulerEnabled = sessionValidationSchedulerEnabled;</span>
<span class="fc" id="L73"> }</span>
public void setSessionValidationScheduler(SessionValidationScheduler sessionValidationScheduler) {
<span class="fc" id="L76"> this.sessionValidationScheduler = sessionValidationScheduler;</span>
<span class="fc" id="L77"> }</span>
public SessionValidationScheduler getSessionValidationScheduler() {
<span class="fc" id="L80"> return sessionValidationScheduler;</span>
}
private void enableSessionValidationIfNecessary() {
<span class="fc" id="L84"> SessionValidationScheduler scheduler = getSessionValidationScheduler();</span>
<span class="fc bfc" id="L85" title="All 6 branches covered."> if (isSessionValidationSchedulerEnabled() &amp;&amp; (scheduler == null || !scheduler.isEnabled())) {</span>
<span class="fc" id="L86"> enableSessionValidation();</span>
}
<span class="fc" id="L88"> }</span>
/**
* If using the underlying default &lt;tt&gt;SessionValidationScheduler&lt;/tt&gt; (that is, the
* {@link #setSessionValidationScheduler(SessionValidationScheduler) setSessionValidationScheduler} method is
* never called) , this method allows one to specify how
* frequently session should be validated (to check for orphans). The default value is
* {@link #DEFAULT_SESSION_VALIDATION_INTERVAL}.
* &lt;p/&gt;
* If you override the default scheduler, it is assumed that overriding instance 'knows' how often to
* validate sessions, and this attribute will be ignored.
* &lt;p/&gt;
* Unless this method is called, the default value is {@link #DEFAULT_SESSION_VALIDATION_INTERVAL}.
*
* @param sessionValidationInterval the time in milliseconds between checking for valid sessions to reap orphans.
*/
public void setSessionValidationInterval(long sessionValidationInterval) {
<span class="nc" id="L105"> this.sessionValidationInterval = sessionValidationInterval;</span>
<span class="nc" id="L106"> }</span>
public long getSessionValidationInterval() {
<span class="fc" id="L109"> return sessionValidationInterval;</span>
}
@Override
protected final Session doGetSession(final SessionKey key) throws InvalidSessionException {
<span class="fc" id="L114"> enableSessionValidationIfNecessary();</span>
<span class="fc" id="L116"> log.trace(&quot;Attempting to retrieve session with key {}&quot;, key);</span>
<span class="fc" id="L118"> Session s = retrieveSession(key);</span>
<span class="fc bfc" id="L119" title="All 2 branches covered."> if (s != null) {</span>
<span class="fc" id="L120"> validate(s, key);</span>
}
<span class="fc" id="L122"> return s;</span>
}
/**
* Looks up a session from the underlying data store based on the specified session key.
*
* @param key the session key to use to look up the target session.
* @return the session identified by {@code sessionId}.
* @throws UnknownSessionException if there is no session identified by {@code sessionId}.
*/
protected abstract Session retrieveSession(SessionKey key) throws UnknownSessionException;
protected Session createSession(SessionContext context) throws AuthorizationException {
<span class="fc" id="L135"> enableSessionValidationIfNecessary();</span>
<span class="fc" id="L136"> return doCreateSession(context);</span>
}
protected abstract Session doCreateSession(SessionContext initData) throws AuthorizationException;
protected void validate(Session session, SessionKey key) throws InvalidSessionException {
try {
<span class="fc" id="L143"> doValidate(session);</span>
<span class="fc" id="L144"> } catch (ExpiredSessionException ese) {</span>
<span class="fc" id="L145"> onExpiration(session, ese, key);</span>
<span class="fc" id="L146"> throw ese;</span>
<span class="nc" id="L147"> } catch (InvalidSessionException ise) {</span>
<span class="nc" id="L148"> onInvalidation(session, ise, key);</span>
<span class="nc" id="L149"> throw ise;</span>
<span class="fc" id="L150"> }</span>
<span class="fc" id="L151"> }</span>
protected void onExpiration(Session s, ExpiredSessionException ese, SessionKey key) {
<span class="fc" id="L154"> log.trace(&quot;Session with id [{}] has expired.&quot;, s.getId());</span>
try {
<span class="fc" id="L156"> onExpiration(s);</span>
<span class="fc" id="L157"> notifyExpiration(s);</span>
} finally {
<span class="fc" id="L159"> afterExpired(s);</span>
<span class="fc" id="L160"> }</span>
<span class="fc" id="L161"> }</span>
protected void onExpiration(Session session) {
<span class="fc" id="L164"> onChange(session);</span>
<span class="fc" id="L165"> }</span>
protected void afterExpired(Session session) {
<span class="fc" id="L168"> }</span>
protected void onInvalidation(Session s, InvalidSessionException ise, SessionKey key) {
<span class="nc bnc" id="L171" title="All 2 branches missed."> if (ise instanceof ExpiredSessionException) {</span>
<span class="nc" id="L172"> onExpiration(s, (ExpiredSessionException) ise, key);</span>
<span class="nc" id="L173"> return;</span>
}
<span class="nc" id="L175"> log.trace(&quot;Session with id [{}] is invalid.&quot;, s.getId());</span>
try {
<span class="nc" id="L177"> onStop(s);</span>
<span class="nc" id="L178"> notifyStop(s);</span>
} finally {
<span class="nc" id="L180"> afterStopped(s);</span>
<span class="nc" id="L181"> }</span>
<span class="nc" id="L182"> }</span>
protected void doValidate(Session session) throws InvalidSessionException {
<span class="pc bpc" id="L185" title="1 of 2 branches missed."> if (session instanceof ValidatingSession) {</span>
<span class="fc" id="L186"> ((ValidatingSession) session).validate();</span>
} else {
<span class="nc" id="L188"> String msg = &quot;The &quot; + getClass().getName() + &quot; implementation only supports validating &quot; +</span>
<span class="nc" id="L189"> &quot;Session implementations of the &quot; + ValidatingSession.class.getName() + &quot; interface. &quot; +</span>
&quot;Please either implement this interface in your session implementation or override the &quot; +
<span class="nc" id="L191"> AbstractValidatingSessionManager.class.getName() + &quot;.doValidate(Session) method to perform validation.&quot;;</span>
<span class="nc" id="L192"> throw new IllegalStateException(msg);</span>
}
<span class="fc" id="L194"> }</span>
/**
* Subclass template hook in case per-session timeout is not based on
* {@link org.apache.shiro.session.Session#getTimeout()}.
* &lt;p/&gt;
* &lt;p&gt;This implementation merely returns {@link org.apache.shiro.session.Session#getTimeout()}&lt;/p&gt;
*
* @param session the session for which to determine session timeout.
* @return the time in milliseconds the specified session may remain idle before expiring.
*/
protected long getTimeout(Session session) {
<span class="nc" id="L206"> return session.getTimeout();</span>
}
protected SessionValidationScheduler createSessionValidationScheduler() {
ExecutorServiceSessionValidationScheduler scheduler;
<span class="fc bfc" id="L212" title="All 2 branches covered."> if (log.isDebugEnabled()) {</span>
<span class="fc" id="L213"> log.debug(&quot;No sessionValidationScheduler set. Attempting to create default instance.&quot;);</span>
}
<span class="fc" id="L215"> scheduler = new ExecutorServiceSessionValidationScheduler(this);</span>
<span class="fc" id="L216"> scheduler.setInterval(getSessionValidationInterval());</span>
<span class="fc bfc" id="L217" title="All 2 branches covered."> if (log.isTraceEnabled()) {</span>
<span class="fc" id="L218"> log.trace(&quot;Created default SessionValidationScheduler instance of type [&quot; + scheduler.getClass().getName() + &quot;].&quot;);</span>
}
<span class="fc" id="L220"> return scheduler;</span>
}
protected synchronized void enableSessionValidation() {
<span class="fc" id="L224"> SessionValidationScheduler scheduler = getSessionValidationScheduler();</span>
<span class="fc bfc" id="L225" title="All 2 branches covered."> if (scheduler == null) {</span>
<span class="fc" id="L226"> scheduler = createSessionValidationScheduler();</span>
<span class="fc" id="L227"> setSessionValidationScheduler(scheduler);</span>
}
// it is possible that that a scheduler was already created and set via 'setSessionValidationScheduler()'
// but would not have been enabled/started yet
<span class="pc bpc" id="L231" title="1 of 2 branches missed."> if (!scheduler.isEnabled()) {</span>
<span class="fc bfc" id="L232" title="All 2 branches covered."> if (log.isInfoEnabled()) {</span>
<span class="fc" id="L233"> log.info(&quot;Enabling session validation scheduler...&quot;);</span>
}
<span class="fc" id="L235"> scheduler.enableSessionValidation();</span>
<span class="fc" id="L236"> afterSessionValidationEnabled();</span>
}
<span class="fc" id="L238"> }</span>
protected void afterSessionValidationEnabled() {
<span class="fc" id="L241"> }</span>
protected synchronized void disableSessionValidation() {
<span class="fc" id="L244"> beforeSessionValidationDisabled();</span>
<span class="fc" id="L245"> SessionValidationScheduler scheduler = getSessionValidationScheduler();</span>
<span class="fc bfc" id="L246" title="All 2 branches covered."> if (scheduler != null) {</span>
try {
<span class="fc" id="L248"> scheduler.disableSessionValidation();</span>
<span class="pc bpc" id="L249" title="1 of 2 branches missed."> if (log.isInfoEnabled()) {</span>
<span class="fc" id="L250"> log.info(&quot;Disabled session validation scheduler.&quot;);</span>
}
<span class="nc" id="L252"> } catch (Exception e) {</span>
<span class="nc bnc" id="L253" title="All 2 branches missed."> if (log.isDebugEnabled()) {</span>
<span class="nc" id="L254"> String msg = &quot;Unable to disable SessionValidationScheduler. Ignoring (shutting down)...&quot;;</span>
<span class="nc" id="L255"> log.debug(msg, e);</span>
}
<span class="fc" id="L257"> }</span>
<span class="fc" id="L258"> LifecycleUtils.destroy(scheduler);</span>
<span class="fc" id="L259"> setSessionValidationScheduler(null);</span>
}
<span class="fc" id="L261"> }</span>
protected void beforeSessionValidationDisabled() {
<span class="fc" id="L264"> }</span>
public void destroy() {
<span class="fc" id="L267"> disableSessionValidation();</span>
<span class="fc" id="L268"> }</span>
/**
* @see ValidatingSessionManager#validateSessions()
*/
public void validateSessions() {
<span class="pc bpc" id="L274" title="1 of 2 branches missed."> if (log.isInfoEnabled()) {</span>
<span class="fc" id="L275"> log.info(&quot;Validating all active sessions...&quot;);</span>
}
<span class="fc" id="L278"> int invalidCount = 0;</span>
<span class="fc" id="L280"> Collection&lt;Session&gt; activeSessions = getActiveSessions();</span>
<span class="pc bpc" id="L282" title="2 of 4 branches missed."> if (activeSessions != null &amp;&amp; !activeSessions.isEmpty()) {</span>
<span class="fc bfc" id="L283" title="All 2 branches covered."> for (Session s : activeSessions) {</span>
try {
//simulate a lookup key to satisfy the method signature.
//this could probably stand to be cleaned up in future versions:
<span class="fc" id="L287"> SessionKey key = new DefaultSessionKey(s.getId());</span>
<span class="fc" id="L288"> validate(s, key);</span>
<span class="fc" id="L289"> } catch (InvalidSessionException e) {</span>
<span class="pc bpc" id="L290" title="1 of 2 branches missed."> if (log.isDebugEnabled()) {</span>
<span class="fc" id="L291"> boolean expired = (e instanceof ExpiredSessionException);</span>
<span class="fc bfc" id="L292" title="All 2 branches covered."> String msg = &quot;Invalidated session with id [&quot; + s.getId() + &quot;]&quot; +</span>
(expired ? &quot; (expired)&quot; : &quot; (stopped)&quot;);
<span class="fc" id="L294"> log.debug(msg);</span>
}
<span class="fc" id="L296"> invalidCount++;</span>
<span class="fc" id="L297"> }</span>
<span class="fc" id="L298"> }</span>
}
<span class="pc bpc" id="L301" title="1 of 2 branches missed."> if (log.isInfoEnabled()) {</span>
<span class="fc" id="L302"> String msg = &quot;Finished session validation.&quot;;</span>
<span class="pc bpc" id="L303" title="1 of 2 branches missed."> if (invalidCount &gt; 0) {</span>
<span class="fc" id="L304"> msg += &quot; [&quot; + invalidCount + &quot;] sessions were stopped.&quot;;</span>
} else {
<span class="nc" id="L306"> msg += &quot; No sessions were stopped.&quot;;</span>
}
<span class="fc" id="L308"> log.info(msg);</span>
}
<span class="fc" id="L310"> }</span>
protected abstract Collection&lt;Session&gt; getActiveSessions();
}
</pre><div class="footer"><span class="right">Created with <a href="http://www.eclemma.org/jacoco">JaCoCo</a> 0.7.7.201606060606</span></div></body></html>