package org.stagemonitor.web.monitor.filter; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Adds support for excluding specific url prefixes of a filter-mapping. * <p/> * Example: * <pre> * <filter> * <filter-name>theFilter</filter-name> * <filter-class>some filter exdending {@link AbstractExclusionFilter}</filter-class> * <init-param> * <param-name>exclude</param-name> * <param-value>rest, /picture/</param-value> * </init-param> * </filter> * </pre> * <p/> * In this example, the filter won't be executed for all URIs starting with /rest or /picture * <p/> * In other words, the following will be checked for each exclude prefix: {@code httpServletRequest.getRequestURI().startsWith(excludedPath)} * * @author fbarnsteiner */ public abstract class AbstractExclusionFilter implements Filter { private Collection<String> excludedPaths; protected AbstractExclusionFilter() { } protected AbstractExclusionFilter(Collection<String> excludedPaths) { setExcludedPaths(excludedPaths); } @Override public final void init(FilterConfig filterConfig) throws ServletException { String excludeParam = filterConfig.getInitParameter("exclude"); if (excludeParam != null && !excludeParam.isEmpty()) { setExcludedPaths(Arrays.asList(excludeParam.split(","))); } initInternal(filterConfig); } /** * Can be used by subclasses to do their initialisation * * @see Filter#init(javax.servlet.FilterConfig) */ public void initInternal(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { if (servletRequest instanceof HttpServletRequest && servletResponse instanceof HttpServletResponse) { HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest; if (isExcluded(httpServletRequest)) { // Don't execute Filter when request matches exclusion pattern filterChain.doFilter(servletRequest, servletResponse); } else { doFilterInternal(httpServletRequest, (HttpServletResponse) servletResponse, filterChain); } } else { filterChain.doFilter(servletRequest, servletResponse); } } private boolean isExcluded(HttpServletRequest request) { if (excludedPaths == null) { return false; } for (String excludedPath : excludedPaths) { if (request.getRequestURI().substring(request.getContextPath().length()).startsWith(excludedPath)) { return true; } } return false; } @Override public void destroy() { } public abstract void doFilterInternal(HttpServletRequest servletRequest, HttpServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException; private void setExcludedPaths(Collection<String> excludedPaths) { this.excludedPaths = new ArrayList<String>(excludedPaths.size()); for (String exclude : excludedPaths) { exclude = exclude.trim(); if (exclude != null && !exclude.isEmpty()) { if (!exclude.startsWith("/")) { exclude = "/" + exclude; } this.excludedPaths.add(exclude); } } } }