Author: rgielen
Date: Sat Apr 25 13:49:50 2009
New Revision: 768529
URL: http://svn.apache.org/viewvc?rev=768529&view=rev
Log:
WW-3017 - Making it possible to have a configurable list of uri-patterns
telling struts not to handle the request
- applied patch provided by Andreas Joseph Krogh
- made some refactoring to eliminate duplicate code and unneeded method calls
- added integration test
Modified:
struts/struts2/trunk/core/src/main/java/org/apache/struts2/StrutsConstants.java
struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/ng/InitOperations.java
struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/ng/PrepareOperations.java
struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/ng/filter/StrutsExecuteFilter.java
struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/ng/filter/StrutsPrepareAndExecuteFilter.java
struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/ng/filter/StrutsPrepareFilter.java
struts/struts2/trunk/core/src/test/java/org/apache/struts2/dispatcher/ng/StrutsPrepareAndExecuteFilterIntegrationTest.java
Modified:
struts/struts2/trunk/core/src/main/java/org/apache/struts2/StrutsConstants.java
URL:
http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/java/org/apache/struts2/StrutsConstants.java?rev=768529&r1=768528&r2=768529&view=diff
==============================================================================
---
struts/struts2/trunk/core/src/main/java/org/apache/struts2/StrutsConstants.java
(original)
+++
struts/struts2/trunk/core/src/main/java/org/apache/struts2/StrutsConstants.java
Sat Apr 25 13:49:50 2009
@@ -44,6 +44,9 @@
/** The URL extension to use to determine if the request is meant for a
Struts action */
public static final String STRUTS_ACTION_EXTENSION =
"struts.action.extension";
+ /** Comma separated list of patterns (java.util.regex.Pattern) to be
excluded from Struts2-processing */
+ public static final String STRUTS_ACTION_EXCLUDE_PATTERN =
"struts.action.exclude_pattern";
+
/** Whether to use the alterative syntax for the tags or not */
public static final String STRUTS_TAG_ALTSYNTAX = "struts.tag.altSyntax";
Modified:
struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/ng/InitOperations.java
URL:
http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/ng/InitOperations.java?rev=768529&r1=768528&r2=768529&view=diff
==============================================================================
---
struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/ng/InitOperations.java
(original)
+++
struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/ng/InitOperations.java
Sat Apr 25 13:49:50 2009
@@ -25,10 +25,10 @@
import org.apache.struts2.dispatcher.Dispatcher;
import org.apache.struts2.dispatcher.StaticContentLoader;
import org.apache.struts2.util.ClassLoaderUtils;
+import org.apache.struts2.StrutsConstants;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Iterator;
+import java.util.*;
+import java.util.regex.Pattern;
/**
* Contains initialization operations
@@ -41,20 +41,20 @@
/**
* Initializes the internal Struts logging
*/
- public void initLogging(HostConfig filterConfig) {
+ public void initLogging( HostConfig filterConfig ) {
String factoryName = filterConfig.getInitParameter("loggerFactory");
if (factoryName != null) {
try {
Class cls = ClassLoaderUtils.loadClass(factoryName,
this.getClass());
LoggerFactory fac = (LoggerFactory) cls.newInstance();
LoggerFactory.setLoggerFactory(fac);
- } catch (InstantiationException e) {
+ } catch ( InstantiationException e ) {
System.err.println("Unable to instantiate logger factory: " +
factoryName + ", using default");
e.printStackTrace();
- } catch (IllegalAccessException e) {
+ } catch ( IllegalAccessException e ) {
System.err.println("Unable to access logger factory: " +
factoryName + ", using default");
e.printStackTrace();
- } catch (ClassNotFoundException e) {
+ } catch ( ClassNotFoundException e ) {
System.err.println("Unable to locate logger factory class: " +
factoryName + ", using default");
e.printStackTrace();
}
@@ -64,7 +64,7 @@
/**
* Creates and initializes the dispatcher
*/
- public Dispatcher initDispatcher(HostConfig filterConfig) {
+ public Dispatcher initDispatcher( HostConfig filterConfig ) {
Dispatcher dispatcher = createDispatcher(filterConfig);
dispatcher.init();
return dispatcher;
@@ -73,7 +73,7 @@
/**
* Initializes the static content loader with the filter configuration
*/
- public StaticContentLoader initStaticContentLoader(HostConfig
filterConfig, Dispatcher dispatcher) {
+ public StaticContentLoader initStaticContentLoader( HostConfig
filterConfig, Dispatcher dispatcher ) {
StaticContentLoader loader =
dispatcher.getContainer().getInstance(StaticContentLoader.class);
loader.setHostConfig(filterConfig);
return loader;
@@ -81,6 +81,7 @@
/**
* @return The dispatcher on the thread.
+ *
* @throws IllegalStateException If there is no dispatcher available
*/
public Dispatcher findDispatcherOnThread() {
@@ -92,11 +93,11 @@
}
/**
- * Create a {...@link Dispatcher}
+ * Create a {...@link Dispatcher}
*/
- private Dispatcher createDispatcher(HostConfig filterConfig) {
+ private Dispatcher createDispatcher( HostConfig filterConfig ) {
Map<String, String> params = new HashMap<String, String>();
- for (Iterator e = filterConfig.getInitParameterNames(); e.hasNext();) {
+ for ( Iterator e = filterConfig.getInitParameterNames(); e.hasNext();
) {
String name = (String) e.next();
String value = filterConfig.getInitParameter(name);
params.put(name, value);
@@ -107,4 +108,31 @@
public void cleanup() {
ActionContext.setContext(null);
}
+
+ /**
+ * Extract a list of patterns to exclude from request filtering
+ *
+ * @param dispatcher The dispatcher to check for exclude pattern
configuration
+ *
+ * @return a List of Patterns for request to exclude if apply, or
<tt>null</tt>
+ *
+ * @see org.apache.struts2.StrutsConstants#STRUTS_ACTION_EXCLUDE_PATTERN
+ */
+ public List<Pattern> buildExcludedPatternsList( Dispatcher dispatcher ) {
+ return
buildExcludedPatternsList(dispatcher.getContainer().getInstance(String.class,
StrutsConstants.STRUTS_ACTION_EXCLUDE_PATTERN));
+ }
+
+ private List<Pattern> buildExcludedPatternsList( String patterns ) {
+ if (null != patterns && patterns.trim().length() != 0) {
+ List<Pattern> list = new ArrayList<Pattern>();
+ String[] tokens = patterns.split(",");
+ for ( String token : tokens ) {
+ list.add(Pattern.compile(token.trim()));
+ }
+ return Collections.unmodifiableList(list);
+ } else {
+ return null;
+ }
+ }
+
}
Modified:
struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/ng/PrepareOperations.java
URL:
http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/ng/PrepareOperations.java?rev=768529&r1=768528&r2=768529&view=diff
==============================================================================
---
struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/ng/PrepareOperations.java
(original)
+++
struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/ng/PrepareOperations.java
Sat Apr 25 13:49:50 2009
@@ -24,6 +24,7 @@
import org.apache.struts2.dispatcher.mapper.ActionMapping;
import org.apache.struts2.dispatcher.mapper.ActionMapper;
import org.apache.struts2.StrutsException;
+import org.apache.struts2.RequestUtils;
import javax.servlet.ServletException;
import javax.servlet.ServletContext;
@@ -38,6 +39,8 @@
import java.io.IOException;
import java.util.HashMap;
+import java.util.List;
+import java.util.regex.Pattern;
/**
* Contains preparation operations for a request before execution
@@ -179,4 +182,48 @@
}
}
}
+
+ /**
+ * Check whether the request matches a list of exclude patterns.
+ *
+ * @param request The request to check patterns against
+ * @param excludedPatterns list of patterns for exclusion
+ *
+ * @return <tt>true</tt> if the request URI matches one of the given
patterns
+ */
+ public boolean isUrlExcluded( HttpServletRequest request, List<Pattern>
excludedPatterns ) {
+ if (excludedPatterns != null) {
+ String uri = getUri(request);
+ for ( Pattern pattern : excludedPatterns ) {
+ if (pattern.matcher(uri).matches()) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Gets the uri from the request
+ *
+ * @param request The request
+ *
+ * @return The uri
+ */
+ private String getUri( HttpServletRequest request ) {
+ // handle http dispatcher includes.
+ String uri = (String)
request.getAttribute("javax.servlet.include.servlet_path");
+ if (uri != null) {
+ return uri;
+ }
+
+ uri = RequestUtils.getServletPath(request);
+ if (uri != null && !"".equals(uri)) {
+ return uri;
+ }
+
+ uri = request.getRequestURI();
+ return uri.substring(request.getContextPath().length());
+ }
+
}
Modified:
struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/ng/filter/StrutsExecuteFilter.java
URL:
http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/ng/filter/StrutsExecuteFilter.java?rev=768529&r1=768528&r2=768529&view=diff
==============================================================================
---
struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/ng/filter/StrutsExecuteFilter.java
(original)
+++
struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/ng/filter/StrutsExecuteFilter.java
Sat Apr 25 13:49:50 2009
@@ -63,8 +63,15 @@
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
+ if (excludeUrl(request)) {
+ chain.doFilter(request, response);
+ return;
+ }
+
// This is necessary since we need the dispatcher instance, which was
created by the prepare filter
- lazyInit();
+ if (execute == null) {
+ lazyInit();
+ }
ActionMapping mapping = prepare.findActionMapping(request, response);
if (mapping == null) {
@@ -77,9 +84,13 @@
}
}
+ private boolean excludeUrl(HttpServletRequest request) {
+ return
request.getAttribute(StrutsPrepareFilter.REQUEST_EXCLUDED_FROM_ACTION_MAPPING)
!= null;
+ }
+
public void destroy() {
prepare = null;
execute = null;
filterConfig = null;
}
-}
\ No newline at end of file
+}
Modified:
struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/ng/filter/StrutsPrepareAndExecuteFilter.java
URL:
http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/ng/filter/StrutsPrepareAndExecuteFilter.java?rev=768529&r1=768528&r2=768529&view=diff
==============================================================================
---
struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/ng/filter/StrutsPrepareAndExecuteFilter.java
(original)
+++
struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/ng/filter/StrutsPrepareAndExecuteFilter.java
Sat Apr 25 13:49:50 2009
@@ -22,15 +22,17 @@
import org.apache.struts2.StrutsStatics;
import org.apache.struts2.dispatcher.Dispatcher;
-import org.apache.struts2.dispatcher.ng.PrepareOperations;
+import org.apache.struts2.dispatcher.mapper.ActionMapping;
import org.apache.struts2.dispatcher.ng.ExecuteOperations;
import org.apache.struts2.dispatcher.ng.InitOperations;
-import org.apache.struts2.dispatcher.mapper.ActionMapping;
+import org.apache.struts2.dispatcher.ng.PrepareOperations;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
+import java.util.List;
+import java.util.regex.Pattern;
/**
* Handles both the preparation and execution phases of the Struts dispatching
process. This filter is better to use
@@ -39,6 +41,7 @@
public class StrutsPrepareAndExecuteFilter implements StrutsStatics, Filter {
private PrepareOperations prepare;
private ExecuteOperations execute;
+ protected List<Pattern> excludedPatterns = null;
public void init(FilterConfig filterConfig) throws ServletException {
InitOperations init = new InitOperations();
@@ -50,6 +53,7 @@
prepare = new PrepareOperations(filterConfig.getServletContext(),
dispatcher);
execute = new ExecuteOperations(filterConfig.getServletContext(),
dispatcher);
+ this.excludedPatterns =
init.buildExcludedPatternsList(dispatcher);
} finally {
init.cleanup();
}
@@ -66,15 +70,19 @@
prepare.createActionContext(request, response);
prepare.assignDispatcherToThread();
request = prepare.wrapRequest(request);
- ActionMapping mapping = prepare.findActionMapping(request,
response, true);
- if (mapping == null) {
- boolean handled =
execute.executeStaticResourceRequest(request, response);
- if (!handled) {
- chain.doFilter(request, response);
- }
- } else {
- execute.executeAction(request, response, mapping);
- }
+ if ( excludedPatterns != null &&
prepare.isUrlExcluded(request, excludedPatterns)) {
+ chain.doFilter(request, response);
+ } else {
+ ActionMapping mapping =
prepare.findActionMapping(request, response, true);
+ if (mapping == null) {
+ boolean handled =
execute.executeStaticResourceRequest(request, response);
+ if (!handled) {
+ chain.doFilter(request,
response);
+ }
+ } else {
+ execute.executeAction(request,
response, mapping);
+ }
+ }
} finally {
prepare.cleanupRequest(request);
}
Modified:
struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/ng/filter/StrutsPrepareFilter.java
URL:
http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/ng/filter/StrutsPrepareFilter.java?rev=768529&r1=768528&r2=768529&view=diff
==============================================================================
---
struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/ng/filter/StrutsPrepareFilter.java
(original)
+++
struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/ng/filter/StrutsPrepareFilter.java
Sat Apr 25 13:49:50 2009
@@ -22,21 +22,27 @@
import org.apache.struts2.StrutsStatics;
import org.apache.struts2.dispatcher.Dispatcher;
-import org.apache.struts2.dispatcher.ng.PrepareOperations;
import org.apache.struts2.dispatcher.ng.InitOperations;
+import org.apache.struts2.dispatcher.ng.PrepareOperations;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
+import java.util.List;
+import java.util.regex.Pattern;
/**
* Prepares the request for execution by a later {...@link
org.apache.struts2.dispatcher.ng.filter.StrutsExecuteFilter} filter instance.
*/
public class StrutsPrepareFilter implements StrutsStatics, Filter {
+
+ protected static final String REQUEST_EXCLUDED_FROM_ACTION_MAPPING =
StrutsPrepareFilter.class.getName() + ".REQUEST_EXCLUDED_FROM_ACTION_MAPPING";
+
private PrepareOperations prepare;
+ private List<Pattern> excludedPatterns = null;
- public void init(FilterConfig filterConfig) throws ServletException {
+ public void init(FilterConfig filterConfig) throws ServletException {
InitOperations init = new InitOperations();
try {
FilterHostConfig config = new FilterHostConfig(filterConfig);
@@ -44,6 +50,7 @@
Dispatcher dispatcher = init.initDispatcher(config);
prepare = new PrepareOperations(filterConfig.getServletContext(),
dispatcher);
+ this.excludedPatterns =
init.buildExcludedPatternsList(dispatcher);
} finally {
init.cleanup();
}
@@ -60,15 +67,18 @@
prepare.createActionContext(request, response);
prepare.assignDispatcherToThread();
request = prepare.wrapRequest(request);
- prepare.findActionMapping(request, response);
-
+ if ( excludedPatterns != null &&
prepare.isUrlExcluded(request, excludedPatterns)) {
+
request.setAttribute(REQUEST_EXCLUDED_FROM_ACTION_MAPPING, new Object());
+ } else {
+ prepare.findActionMapping(request, response);
+ }
chain.doFilter(request, response);
} finally {
prepare.cleanupRequest(request);
}
}
- public void destroy() {
+ public void destroy() {
prepare.cleanupDispatcher();
}
}
\ No newline at end of file
Modified:
struts/struts2/trunk/core/src/test/java/org/apache/struts2/dispatcher/ng/StrutsPrepareAndExecuteFilterIntegrationTest.java
URL:
http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/test/java/org/apache/struts2/dispatcher/ng/StrutsPrepareAndExecuteFilterIntegrationTest.java?rev=768529&r1=768528&r2=768529&view=diff
==============================================================================
---
struts/struts2/trunk/core/src/test/java/org/apache/struts2/dispatcher/ng/StrutsPrepareAndExecuteFilterIntegrationTest.java
(original)
+++
struts/struts2/trunk/core/src/test/java/org/apache/struts2/dispatcher/ng/StrutsPrepareAndExecuteFilterIntegrationTest.java
Sat Apr 25 13:49:50 2009
@@ -32,7 +32,10 @@
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
+import javax.servlet.FilterConfig;
import java.io.IOException;
+import java.util.regex.Pattern;
+import java.util.ArrayList;
/**
* Integration tests for the filter
@@ -113,6 +116,32 @@
assertTrue((Boolean) request.getAttribute("__invoked"));
}
+ public void testUriPatternExclusion() throws ServletException, IOException
{
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ MockFilterConfig filterConfig = new MockFilterConfig();
+ MockFilterChain filterChain = new MockFilterChain() {
+ @Override
+ public void doFilter(ServletRequest req, ServletResponse res) {
+ req.setAttribute("i_was", "invoked");
+ }
+ };
+
+ request.setRequestURI("/hello.action");
+ StrutsPrepareAndExecuteFilter filter = new
StrutsPrepareAndExecuteFilter() {
+ @Override
+ public void init( FilterConfig filterConfig ) throws
ServletException {
+ super.init(filterConfig);
+ excludedPatterns = new ArrayList<Pattern>();
+ excludedPatterns.add(Pattern.compile(".*hello.*"));
+ }
+ };
+ filter.init(filterConfig);
+ filter.doFilter(request, response, filterChain);
+ assertEquals(200, response.getStatus());
+ assertEquals("invoked", request.getAttribute("i_was"));
+ }
+
public void testStaticFallthrough() throws ServletException, IOException {
MockHttpServletRequest request = new MockHttpServletRequest();
MockHttpServletResponse response = new MockHttpServletResponse();