<?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>SimpleFilterChainResolver.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-guice</a> &gt; <a href="index.source.html" class="el_package">org.apache.shiro.guice.web</a> &gt; <span class="el_source">SimpleFilterChainResolver.java</span></div><h1>SimpleFilterChainResolver.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.guice.web;

import java.util.Arrays;
import java.util.Iterator;
import java.util.Map;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

import com.google.inject.Injector;
import com.google.inject.Key;

import org.apache.shiro.util.PatternMatcher;
import org.apache.shiro.web.filter.mgt.FilterChainResolver;
import org.apache.shiro.web.util.WebUtils;

class SimpleFilterChainResolver implements FilterChainResolver {
    private final Map&lt;String, Key&lt;? extends Filter&gt;[]&gt; chains;
    private final Injector injector;
    private final PatternMatcher patternMatcher;

<span class="fc" id="L42">    SimpleFilterChainResolver(Map&lt;String, Key&lt;? extends Filter&gt;[]&gt; chains, Injector injector, PatternMatcher patternMatcher) {</span>
<span class="fc" id="L43">        this.chains = chains;</span>
<span class="fc" id="L44">        this.injector = injector;</span>
<span class="fc" id="L45">        this.patternMatcher = patternMatcher;</span>
<span class="fc" id="L46">    }</span>

    public FilterChain getChain(ServletRequest request, ServletResponse response, final FilterChain originalChain) {
<span class="fc" id="L49">        String path = WebUtils.getPathWithinApplication(WebUtils.toHttp(request));</span>
<span class="fc bfc" id="L50" title="All 2 branches covered.">        for (final String pathPattern : chains.keySet()) {</span>
<span class="fc bfc" id="L51" title="All 2 branches covered.">            if (patternMatcher.matches(pathPattern, path)) {</span>
<span class="fc" id="L52">                final Iterator&lt;Key&lt;? extends Filter&gt;&gt; chain = Arrays.asList(chains.get(pathPattern)).iterator();</span>
<span class="fc" id="L53">                return new SimpleFilterChain(originalChain, new Iterator&lt;Filter&gt;() {</span>
                    public boolean hasNext() {
<span class="fc" id="L55">                        return chain.hasNext();</span>
                    }

                    public Filter next() {
<span class="fc" id="L59">                        return injector.getInstance(chain.next());</span>
                    }

                    public void remove() {
<span class="nc" id="L63">                        throw new UnsupportedOperationException();</span>
                    }
                });
            }
<span class="fc" id="L67">        }</span>
<span class="fc" id="L68">        return null;</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>