Revision: 1319
http://stripes.svn.sourceforge.net/stripes/?rev=1319&view=rev
Author: bengunter
Date: 2010-11-10 18:55:09 +0000 (Wed, 10 Nov 2010)
Log Message:
-----------
Applied fix for STS-678 from 1.5.x to trunk.
Modified Paths:
--------------
trunk/stripes/src/net/sourceforge/stripes/controller/DynamicMappingFilter.java
Modified:
trunk/stripes/src/net/sourceforge/stripes/controller/DynamicMappingFilter.java
===================================================================
---
trunk/stripes/src/net/sourceforge/stripes/controller/DynamicMappingFilter.java
2010-11-10 18:10:34 UTC (rev 1318)
+++
trunk/stripes/src/net/sourceforge/stripes/controller/DynamicMappingFilter.java
2010-11-10 18:55:09 UTC (rev 1319)
@@ -19,19 +19,38 @@
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collections;
import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+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.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
+import javax.xml.namespace.QName;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathExpressionException;
+import javax.xml.xpath.XPathFactory;
import net.sourceforge.stripes.action.ActionBean;
import net.sourceforge.stripes.config.Configuration;
@@ -39,29 +58,29 @@
import net.sourceforge.stripes.util.HttpUtil;
import net.sourceforge.stripes.util.Log;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.SAXException;
+
/**
* <p>
* A servlet filter that dynamically maps URLs to {...@link ActionBean}s. This
filter can be used to
- * allow Stripes to dispatch requests to {...@link ActionBean}s based on their
URL binding, even if
- * the URL to which they are bound is not explicitly mapped in {...@code
web.xml}.
+ * allow Stripes to dispatch requests to {...@link ActionBean}s based on their
URL binding, even if the
+ * URL to which they are bound is not explicitly mapped in {...@code web.xml}.
* </p>
* <p>
- * There are a few caveats that must be observed when using this filter:
- * <ul>
- * <li>{...@link StripesFilter} <em>MUST</em> be defined in {...@code web.xml}
so that it will be
- * loaded and initialized.</li>
- * <li>This filter <em>MUST</em> be mapped to {...@code /*} to work
correctly.</li>
- * <li>This filter <em>MUST</em> be the last filter in the filter chain. When
it dynamically maps
- * an {...@link ActionBean} to a URL, the filter chain is interrupted.</li>
- * </ul>
+ * One caveat must be observed when using this filter. This filter
<em>MUST</em> be the last filter
+ * in the filter chain. When it dynamically maps an {...@link ActionBean} to a
URL, the filter chain is
+ * interrupted.
* </p>
* <p>
- * {...@link StripesFilter} and {...@link DispatcherServlet} need not be
mapped to any URL patterns in
- * {...@code web.xml} since this filter will determine at runtime whether or
not they need to be
- * invoked. In fact, you don't even need to define {...@link
DispatcherServlet} in {...@code web.xml} at
- * all because this filter uses an instance it creates and manages internally.
However, some
- * resources, such as JSPs, may require access to the Stripes {...@link
Configuration}. Thus,
- * {...@link StripesFilter} should be mapped to {...@code *.jsp} if you intend
to access JSPs directly.
+ * {...@link StripesFilter} and/or {...@link DispatcherServlet} may be
declared in {...@code web.xml}, but
+ * neither is required for this filter to work. If you choose not to declare
{...@link StripesFilter}
+ * in {...@code web.xml}, then this filter should be configured the way you
would normally configure
+ * {...@link StripesFilter}. However, some resources, such as JSPs, may
require access to the Stripes
+ * {...@link Configuration} through {...@link StripesFilter}. If you intend to
access JSPs directly, then
+ * {...@link StripesFilter} should be explicitly mapped to {...@code *.jsp}.
* </p>
* <p>
* This filter takes the following approach to determining when to dispatch an
{...@link ActionBean}:
@@ -76,15 +95,15 @@
* </p>
* <p>
* One benefit of this approach is that static resources can be delivered from
the same namespace to
- * which an {...@link ActionBean} is mapped using clean URLs. (Form more
information on clean URLs, see
+ * which an {...@link ActionBean} is mapped using clean URLs. (For more
information on clean URLs, see
* {...@link UrlBinding}.) For example, if your {...@code UserActionBean} is
mapped to
* {...@code @UrlBinding("/user/{id}/{$event}")} and you have a static file at
{...@code /user/icon.gif},
* then your icon will be delivered correctly because the initial request will
not have returned a
* {...@code 404} error.
* </p>
* <p>
- * This filter accepts one init-param. {...@code IncludeBufferSize} (optional,
default 1024) sets the
- * number of characters to be buffered by {...@link TempBufferWriter} for
include requests. See
+ * The {...@code IncludeBufferSize} initialization parameter (optional,
default 1024) sets the number
+ * of characters to be buffered by {...@link TempBufferWriter} for include
requests. See
* {...@link TempBufferWriter} for more information.
* <p>
* This is the suggested mapping for this filter in {...@code web.xml}.
@@ -98,6 +117,10 @@
* <filter-class>
* net.sourceforge.stripes.controller.DynamicMappingFilter
* </filter-class>
+ * <init-param>
+ * <param-name>ActionResolver.Packages</param-name>
+ *
<param-value>com.yourcompany.stripes.action</param-value>
+ * </init-param>
* </filter>
*
* <filter-mapping>
@@ -279,36 +302,48 @@
* The name of the init-param that can be used to set the size of the
buffer used by
* {...@link TempBufferWriter} before it overflows.
*/
- private static final String INCLUDE_BUFFER_SIZE_PARAM =
"IncludeBufferSize";
+ public static final String INCLUDE_BUFFER_SIZE_PARAM = "IncludeBufferSize";
+ /**
+ * The attribute name used to store a reference to {...@link
StripesFilter} in the servlet context.
+ */
+ public static final String CONTEXT_KEY_STRIPES_FILTER =
StripesFilter.class.getName();
+
+ /**
+ * Request header that indicates that the current request is part of the
process of trying to
+ * force initialization of {...@link StripesFilter}. If this header is
present then
+ * {...@link DynamicMappingFilter} makes no attempt to map the request to
an {...@link ActionBean}.
+ */
+ private static final String REQ_HEADER_INIT_FLAG =
"X-Dynamic-Mapping-Filter-Init";
+
/** The size of the buffer used by {...@link TempBufferWriter} before it
overflows. */
private static int includeBufferSize = 1024;
/** Logger */
private static Log log = Log.getInstance(DynamicMappingFilter.class);
- private boolean initialized = false;
+ private FilterConfig filterConfig;
private ServletContext servletContext;
private StripesFilter stripesFilter;
private DispatcherServlet stripesDispatcher;
+ private boolean stripesFilterIsInternal, initializing;
public void init(final FilterConfig config) throws ServletException {
try {
- includeBufferSize =
Integer.valueOf(config.getInitParameter(INCLUDE_BUFFER_SIZE_PARAM)
- .trim());
- log.info(DynamicMappingFilter.class.getName(), " include buffer
size is ",
- includeBufferSize);
+ String value = config.getInitParameter(INCLUDE_BUFFER_SIZE_PARAM);
+ if (value != null) {
+ includeBufferSize = Integer.valueOf(value.trim());
+ log.info(getClass().getSimpleName(), " include buffer size is
", includeBufferSize);
+ }
}
- catch (NullPointerException e) {
- // ignore it
- }
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 of ", includeBufferSize, ".");
+ "'. Using default value ", includeBufferSize, ".");
}
+ this.filterConfig = config;
this.servletContext = config.getServletContext();
this.stripesDispatcher = new DispatcherServlet();
this.stripesDispatcher.init(new ServletConfig() {
@@ -331,15 +366,25 @@
}
public void destroy() {
- stripesDispatcher.destroy();
+ try {
+ if (stripesDispatcher != null)
+ stripesDispatcher.destroy();
+ }
+ finally {
+ stripesDispatcher = null;
+
+ try {
+ if (stripesFilterIsInternal && stripesFilter != null)
+ stripesFilter.destroy();
+ }
+ finally {
+ stripesFilter = null;
+ }
+ }
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain)
throws IOException, ServletException {
- // Initialize (only once)
- if (!initialized)
- doOneTimeConfiguration();
-
// Wrap the response in a wrapper that catches errors (but not
exceptions)
final ErrorTrappingResponseWrapper wrapper = new
ErrorTrappingResponseWrapper(
(HttpServletResponse) response);
@@ -349,22 +394,34 @@
boolean fileNotFoundExceptionThrown = false;
try {
- chain.doFilter(request, wrapper);
+ chain.doFilter(request, wrapper);
}
catch (FileNotFoundException exc) {
- fileNotFoundExceptionThrown = true;
+ fileNotFoundExceptionThrown = true;
}
+ // Check the instance field as well as request header for
initialization request
+ boolean initializing = this.initializing
+ || ((HttpServletRequest)
request).getHeader(REQ_HEADER_INIT_FLAG) != null;
+
// If a FileNotFoundException or SC_NOT_FOUND error occurred, then try
to match an ActionBean to the URL
Integer errorCode = wrapper.getErrorCode();
- if ((errorCode != null && errorCode ==
HttpServletResponse.SC_NOT_FOUND) || fileNotFoundExceptionThrown) {
- stripesFilter.doFilter(request, response, new FilterChain() {
+ if (!initializing && (errorCode != null && errorCode ==
HttpServletResponse.SC_NOT_FOUND)
+ || fileNotFoundExceptionThrown) {
+ // Get a reference to a StripesFilter instance
+ StripesFilter sf = getStripesFilter();
+ if (sf == null) {
+ initStripesFilter((HttpServletRequest) request, wrapper);
+ sf = getStripesFilter();
+ }
+
+ sf.doFilter(request, response, new FilterChain() {
public void doFilter(ServletRequest request, ServletResponse
response)
throws IOException, ServletException {
// Look for an ActionBean that is mapped to the URI
String uri =
HttpUtil.getRequestedPath((HttpServletRequest) request);
- Class<? extends ActionBean> beanType =
stripesFilter.getInstanceConfiguration()
- .getActionResolver().getActionBeanType(uri);
+ Class<? extends ActionBean> beanType = getStripesFilter()
+
.getInstanceConfiguration().getActionResolver().getActionBeanType(uri);
// If found then call the dispatcher directly. Otherwise,
send the error.
if (beanType == null) {
@@ -382,16 +439,354 @@
}
/**
- * Perform initialization that can't be done in {...@code init(..)}. This
is normally called only
- * once, on the first invocation of {...@code doFilter(..)}.
+ * Get a reference to {...@link StripesFilter}. The first time this method
is called, the reference
+ * will be looked up in the servlet context and cached in the {...@link
#stripesFilter} field.
*/
- protected void doOneTimeConfiguration() throws ServletException {
- stripesFilter = (StripesFilter)
servletContext.getAttribute(StripesFilter.class.getName());
+ protected StripesFilter getStripesFilter() {
if (stripesFilter == null) {
- throw new StripesServletException("Could not get a reference to
StripesFilter from "
- + "the servlet context. The dynamic mapping filter works
in conjunction with "
- + "StripesFilter and requires that it be defined in
web.xml");
+ stripesFilter = (StripesFilter)
servletContext.getAttribute(CONTEXT_KEY_STRIPES_FILTER);
+ if (stripesFilter != null) {
+ log.debug("Found StripesFilter in the servlet context.");
+ }
}
- initialized = true;
+
+ return stripesFilter;
}
+
+ /**
+ * The servlet spec allows a container to wait until a filter is required
to process a request
+ * before it initializes the filter. Since we need to get a reference to
{...@link StripesFilter}
+ * 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 {
+ try {
+ 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);
+ if (filterNodes == null || filterNodes.getLength() != 1) {
+ String msg;
+ if (filterNodes.getLength() < 1) {
+ msg = "StripesFilter is not declared in web.xml. ";
+ }
+ else {
+ msg = "StripesFilter is declared multiple times in
web.xml; refusing to use either one. ";
+ }
+
+ log.info(msg, "Initializing with \"",
filterConfig.getFilterName(),
+ "\" configuration.");
+ createStripesFilter(filterConfig);
+ }
+ else {
+ Node filterNode = filterNodes.item(0);
+ final String name = eval("filter-name", filterNode,
XPathConstants.STRING);
+ log.debug("Found StripesFilter declared as ", name, " in
web.xml");
+
+ 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.");
+
+ final Map<String, String> parameters =
getFilterParameters(filterNode);
+ createStripesFilter(new FilterConfig() {
+ public ServletContext getServletContext() {
+ return servletContext;
+ }
+
+ public Enumeration<String> getInitParameterNames() {
+ return
Collections.enumeration(parameters.keySet());
+ }
+
+ public String getInitParameter(String name) {
+ return parameters.get(name);
+ }
+
+ public String getFilterName() {
+ return name;
+ }
+ });
+ }
+ else {
+ issueRequests(patterns, request, response);
+ }
+ }
+ }
+ catch (RuntimeException e) {
+ throw e;
+ }
+ catch (Exception e) {
+ throw new StripesServletException(
+ "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.";
+ 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"));
+ }
+
+ /**
+ * 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}
+ * @return The result returned by {...@link XPath#evaluate(String, Object,
QName)}
+ * @throws XPathExpressionException If the xpath expression is invalid
+ */
+ @SuppressWarnings("unchecked")
+ protected <T> T eval(String expression, Node source, QName returnType)
+ throws XPathExpressionException {
+ XPath xpath = XPathFactory.newInstance().newXPath();
+ return (T) xpath.evaluate(expression, source, 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 <filter>}) {...@link Node}
containing the filter
+ * declaration from {...@code web.xml}
+ * @return A list of all the patterns to which the filter is mapped
+ * @throws XPathExpressionException In case of failure evaluating an xpath
expression
+ */
+ protected List<String> getFilterUrlPatterns(Node filterNode) throws
XPathExpressionException {
+ String filterName = eval("filter-name", filterNode,
XPathConstants.STRING);
+ Document document = filterNode.getOwnerDocument();
+
+ NodeList urlMappings =
eval("/web-app/filter-mapping/filter-name[text()='" + filterName
+ + "']/../url-pattern", document, XPathConstants.NODESET);
+ NodeList servletMappings =
eval("/web-app/filter-mapping/filter-name[text()='" + filterName
+ + "']/../servlet-name", document, XPathConstants.NODESET);
+
+ List<String> patterns = new ArrayList<String>();
+ if (urlMappings != null && urlMappings.getLength() > 0) {
+ for (int i = 0; i < urlMappings.getLength(); i++) {
+ patterns.add(urlMappings.item(i).getTextContent().trim());
+ }
+ }
+
+ if (servletMappings != null && servletMappings.getLength() > 0) {
+ 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);
+ for (int j = 0; j < urlMappings.getLength(); j++) {
+ patterns.add(urlMappings.item(j).getTextContent().trim());
+ }
+ }
+ }
+
+ log.debug("Filter ", filterName, " maps to ", patterns);
+ return patterns;
+ }
+
+ /**
+ * Get the initialization parameters for a filter declared in {...@code
web.xml}.
+ *
+ * @param filterNode The DOM ({...@code <filter>}) {...@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 {
+ Map<String, String> params = new LinkedHashMap<String, String>();
+ NodeList paramNodes = eval("init-param", filterNode,
XPathConstants.NODESET);
+ for (int i = 0; i < paramNodes.getLength(); i++) {
+ Node node = paramNodes.item(i);
+ String key = eval("param-name", node, XPathConstants.STRING);
+ String value = eval("param-value", node, XPathConstants.STRING);
+ params.put(key, value);
+ }
+ return params;
+ }
+
+ /**
+ * 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
+ */
+ protected void createStripesFilter(FilterConfig config) throws
ServletException {
+ StripesFilter filter = new StripesFilter();
+ filter.init(config);
+ this.stripesFilter = filter;
+ this.stripesFilterIsInternal = true;
+ }
+
+ /**
+ * Issue a series of requests in an attempt to force an invocation (and
initialization) of
+ * {...@link StripesFilter} in the application context. All patterns will
be requested first with
+ * 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) {
+ // Replace globs in the patterns with a random string
+ String random = "stripes-dmf-request-" + UUID.randomUUID();
+ List<String> uris = new ArrayList<String>(patterns.size());
+ for (String pattern : patterns) {
+ String uri = pattern.replace("*", random);
+ if (!uri.startsWith("/"))
+ uri = "/" + uri;
+ uris.add(uri);
+ }
+
+ // Set the HTTP method to something generally harmless
+ HttpServletRequestWrapper req = new HttpServletRequestWrapper(request)
{
+ @Override
+ public String getMethod() {
+ return "OPTIONS";
+ }
+ };
+
+ // Response swallows all output
+ HttpServletResponseWrapper rsp = new
HttpServletResponseWrapper(response) {
+ @Override
+ public ServletOutputStream getOutputStream() throws IOException {
+ return new ServletOutputStream() {
+ @Override
+ public void write(int b) throws IOException {
+ // No output
+ }
+ };
+ }
+
+ @Override
+ public PrintWriter getWriter() throws IOException {
+ return new PrintWriter(getOutputStream());
+ }
+ };
+
+ // Try forward first
+ log.info("Found StripesFilter declared and mapped in web.xml but not
yet initialized.");
+ Iterator<String> iterator = uris.iterator();
+ while (getStripesFilter() == null && iterator.hasNext()) {
+ String uri = iterator.next();
+ log.info("Try to force initialization of StripesFilter with
forward to ", uri);
+ try {
+ initializing = true;
+ RequestDispatcher dispatcher =
servletContext.getRequestDispatcher(uri);
+ dispatcher.forward(req, rsp);
+ }
+ catch (Exception e) {
+ log.debug(e, "Ignored exception during forward");
+ }
+ finally {
+ initializing = false;
+ response.reset();
+ }
+ }
+
+ // If forward failed, try include
+ iterator = uris.iterator();
+ while (getStripesFilter() == null && iterator.hasNext()) {
+ String uri = iterator.next();
+ log.info("Try to force initialization of StripesFilter with
include of ", uri);
+ try {
+ initializing = true;
+ RequestDispatcher dispatcher =
servletContext.getRequestDispatcher(uri);
+ dispatcher.forward(req, rsp);
+ }
+ catch (Exception e) {
+ log.debug(e, "Ignored exception during forward");
+ }
+ finally {
+ initializing = false;
+ response.reset();
+ }
+ }
+
+ // If both forward and include failed, then do something truly
abominable ...
+ iterator = uris.iterator();
+ while (getStripesFilter() == null && iterator.hasNext()) {
+ try {
+ String uri = iterator.next();
+ log.info("Try to force initialization of StripesFilter with
request to ", uri);
+ requestRemotely(request, uri);
+ }
+ catch (Exception e) {
+ log.debug(e, "Ignored exception during request");
+ }
+ }
+ }
+
+ /**
+ * 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
+ */
+ @SuppressWarnings("unchecked")
+ public void requestRemotely(HttpServletRequest request, String
relativePath) {
+ HttpURLConnection cxn = null;
+ try {
+ // Create a new URL using the current request's protocol, port and
context
+ String protocol = new
URL(request.getRequestURL().toString()).getProtocol();
+ String file = request.getContextPath() + relativePath;
+ URL url = new URL(protocol, request.getLocalAddr(),
request.getLocalPort(), file);
+ cxn = (HttpURLConnection) url.openConnection();
+
+ // Set the HTTP method to something generally harmless
+ cxn.setRequestMethod("OPTIONS");
+
+ // Copy all the request headers to the new request
+ Enumeration<String> headerNames = request.getHeaderNames();
+ while (headerNames.hasMoreElements()) {
+ String hdr = headerNames.nextElement();
+ cxn.setRequestProperty(hdr, request.getHeader(hdr));
+ }
+
+ // Set a flag to let DMF know not to process the request
+ cxn.setRequestProperty(REQ_HEADER_INIT_FLAG, "true");
+
+ // Log the HTTP status
+ log.debug(cxn.getResponseCode(), " ", cxn.getResponseMessage(), "
(", cxn
+ .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) {
+ // Ignore
+ }
+ }
+ }
}
This was sent by the SourceForge.net collaborative development platform, the
world's largest Open Source development site.
------------------------------------------------------------------------------
The Next 800 Companies to Lead America's Growth: New Video Whitepaper
David G. Thomson, author of the best-selling book "Blueprint to a
Billion" shares his insights and actions to help propel your
business during the next growth cycle. Listen Now!
http://p.sf.net/sfu/SAP-dev2dev
_______________________________________________
Stripes-development mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/stripes-development