blob: 16b86925f4f8df2f5dc34d9a4afd70fb26e925f8 [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>DelegatingSubject.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 :: Core</a> &gt; <a href="index.source.html" class="el_package">org.apache.shiro.subject.support</a> &gt; <span class="el_source">DelegatingSubject.java</span></div><h1>DelegatingSubject.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.subject.support;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.HostAuthenticationToken;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.authz.Permission;
import org.apache.shiro.authz.UnauthenticatedException;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.session.InvalidSessionException;
import org.apache.shiro.session.ProxiedSession;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.SessionException;
import org.apache.shiro.session.mgt.DefaultSessionContext;
import org.apache.shiro.session.mgt.SessionContext;
import org.apache.shiro.subject.ExecutionException;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.CollectionUtils;
import org.apache.shiro.util.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* Implementation of the {@code Subject} interface that delegates
* method calls to an underlying {@link org.apache.shiro.mgt.SecurityManager SecurityManager} instance for security checks.
* It is essentially a {@code SecurityManager} proxy.
* &lt;p/&gt;
* This implementation does not maintain state such as roles and permissions (only {@code Subject}
* {@link #getPrincipals() principals}, such as usernames or user primary keys) for better performance in a stateless
* architecture. It instead asks the underlying {@code SecurityManager} every time to perform
* the authorization check.
* &lt;p/&gt;
* A common misconception in using this implementation is that an EIS resource (RDBMS, etc) would
* be &amp;quot;hit&amp;quot; every time a method is called. This is not necessarily the case and is
* up to the implementation of the underlying {@code SecurityManager} instance. If caching of authorization
* data is desired (to eliminate EIS round trips and therefore improve database performance), it is considered
* much more elegant to let the underlying {@code SecurityManager} implementation or its delegate components
* manage caching, not this class. A {@code SecurityManager} is considered a business-tier component,
* where caching strategies are better managed.
* &lt;p/&gt;
* Applications from large and clustered to simple and JVM-local all benefit from
* stateless architectures. This implementation plays a part in the stateless programming
* paradigm and should be used whenever possible.
*
* @since 0.1
*/
<span class="pc bpc" id="L71" title="1 of 2 branches missed.">public class DelegatingSubject implements Subject {</span>
<span class="fc" id="L73"> private static final Logger log = LoggerFactory.getLogger(DelegatingSubject.class);</span>
<span class="fc" id="L75"> private static final String RUN_AS_PRINCIPALS_SESSION_KEY =</span>
<span class="fc" id="L76"> DelegatingSubject.class.getName() + &quot;.RUN_AS_PRINCIPALS_SESSION_KEY&quot;;</span>
protected PrincipalCollection principals;
protected boolean authenticated;
protected String host;
protected Session session;
/**
* @since 1.2
*/
protected boolean sessionCreationEnabled;
protected transient SecurityManager securityManager;
public DelegatingSubject(SecurityManager securityManager) {
<span class="fc" id="L90"> this(null, false, null, null, securityManager);</span>
<span class="fc" id="L91"> }</span>
public DelegatingSubject(PrincipalCollection principals, boolean authenticated, String host,
Session session, SecurityManager securityManager) {
<span class="fc" id="L95"> this(principals, authenticated, host, session, true, securityManager);</span>
<span class="fc" id="L96"> }</span>
//since 1.2
public DelegatingSubject(PrincipalCollection principals, boolean authenticated, String host,
<span class="fc" id="L100"> Session session, boolean sessionCreationEnabled, SecurityManager securityManager) {</span>
<span class="pc bpc" id="L101" title="1 of 2 branches missed."> if (securityManager == null) {</span>
<span class="nc" id="L102"> throw new IllegalArgumentException(&quot;SecurityManager argument cannot be null.&quot;);</span>
}
<span class="fc" id="L104"> this.securityManager = securityManager;</span>
<span class="fc" id="L105"> this.principals = principals;</span>
<span class="fc" id="L106"> this.authenticated = authenticated;</span>
<span class="fc" id="L107"> this.host = host;</span>
<span class="fc bfc" id="L108" title="All 2 branches covered."> if (session != null) {</span>
<span class="fc" id="L109"> this.session = decorate(session);</span>
}
<span class="fc" id="L111"> this.sessionCreationEnabled = sessionCreationEnabled;</span>
<span class="fc" id="L112"> }</span>
protected Session decorate(Session session) {
<span class="pc bpc" id="L115" title="1 of 2 branches missed."> if (session == null) {</span>
<span class="nc" id="L116"> throw new IllegalArgumentException(&quot;session cannot be null&quot;);</span>
}
<span class="fc" id="L118"> return new StoppingAwareProxiedSession(session, this);</span>
}
public SecurityManager getSecurityManager() {
<span class="fc" id="L122"> return securityManager;</span>
}
private static boolean isEmpty(PrincipalCollection pc) {
<span class="pc bpc" id="L126" title="1 of 4 branches missed."> return pc == null || pc.isEmpty();</span>
}
protected boolean hasPrincipals() {
<span class="fc bfc" id="L130" title="All 2 branches covered."> return !isEmpty(getPrincipals());</span>
}
/**
* Returns the host name or IP associated with the client who created/is interacting with this Subject.
*
* @return the host name or IP associated with the client who created/is interacting with this Subject.
*/
public String getHost() {
<span class="fc" id="L139"> return this.host;</span>
}
private Object getPrimaryPrincipal(PrincipalCollection principals) {
<span class="fc bfc" id="L143" title="All 2 branches covered."> if (!isEmpty(principals)) {</span>
<span class="fc" id="L144"> return principals.getPrimaryPrincipal();</span>
}
<span class="fc" id="L146"> return null;</span>
}
/**
* @see Subject#getPrincipal()
*/
public Object getPrincipal() {
<span class="fc" id="L153"> return getPrimaryPrincipal(getPrincipals());</span>
}
public PrincipalCollection getPrincipals() {
<span class="fc" id="L157"> List&lt;PrincipalCollection&gt; runAsPrincipals = getRunAsPrincipalsStack();</span>
<span class="fc bfc" id="L158" title="All 2 branches covered."> return CollectionUtils.isEmpty(runAsPrincipals) ? this.principals : runAsPrincipals.get(0);</span>
}
public boolean isPermitted(String permission) {
<span class="pc bpc" id="L162" title="1 of 4 branches missed."> return hasPrincipals() &amp;&amp; securityManager.isPermitted(getPrincipals(), permission);</span>
}
public boolean isPermitted(Permission permission) {
<span class="nc bnc" id="L166" title="All 4 branches missed."> return hasPrincipals() &amp;&amp; securityManager.isPermitted(getPrincipals(), permission);</span>
}
public boolean[] isPermitted(String... permissions) {
<span class="nc bnc" id="L170" title="All 2 branches missed."> if (hasPrincipals()) {</span>
<span class="nc" id="L171"> return securityManager.isPermitted(getPrincipals(), permissions);</span>
} else {
<span class="nc" id="L173"> return new boolean[permissions.length];</span>
}
}
public boolean[] isPermitted(List&lt;Permission&gt; permissions) {
<span class="nc bnc" id="L178" title="All 2 branches missed."> if (hasPrincipals()) {</span>
<span class="nc" id="L179"> return securityManager.isPermitted(getPrincipals(), permissions);</span>
} else {
<span class="nc" id="L181"> return new boolean[permissions.size()];</span>
}
}
public boolean isPermittedAll(String... permissions) {
<span class="nc bnc" id="L186" title="All 4 branches missed."> return hasPrincipals() &amp;&amp; securityManager.isPermittedAll(getPrincipals(), permissions);</span>
}
public boolean isPermittedAll(Collection&lt;Permission&gt; permissions) {
<span class="nc bnc" id="L190" title="All 4 branches missed."> return hasPrincipals() &amp;&amp; securityManager.isPermittedAll(getPrincipals(), permissions);</span>
}
protected void assertAuthzCheckPossible() throws AuthorizationException {
<span class="pc bpc" id="L194" title="1 of 2 branches missed."> if (!hasPrincipals()) {</span>
<span class="fc" id="L195"> String msg = &quot;This subject is anonymous - it does not have any identifying principals and &quot; +</span>
&quot;authorization operations require an identity to check against. A Subject instance will &quot; +
&quot;acquire these identifying principals automatically after a successful login is performed &quot; +
<span class="fc" id="L198"> &quot;be executing &quot; + Subject.class.getName() + &quot;.login(AuthenticationToken) or when 'Remember Me' &quot; +</span>
&quot;functionality is enabled by the SecurityManager. This exception can also occur when a &quot; +
&quot;previously logged-in Subject has logged out which &quot; +
&quot;makes it anonymous again. Because an identity is currently not known due to any of these &quot; +
&quot;conditions, authorization is denied.&quot;;
<span class="fc" id="L203"> throw new UnauthenticatedException(msg);</span>
}
<span class="nc" id="L205"> }</span>
public void checkPermission(String permission) throws AuthorizationException {
<span class="nc" id="L208"> assertAuthzCheckPossible();</span>
<span class="nc" id="L209"> securityManager.checkPermission(getPrincipals(), permission);</span>
<span class="nc" id="L210"> }</span>
public void checkPermission(Permission permission) throws AuthorizationException {
<span class="nc" id="L213"> assertAuthzCheckPossible();</span>
<span class="nc" id="L214"> securityManager.checkPermission(getPrincipals(), permission);</span>
<span class="nc" id="L215"> }</span>
public void checkPermissions(String... permissions) throws AuthorizationException {
<span class="nc" id="L218"> assertAuthzCheckPossible();</span>
<span class="nc" id="L219"> securityManager.checkPermissions(getPrincipals(), permissions);</span>
<span class="nc" id="L220"> }</span>
public void checkPermissions(Collection&lt;Permission&gt; permissions) throws AuthorizationException {
<span class="nc" id="L223"> assertAuthzCheckPossible();</span>
<span class="nc" id="L224"> securityManager.checkPermissions(getPrincipals(), permissions);</span>
<span class="nc" id="L225"> }</span>
public boolean hasRole(String roleIdentifier) {
<span class="pc bpc" id="L228" title="1 of 4 branches missed."> return hasPrincipals() &amp;&amp; securityManager.hasRole(getPrincipals(), roleIdentifier);</span>
}
public boolean[] hasRoles(List&lt;String&gt; roleIdentifiers) {
<span class="nc bnc" id="L232" title="All 2 branches missed."> if (hasPrincipals()) {</span>
<span class="nc" id="L233"> return securityManager.hasRoles(getPrincipals(), roleIdentifiers);</span>
} else {
<span class="nc" id="L235"> return new boolean[roleIdentifiers.size()];</span>
}
}
public boolean hasAllRoles(Collection&lt;String&gt; roleIdentifiers) {
<span class="nc bnc" id="L240" title="All 4 branches missed."> return hasPrincipals() &amp;&amp; securityManager.hasAllRoles(getPrincipals(), roleIdentifiers);</span>
}
public void checkRole(String role) throws AuthorizationException {
<span class="nc" id="L244"> assertAuthzCheckPossible();</span>
<span class="nc" id="L245"> securityManager.checkRole(getPrincipals(), role);</span>
<span class="nc" id="L246"> }</span>
public void checkRoles(String... roleIdentifiers) throws AuthorizationException {
<span class="nc" id="L249"> assertAuthzCheckPossible();</span>
<span class="nc" id="L250"> securityManager.checkRoles(getPrincipals(), roleIdentifiers);</span>
<span class="nc" id="L251"> }</span>
public void checkRoles(Collection&lt;String&gt; roles) throws AuthorizationException {
<span class="nc" id="L254"> assertAuthzCheckPossible();</span>
<span class="nc" id="L255"> securityManager.checkRoles(getPrincipals(), roles);</span>
<span class="nc" id="L256"> }</span>
public void login(AuthenticationToken token) throws AuthenticationException {
<span class="fc" id="L259"> clearRunAsIdentitiesInternal();</span>
<span class="fc" id="L260"> Subject subject = securityManager.login(this, token);</span>
PrincipalCollection principals;
<span class="fc" id="L264"> String host = null;</span>
<span class="pc bpc" id="L266" title="1 of 2 branches missed."> if (subject instanceof DelegatingSubject) {</span>
<span class="fc" id="L267"> DelegatingSubject delegating = (DelegatingSubject) subject;</span>
//we have to do this in case there are assumed identities - we don't want to lose the 'real' principals:
<span class="fc" id="L269"> principals = delegating.principals;</span>
<span class="fc" id="L270"> host = delegating.host;</span>
<span class="fc" id="L271"> } else {</span>
<span class="nc" id="L272"> principals = subject.getPrincipals();</span>
}
<span class="pc bpc" id="L275" title="2 of 4 branches missed."> if (principals == null || principals.isEmpty()) {</span>
<span class="nc" id="L276"> String msg = &quot;Principals returned from securityManager.login( token ) returned a null or &quot; +</span>
&quot;empty value. This value must be non null and populated with one or more elements.&quot;;
<span class="nc" id="L278"> throw new IllegalStateException(msg);</span>
}
<span class="fc" id="L280"> this.principals = principals;</span>
<span class="fc" id="L281"> this.authenticated = true;</span>
<span class="pc bpc" id="L282" title="1 of 2 branches missed."> if (token instanceof HostAuthenticationToken) {</span>
<span class="fc" id="L283"> host = ((HostAuthenticationToken) token).getHost();</span>
}
<span class="fc bfc" id="L285" title="All 2 branches covered."> if (host != null) {</span>
<span class="fc" id="L286"> this.host = host;</span>
}
<span class="fc" id="L288"> Session session = subject.getSession(false);</span>
<span class="pc bpc" id="L289" title="1 of 2 branches missed."> if (session != null) {</span>
<span class="fc" id="L290"> this.session = decorate(session);</span>
} else {
<span class="nc" id="L292"> this.session = null;</span>
}
<span class="fc" id="L294"> }</span>
public boolean isAuthenticated() {
<span class="fc" id="L297"> return authenticated;</span>
}
public boolean isRemembered() {
<span class="nc" id="L301"> PrincipalCollection principals = getPrincipals();</span>
<span class="nc bnc" id="L302" title="All 6 branches missed."> return principals != null &amp;&amp; !principals.isEmpty() &amp;&amp; !isAuthenticated();</span>
}
/**
* Returns {@code true} if this Subject is allowed to create sessions, {@code false} otherwise.
*
* @return {@code true} if this Subject is allowed to create sessions, {@code false} otherwise.
* @since 1.2
*/
protected boolean isSessionCreationEnabled() {
<span class="fc" id="L312"> return this.sessionCreationEnabled;</span>
}
public Session getSession() {
<span class="fc" id="L316"> return getSession(true);</span>
}
public Session getSession(boolean create) {
<span class="pc bpc" id="L320" title="1 of 2 branches missed."> if (log.isTraceEnabled()) {</span>
<span class="fc bfc" id="L321" title="All 4 branches covered."> log.trace(&quot;attempting to get session; create = &quot; + create +</span>
&quot;; session is null = &quot; + (this.session == null) +
<span class="pc bpc" id="L323" title="1 of 2 branches missed."> &quot;; session has id = &quot; + (this.session != null &amp;&amp; session.getId() != null));</span>
}
<span class="fc bfc" id="L326" title="All 4 branches covered."> if (this.session == null &amp;&amp; create) {</span>
//added in 1.2:
<span class="pc bpc" id="L329" title="1 of 2 branches missed."> if (!isSessionCreationEnabled()) {</span>
<span class="nc" id="L330"> String msg = &quot;Session creation has been disabled for the current subject. This exception indicates &quot; +</span>
&quot;that there is either a programming error (using a session when it should never be &quot; +
&quot;used) or that Shiro's configuration needs to be adjusted to allow Sessions to be created &quot; +
<span class="nc" id="L333"> &quot;for the current Subject. See the &quot; + DisabledSessionException.class.getName() + &quot; JavaDoc &quot; +</span>
&quot;for more.&quot;;
<span class="nc" id="L335"> throw new DisabledSessionException(msg);</span>
}
<span class="fc" id="L338"> log.trace(&quot;Starting session for host {}&quot;, getHost());</span>
<span class="fc" id="L339"> SessionContext sessionContext = createSessionContext();</span>
<span class="fc" id="L340"> Session session = this.securityManager.start(sessionContext);</span>
<span class="fc" id="L341"> this.session = decorate(session);</span>
}
<span class="fc" id="L343"> return this.session;</span>
}
protected SessionContext createSessionContext() {
<span class="fc" id="L347"> SessionContext sessionContext = new DefaultSessionContext();</span>
<span class="fc bfc" id="L348" title="All 2 branches covered."> if (StringUtils.hasText(host)) {</span>
<span class="fc" id="L349"> sessionContext.setHost(host);</span>
}
<span class="fc" id="L351"> return sessionContext;</span>
}
private void clearRunAsIdentitiesInternal() {
//try/catch added for SHIRO-298
try {
<span class="fc" id="L357"> clearRunAsIdentities();</span>
<span class="nc" id="L358"> } catch (SessionException se) {</span>
<span class="nc" id="L359"> log.debug(&quot;Encountered session exception trying to clear 'runAs' identities during logout. This &quot; +</span>
&quot;can generally safely be ignored.&quot;, se);
<span class="fc" id="L361"> }</span>
<span class="fc" id="L362"> }</span>
public void logout() {
try {
<span class="fc" id="L366"> clearRunAsIdentitiesInternal();</span>
<span class="fc" id="L367"> this.securityManager.logout(this);</span>
} finally {
<span class="fc" id="L369"> this.session = null;</span>
<span class="fc" id="L370"> this.principals = null;</span>
<span class="fc" id="L371"> this.authenticated = false;</span>
//Don't set securityManager to null here - the Subject can still be
//used, it is just considered anonymous at this point. The SecurityManager instance is
//necessary if the subject would log in again or acquire a new session. This is in response to
//https://issues.apache.org/jira/browse/JSEC-22
//this.securityManager = null;
}
<span class="fc" id="L378"> }</span>
private void sessionStopped() {
<span class="fc" id="L381"> this.session = null;</span>
<span class="fc" id="L382"> }</span>
public &lt;V&gt; V execute(Callable&lt;V&gt; callable) throws ExecutionException {
<span class="fc" id="L385"> Callable&lt;V&gt; associated = associateWith(callable);</span>
try {
<span class="fc" id="L387"> return associated.call();</span>
<span class="nc" id="L388"> } catch (Throwable t) {</span>
<span class="nc" id="L389"> throw new ExecutionException(t);</span>
}
}
public void execute(Runnable runnable) {
<span class="fc" id="L394"> Runnable associated = associateWith(runnable);</span>
<span class="fc" id="L395"> associated.run();</span>
<span class="fc" id="L396"> }</span>
public &lt;V&gt; Callable&lt;V&gt; associateWith(Callable&lt;V&gt; callable) {
<span class="fc" id="L399"> return new SubjectCallable&lt;V&gt;(this, callable);</span>
}
public Runnable associateWith(Runnable runnable) {
<span class="pc bpc" id="L403" title="1 of 2 branches missed."> if (runnable instanceof Thread) {</span>
<span class="nc" id="L404"> String msg = &quot;This implementation does not support Thread arguments because of JDK ThreadLocal &quot; +</span>
&quot;inheritance mechanisms required by Shiro. Instead, the method argument should be a non-Thread &quot; +
&quot;Runnable and the return value from this method can then be given to an ExecutorService or &quot; +
&quot;another Thread.&quot;;
<span class="nc" id="L408"> throw new UnsupportedOperationException(msg);</span>
}
<span class="fc" id="L410"> return new SubjectRunnable(this, runnable);</span>
}
private class StoppingAwareProxiedSession extends ProxiedSession {
private final DelegatingSubject owner;
<span class="fc" id="L417"> private StoppingAwareProxiedSession(Session target, DelegatingSubject owningSubject) {</span>
<span class="fc" id="L418"> super(target);</span>
<span class="fc" id="L419"> owner = owningSubject;</span>
<span class="fc" id="L420"> }</span>
public void stop() throws InvalidSessionException {
<span class="fc" id="L423"> super.stop();</span>
<span class="fc" id="L424"> owner.sessionStopped();</span>
<span class="fc" id="L425"> }</span>
}
// ======================================
// 'Run As' support implementations
// ======================================
public void runAs(PrincipalCollection principals) {
<span class="pc bpc" id="L434" title="1 of 2 branches missed."> if (!hasPrincipals()) {</span>
<span class="nc" id="L435"> String msg = &quot;This subject does not yet have an identity. Assuming the identity of another &quot; +</span>
&quot;Subject is only allowed for Subjects with an existing identity. Try logging this subject in &quot; +
<span class="nc" id="L437"> &quot;first, or using the &quot; + Subject.Builder.class.getName() + &quot; to build ad hoc Subject instances &quot; +</span>
&quot;with identities as necessary.&quot;;
<span class="nc" id="L439"> throw new IllegalStateException(msg);</span>
}
<span class="fc" id="L441"> pushIdentity(principals);</span>
<span class="fc" id="L442"> }</span>
public boolean isRunAs() {
<span class="fc" id="L445"> List&lt;PrincipalCollection&gt; stack = getRunAsPrincipalsStack();</span>
<span class="fc bfc" id="L446" title="All 2 branches covered."> return !CollectionUtils.isEmpty(stack);</span>
}
public PrincipalCollection getPreviousPrincipals() {
<span class="fc" id="L450"> PrincipalCollection previousPrincipals = null;</span>
<span class="fc" id="L451"> List&lt;PrincipalCollection&gt; stack = getRunAsPrincipalsStack();</span>
<span class="fc bfc" id="L452" title="All 2 branches covered."> int stackSize = stack != null ? stack.size() : 0;</span>
<span class="fc bfc" id="L453" title="All 2 branches covered."> if (stackSize &gt; 0) {</span>
<span class="fc bfc" id="L454" title="All 2 branches covered."> if (stackSize == 1) {</span>
<span class="fc" id="L455"> previousPrincipals = this.principals;</span>
} else {
//always get the one behind the current:
<span class="pc bpc" id="L458" title="2 of 4 branches missed."> assert stack != null;</span>
<span class="fc" id="L459"> previousPrincipals = stack.get(1);</span>
}
}
<span class="fc" id="L462"> return previousPrincipals;</span>
}
public PrincipalCollection releaseRunAs() {
<span class="fc" id="L466"> return popIdentity();</span>
}
@SuppressWarnings(&quot;unchecked&quot;)
private List&lt;PrincipalCollection&gt; getRunAsPrincipalsStack() {
<span class="fc" id="L471"> Session session = getSession(false);</span>
<span class="fc bfc" id="L472" title="All 2 branches covered."> if (session != null) {</span>
<span class="fc" id="L473"> return (List&lt;PrincipalCollection&gt;) session.getAttribute(RUN_AS_PRINCIPALS_SESSION_KEY);</span>
}
<span class="fc" id="L475"> return null;</span>
}
private void clearRunAsIdentities() {
<span class="fc" id="L479"> Session session = getSession(false);</span>
<span class="fc bfc" id="L480" title="All 2 branches covered."> if (session != null) {</span>
<span class="fc" id="L481"> session.removeAttribute(RUN_AS_PRINCIPALS_SESSION_KEY);</span>
}
<span class="fc" id="L483"> }</span>
private void pushIdentity(PrincipalCollection principals) throws NullPointerException {
<span class="pc bpc" id="L486" title="1 of 2 branches missed."> if (isEmpty(principals)) {</span>
<span class="nc" id="L487"> String msg = &quot;Specified Subject principals cannot be null or empty for 'run as' functionality.&quot;;</span>
<span class="nc" id="L488"> throw new NullPointerException(msg);</span>
}
<span class="fc" id="L490"> List&lt;PrincipalCollection&gt; stack = getRunAsPrincipalsStack();</span>
<span class="fc bfc" id="L491" title="All 2 branches covered."> if (stack == null) {</span>
<span class="fc" id="L492"> stack = new CopyOnWriteArrayList&lt;PrincipalCollection&gt;();</span>
}
<span class="fc" id="L494"> stack.add(0, principals);</span>
<span class="fc" id="L495"> Session session = getSession();</span>
<span class="fc" id="L496"> session.setAttribute(RUN_AS_PRINCIPALS_SESSION_KEY, stack);</span>
<span class="fc" id="L497"> }</span>
private PrincipalCollection popIdentity() {
<span class="fc" id="L500"> PrincipalCollection popped = null;</span>
<span class="fc" id="L502"> List&lt;PrincipalCollection&gt; stack = getRunAsPrincipalsStack();</span>
<span class="pc bpc" id="L503" title="1 of 2 branches missed."> if (!CollectionUtils.isEmpty(stack)) {</span>
<span class="fc" id="L504"> popped = stack.remove(0);</span>
Session session;
<span class="fc bfc" id="L506" title="All 2 branches covered."> if (!CollectionUtils.isEmpty(stack)) {</span>
//persist the changed stack to the session
<span class="fc" id="L508"> session = getSession();</span>
<span class="fc" id="L509"> session.setAttribute(RUN_AS_PRINCIPALS_SESSION_KEY, stack);</span>
} else {
//stack is empty, remove it from the session:
<span class="fc" id="L512"> clearRunAsIdentities();</span>
}
}
<span class="fc" id="L516"> return popped;</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>