blob: 02a4398750bf80643902e9592d3dd83111dbbf10 [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>OncePerRequestFilter.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 :: Jar Bundle</a> &gt; <a href="../index.html" class="el_bundle">shiro-web</a> &gt; <a href="index.source.html" class="el_package">org.apache.shiro.web.servlet</a> &gt; <span class="el_source">OncePerRequestFilter.java</span></div><h1>OncePerRequestFilter.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.web.servlet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.IOException;
/**
* Filter base class that guarantees to be just executed once per request,
* on any servlet container. It provides a {@link #doFilterInternal}
* method with HttpServletRequest and HttpServletResponse arguments.
* &lt;p/&gt;
* The {@link #getAlreadyFilteredAttributeName} method determines how
* to identify that a request is already filtered. The default implementation
* is based on the configured name of the concrete filter instance.
* &lt;h3&gt;Controlling filter execution&lt;/h3&gt;
* 1.2 introduced the {@link #isEnabled(javax.servlet.ServletRequest, javax.servlet.ServletResponse)} method and
* {@link #isEnabled()} property to allow explicit controll over whether the filter executes (or allows passthrough)
* for any given request.
* &lt;p/&gt;
* &lt;b&gt;NOTE&lt;/b&gt; This class was initially borrowed from the Spring framework but has continued modifications.
*
* @since 0.1
*/
<span class="fc" id="L47">public abstract class OncePerRequestFilter extends NameableFilter {</span>
/**
* Private internal log instance.
*/
<span class="fc" id="L52"> private static final Logger log = LoggerFactory.getLogger(OncePerRequestFilter.class);</span>
/**
* Suffix that gets appended to the filter name for the &quot;already filtered&quot; request attribute.
*
* @see #getAlreadyFilteredAttributeName
*/
public static final String ALREADY_FILTERED_SUFFIX = &quot;.FILTERED&quot;;
/**
* Determines generally if this filter should execute or let requests fall through to the next chain element.
*
* @see #isEnabled()
*/
<span class="fc" id="L66"> private boolean enabled = true; //most filters wish to execute when configured, so default to true</span>
/**
* Returns {@code true} if this filter should &lt;em&gt;generally&lt;/em&gt;&lt;b&gt;*&lt;/b&gt; execute for any request,
* {@code false} if it should let the request/response pass through immediately to the next
* element in the {@link FilterChain}. The default value is {@code true}, as most filters would inherently need
* to execute when configured.
* &lt;p/&gt;
* &lt;b&gt;*&lt;/b&gt; This configuration property is for general configuration for any request that comes through
* the filter. The
* {@link #isEnabled(javax.servlet.ServletRequest, javax.servlet.ServletResponse) isEnabled(request,response)}
* method actually determines whether or not if the filter is enabled based on the current request.
*
* @return {@code true} if this filter should &lt;em&gt;generally&lt;/em&gt; execute, {@code false} if it should let the
* request/response pass through immediately to the next element in the {@link FilterChain}.
* @since 1.2
*/
public boolean isEnabled() {
<span class="fc" id="L84"> return enabled;</span>
}
/**
* Sets whether or not this filter &lt;em&gt;generally&lt;/em&gt; executes for any request. See the
* {@link #isEnabled() isEnabled()} JavaDoc as to what &lt;em&gt;general&lt;/em&gt; execution means.
*
* @param enabled whether or not this filter &lt;em&gt;generally&lt;/em&gt; executes.
* @since 1.2
*/
public void setEnabled(boolean enabled) {
<span class="fc" id="L95"> this.enabled = enabled;</span>
<span class="fc" id="L96"> }</span>
/**
* This {@code doFilter} implementation stores a request attribute for
* &quot;already filtered&quot;, proceeding without filtering again if the
* attribute is already there.
*
* @see #getAlreadyFilteredAttributeName
* @see #shouldNotFilter
* @see #doFilterInternal
*/
public final void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
<span class="fc" id="L109"> String alreadyFilteredAttributeName = getAlreadyFilteredAttributeName();</span>
<span class="pc bpc" id="L110" title="1 of 2 branches missed."> if ( request.getAttribute(alreadyFilteredAttributeName) != null ) {</span>
<span class="nc" id="L111"> log.trace(&quot;Filter '{}' already executed. Proceeding without invoking this filter.&quot;, getName());</span>
<span class="nc" id="L112"> filterChain.doFilter(request, response);</span>
} else //noinspection deprecation
<span class="fc bfc" id="L114" title="All 2 branches covered."> if (/* added in 1.2: */ !isEnabled(request, response) ||</span>
<span class="pc bpc" id="L115" title="1 of 2 branches missed."> /* retain backwards compatibility: */ shouldNotFilter(request) ) {</span>
<span class="fc" id="L116"> log.debug(&quot;Filter '{}' is not enabled for the current request. Proceeding without invoking this filter.&quot;,</span>
<span class="fc" id="L117"> getName());</span>
<span class="fc" id="L118"> filterChain.doFilter(request, response);</span>
} else {
// Do invoke this filter...
<span class="fc" id="L121"> log.trace(&quot;Filter '{}' not yet executed. Executing now.&quot;, getName());</span>
<span class="fc" id="L122"> request.setAttribute(alreadyFilteredAttributeName, Boolean.TRUE);</span>
try {
<span class="fc" id="L125"> doFilterInternal(request, response, filterChain);</span>
} finally {
// Once the request has finished, we're done and we don't
// need to mark as 'already filtered' any more.
<span class="pc" id="L129"> request.removeAttribute(alreadyFilteredAttributeName);</span>
<span class="fc" id="L130"> }</span>
}
<span class="fc" id="L132"> }</span>
/**
* Returns {@code true} if this filter should filter the specified request, {@code false} if it should let the
* request/response pass through immediately to the next element in the {@code FilterChain}.
* &lt;p/&gt;
* This default implementation merely returns the value of {@link #isEnabled() isEnabled()}, which is
* {@code true} by default (to ensure the filter always executes by default), but it can be overridden by
* subclasses for request-specific behavior if necessary. For example, a filter could be enabled or disabled
* based on the request path being accessed.
* &lt;p/&gt;
* &lt;b&gt;Helpful Hint:&lt;/b&gt; if your subclass extends {@link org.apache.shiro.web.filter.PathMatchingFilter PathMatchingFilter},
* you may wish to instead override the
* {@link org.apache.shiro.web.filter.PathMatchingFilter#isEnabled(javax.servlet.ServletRequest, javax.servlet.ServletResponse, String, Object)
* PathMatchingFilter.isEnabled(request,response,path,pathSpecificConfig)}
* method if you want to make your enable/disable decision based on any path-specific configuration.
*
* @param request the incoming servlet request
* @param response the outbound servlet response
* @return {@code true} if this filter should filter the specified request, {@code false} if it should let the
* request/response pass through immediately to the next element in the {@code FilterChain}.
* @throws IOException in the case of any IO error
* @throws ServletException in the case of any error
* @see org.apache.shiro.web.filter.PathMatchingFilter#isEnabled(javax.servlet.ServletRequest, javax.servlet.ServletResponse, String, Object)
* @since 1.2
*/
@SuppressWarnings({&quot;UnusedParameters&quot;})
protected boolean isEnabled(ServletRequest request, ServletResponse response) throws ServletException, IOException {
<span class="fc" id="L160"> return isEnabled();</span>
}
/**
* Return name of the request attribute that identifies that a request has already been filtered.
* &lt;p/&gt;
* The default implementation takes the configured {@link #getName() name} and appends &amp;quot;{@code .FILTERED}&amp;quot;.
* If the filter is not fully initialized, it falls back to the implementation's class name.
*
* @return the name of the request attribute that identifies that a request has already been filtered.
* @see #getName
* @see #ALREADY_FILTERED_SUFFIX
*/
protected String getAlreadyFilteredAttributeName() {
<span class="fc" id="L174"> String name = getName();</span>
<span class="fc bfc" id="L175" title="All 2 branches covered."> if (name == null) {</span>
<span class="fc" id="L176"> name = getClass().getName();</span>
}
<span class="fc" id="L178"> return name + ALREADY_FILTERED_SUFFIX;</span>
}
/**
* Can be overridden in subclasses for custom filtering control,
* returning &lt;code&gt;true&lt;/code&gt; to avoid filtering of the given request.
* &lt;p&gt;The default implementation always returns &lt;code&gt;false&lt;/code&gt;.
*
* @param request current HTTP request
* @return whether the given request should &lt;i&gt;not&lt;/i&gt; be filtered
* @throws ServletException in case of errors
* @deprecated in favor of overriding {@link #isEnabled(javax.servlet.ServletRequest, javax.servlet.ServletResponse)}
* for custom behavior. This method will be removed in Shiro 2.0.
*/
@Deprecated
@SuppressWarnings({&quot;UnusedDeclaration&quot;})
protected boolean shouldNotFilter(ServletRequest request) throws ServletException {
<span class="fc" id="L195"> return false;</span>
}
/**
* Same contract as for
* {@link #doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)},
* but guaranteed to be invoked only once per request.
*
* @param request incoming {@code ServletRequest}
* @param response outgoing {@code ServletResponse}
* @param chain the {@code FilterChain} to execute
* @throws ServletException if there is a problem processing the request
* @throws IOException if there is an I/O problem processing the request
*/
protected abstract void doFilterInternal(ServletRequest request, ServletResponse response, FilterChain chain)
throws ServletException, IOException;
}
</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>