001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one
003     * or more contributor license agreements.  See the NOTICE file
004     * distributed with this work for additional information
005     * regarding copyright ownership.  The ASF licenses this file
006     * to you under the Apache License, Version 2.0 (the
007     * "License"); you may not use this file except in compliance
008     * with the License.  You may obtain a copy of the License at
009     *
010     *     http://www.apache.org/licenses/LICENSE-2.0
011     *
012     * Unless required by applicable law or agreed to in writing,
013     * software distributed under the License is distributed on an
014     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015     * KIND, either express or implied.  See the License for the
016     * specific language governing permissions and limitations
017     * under the License.
018     */
019    package org.apache.shiro.web.servlet;
020    
021    import org.apache.shiro.util.StringUtils;
022    import org.slf4j.Logger;
023    import org.slf4j.LoggerFactory;
024    
025    import javax.servlet.Filter;
026    import javax.servlet.FilterConfig;
027    import javax.servlet.ServletException;
028    
029    /**
030     * Base abstract Filter simplifying Filter initialization and {@link #getInitParam(String) access} to init parameters.
031     * Subclass initialization logic should be performed by overriding the {@link #onFilterConfigSet()} template method.
032     * FilterChain execution logic (the
033     * {@link #doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)} method
034     * is left to subclasses.
035     *
036     * @since 1.0
037     */
038    public abstract class AbstractFilter extends ServletContextSupport implements Filter {
039    
040        private static transient final Logger log = LoggerFactory.getLogger(AbstractFilter.class);
041    
042        /**
043         * FilterConfig provided by the Servlet container at start-up.
044         */
045        protected FilterConfig filterConfig;
046    
047        /**
048         * Returns the servlet container specified {@code FilterConfig} instance provided at
049         * {@link #init(javax.servlet.FilterConfig) startup}.
050         *
051         * @return the servlet container specified {@code FilterConfig} instance provided at start-up.
052         */
053        public FilterConfig getFilterConfig() {
054            return filterConfig;
055        }
056    
057        /**
058         * Sets the FilterConfig <em>and</em> the {@code ServletContext} as attributes of this class for use by
059         * subclasses.  That is:
060         * <pre>
061         * this.filterConfig = filterConfig;
062         * setServletContext(filterConfig.getServletContext());</pre>
063         *
064         * @param filterConfig the FilterConfig instance provided by the Servlet container at start-up.
065         */
066        public void setFilterConfig(FilterConfig filterConfig) {
067            this.filterConfig = filterConfig;
068            setServletContext(filterConfig.getServletContext());
069        }
070    
071        /**
072         * Returns the value for the named {@code init-param}, or {@code null} if there was no {@code init-param}
073         * specified by that name.
074         *
075         * @param paramName the name of the {@code init-param}
076         * @return the value for the named {@code init-param}, or {@code null} if there was no {@code init-param}
077         *         specified by that name.
078         */
079        protected String getInitParam(String paramName) {
080            FilterConfig config = getFilterConfig();
081            if (config != null) {
082                return StringUtils.clean(config.getInitParameter(paramName));
083            }
084            return null;
085        }
086    
087        /**
088         * Sets the filter's {@link #setFilterConfig filterConfig} and then immediately calls
089         * {@link #onFilterConfigSet() onFilterConfigSet()} to trigger any processing a subclass might wish to perform.
090         *
091         * @param filterConfig the servlet container supplied FilterConfig instance.
092         * @throws javax.servlet.ServletException if {@link #onFilterConfigSet() onFilterConfigSet()} throws an Exception.
093         */
094        public final void init(FilterConfig filterConfig) throws ServletException {
095            setFilterConfig(filterConfig);
096            try {
097                onFilterConfigSet();
098            } catch (Exception e) {
099                if (e instanceof ServletException) {
100                    throw (ServletException) e;
101                } else {
102                    if (log.isErrorEnabled()) {
103                        log.error("Unable to start Filter: [" + e.getMessage() + "].", e);
104                    }
105                    throw new ServletException(e);
106                }
107            }
108        }
109    
110        /**
111         * Template method to be overridden by subclasses to perform initialization logic at start-up.  The
112         * {@code ServletContext} and {@code FilterConfig} will be accessible
113         * (and non-{@code null}) at the time this method is invoked via the
114         * {@link #getServletContext() getServletContext()} and {@link #getFilterConfig() getFilterConfig()}
115         * methods respectively.
116         * <p/>
117         * {@code init-param} values may be conveniently obtained via the {@link #getInitParam(String)} method.
118         *
119         * @throws Exception if the subclass has an error upon initialization.
120         */
121        protected void onFilterConfigSet() throws Exception {
122        }
123    
124        /**
125         * Default no-op implementation that can be overridden by subclasses for custom cleanup behavior.
126         */
127        public void destroy() {
128        }
129    
130    
131    }