<?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>WebIniSecurityManagerFactory.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 :: All (aggregate jar)</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.config</a> &gt; <span class="el_source">WebIniSecurityManagerFactory.java</span></div><h1>WebIniSecurityManagerFactory.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.config;

import org.apache.shiro.config.Ini;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.web.filter.mgt.DefaultFilter;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;

import javax.servlet.Filter;
import java.util.Map;

/**
 * Differs from the parent class only in the {@link #createDefaultInstance()} method, to
 * ensure a web-capable {@code SecurityManager} instance is created by default.
 *
 * @since 1.0
 * @deprecated use Shiro's {@code Environment} mechanisms instead.
 */
@Deprecated
public class WebIniSecurityManagerFactory extends IniSecurityManagerFactory {

    /**
     * Creates a new {@code WebIniSecurityManagerFactory} instance which will construct web-capable
     * {@code SecurityManager} instances.
     */
    public WebIniSecurityManagerFactory() {
<span class="fc" id="L45">        super();</span>
<span class="fc" id="L46">    }</span>

    /**
     * Creates a new {@code WebIniSecurityManagerFactory} instance which will construct web-capable
     * {@code SecurityManager} instances.  Uses the given {@link Ini} instance to construct the instance.
     *
     * @param config the Ini configuration that will be used to construct new web-capable {@code SecurityManager}
     *               instances.
     */
    public WebIniSecurityManagerFactory(Ini config) {
<span class="fc" id="L56">        super(config);</span>
<span class="fc" id="L57">    }</span>

    /**
     * Simply returns &lt;code&gt;new {@link DefaultWebSecurityManager}();&lt;/code&gt; to ensure a web-capable
     * {@code SecurityManager} is available by default.
     *
     * @return a new web-capable {@code SecurityManager} instance.
     */
    @Override
    protected SecurityManager createDefaultInstance() {
<span class="fc" id="L67">        return new DefaultWebSecurityManager();</span>
    }

    @SuppressWarnings({&quot;unchecked&quot;})
    @Override
    protected Map&lt;String, ?&gt; createDefaults(Ini ini, Ini.Section mainSection) {
<span class="fc" id="L73">        Map defaults = super.createDefaults(ini, mainSection);</span>
        //add the default filters:
<span class="fc" id="L75">        Map&lt;String, Filter&gt; defaultFilters = DefaultFilter.createInstanceMap(null);</span>
<span class="fc" id="L76">        defaults.putAll(defaultFilters);</span>
<span class="fc" id="L77">        return defaults;</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>