package org.appfuse.webapp.filter; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.util.PatternMatchUtils; import org.springframework.web.util.UrlPathHelper; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.RequestDispatcher; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.Iterator; import java.util.Set; /** * A simple filter that allows the application to continue using the .html prefix for active * pages but still allows Dojo to serve up its HTML template code. The filter works on an * include/exclude basis where all requests for active pages are redirected by the filter to * the dispatch servlet. All Dojo related .html requests are allowed to pass straight through * to be processed by the servlet container as per normal. */ public class DojoFilter implements Filter { private static Log log = LogFactory.getLog(DojoFilter.class); private final static String DEFAULT_INCLUDES = "*.html"; private final static String DEFAULT_EXCLUDES = ""; public static final String INCLUDES_PARAMETER="includes"; public static final String EXCLUDES_PARAMETER="excludes"; public static final String ACTION_SERVLET_NAME_PARAMETER="action_servlet_name"; public static final String _REQUEST_PARSED = "org.appfuse.webapp.request.parsed"; private String[] excludes; private String[] includes; private String actionServletName = "action"; private RequestDispatcher actionServletRequestDispatcher; /** * Read the includes/excludes paramters and set the filter accordingly. */ public void init(FilterConfig filterConfig) { String includesParam = filterConfig.getInitParameter(INCLUDES_PARAMETER); if (StringUtils.isEmpty(includesParam)) { includes = parsePatterns(DEFAULT_INCLUDES); } else { includes = parsePatterns(includesParam); } String excludesParam = filterConfig.getInitParameter(EXCLUDES_PARAMETER); if (StringUtils.isEmpty(excludesParam)) { excludes = parsePatterns(DEFAULT_EXCLUDES); } else { excludes = parsePatterns(excludesParam); } String actionServletNameParam = filterConfig.getInitParameter(ACTION_SERVLET_NAME_PARAMETER); if (StringUtils.isNotEmpty(actionServletNameParam)) { actionServletName = actionServletNameParam; } ServletContext servletContext = filterConfig.getServletContext(); actionServletRequestDispatcher = servletContext.getNamedDispatcher(actionServletName); if (actionServletRequestDispatcher == null) { log.error("No action servlet named [" + actionServletName + "] could be found. Please check configuration in web.xml."); throw new RuntimeException("Could not instantiate dojo filter: no valid action servlet specified, or action servlet not found."); } } private String[] parsePatterns(String delimitedPatterns) { //make sure no patterns are repeated. Set patternSet = org.springframework.util.StringUtils.commaDelimitedListToSet(delimitedPatterns); String[] patterns = new String[patternSet.size()]; int i = 0; for (Iterator iterator = patternSet.iterator(); iterator.hasNext(); i++) { //no trailing/leading white space. String pattern = (String) iterator.next(); patterns[i] = pattern.trim(); } return patterns; } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { if (request.getAttribute(_REQUEST_PARSED) != null) { chain.doFilter(request, response); return; } final HttpServletRequest req = (HttpServletRequest) request; final HttpServletResponse res = (HttpServletResponse) response; UrlPathHelper urlPathHelper = new UrlPathHelper(); String path = urlPathHelper.getPathWithinApplication(req); boolean pathExcluded = PatternMatchUtils.simpleMatch(excludes, path); boolean pathIncluded = PatternMatchUtils.simpleMatch(includes, path); if (pathIncluded && ! pathExcluded) { // req.setAttribute(_REQUEST_PARSED, Boolean.TRUE); actionServletRequestDispatcher.forward(req, res); return; } chain.doFilter(req, res); } public void destroy() { actionServletRequestDispatcher = null; } }