package org.jboss.seam.web;
import java.util.regex.Pattern;
import javax.servlet.Filter;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
/**
* Abstract superclass for Seam components that act as servlet filters. Note
* that since a filter is potentially called outside of a set of Seam contexts,
* it is not a true Seam component.
*
* However, we are able to reuse the functionality for component scanning,
* installation and configuration for filters. All filters must specify
* the @Filter annotation to be included by Seam's master filter.
*
* @see org.jboss.seam.annotations.web.Filter
* @author Shane Bryzak
*
*/
public abstract class AbstractFilter implements Filter
{
private ServletContext servletContext;
private String urlPattern;
private String excludeUrlPattern;
private String regexUrlPattern;
private Pattern pattern;
private boolean disabled;
public void init(FilterConfig filterConfig) throws ServletException
{
servletContext = filterConfig.getServletContext();
}
protected ServletContext getServletContext()
{
return servletContext;
}
public String getUrlPattern()
{
return urlPattern;
}
public void setUrlPattern(String urlPattern)
{
this.urlPattern = urlPattern;
}
public String getRegexUrlPattern()
{
return this.regexUrlPattern;
}
public String getExcludeUrlPattern()
{
return excludeUrlPattern;
}
public void setExcludeUrlPattern(String excludeUrlPattern)
{
this.excludeUrlPattern = excludeUrlPattern;
}
public void setRegexUrlPattern(String regexUrlPattern)
{
this.regexUrlPattern = regexUrlPattern;
pattern = null;
}
private Pattern getPattern()
{
if (pattern == null && getRegexUrlPattern() != null)
{
pattern = Pattern.compile(getRegexUrlPattern());
}
return pattern;
}
public boolean isDisabled()
{
return disabled;
}
public void setDisabled(boolean disabled)
{
this.disabled = disabled;
}
/**
* Pattern matching code, adapted from Tomcat. This method checks to see if
* the specified path matches the specified pattern.
*
* @param request ServletRequest The request containing the path
* @return boolean True if the path matches the pattern, false otherwise
*/
public boolean isMappedToCurrentRequestPath(ServletRequest request)
{
if (!(request instanceof HttpServletRequest))
{
return true;
}
HttpServletRequest httpRequest = (HttpServletRequest)request;
String path = httpRequest.getRequestURI().replaceFirst(httpRequest.getContextPath(), "");
String urlPattern = getUrlPattern();
String excludeUrlPattern = getExcludeUrlPattern();
Pattern regexPattern = getPattern();
if (urlPattern != null)
{
if(excludeUrlPattern!=null)
return (matchesTomcatPattern(path, urlPattern) && !matchesTomcatPattern(path, excludeUrlPattern));
return matchesTomcatPattern(path, urlPattern);
}
else if (regexPattern != null)
{
return matchesRegexPattern(path, regexPattern);
}
else
{
return true;
}
}
private static boolean matchesRegexPattern(String path, Pattern pattern)
{
return pattern.matcher(path).matches();
}
private static boolean matchesTomcatPattern(String path, String pattern)
{
if (pattern==null) return true;
if (path == null || "".equals(path)) path = "/";
if (pattern == null || "".equals(pattern)) pattern = "/";
// Check for an exact match
if (path.equals(pattern)) return true;
// Check for path prefix matching
if (pattern.startsWith("/") && pattern.endsWith("/*"))
{
pattern = pattern.substring(0, pattern.length() - 2);
if (pattern.length() == 0) return true;
if (path.endsWith("/")) path = path.substring(0, path.length() - 1);
while (true)
{
if (pattern.equals(path)) return true;
int slash = path.lastIndexOf('/');
if (slash <= 0) break;
path = path.substring(0, slash);
}
return false;
}
// Check for suffix matching
if (pattern.startsWith("*."))
{
int para=path.indexOf('?');
if(para>0)
path = path.substring(0, para);
para=path.indexOf(';');
if(para>0)
path = path.substring(0, para);
int slash = path.lastIndexOf('/');
int period = path.lastIndexOf('.');
if ((slash >= 0) && (period > slash) && path.endsWith(pattern.substring(1)))
{
return true;
}
return false;
}
// Check for universal mapping
if (pattern.equals("/")) return true;
return false;
}
public void destroy() {}
}