001    /*
002    Copyright (c) 1996-2012, Damon Hart-Davis
003    All rights reserved.
004    
005    Redistribution and use in source and binary forms, with or without
006    modification, are permitted provided that the following conditions are
007    met:
008    
009      * Redistributions of source code must retain the above copyright
010        notice, this list of conditions and the following disclaimer.
011    
012      * Redistributions in binary form must reproduce the above copyright
013        notice, this list of conditions and the following disclaimer in the
014        documentation and/or other materials provided with the
015        distribution.
016    
017    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
018    IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
019    TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
020    PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
021    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
022    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
023    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
024    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
025    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
026    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
027    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
028    */
029    package org.hd.d.pg2k.webSvr.util;
030    
031    import java.io.IOException;
032    
033    import javax.servlet.Filter;
034    import javax.servlet.FilterChain;
035    import javax.servlet.FilterConfig;
036    import javax.servlet.ServletException;
037    import javax.servlet.ServletRequest;
038    import javax.servlet.ServletResponse;
039    
040    /**Filter to dynamically load and wrap a pluggable filter.
041     * This enables filters to be loaded entirely at runtime.
042     * <p>
043     * The param pluginClassName is used to give the class name of a
044     * Filter class to load and pass filter calls on to.
045     * If this class cannot be found or loaded, or is not specified,
046     * this PluginFilter performs no transformations at all.
047     */
048    public final class PluginFilter implements Filter
049        {
050        /**The filter configuration object we are associated with.
051         * If this value is null, this filter instance is not currently configured.
052         */
053        private FilterConfig config;
054    
055        /**Config parameter; name of flag to record overload, or null if none chosen. */
056        private String pluginClassName;
057    
058        /**Our plug-in class; or null if none loaded. */
059        private Filter plugin;
060    
061    
062        /**Place this filter into service.
063         * @param filterConfig  the filter configuration object
064         */
065        public void init(final FilterConfig filterConfig)
066            {
067            config = filterConfig;
068    
069            pluginClassName = null;
070            if(plugin != null) { plugin.destroy(); plugin = null; }
071    
072            if(filterConfig != null)
073                {
074                pluginClassName = filterConfig.getInitParameter("pluginClassName");
075                if(pluginClassName != null)
076                    {
077                    try {
078                        plugin = (Filter) (Class.forName(pluginClassName).newInstance());
079                        // Successful!  Initialise the plugin.
080                        plugin.init(filterConfig);
081                        }
082                    catch(final ClassNotFoundException e)
083                        {
084                        plugin = null;
085                        filterConfig.getServletContext().log("could not find plugin for class " + pluginClassName);
086                        }
087                    catch(final Exception e)
088                        {
089                        plugin = null;
090                        filterConfig.getServletContext().log("could not init plugin for class " + pluginClassName, e);
091                        }
092                    }
093                }
094            }
095    
096        /**Take this filter out of service. */
097        public void destroy()
098            {
099            if(plugin != null)
100                {
101                plugin.destroy();
102                plugin = null;
103                }
104    
105            // Help GC.
106            config = null;
107            }
108    
109        /**Called to handle each request. */
110        public void doFilter(final ServletRequest request,
111                             final ServletResponse response,
112                             final FilterChain chain)
113            throws IOException, ServletException
114            {
115            if(plugin == null)
116                {
117                // Pass-though because no plugin.
118                chain.doFilter(request, response);
119                return;
120                }
121    
122            // Hand the request to the plugin to process!
123            plugin.doFilter(request, response, chain);
124            }
125        }
126