My friend Google said there were a number of others who wanted to do the same thing but they were being pointed to servlet 3.0. Unfortunately, servlet 3.0 and J2EE 6 were not an option for me, so it was looking like a tough nut to crack.
Then it struck me, what if I created a generic, conditional servlet filter that took the name of the class of the real filter as an init param? And, what if I passed in the condition that was to be evaluated to determine whether or not to create and/or invoke the real filter? Then, in the conditional filter, I could examine the condition and, as necessary, dynamically create an instance of the wrapped filter class.
Turns out it worked like a charm. Here's how. First the filter definition in web.xml:
CAS Authentication Filter my.org.security.servlet.ConditionalFilter condition cas/enabled wrapped-class org.jasig.cas.client.authentication.AuthenticationFilter
public class ConditionalFilter implements Filter { // instance of the actual filter being wrapped private Filter _wrappedFilter; // are we to ignore the wrapped filter? private boolean _ignore = true; public ConditionalFilter() { } // constructor public void init(FilterConfig filterConfig) throws ServletException { // the 'condition' init param tells us whether or not // the wrapped filter is active _ignore = !checkCondition(filterConfig.getInitParameter("condition")); try { if (!_ignore) { // the wrapped filter is active so we create an instance // of it and initialize it _wrappedFilter = getFilterInstance( filterConfig.getInitParameter("wrapped-class") ); _wrappedFilter.init(filterConfig); } } catch (Exception e) { throw new ServletException(e); } } // init() public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException { if (!_ignore) { // the wrapped filter is active so we let it do its work _wrappedFilter.doFilter(request, response, filterChain); } else { // wrapped filter is inactive so simply move on to the next filter filterChain.doFilter(request, response); } } // doFilter() public void destroy() { if (_ignore) { _wrappedFilter.destroy(); } } // destroy() private Filter getFilterInstance(String className) throws ClassNotFoundException, InvalidClassException, InvocationTargetException, IllegalAccessException, InstantiationException, NoSuchMethodException { // try to create an instance of the wrapped filter // with the given class name Class filterClass = Class.forName(className); java.lang.reflect.Constructor constructor = filterClass.getConstructor(); Object filter = constructor.newInstance(); if (!(filter instanceof Filter)) { throw new InvalidClassException( String.format("'%s' is not an instance of Filter", className) ); } return (Filter)filter; } // getFilterInstance() /* * looks up the configured 'condition' via JNDI to determine * whether or not the wrapped filter is active */ private boolean checkCondition(String condition) { boolean result = false; try { InitialContext context = new InitialContext(); String path = String.format("java:comp/env/%s", condition); result =(Boolean)context.lookup(path); } catch (final NamingException e) { System.out.println( "unable to load condition from JNDI" ); } return result; } // checkCondition() } // class ConditionalFilter
No comments:
Post a Comment