Author: rgielen Date: Thu Aug 21 14:56:46 2008 New Revision: 687874 URL: http://svn.apache.org/viewvc?rev=687874&view=rev Log: WW-2779: Applying Musachy's fix to 2.0.x branch
Modified: struts/struts2/branches/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/dispatcher/FilterDispatcher.java Modified: struts/struts2/branches/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/dispatcher/FilterDispatcher.java URL: http://svn.apache.org/viewvc/struts/struts2/branches/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/dispatcher/FilterDispatcher.java?rev=687874&r1=687873&r2=687874&view=diff ============================================================================== --- struts/struts2/branches/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/dispatcher/FilterDispatcher.java (original) +++ struts/struts2/branches/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/dispatcher/FilterDispatcher.java Thu Aug 21 14:56:46 2008 @@ -23,7 +23,9 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.io.UnsupportedEncodingException; import java.net.URLDecoder; +import java.net.URL; import java.util.ArrayList; import java.util.Calendar; import java.util.Enumeration; @@ -431,62 +433,31 @@ * Locate a static resource and copy directly to the response, * setting the appropriate caching headers. * - * @param name The resource name + * @param path The resource path * @param request The request * @param response The response * @throws IOException If anything goes wrong */ - protected void findStaticResource(String name, HttpServletRequest request, HttpServletResponse response) throws IOException { - if (!name.endsWith(".class")) { - for (String pathPrefix : pathPrefixes) { - InputStream is = findInputStream(name, pathPrefix); + public void findStaticResource(String path, HttpServletRequest request, HttpServletResponse response) + throws IOException { + String name = cleanupPath(path); + for (String pathPrefix : pathPrefixes) { + URL resourceUrl = findResource(buildPath(name, pathPrefix)); + if (resourceUrl != null) { + InputStream is = null; + try { + //check that the resource path is under the pathPrefix path + String pathEnding = buildPath(name, pathPrefix); + if (resourceUrl.getFile().endsWith(pathEnding)) + is = resourceUrl.openStream(); + } catch (Exception ex) { + // just ignore it + continue; + } + + //not inside the try block, as this could throw IOExceptions also if (is != null) { - Calendar cal = Calendar.getInstance(); - - // check for if-modified-since, prior to any other headers - long ifModifiedSince = 0; - try { - ifModifiedSince = request.getDateHeader("If-Modified-Since"); - } catch (Exception e) { - LOG.warn("Invalid If-Modified-Since header value: '" + request.getHeader("If-Modified-Since") + "', ignoring"); - } - long lastModifiedMillis = lastModifiedCal.getTimeInMillis(); - long now = cal.getTimeInMillis(); - cal.add(Calendar.DAY_OF_MONTH, 1); - long expires = cal.getTimeInMillis(); - - if (ifModifiedSince > 0 && ifModifiedSince <= lastModifiedMillis) { - // not modified, content is not sent - only basic headers and status SC_NOT_MODIFIED - response.setDateHeader("Expires", expires); - response.setStatus(HttpServletResponse.SC_NOT_MODIFIED); - is.close(); - return; - } - - // set the content-type header - String contentType = getContentType(name); - if (contentType != null) { - response.setContentType(contentType); - } - - if (serveStaticBrowserCache) { - // set heading information for caching static content - response.setDateHeader("Date", now); - response.setDateHeader("Expires", expires); - response.setDateHeader("Retry-After", expires); - response.setHeader("Cache-Control", "public"); - response.setDateHeader("Last-Modified", lastModifiedMillis); - } else { - response.setHeader("Cache-Control", "no-cache"); - response.setHeader("Pragma", "no-cache"); - response.setHeader("Expires", "-1"); - } - - try { - copy(is, response.getOutputStream()); - } finally { - is.close(); - } + process(is, path, request, response); return; } } @@ -496,6 +467,88 @@ } /** + * Look for a static resource in the classpath. + * + * @param path The resource path + * @return The inputstream of the resource + * @throws IOException If there is a problem locating the resource + */ + protected URL findResource(String path) throws IOException { + return ClassLoaderUtil.getResource(path, getClass()); + } + + /** + * @param name resource name + * @param packagePrefix The package prefix to use to locate the resource + * @return full path + * @throws java.io.UnsupportedEncodingException + * @throws IOException + */ + protected String buildPath(String name, String packagePrefix) throws UnsupportedEncodingException { + String resourcePath; + if (packagePrefix.endsWith("/") && name.startsWith("/")) { + resourcePath = packagePrefix + name.substring(1); + } else { + resourcePath = packagePrefix + name; + } + + return URLDecoder.decode(resourcePath, encoding); + } + + protected void process(InputStream is, String path, HttpServletRequest request, HttpServletResponse response) throws IOException { + if (is != null) { + Calendar cal = Calendar.getInstance(); + + // check for if-modified-since, prior to any other headers + long ifModifiedSince = 0; + try { + ifModifiedSince = request.getDateHeader("If-Modified-Since"); + } catch (Exception e) { + LOG.warn("Invalid If-Modified-Since header value: '" + + request.getHeader("If-Modified-Since") + "', ignoring"); + } + long lastModifiedMillis = lastModifiedCal.getTimeInMillis(); + long now = cal.getTimeInMillis(); + cal.add(Calendar.DAY_OF_MONTH, 1); + long expires = cal.getTimeInMillis(); + + if (ifModifiedSince > 0 && ifModifiedSince <= lastModifiedMillis) { + // not modified, content is not sent - only basic + // headers and status SC_NOT_MODIFIED + response.setDateHeader("Expires", expires); + response.setStatus(HttpServletResponse.SC_NOT_MODIFIED); + is.close(); + return; + } + + // set the content-type header + String contentType = getContentType(path); + if (contentType != null) { + response.setContentType(contentType); + } + + if (serveStaticBrowserCache) { + // set heading information for caching static content + response.setDateHeader("Date", now); + response.setDateHeader("Expires", expires); + response.setDateHeader("Retry-After", expires); + response.setHeader("Cache-Control", "public"); + response.setDateHeader("Last-Modified", lastModifiedMillis); + } else { + response.setHeader("Cache-Control", "no-cache"); + response.setHeader("Pragma", "no-cache"); + response.setHeader("Expires", "-1"); + } + + try { + copy(is, response.getOutputStream()); + } finally { + is.close(); + } + } + } + + /** * Determine the content type for the resource name. * * @param name The resource name @@ -559,4 +612,13 @@ return ClassLoaderUtil.getResourceAsStream(resourcePath, getClass()); } + + /** + * @param path requested path + * @return path without leading "/struts" or "/static" + */ + protected String cleanupPath(String path) { + //path will start with "/struts" or "/static", remove them + return path.substring(7); + } }