⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 filterchainproxy.java

📁 acegi构造安全的java系统
💻 JAVA
字号:
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed 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.acegisecurity.util;import org.acegisecurity.ConfigAttribute;import org.acegisecurity.ConfigAttributeDefinition;import org.acegisecurity.intercept.web.FilterInvocation;import org.acegisecurity.intercept.web.FilterInvocationDefinitionSource;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;import org.springframework.beans.BeansException;import org.springframework.beans.factory.InitializingBean;import org.springframework.context.ApplicationContext;import org.springframework.context.ApplicationContextAware;import org.springframework.util.Assert;import java.io.IOException;import java.util.Iterator;import java.util.LinkedHashSet;import java.util.List;import java.util.Set;import java.util.Vector;import javax.servlet.Filter;import javax.servlet.FilterChain;import javax.servlet.FilterConfig;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;/** * Delegates <code>Filter</code> requests to a list of Spring-managed beans.<p>The <code>FilterChainProxy</code> is * loaded via a standard {@link org.acegisecurity.util.FilterToBeanProxy} declaration in <code>web.xml</code>. * <code>FilterChainProxy</code> will then pass {@link #init(FilterConfig)}, {@link #destroy()} and {@link * #doFilter(ServletRequest, ServletResponse, FilterChain)} invocations through to each <code>Filter</code> defined * against <code>FilterChainProxy</code>.</p> *  <p><code>FilterChainProxy</code> is configured using a standard {@link * org.acegisecurity.intercept.web.FilterInvocationDefinitionSource}. Each possible URI pattern that * <code>FilterChainProxy</code> should service must be entered. The first matching URI pattern located by * <code>FilterInvocationDefinitionSource</code> for a given request will be used to define all of the * <code>Filter</code>s that apply to that request. NB: This means you must put most specific URI patterns at the top * of the list, and ensure all <code>Filter</code>s that should apply for a given URI pattern are entered against the * respective entry. The <code>FilterChainProxy</code> will not iterate the remainder of the URI patterns to locate * additional <code>Filter</code>s.  The <code>FilterInvocationDefinitionSource</code> described the applicable URI * pattern to fire the filter chain, followed by a list of configuration attributes. Each configuration attribute's * {@link org.acegisecurity.ConfigAttribute#getAttribute()} corresponds to a bean name that is available from the * application context.</p> *  <p><code>FilterChainProxy</code> respects normal handling of <code>Filter</code>s that elect not to call {@link * javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, * javax.servlet.FilterChain)}, in that the remainder of the origial or <code>FilterChainProxy</code>-declared filter * chain will not be called.</p> *  <p>It is particularly noted the <code>Filter</code> lifecycle mismatch between the servlet container and IoC * container. As per {@link org.acegisecurity.util.FilterToBeanProxy} JavaDocs, we recommend you allow the IoC * container to manage lifecycle instead of the servlet container. By default the <code>FilterToBeanProxy</code> will * never call this class' {@link #init(FilterConfig)} and {@link #destroy()} methods, meaning each of the filters * defined against <code>FilterInvocationDefinitionSource</code> will not be called. If you do need your filters to be * initialized and destroyed, please set the <code>lifecycle</code> initialization parameter against the * <code>FilterToBeanProxy</code> to specify servlet container lifecycle management.</p> *  <p>If a filter name of {@link #TOKEN_NONE} is used, this allows specification of a filter pattern which should * never cause any filters to fire.</p> * * @author Carlos Sanchez * @author Ben Alex * @version $Id: FilterChainProxy.java 1864 2007-05-25 02:03:12Z benalex $ */public class FilterChainProxy implements Filter, InitializingBean, ApplicationContextAware {    //~ Static fields/initializers =====================================================================================    private static final Log logger = LogFactory.getLog(FilterChainProxy.class);    public static final String TOKEN_NONE = "#NONE#";    //~ Instance fields ================================================================================================    private ApplicationContext applicationContext;    private FilterInvocationDefinitionSource filterInvocationDefinitionSource;    //~ Methods ========================================================================================================    public void afterPropertiesSet() throws Exception {        Assert.notNull(filterInvocationDefinitionSource, "filterInvocationDefinitionSource must be specified");        Assert.notNull(this.filterInvocationDefinitionSource.getConfigAttributeDefinitions(),            "FilterChainProxy requires the FilterInvocationDefinitionSource to return a non-null response to "                    + "getConfigAttributeDefinitions()");    }    public void destroy() {        Filter[] filters = obtainAllDefinedFilters();        for (int i = 0; i < filters.length; i++) {            if (filters[i] != null) {                if (logger.isDebugEnabled()) {                    logger.debug("Destroying Filter defined in ApplicationContext: '" + filters[i].toString() + "'");                }                filters[i].destroy();            }        }    }    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)        throws IOException, ServletException {        FilterInvocation fi = new FilterInvocation(request, response, chain);        ConfigAttributeDefinition cad = this.filterInvocationDefinitionSource.getAttributes(fi);        if (cad == null) {            if (logger.isDebugEnabled()) {                logger.debug(fi.getRequestUrl() + " has no matching filters");            }            chain.doFilter(request, response);            return;        }        Filter[] filters = obtainAllDefinedFilters(cad);        if (filters.length == 0) {            if (logger.isDebugEnabled()) {                logger.debug(fi.getRequestUrl() + " has an empty filter list");            }            chain.doFilter(request, response);            return;        }        VirtualFilterChain virtualFilterChain = new VirtualFilterChain(fi, filters);        virtualFilterChain.doFilter(fi.getRequest(), fi.getResponse());    }    public FilterInvocationDefinitionSource getFilterInvocationDefinitionSource() {        return filterInvocationDefinitionSource;    }    public void init(FilterConfig filterConfig) throws ServletException {        Filter[] filters = obtainAllDefinedFilters();        for (int i = 0; i < filters.length; i++) {            if (filters[i] != null) {                if (logger.isDebugEnabled()) {                    logger.debug("Initializing Filter defined in ApplicationContext: '" + filters[i].toString() + "'");                }                filters[i].init(filterConfig);            }        }    }    /**     * Obtains all of the <b>unique</b><code>Filter</code> instances registered against the     * <code>FilterInvocationDefinitionSource</code>.<p>This is useful in ensuring a <code>Filter</code> is not     * initialized or destroyed twice.</p>     *     * @return all of the <code>Filter</code> instances in the application context for which there has been an entry     *         against the <code>FilterInvocationDefinitionSource</code> (only one entry is included in the array for     *         each <code>Filter</code> that actually exists in application context, even if a given     *         <code>Filter</code> is defined multiples times by the <code>FilterInvocationDefinitionSource</code>)     */    protected Filter[] obtainAllDefinedFilters() {        Iterator cads = this.filterInvocationDefinitionSource.getConfigAttributeDefinitions();        Set list = new LinkedHashSet();        while (cads.hasNext()) {            ConfigAttributeDefinition attribDef = (ConfigAttributeDefinition) cads.next();            Filter[] filters = obtainAllDefinedFilters(attribDef);            for (int i = 0; i < filters.length; i++) {                list.add(filters[i]);            }        }        return (Filter[]) list.toArray(new Filter[0]);    }    /**     * Obtains all of the <code>Filter</code> instances registered against the specified     * <code>ConfigAttributeDefinition</code>.     *     * @param configAttributeDefinition for which we want to obtain associated <code>Filter</code>s     *     * @return the <code>Filter</code>s against the specified <code>ConfigAttributeDefinition</code> (never     *         <code>null</code>)     *     * @throws IllegalArgumentException DOCUMENT ME!     */    private Filter[] obtainAllDefinedFilters(ConfigAttributeDefinition configAttributeDefinition) {        List list = new Vector();        Iterator attributes = configAttributeDefinition.getConfigAttributes();        while (attributes.hasNext()) {            ConfigAttribute attr = (ConfigAttribute) attributes.next();            String filterName = attr.getAttribute();            if (filterName == null) {                throw new IllegalArgumentException("Configuration attribute: '" + attr                    + "' returned null to the getAttribute() method, which is invalid when used with FilterChainProxy");            }            if (!filterName.equals(TOKEN_NONE)) {                list.add(this.applicationContext.getBean(filterName, Filter.class));            }        }        return (Filter[]) list.toArray(new Filter[list.size()]);    }    public void setApplicationContext(ApplicationContext applicationContext)        throws BeansException {        this.applicationContext = applicationContext;    }    public void setFilterInvocationDefinitionSource(FilterInvocationDefinitionSource filterInvocationDefinitionSource) {        this.filterInvocationDefinitionSource = filterInvocationDefinitionSource;    }    //~ Inner Classes ==================================================================================================    /**     * A <code>FilterChain</code> that records whether or not {@link     * FilterChain#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse)} is called.<p>This     * <code>FilterChain</code> is used by <code>FilterChainProxy</code> to determine if the next <code>Filter</code>     * should be called or not.</p>     */    private class VirtualFilterChain implements FilterChain {        private FilterInvocation fi;        private Filter[] additionalFilters;        private int currentPosition = 0;        public VirtualFilterChain(FilterInvocation filterInvocation, Filter[] additionalFilters) {            this.fi = filterInvocation;            this.additionalFilters = additionalFilters;        }        private VirtualFilterChain() {}        public void doFilter(ServletRequest request, ServletResponse response)            throws IOException, ServletException {            if (currentPosition == additionalFilters.length) {                if (logger.isDebugEnabled()) {                    logger.debug(fi.getRequestUrl()                        + " reached end of additional filter chain; proceeding with original chain");                }                fi.getChain().doFilter(request, response);            } else {                currentPosition++;                if (logger.isDebugEnabled()) {                    logger.debug(fi.getRequestUrl() + " at position " + currentPosition + " of "                        + additionalFilters.length + " in additional filter chain; firing Filter: '"                        + additionalFilters[currentPosition - 1] + "'");                }                additionalFilters[currentPosition - 1].doFilter(request, response, this);            }        }    }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -