| <?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>IniWebEnvironment.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> > <a href="../index.html" class="el_bundle">shiro-web</a> > <a href="index.source.html" class="el_package">org.apache.shiro.web.env</a> > <span class="el_source">IniWebEnvironment.java</span></div><h1>IniWebEnvironment.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 |
| * "License"); 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 |
| * "AS IS" 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.env; |
| |
| import org.apache.shiro.config.ConfigurationException; |
| import org.apache.shiro.config.Ini; |
| import org.apache.shiro.config.IniFactorySupport; |
| import org.apache.shiro.io.ResourceUtils; |
| import org.apache.shiro.util.CollectionUtils; |
| import org.apache.shiro.util.Destroyable; |
| import org.apache.shiro.util.Initializable; |
| import org.apache.shiro.util.StringUtils; |
| import org.apache.shiro.web.config.IniFilterChainResolverFactory; |
| import org.apache.shiro.web.config.WebIniSecurityManagerFactory; |
| import org.apache.shiro.web.filter.mgt.FilterChainResolver; |
| import org.apache.shiro.web.mgt.WebSecurityManager; |
| import org.apache.shiro.web.util.WebUtils; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| import javax.servlet.ServletContext; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.util.Map; |
| |
| /** |
| * {@link WebEnvironment} implementation configured by an {@link Ini} instance or {@code Ini} resource locations. |
| * |
| * @since 1.2 |
| */ |
| <span class="fc" id="L47">public class IniWebEnvironment extends ResourceBasedWebEnvironment implements Initializable, Destroyable {</span> |
| |
| public static final String DEFAULT_WEB_INI_RESOURCE_PATH = "/WEB-INF/shiro.ini"; |
| |
| <span class="fc" id="L51"> private static final Logger log = LoggerFactory.getLogger(IniWebEnvironment.class);</span> |
| |
| /** |
| * The Ini that configures this WebEnvironment instance. |
| */ |
| private Ini ini; |
| |
| /** |
| * Initializes this instance by resolving any potential (explicit or resource-configured) {@link Ini} |
| * configuration and calling {@link #configure() configure} for actual instance configuration. |
| */ |
| public void init() { |
| <span class="fc" id="L63"> Ini ini = getIni();</span> |
| |
| <span class="fc" id="L65"> String[] configLocations = getConfigLocations();</span> |
| |
| <span class="pc bpc" id="L67" title="5 of 8 branches missed."> if (log.isWarnEnabled() && !CollectionUtils.isEmpty(ini) &&</span> |
| configLocations != null && configLocations.length > 0) { |
| <span class="nc" id="L69"> log.warn("Explicit INI instance has been provided, but configuration locations have also been " +</span> |
| "specified. The {} implementation does not currently support multiple Ini config, but this may " + |
| "be supported in the future. Only the INI instance will be used for configuration.", |
| <span class="nc" id="L72"> IniWebEnvironment.class.getName());</span> |
| } |
| |
| <span class="pc bpc" id="L75" title="1 of 2 branches missed."> if (CollectionUtils.isEmpty(ini)) {</span> |
| <span class="nc" id="L76"> log.debug("Checking any specified config locations.");</span> |
| <span class="nc" id="L77"> ini = getSpecifiedIni(configLocations);</span> |
| } |
| |
| <span class="pc bpc" id="L80" title="1 of 2 branches missed."> if (CollectionUtils.isEmpty(ini)) {</span> |
| <span class="nc" id="L81"> log.debug("No INI instance or config locations specified. Trying default config locations.");</span> |
| <span class="nc" id="L82"> ini = getDefaultIni();</span> |
| } |
| |
| <span class="pc bpc" id="L85" title="1 of 2 branches missed."> if (CollectionUtils.isEmpty(ini)) {</span> |
| <span class="nc" id="L86"> String msg = "Shiro INI configuration was either not found or discovered to be empty/unconfigured.";</span> |
| <span class="nc" id="L87"> throw new ConfigurationException(msg);</span> |
| } |
| |
| <span class="fc" id="L90"> setIni(ini);</span> |
| |
| <span class="fc" id="L92"> configure();</span> |
| <span class="fc" id="L93"> }</span> |
| |
| protected void configure() { |
| |
| <span class="fc" id="L97"> this.objects.clear();</span> |
| |
| <span class="fc" id="L99"> WebSecurityManager securityManager = createWebSecurityManager();</span> |
| <span class="fc" id="L100"> setWebSecurityManager(securityManager);</span> |
| |
| <span class="fc" id="L102"> FilterChainResolver resolver = createFilterChainResolver();</span> |
| <span class="pc bpc" id="L103" title="1 of 2 branches missed."> if (resolver != null) {</span> |
| <span class="nc" id="L104"> setFilterChainResolver(resolver);</span> |
| } |
| <span class="fc" id="L106"> }</span> |
| |
| protected Ini getSpecifiedIni(String[] configLocations) throws ConfigurationException { |
| |
| <span class="nc" id="L110"> Ini ini = null;</span> |
| |
| <span class="nc bnc" id="L112" title="All 4 branches missed."> if (configLocations != null && configLocations.length > 0) {</span> |
| |
| <span class="nc bnc" id="L114" title="All 2 branches missed."> if (configLocations.length > 1) {</span> |
| <span class="nc" id="L115"> log.warn("More than one Shiro .ini config location has been specified. Only the first will be " +</span> |
| "used for configuration as the {} implementation does not currently support multiple " + |
| <span class="nc" id="L117"> "files. This may be supported in the future however.", IniWebEnvironment.class.getName());</span> |
| } |
| |
| //required, as it is user specified: |
| <span class="nc" id="L121"> ini = createIni(configLocations[0], true);</span> |
| } |
| |
| <span class="nc" id="L124"> return ini;</span> |
| } |
| |
| protected Ini getDefaultIni() { |
| |
| <span class="nc" id="L129"> Ini ini = null;</span> |
| |
| <span class="nc" id="L131"> String[] configLocations = getDefaultConfigLocations();</span> |
| <span class="nc bnc" id="L132" title="All 2 branches missed."> if (configLocations != null) {</span> |
| <span class="nc bnc" id="L133" title="All 2 branches missed."> for (String location : configLocations) {</span> |
| <span class="nc" id="L134"> ini = createIni(location, false);</span> |
| <span class="nc bnc" id="L135" title="All 2 branches missed."> if (!CollectionUtils.isEmpty(ini)) {</span> |
| <span class="nc" id="L136"> log.debug("Discovered non-empty INI configuration at location '{}'. Using for configuration.",</span> |
| location); |
| <span class="nc" id="L138"> break;</span> |
| } |
| } |
| } |
| |
| <span class="nc" id="L143"> return ini;</span> |
| } |
| |
| /** |
| * Creates an {@link Ini} instance reflecting the specified path, or {@code null} if the path does not exist and |
| * is not required. |
| * <p/> |
| * If the path is required and does not exist or is empty, a {@link ConfigurationException} will be thrown. |
| * |
| * @param configLocation the resource path to load into an {@code Ini} instance. |
| * @param required if the path must exist and be converted to a non-empty {@link Ini} instance. |
| * @return an {@link Ini} instance reflecting the specified path, or {@code null} if the path does not exist and |
| * is not required. |
| * @throws ConfigurationException if the path is required but results in a null or empty Ini instance. |
| */ |
| protected Ini createIni(String configLocation, boolean required) throws ConfigurationException { |
| |
| <span class="nc" id="L160"> Ini ini = null;</span> |
| |
| <span class="nc bnc" id="L162" title="All 2 branches missed."> if (configLocation != null) {</span> |
| <span class="nc" id="L163"> ini = convertPathToIni(configLocation, required);</span> |
| } |
| <span class="nc bnc" id="L165" title="All 4 branches missed."> if (required && CollectionUtils.isEmpty(ini)) {</span> |
| <span class="nc" id="L166"> String msg = "Required configuration location '" + configLocation + "' does not exist or did not " +</span> |
| "contain any INI configuration."; |
| <span class="nc" id="L168"> throw new ConfigurationException(msg);</span> |
| } |
| |
| <span class="nc" id="L171"> return ini;</span> |
| } |
| |
| protected FilterChainResolver createFilterChainResolver() { |
| |
| <span class="fc" id="L176"> FilterChainResolver resolver = null;</span> |
| |
| <span class="fc" id="L178"> Ini ini = getIni();</span> |
| |
| <span class="pc bpc" id="L180" title="1 of 2 branches missed."> if (!CollectionUtils.isEmpty(ini)) {</span> |
| //only create a resolver if the 'filters' or 'urls' sections are defined: |
| <span class="fc" id="L182"> Ini.Section urls = ini.getSection(IniFilterChainResolverFactory.URLS);</span> |
| <span class="fc" id="L183"> Ini.Section filters = ini.getSection(IniFilterChainResolverFactory.FILTERS);</span> |
| <span class="pc bpc" id="L184" title="2 of 4 branches missed."> if (!CollectionUtils.isEmpty(urls) || !CollectionUtils.isEmpty(filters)) {</span> |
| //either the urls section or the filters section was defined. Go ahead and create the resolver: |
| <span class="nc" id="L186"> IniFilterChainResolverFactory factory = new IniFilterChainResolverFactory(ini, this.objects);</span> |
| <span class="nc" id="L187"> resolver = factory.getInstance();</span> |
| } |
| } |
| |
| <span class="fc" id="L191"> return resolver;</span> |
| } |
| |
| protected WebSecurityManager createWebSecurityManager() { |
| WebIniSecurityManagerFactory factory; |
| <span class="fc" id="L196"> Ini ini = getIni();</span> |
| <span class="pc bpc" id="L197" title="1 of 2 branches missed."> if (CollectionUtils.isEmpty(ini)) {</span> |
| <span class="nc" id="L198"> factory = new WebIniSecurityManagerFactory();</span> |
| } else { |
| <span class="fc" id="L200"> factory = new WebIniSecurityManagerFactory(ini);</span> |
| } |
| |
| <span class="fc" id="L203"> WebSecurityManager wsm = (WebSecurityManager)factory.getInstance();</span> |
| |
| //SHIRO-306 - get beans after they've been created (the call was before the factory.getInstance() call, |
| //which always returned null. |
| <span class="fc" id="L207"> Map<String, ?> beans = factory.getBeans();</span> |
| <span class="pc bpc" id="L208" title="1 of 2 branches missed."> if (!CollectionUtils.isEmpty(beans)) {</span> |
| <span class="fc" id="L209"> this.objects.putAll(beans);</span> |
| } |
| |
| <span class="fc" id="L212"> return wsm;</span> |
| } |
| |
| /** |
| * Returns an array with two elements, {@code /WEB-INF/shiro.ini} and {@code classpath:shiro.ini}. |
| * |
| * @return an array with two elements, {@code /WEB-INF/shiro.ini} and {@code classpath:shiro.ini}. |
| */ |
| protected String[] getDefaultConfigLocations() { |
| <span class="nc" id="L221"> return new String[]{</span> |
| DEFAULT_WEB_INI_RESOURCE_PATH, |
| IniFactorySupport.DEFAULT_INI_RESOURCE_PATH |
| }; |
| } |
| |
| /** |
| * Converts the specified file path to an {@link Ini} instance. |
| * <p/> |
| * If the path does not have a resource prefix as defined by {@link org.apache.shiro.io.ResourceUtils#hasResourcePrefix(String)}, the |
| * path is expected to be resolvable by the {@code ServletContext} via |
| * {@link javax.servlet.ServletContext#getResourceAsStream(String)}. |
| * |
| * @param path the path of the INI resource to load into an INI instance. |
| * @param required if the specified path must exist |
| * @return an INI instance populated based on the given INI resource path. |
| */ |
| private Ini convertPathToIni(String path, boolean required) { |
| |
| //TODO - this logic is ugly - it'd be ideal if we had a Resource API to polymorphically encaspulate this behavior |
| |
| <span class="nc" id="L242"> Ini ini = null;</span> |
| |
| <span class="nc bnc" id="L244" title="All 2 branches missed."> if (StringUtils.hasText(path)) {</span> |
| <span class="nc" id="L245"> InputStream is = null;</span> |
| |
| //SHIRO-178: Check for servlet context resource and not only resource paths: |
| <span class="nc bnc" id="L248" title="All 2 branches missed."> if (!ResourceUtils.hasResourcePrefix(path)) {</span> |
| <span class="nc" id="L249"> is = getServletContextResourceStream(path);</span> |
| } else { |
| try { |
| <span class="nc" id="L252"> is = ResourceUtils.getInputStreamForPath(path);</span> |
| <span class="nc" id="L253"> } catch (IOException e) {</span> |
| <span class="nc bnc" id="L254" title="All 2 branches missed."> if (required) {</span> |
| <span class="nc" id="L255"> throw new ConfigurationException(e);</span> |
| } else { |
| <span class="nc bnc" id="L257" title="All 2 branches missed."> if (log.isDebugEnabled()) {</span> |
| <span class="nc" id="L258"> log.debug("Unable to load optional path '" + path + "'.", e);</span> |
| } |
| } |
| <span class="nc" id="L261"> }</span> |
| } |
| <span class="nc bnc" id="L263" title="All 2 branches missed."> if (is != null) {</span> |
| <span class="nc" id="L264"> ini = new Ini();</span> |
| <span class="nc" id="L265"> ini.load(is);</span> |
| } else { |
| <span class="nc bnc" id="L267" title="All 2 branches missed."> if (required) {</span> |
| <span class="nc" id="L268"> throw new ConfigurationException("Unable to load resource path '" + path + "'");</span> |
| } |
| } |
| } |
| |
| <span class="nc" id="L273"> return ini;</span> |
| } |
| |
| //TODO - this logic is ugly - it'd be ideal if we had a Resource API to polymorphically encaspulate this behavior |
| private InputStream getServletContextResourceStream(String path) { |
| <span class="nc" id="L278"> InputStream is = null;</span> |
| |
| <span class="nc" id="L280"> path = WebUtils.normalize(path);</span> |
| <span class="nc" id="L281"> ServletContext sc = getServletContext();</span> |
| <span class="nc bnc" id="L282" title="All 2 branches missed."> if (sc != null) {</span> |
| <span class="nc" id="L283"> is = sc.getResourceAsStream(path);</span> |
| } |
| |
| <span class="nc" id="L286"> return is;</span> |
| } |
| |
| /** |
| * Returns the {@code Ini} instance reflecting this WebEnvironment's configuration. |
| * |
| * @return the {@code Ini} instance reflecting this WebEnvironment's configuration. |
| */ |
| public Ini getIni() { |
| <span class="fc" id="L295"> return this.ini;</span> |
| } |
| |
| /** |
| * Allows for configuration via a direct {@link Ini} instance instead of via |
| * {@link #getConfigLocations() config locations}. |
| * <p/> |
| * If the specified instance is null or empty, the fallback/default resource-based configuration will be used. |
| * |
| * @param ini the ini instance to use for creation. |
| */ |
| public void setIni(Ini ini) { |
| <span class="fc" id="L307"> this.ini = ini;</span> |
| <span class="fc" id="L308"> }</span> |
| } |
| </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> |