Skip to content

Commit

Permalink
fix #37 : setStatus is not necessarily an error
Browse files Browse the repository at this point in the history
  • Loading branch information
vankeisb committed Jan 27, 2016
1 parent f81bb82 commit e0eec13
Showing 1 changed file with 59 additions and 56 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,16 +30,7 @@
import java.util.Map;
import java.util.UUID;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
Expand Down Expand Up @@ -108,7 +99,7 @@
* <p>
* This is the suggested mapping for this filter in {@code web.xml}.
* </p>
*
*
* <pre>
* &lt;filter&gt;
* &lt;description&gt;Dynamically maps URLs to ActionBeans.&lt;/description&gt;
Expand All @@ -122,7 +113,7 @@
* &lt;param-value&gt;com.yourcompany.stripes.action&lt;/param-value&gt;
* &lt;/init-param&gt;
* &lt;/filter&gt;
*
*
* &lt;filter-mapping&gt;
* &lt;filter-name&gt;DynamicMappingFilter&lt;/filter-name&gt;
* &lt;url-pattern&gt;/*&lt;/url-pattern&gt;
Expand All @@ -131,7 +122,7 @@
* &lt;dispatcher&gt;INCLUDE&lt;/dispatcher&gt;
* &lt;/filter-mapping&gt;
* </pre>
*
*
* @author Ben Gunter
* @since Stripes 1.5
* @see UrlBinding
Expand Down Expand Up @@ -161,7 +152,7 @@ public class DynamicMappingFilter implements Filter {
* normally. If there is a 404 and the URL does not match an ActionBean then the "missing
* resource" message is sent through.
* </p>
*
*
* @author Ben Gunter
* @since Stripes 1.5
*/
Expand Down Expand Up @@ -202,7 +193,7 @@ else if (buffer.getBuffer().length() + length > includeBufferSize) {

/**
* Write the contents of the buffer to the underlying writer. After a call to
* {@link #overflow()}, all future writes to this writer will pass directly to the
* this method, all future writes to this writer will pass directly to the
* underlying writer.
*/
protected void overflow() {
Expand All @@ -217,7 +208,7 @@ protected void overflow() {
* An {@link HttpServletResponseWrapper} that traps HTTP errors by overriding
* {@code sendError(int, ..)}. The error code can be retrieved by calling
* {@link #getErrorCode()}. A call to {@link #proceed()} sends the error to the client.
*
*
* @author Ben Gunter
* @since Stripes 1.5
*/
Expand Down Expand Up @@ -275,6 +266,7 @@ public Integer getErrorCode() {
}

/** Clear error code and error message. */
@SuppressWarnings("unused")
public void clearError() {
this.errorCode = null;
this.errorMessage = null;
Expand All @@ -297,15 +289,25 @@ public void proceed() throws IOException {
}
}

private boolean isError(int sc) {
return sc >= 400 && sc <= 500;
}

@Override
public void setStatus(int sc) {
this.errorCode = sc;
super.setStatus(sc);
if (isError(sc)) {
this.errorCode = sc;
}
}

@Override
public void setStatus(int sc, String sm) {
this.errorCode = sc;
this.errorMessage = sm;
super.setStatus(sc, sm);
if (isError(sc)) {
this.errorCode = sc;
this.errorMessage = sm;
}
}
}

Expand Down Expand Up @@ -349,9 +351,9 @@ public void init(final FilterConfig config) throws ServletException {
}
catch (Exception e) {
log.warn(e, "Could not interpret '",
config.getInitParameter(INCLUDE_BUFFER_SIZE_PARAM),
"' as a number for init-param '", INCLUDE_BUFFER_SIZE_PARAM,
"'. Using default value ", includeBufferSize, ".");
config.getInitParameter(INCLUDE_BUFFER_SIZE_PARAM),
"' as a number for init-param '", INCLUDE_BUFFER_SIZE_PARAM,
"'. Using default value ", includeBufferSize, ".");
}

this.filterConfig = config;
Expand Down Expand Up @@ -395,10 +397,10 @@ public void destroy() {
}

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
throws IOException, ServletException {
// Wrap the response in a wrapper that catches errors (but not exceptions)
final ErrorTrappingResponseWrapper wrapper = new ErrorTrappingResponseWrapper(
(HttpServletResponse) response);
(HttpServletResponse) response);
wrapper.setInclude(request.getAttribute(StripesConstants.REQ_ATTR_INCLUDE_PATH) != null);

// Catch FileNotFoundException, which some containers (e.g. GlassFish) throw instead of setting SC_NOT_FOUND
Expand All @@ -423,7 +425,7 @@ public void doFilter(ServletRequest request, ServletResponse response, FilterCha
// Check the instance field as well as request header for initialization request
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
boolean initializing = this.initializing
|| httpServletRequest.getHeader(REQ_HEADER_INIT_FLAG) != null;
|| httpServletRequest.getHeader(REQ_HEADER_INIT_FLAG) != null;

// If a FileNotFoundException or SC_NOT_FOUND error occurred, then try to match an ActionBean to the URL
boolean notFound = false;
Expand All @@ -435,7 +437,7 @@ public void doFilter(ServletRequest request, ServletResponse response, FilterCha
// special handling for WildFly,
// see http://www.stripesframework.org/jira/browse/STS-916
if ("POST".equals(httpServletRequest.getMethod())
&& errorCode == HttpServletResponse.SC_METHOD_NOT_ALLOWED) {
&& errorCode == HttpServletResponse.SC_METHOD_NOT_ALLOWED) {
notFound = true;
}
}
Expand All @@ -450,11 +452,11 @@ public void doFilter(ServletRequest request, ServletResponse response, FilterCha

sf.doFilter(request, response, new FilterChain() {
public void doFilter(ServletRequest request, ServletResponse response)
throws IOException, ServletException {
throws IOException, ServletException {
// Look for an ActionBean that is mapped to the URI
String uri = HttpUtil.getRequestedPath((HttpServletRequest) request);
Class<? extends ActionBean> beanType = getStripesFilter()
.getInstanceConfiguration().getActionResolver().getActionBeanType(uri);
.getInstanceConfiguration().getActionResolver().getActionBeanType(uri);

// If found then call the dispatcher directly. Otherwise, send the error.
if (beanType == null) {
Expand Down Expand Up @@ -492,13 +494,13 @@ protected StripesFilter getStripesFilter() {
* from the servlet context, we really need {@link StripesFilter} to have been initialized at
* the time we process our first request. If that didn't happen automatically, this method does
* its best to force it to happen.
*
*
* @param request The current request
* @param response The current response
* @throws ServletException If anything goes wrong that simply can't be ignored.
*/
protected synchronized void initStripesFilter(HttpServletRequest request,
HttpServletResponse response) throws ServletException {
HttpServletResponse response) throws ServletException {
try {
// Check if another thread got into this method before the current thread
if (getStripesFilter() != null)
Expand All @@ -507,7 +509,7 @@ protected synchronized void initStripesFilter(HttpServletRequest request,
log.info("StripesFilter not initialized. Checking the situation in web.xml ...");
Document document = parseWebXml();
NodeList filterNodes = eval("/web-app/filter/filter-class[text()='"
+ StripesFilter.class.getName() + "']/..", document, XPathConstants.NODESET);
+ StripesFilter.class.getName() + "']/..", document, XPathConstants.NODESET);
if (filterNodes == null || filterNodes.getLength() != 1) {
String msg;
if (filterNodes == null || filterNodes.getLength() < 1) {
Expand All @@ -518,7 +520,7 @@ protected synchronized void initStripesFilter(HttpServletRequest request,
}

log.info(msg, "Initializing with \"", filterConfig.getFilterName(),
"\" configuration.");
"\" configuration.");
createStripesFilter(filterConfig);
}
else {
Expand All @@ -529,7 +531,7 @@ protected synchronized void initStripesFilter(HttpServletRequest request,
List<String> patterns = getFilterUrlPatterns(filterNode);
if (patterns.isEmpty()) {
log.info("StripesFilter is declared but not mapped in web.xml. ",
"Initializing with \"", name, "\" configuration from web.xml.");
"Initializing with \"", name, "\" configuration from web.xml.");

final Map<String, String> parameters = getFilterParameters(filterNode);
createStripesFilter(new FilterConfig() {
Expand Down Expand Up @@ -560,34 +562,34 @@ public String getFilterName() {
}
catch (Exception e) {
throw new StripesServletException(
"Unhandled exception trying to force initialization of StripesFilter", e);
"Unhandled exception trying to force initialization of StripesFilter", e);
}

// Blow up if no StripesFilter instance could be acquired or created
if (getStripesFilter() == null) {
String msg = "There is no StripesFilter instance available in the servlet context, "
+ "and DynamicMappingFilter was unable to initialize one. See previous log "
+ "messages for more information.";
+ "and DynamicMappingFilter was unable to initialize one. See previous log "
+ "messages for more information.";
log.error(msg);
throw new StripesServletException(msg);
}
}

/**
* Parse the application's {@code web.xml} file and return a DOM {@link Document}.
*
*
* @throws ParserConfigurationException If thrown by the XML parser
* @throws IOException If thrown by the XML parser
* @throws SAXException If thrown by the XML parser
*/
protected Document parseWebXml() throws SAXException, IOException, ParserConfigurationException {
return DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(
servletContext.getResourceAsStream("/WEB-INF/web.xml"));
servletContext.getResourceAsStream("/WEB-INF/web.xml"));
}

/**
* Evaluate an xpath expression against a DOM {@link Node} and return the result.
*
*
* @param expression The expression to evaluate
* @param source The node against which the expression will be evaluated
* @param returnType One of the constants defined in {@link XPathConstants}
Expand All @@ -596,7 +598,7 @@ protected Document parseWebXml() throws SAXException, IOException, ParserConfigu
*/
@SuppressWarnings("unchecked")
protected <T> T eval(String expression, Node source, QName returnType)
throws XPathExpressionException {
throws XPathExpressionException {
XPath xpath = XPathFactory.newInstance().newXPath();
return (T) xpath.evaluate(expression, source, returnType);
}
Expand All @@ -605,7 +607,7 @@ protected <T> T eval(String expression, Node source, QName returnType)
* Get all the URL patterns to which a filter is mapped in {@code web.xml}. This includes direct
* mappings using {@code filter-mapping/url-pattern} and indirect mappings using
* {@code filter-mapping/servlet-name} and {@code servlet-mapping/url-pattern}.
*
*
* @param filterNode The DOM ({@code &lt;filter&gt;}) {@link Node} containing the filter
* declaration from {@code web.xml}
* @return A list of all the patterns to which the filter is mapped
Expand All @@ -616,9 +618,9 @@ protected List<String> getFilterUrlPatterns(Node filterNode) throws XPathExpress
Document document = filterNode.getOwnerDocument();

NodeList urlMappings = eval("/web-app/filter-mapping/filter-name[text()='" + filterName
+ "']/../url-pattern", document, XPathConstants.NODESET);
+ "']/../url-pattern", document, XPathConstants.NODESET);
NodeList servletMappings = eval("/web-app/filter-mapping/filter-name[text()='" + filterName
+ "']/../servlet-name", document, XPathConstants.NODESET);
+ "']/../servlet-name", document, XPathConstants.NODESET);

List<String> patterns = new ArrayList<String>();
if (urlMappings != null && urlMappings.getLength() > 0) {
Expand All @@ -631,7 +633,7 @@ protected List<String> getFilterUrlPatterns(Node filterNode) throws XPathExpress
for (int i = 0; i < servletMappings.getLength(); i++) {
String servletName = servletMappings.item(i).getTextContent().trim();
urlMappings = eval("/web-app/servlet-mapping/servlet-name[text()='" + servletName
+ "']/../url-pattern", document, XPathConstants.NODESET);
+ "']/../url-pattern", document, XPathConstants.NODESET);
for (int j = 0; j < urlMappings.getLength(); j++) {
patterns.add(urlMappings.item(j).getTextContent().trim());
}
Expand All @@ -644,14 +646,14 @@ protected List<String> getFilterUrlPatterns(Node filterNode) throws XPathExpress

/**
* Get the initialization parameters for a filter declared in {@code web.xml}.
*
*
* @param filterNode The DOM ({@code &lt;filter&gt;}) {@link Node} containing the filter
* declaration from {@code web.xml}
* @return A map of parameter names to parameter values
* @throws XPathExpressionException In case of failure evaluation an xpath expression
*/
protected Map<String, String> getFilterParameters(Node filterNode)
throws XPathExpressionException {
throws XPathExpressionException {
Map<String, String> params = new LinkedHashMap<String, String>();
NodeList paramNodes = eval("init-param", filterNode, XPathConstants.NODESET);
for (int i = 0; i < paramNodes.getLength(); i++) {
Expand All @@ -665,7 +667,7 @@ protected Map<String, String> getFilterParameters(Node filterNode)

/**
* Create and initialize an instance of {@link StripesFilter} with the given configuration.
*
*
* @param config The filter configuration
* @throws ServletException If initialization of the filter fails
*/
Expand All @@ -682,14 +684,14 @@ protected void createStripesFilter(FilterConfig config) throws ServletException
* an internal forward, then an include and finally with a brand new request to the address and
* port returned by {@link HttpServletRequest#getLocalAddr()} and
* {@link HttpServletRequest#getLocalPort()}, respectively.
*
*
* @param patterns The list of patterns to request, as specified by {@code url-pattern} elements
* in {@code web.xml}
* @param request The current request, required to process a forward or include
* @param response The current response, required to process a forward or include
*/
protected void issueRequests(List<String> patterns, HttpServletRequest request,
HttpServletResponse response) {
HttpServletResponse response) {
// Replace globs in the patterns with a random string
String random = "stripes-dmf-request-" + UUID.randomUUID();
List<String> uris = new ArrayList<String>(patterns.size());
Expand Down Expand Up @@ -754,10 +756,10 @@ public PrintWriter getWriter() throws IOException {
try {
initializing = true;
RequestDispatcher dispatcher = servletContext.getRequestDispatcher(uri);
dispatcher.forward(req, rsp);
dispatcher.include(req, rsp);
}
catch (Exception e) {
log.debug(e, "Ignored exception during forward");
log.debug(e, "Ignored exception during include");
}
finally {
initializing = false;
Expand All @@ -783,7 +785,7 @@ public PrintWriter getWriter() throws IOException {
* Issue a new request to a path relative to the request's context. The connection is made to
* the address and port returned by {@link HttpServletRequest#getLocalAddr()} and
* {@link HttpServletRequest#getLocalPort()}, respectively.
*
*
* @param request The current request
* @param relativePath The context-relative path to request
*/
Expand Down Expand Up @@ -812,16 +814,17 @@ public void requestRemotely(HttpServletRequest request, String relativePath) {

// Log the HTTP status
log.debug(cxn.getResponseCode(), " ", cxn.getResponseMessage(), " (", cxn
.getContentLength(), " bytes) from ", url);
.getContentLength(), " bytes) from ", url);
}
catch (Exception e) {
log.debug(e, "Request failed trying to force initialization of StripesFilter");
}
finally {
try {
cxn.disconnect();
}
catch (Exception e) {
if (cxn != null) {
cxn.disconnect();
}
} catch (Exception e) {
// Ignore
}
}
Expand Down

0 comments on commit e0eec13

Please sign in to comment.