Last active
December 23, 2015 06:29
-
-
Save novoj/6593787 to your computer and use it in GitHub Desktop.
Patch for Stripes framework on WebSphere 8.x
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package net.sourceforge.stripes.controller; | |
import net.sourceforge.stripes.action.ActionBean; | |
import net.sourceforge.stripes.exception.StripesServletException; | |
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; | |
import javax.servlet.*; | |
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 java.io.*; | |
import java.net.HttpURLConnection; | |
import java.net.URL; | |
import java.util.*; | |
/** | |
* Hacked version of Stripes DynamicMappingFilter that overcomes changes in WebSphere 8.0.0.6. | |
* IBM you stole me 12 hours of my life! | |
* | |
* @author Jan Novotný (novotny@fg.cz), FG Forrest a.s. (c) 2013 | |
*/ | |
public class HackedDynamicMappingFilter extends DynamicMappingFilter { | |
/** | |
* <p> | |
* A {@link java.io.Writer} that passes characters to a {@link java.io.PrintWriter}. It buffers the first | |
* {@code N} characters written to it and automatically overflows when the number of characters | |
* written exceeds the limit. The size of the buffer defaults to 1024 characters, but it can be | |
* changed using the {@code IncludeBufferSize} filter init-param in {@code web.xml}. If | |
* {@code IncludeBufferSize} is zero or negative, then a {@link TempBufferWriter} will not be | |
* used at all. This is only a good idea if your servlet container does not write an error | |
* message to output when it can't find an included resource or if you only include resources | |
* that do not depend on this filter to be delivered, such as other servlets, JSPs, static | |
* resources, ActionBeans that are mapped with a prefix ({@code /action/*}) or suffix ({@code *.action}), | |
* etc. | |
* </p> | |
* <p> | |
* This writer is used to partially buffer the output of includes. Some (all?) servlet | |
* containers write a message to the output stream indicating if an included resource is missing | |
* because if the response has already been committed, they cannot send a 404 error. Since the | |
* filter depends on getting a 404 before it attempts to dispatch an {@code ActionBean}, that | |
* is problematic. So in using this writer, we assume that the length of the "missing resource" | |
* message will be less than the buffer size and we discard that message if we're able to map | |
* the included URL to an {@code ActionBean}. If there is no 404 then the output will be sent | |
* 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 | |
*/ | |
public static class TempBufferWriter extends Writer { | |
private StringWriter buffer; | |
private PrintWriter out; | |
public TempBufferWriter(PrintWriter out) { | |
this.out = out; | |
this.buffer = new StringWriter(includeBufferSize); | |
} | |
@Override | |
public void close() throws IOException { | |
flush(); | |
out.close(); | |
} | |
@Override | |
public void flush() throws IOException { | |
overflow(); | |
out.flush(); | |
} | |
@Override | |
public void write(char[] chars, int offset, int length) throws IOException { | |
if (buffer == null) { | |
out.write(chars, offset, length); | |
} | |
else if (buffer.getBuffer().length() + length > includeBufferSize) { | |
overflow(); | |
out.write(chars, offset, length); | |
} | |
else { | |
buffer.write(chars, offset, length); | |
} | |
} | |
/** | |
* 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 | |
* underlying writer. | |
*/ | |
protected void overflow() { | |
if (buffer != null) { | |
out.print(buffer.toString()); | |
buffer = null; | |
} | |
} | |
} | |
/** | |
* An {@link javax.servlet.http.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 | |
*/ | |
public static class ErrorTrappingResponseWrapper extends HttpServletResponseWrapper { | |
private Integer errorCode; | |
private String errorMessage; | |
private boolean include; | |
private PrintWriter printWriter; | |
private TempBufferWriter tempBufferWriter; | |
/** Wrap the given {@code response}. */ | |
public ErrorTrappingResponseWrapper(HttpServletResponse response) { | |
super(response); | |
} | |
@Override | |
public void sendError(int errorCode, String errorMessage) throws IOException { | |
this.errorCode = errorCode; | |
this.errorMessage = errorMessage; | |
} | |
@Override | |
public void sendError(int errorCode) throws IOException { | |
this.errorCode = errorCode; | |
this.errorMessage = null; | |
} | |
@Override | |
public void setStatus(int sc) { | |
this.errorCode = sc; | |
} | |
@Override | |
public void setStatus(int sc, String sm) { | |
this.errorCode = sc; | |
this.errorMessage = sm; | |
} | |
@Override | |
public PrintWriter getWriter() throws IOException { | |
if (isInclude() && includeBufferSize > 0) { | |
if (printWriter == null) { | |
tempBufferWriter = new TempBufferWriter(super.getWriter()); | |
printWriter = new PrintWriter(tempBufferWriter); | |
} | |
return printWriter; | |
} | |
else { | |
return super.getWriter(); | |
} | |
} | |
/** True if the currently executing request is an include. */ | |
public boolean isInclude() { | |
return include; | |
} | |
/** Indicate if the currently executing request is an include. */ | |
public void setInclude(boolean include) { | |
this.include = include; | |
} | |
/** Get the error code that was passed into {@code sendError(int, ..)} */ | |
public Integer getErrorCode() { | |
return errorCode; | |
} | |
/** Clear error code and error message. */ | |
public void clearError() { | |
this.errorCode = null; | |
this.errorMessage = null; | |
} | |
/** | |
* Send the error, if any, to the client. If {@code sendError(int, ..)} has not previously | |
* been called, then do nothing. | |
*/ | |
public void proceed() throws IOException { | |
// Explicitly overflow the buffer so the output gets written | |
if (tempBufferWriter != null) | |
tempBufferWriter.overflow(); | |
if (errorCode != null) { | |
if (errorMessage == null) | |
super.sendError(errorCode); | |
else | |
super.sendError(errorCode, errorMessage); | |
} | |
} | |
} | |
/** | |
* The name of the init-param that can be used to set the size of the buffer used by | |
* {@link TempBufferWriter} before it overflows. | |
*/ | |
public static final String INCLUDE_BUFFER_SIZE_PARAM = "IncludeBufferSize"; | |
/** | |
* The attribute name used to store a reference to {@link net.sourceforge.stripes.controller.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 net.sourceforge.stripes.action.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 FilterConfig filterConfig; | |
private ServletContext servletContext; | |
private StripesFilter stripesFilter; | |
private DispatcherServlet stripesDispatcher; | |
private boolean stripesFilterIsInternal, initializing; | |
public void init(final FilterConfig config) throws ServletException { | |
try { | |
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 (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, "."); | |
} | |
this.filterConfig = config; | |
this.servletContext = config.getServletContext(); | |
this.stripesDispatcher = new DispatcherServlet(); | |
this.stripesDispatcher.init(new ServletConfig() { | |
public String getInitParameter(String name) { | |
return config.getInitParameter(name); | |
} | |
public Enumeration<?> getInitParameterNames() { | |
return config.getInitParameterNames(); | |
} | |
public ServletContext getServletContext() { | |
return config.getServletContext(); | |
} | |
public String getServletName() { | |
return config.getFilterName(); | |
} | |
}); | |
} | |
public void 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 { | |
// Wrap the response in a wrapper that catches errors (but not exceptions) | |
final ErrorTrappingResponseWrapper wrapper = new ErrorTrappingResponseWrapper( | |
(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 | |
boolean fileNotFoundExceptionThrown = false; | |
try { | |
chain.doFilter(request, wrapper); | |
} | |
catch (FileNotFoundException exc) { | |
fileNotFoundExceptionThrown = true; | |
} | |
catch (ServletException ex) { | |
if (ex.getCause() instanceof FileNotFoundException) { | |
fileNotFoundExceptionThrown = true; | |
} else { | |
throw ex; | |
} | |
} | |
// 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 (!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 = getStripesFilter() | |
.getInstanceConfiguration().getActionResolver().getActionBeanType(uri); | |
// If found then call the dispatcher directly. Otherwise, send the error. | |
if (beanType == null) { | |
wrapper.proceed(); | |
} | |
else { | |
stripesDispatcher.service(request, response); | |
} | |
} | |
}); | |
} | |
else { | |
wrapper.proceed(); | |
} | |
} | |
/** | |
* Get the context-relative URI of the current include, forward or request. | |
* | |
* @deprecated Use {@link HttpUtil#getRequestedPath(HttpServletRequest)} instead. | |
*/ | |
@Deprecated | |
protected String getRequestURI(HttpServletRequest request) { | |
// Check for an include | |
String uri = (String) request.getAttribute("javax.servlet.include.request_uri"); | |
// If not an include, then use the request methods | |
if (uri == null) | |
uri = request.getRequestURI(); | |
// Trim the context path from the front | |
String contextPath = request.getContextPath(); | |
if (contextPath.length() > 1) | |
uri = uri.substring(contextPath.length()); | |
return uri; | |
} | |
/** | |
* 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 StripesFilter getStripesFilter() { | |
if (stripesFilter == null) { | |
stripesFilter = (StripesFilter) servletContext.getAttribute(CONTEXT_KEY_STRIPES_FILTER); | |
if (stripesFilter != null) { | |
log.debug("Found StripesFilter in the servlet context."); | |
} | |
} | |
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 { | |
// Check if another thread got into this method before the current thread | |
if (getStripesFilter() != null) | |
return; | |
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 == null || 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 javax.xml.parsers.ParserConfigurationException If thrown by the XML parser | |
* @throws IOException If thrown by the XML parser | |
* @throws org.xml.sax.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 javax.xml.xpath.XPath#evaluate(String, Object, javax.xml.namespace.QName)} | |
* @throws javax.xml.xpath.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 | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment