From b79d3827a2aa635a84f432c95d5c874b97ae4ee4 Mon Sep 17 00:00:00 2001 From: markt Date: Mon, 7 Dec 2009 16:43:25 +0000 Subject: [PATCH] Add support for WebFilter Remove wrappers to implement isAsyncSupported() having found the setAttribute() code It is individual filters rather than the whole filter chain that need to be considered for isAsyncSupported git-svn-id: https://svn.apache.org/repos/asf/tomcat/trunk@887992 13f79535-47bb-0310-9956-ffa450edef68 --- .../catalina/core/ApplicationDispatcher.java | 13 +--- .../catalina/core/ApplicationFilterChain.java | 66 +++------------- .../apache/catalina/core/StandardWrapperValve.java | 4 - java/org/apache/catalina/deploy/FilterDef.java | 8 +- .../org/apache/catalina/startup/ContextConfig.java | 87 +++++++++++++++++++--- java/org/apache/catalina/startup/WebXml.java | 12 ++- 6 files changed, 101 insertions(+), 89 deletions(-) diff --git a/java/org/apache/catalina/core/ApplicationDispatcher.java b/java/org/apache/catalina/core/ApplicationDispatcher.java index 74b2dff8e..f5248b3ab 100644 --- a/java/org/apache/catalina/core/ApplicationDispatcher.java +++ b/java/org/apache/catalina/core/ApplicationDispatcher.java @@ -641,15 +641,6 @@ final class ApplicationDispatcher ApplicationFilterChain filterChain = factory.createFilterChain(request, wrapper,servlet); - Object origAsyncSupported = request.getAttribute(Globals.ASYNC_SUPPORTED_ATTR); - //we have a new filter chain, setup isAsyncSupported here - boolean filterAsyncSupported = filterChain.isAsyncSupported(); - if (!filterAsyncSupported && request.isAsyncSupported()) { - //the request says we support it, but the filters don't - //TODO SERVLET3 - async - request.setAttribute(Globals.ASYNC_SUPPORTED_ATTR, Boolean.FALSE); - } - // Call the service() method for the allocated servlet instance try { String jspFile = wrapper.getJspFile(); @@ -704,8 +695,6 @@ final class ApplicationDispatcher wrapper.getLogger().error(sm.getString("applicationDispatcher.serviceException", wrapper.getName()), e); runtimeException = e; - } finally { - request.setAttribute(Globals.ASYNC_SUPPORTED_ATTR, origAsyncSupported); } // Release the filter chain (if any) for this request @@ -715,7 +704,7 @@ final class ApplicationDispatcher } catch (Throwable e) { wrapper.getLogger().error(sm.getString("standardWrapper.releaseFilters", wrapper.getName()), e); - // FIXME: Exception handling needs to be simpiler to what is in the StandardWrapperValue + // FIXME: Exception handling needs to be simpler to what is in the StandardWrapperValue } // Deallocate the allocated servlet instance diff --git a/java/org/apache/catalina/core/ApplicationFilterChain.java b/java/org/apache/catalina/core/ApplicationFilterChain.java index 64df629e4..438d92c92 100644 --- a/java/org/apache/catalina/core/ApplicationFilterChain.java +++ b/java/org/apache/catalina/core/ApplicationFilterChain.java @@ -28,10 +28,8 @@ import javax.servlet.FilterChain; import javax.servlet.Servlet; import javax.servlet.ServletException; import javax.servlet.ServletRequest; -import javax.servlet.ServletRequestWrapper; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletRequestWrapper; import javax.servlet.http.HttpServletResponse; import org.apache.catalina.Globals; @@ -224,6 +222,11 @@ final class ApplicationFilterChain implements FilterChain, CometFilterChain { support.fireInstanceEvent(InstanceEvent.BEFORE_FILTER_EVENT, filter, request, response); + if (request.isAsyncSupported() && "false".equalsIgnoreCase( + filterConfig.getFilterDef().getAsyncSupported())) { + request.setAttribute(Globals.ASYNC_SUPPORTED_ATTR, + Boolean.FALSE); + } if( Globals.IS_SECURITY_ENABLED ) { final ServletRequest req = request; final ServletResponse res = response; @@ -275,25 +278,17 @@ final class ApplicationFilterChain implements FilterChain, CometFilterChain { support.fireInstanceEvent(InstanceEvent.BEFORE_SERVICE_EVENT, servlet, request, response); - ServletRequest wRequest; if (request.isAsyncSupported() && !support.getWrapper().isAsyncSupported()) { - if (request instanceof HttpServletRequest) { - wRequest = new HttpServletRequestNoAsyc( - (HttpServletRequest) request); - } else { - // Must be a ServletRequest - wRequest = new ServletRequestNoAsyc(request); - } - } else { - wRequest = request; + request.setAttribute(Globals.ASYNC_SUPPORTED_ATTR, + Boolean.FALSE); } // Use potentially wrapped request from this point - if ((wRequest instanceof HttpServletRequest) && + if ((request instanceof HttpServletRequest) && (response instanceof HttpServletResponse)) { if( Globals.IS_SECURITY_ENABLED ) { - final ServletRequest req = wRequest; + final ServletRequest req = request; final ServletResponse res = response; Principal principal = ((HttpServletRequest) req).getUserPrincipal(); @@ -305,12 +300,11 @@ final class ApplicationFilterChain implements FilterChain, CometFilterChain { principal); args = null; } else { - servlet.service(wRequest, response); + servlet.service(request, response); } } else { - servlet.service(wRequest, response); + servlet.service(request, response); } - // Stop using wrapped request now Servlet has been processed support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT, servlet, request, response); } catch (IOException e) { @@ -586,42 +580,4 @@ final class ApplicationFilterChain implements FilterChain, CometFilterChain { this.support = support; } - - public boolean isAsyncSupported() { - boolean supported = true; - for (ApplicationFilterConfig config : filters) { - if (config!=null && config.getFilterDef()!=null) { - supported = supported & config.getFilterDef().isAsyncSupported(); - } - } - return supported; - } - - - // --------------------------------- Wrapper classes for isAsyncSupported() - - private class HttpServletRequestNoAsyc extends HttpServletRequestWrapper { - - public HttpServletRequestNoAsyc(HttpServletRequest request) { - super(request); - } - - @Override - public boolean isAsyncSupported() { - return false; - } - } - - private class ServletRequestNoAsyc extends ServletRequestWrapper { - - public ServletRequestNoAsyc(ServletRequest request) { - super(request); - } - - @Override - public boolean isAsyncSupported() { - return false; - } - } - } diff --git a/java/org/apache/catalina/core/StandardWrapperValve.java b/java/org/apache/catalina/core/StandardWrapperValve.java index 542ffc1dc..01fd140ba 100644 --- a/java/org/apache/catalina/core/StandardWrapperValve.java +++ b/java/org/apache/catalina/core/StandardWrapperValve.java @@ -203,10 +203,6 @@ final class StandardWrapperValve // Reset comet flag value after creating the filter chain request.setComet(false); - //check filters to see if we support async or not. - if (filterChain != null && request.isAsyncSupported()) { - request.setAsyncSupported(filterChain.isAsyncSupported()); - } // Call the filter chain for this request // NOTE: This also calls the servlet's service() method diff --git a/java/org/apache/catalina/deploy/FilterDef.java b/java/org/apache/catalina/deploy/FilterDef.java index a3ddd4056..c1a4833bf 100644 --- a/java/org/apache/catalina/deploy/FilterDef.java +++ b/java/org/apache/catalina/deploy/FilterDef.java @@ -136,13 +136,13 @@ public class FilterDef implements Serializable { this.smallIcon = smallIcon; } - private boolean asyncSupported = false; + private String asyncSupported = null; - public boolean isAsyncSupported() { + public String getAsyncSupported() { return asyncSupported; } - - public void setAsyncSupported(boolean asyncSupported) { + + public void setAsyncSupported(String asyncSupported) { this.asyncSupported = asyncSupported; } diff --git a/java/org/apache/catalina/startup/ContextConfig.java b/java/org/apache/catalina/startup/ContextConfig.java index fcd383298..0b2cc1af8 100644 --- a/java/org/apache/catalina/startup/ContextConfig.java +++ b/java/org/apache/catalina/startup/ContextConfig.java @@ -1673,10 +1673,11 @@ public class ContextConfig String type = ae.getAnnotationType(); if ("Ljavax/servlet/annotation/WebServlet;".equals(type)) { processAnnotationWebServlet(className, ae, fragment); + }else if ("Ljavax/servlet/annotation/WebFilter;".equals(type)) { + processAnnotationWebFilter(className, ae, fragment); }else if ("Ljavax/servlet/annotation/WebListener;".equals(type)) { fragment.addListener(className); } else { - // TODO SERVLET 3 - Other annotations // Unknown annotation - ignore } } @@ -1688,22 +1689,22 @@ public class ContextConfig // Skip this annotation. Entry in web.xml takes priority return; } - boolean mappingSet = false; + boolean urlPatternsSet = false; ServletDef servletDef = new ServletDef(); servletDef.setServletName(className); servletDef.setServletClass(className); - String[] mappings = null; + String[] urlPatterns = null; ElementValuePair[] evps = ae.getElementValuePairs(); for (ElementValuePair evp : evps) { String name = evp.getNameString(); if ("value".equals(name) || "urlPatterns".equals(name)) { - if (mappingSet) { + if (urlPatternsSet) { throw new IllegalArgumentException(sm.getString( "contextConfig.urlPatternValue", className)); } - mappingSet = true; - mappings = processAnnotationsUrlPatterns(evp.getValue()); + urlPatternsSet = true; + urlPatterns = processAnnotationsStringArray(evp.getValue()); } else if ("name".equals(name)) { servletDef.setServletName(evp.getValue().stringifyValue()); } else if ("description".equals(name)) { @@ -1729,16 +1730,82 @@ public class ContextConfig // Ignore } } - if (mappings != null) { + if (urlPatterns != null) { fragment.addServlet(servletDef); - for (String mapping : mappings) { - fragment.addServletMapping(mapping, + for (String urlPattern : urlPatterns) { + fragment.addServletMapping(urlPattern, servletDef.getServletName()); } } } - protected String[] processAnnotationsUrlPatterns(ElementValue ev) { + protected void processAnnotationWebFilter(String className, + AnnotationEntry ae, WebXml fragment) { + if (fragment.getFilters().containsKey(className)) { + // Skip this annotation. Entry in web.xml takes priority + return; + } + boolean urlPatternsSet = false; + FilterDef filterDef = new FilterDef(); + FilterMap filterMap = new FilterMap(); + filterDef.setFilterName(className); + filterDef.setFilterClass(className); + String[] urlPatterns = null; + + ElementValuePair[] evps = ae.getElementValuePairs(); + for (ElementValuePair evp : evps) { + String name = evp.getNameString(); + if ("value".equals(name) || "urlPatterns".equals(name)) { + if (urlPatternsSet) { + throw new IllegalArgumentException(sm.getString( + "contextConfig.urlPatternValue", className)); + } + urlPatternsSet = true; + urlPatterns = processAnnotationsStringArray(evp.getValue()); + for (String urlPattern : urlPatterns) { + filterMap.addURLPattern(urlPattern); + } + } else if ("filterName".equals(name)) { + filterDef.setFilterName(evp.getValue().stringifyValue()); + } else if ("servletNames".equals(name)) { + String[] servletNames = + processAnnotationsStringArray(evp.getValue()); + for (String servletName : servletNames) { + filterMap.addServletName(servletName); + } + } else if ("dispatcherTypes".equals(name)) { + String[] dispatcherTypes = + processAnnotationsStringArray(evp.getValue()); + for (String dispatcherType : dispatcherTypes) { + filterMap.setDispatcher(dispatcherType); + } + } else if ("description".equals(name)) { + filterDef.setDescription(evp.getValue().stringifyValue()); + } else if ("displayName".equals(name)) { + filterDef.setDisplayName(evp.getValue().stringifyValue()); + } else if ("largeIcon".equals(name)) { + filterDef.setLargeIcon(evp.getValue().stringifyValue()); + } else if ("smallIcon".equals(name)) { + filterDef.setSmallIcon(evp.getValue().stringifyValue()); + } else if ("asyncSupported".equals(name)) { + filterDef.setAsyncSupported(evp.getValue().stringifyValue()); + } else if ("initParams".equals(name)) { + Map initParams = + processAnnotationWebInitParams(evp.getValue()); + for (String paramName : initParams.keySet()) { + filterDef.addInitParameter(paramName, + initParams.get(paramName)); + } + } else { + // Ignore + } + } + fragment.addFilter(filterDef); + filterMap.setFilterName(filterDef.getFilterName()); + fragment.addFilterMapping(filterMap); + } + + protected String[] processAnnotationsStringArray(ElementValue ev) { ArrayList values = new ArrayList(); if (ev instanceof ArrayElementValue) { ElementValue[] arrayValues = diff --git a/java/org/apache/catalina/startup/WebXml.java b/java/org/apache/catalina/startup/WebXml.java index ba7a352c8..06643fb73 100644 --- a/java/org/apache/catalina/startup/WebXml.java +++ b/java/org/apache/catalina/startup/WebXml.java @@ -962,11 +962,15 @@ public class WebXml { } private boolean mergeFilter(FilterDef src, FilterDef dest, boolean failOnConflict) { - if (src.isAsyncSupported() != dest.isAsyncSupported()) { - // Always fail - return false; + if (dest.getAsyncSupported() == null) { + dest.setAsyncSupported(src.getAsyncSupported()); + } else if (src.getAsyncSupported() != null) { + if (failOnConflict && + !src.getAsyncSupported().equals(dest.getAsyncSupported())) { + return false; + } } - + if (dest.getFilterClass() == null) { dest.setFilterClass(src.getFilterClass()); } else if (src.getFilterClass() != null) { -- 2.11.0