You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@struts.apache.org by mu...@apache.org on 2008/05/05 15:09:51 UTC
svn commit: r653471 - in /struts/struts2/trunk/core/src/main:
java/org/apache/struts2/ java/org/apache/struts2/config/
java/org/apache/struts2/dispatcher/ resources/
Author: musachy
Date: Mon May 5 06:09:50 2008
New Revision: 653471
URL: http://svn.apache.org/viewvc?rev=653471&view=rev
Log:
* Refactor static content loading out of FilterDispatcher into DefaultStaticContentLoader, and add an extension point for it.
Added:
struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/DefaultStaticContentLoader.java
struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/StaticContentLoader.java
Modified:
struts/struts2/trunk/core/src/main/java/org/apache/struts2/StrutsConstants.java
struts/struts2/trunk/core/src/main/java/org/apache/struts2/config/BeanSelectionProvider.java
struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/FilterDispatcher.java
struts/struts2/trunk/core/src/main/resources/struts-default.xml
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=653471&r1=653470&r2=653471&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 Mon May 5 06:09:50 2008
@@ -184,4 +184,7 @@
/** The {@link com.opensymphony.xwork2.util.PatternMatcher} implementation class */
public static final String STRUTS_PATTERNMATCHER = "struts.patternMatcher";
+ /** The {@link org.apache.struts2.dispatcher.StaticContentLoader} implementation class */
+ public static final String STRUTS_STATIC_CONTENT_LOADER = "struts.staticContentLoader";
+
}
Modified: struts/struts2/trunk/core/src/main/java/org/apache/struts2/config/BeanSelectionProvider.java
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/java/org/apache/struts2/config/BeanSelectionProvider.java?rev=653471&r1=653470&r2=653471&view=diff
==============================================================================
--- struts/struts2/trunk/core/src/main/java/org/apache/struts2/config/BeanSelectionProvider.java (original)
+++ struts/struts2/trunk/core/src/main/java/org/apache/struts2/config/BeanSelectionProvider.java Mon May 5 06:09:50 2008
@@ -26,6 +26,8 @@
import org.apache.struts2.StrutsConstants;
import org.apache.struts2.components.UrlRenderer;
+import org.apache.struts2.dispatcher.DefaultStaticContentLoader;
+import org.apache.struts2.dispatcher.StaticContentLoader;
import org.apache.struts2.dispatcher.mapper.ActionMapper;
import org.apache.struts2.dispatcher.multipart.MultiPartRequest;
import org.apache.struts2.views.freemarker.FreemarkerManager;
@@ -151,6 +153,12 @@
* <td>singleton</td>
* <td>Matches patterns, such as action names, generally used in configuration (since 2.1)</td>
* </tr>
+ * <tr>
+ * <td>org.apache.struts2.views.dispatcher.DefaultStaticContentLoader</td>
+ * <td>struts.staticContentLoader</td>
+ * <td>singleton</td>
+ * <td>Loads static resources (since 2.1)</td>
+ * </tr>
* </table>
*
* <!-- END SNIPPET: extensionPoints -->
@@ -209,6 +217,7 @@
alias(ReflectionProvider.class, StrutsConstants.STRUTS_REFLECTIONPROVIDER, builder, props);
alias(ReflectionContextFactory.class, StrutsConstants.STRUTS_REFLECTIONCONTEXTFACTORY, builder, props);
alias(PatternMatcher.class, StrutsConstants.STRUTS_PATTERNMATCHER, builder, props);
+ alias(StaticContentLoader.class, StrutsConstants.STRUTS_STATIC_CONTENT_LOADER, builder, props);
if ("true".equalsIgnoreCase(props.getProperty(StrutsConstants.STRUTS_DEVMODE))) {
props.setProperty(StrutsConstants.STRUTS_I18N_RELOAD, "true");
Added: struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/DefaultStaticContentLoader.java
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/DefaultStaticContentLoader.java?rev=653471&view=auto
==============================================================================
--- struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/DefaultStaticContentLoader.java (added)
+++ struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/DefaultStaticContentLoader.java Mon May 5 06:09:50 2008
@@ -0,0 +1,343 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.struts2.dispatcher;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.List;
+import java.util.StringTokenizer;
+
+import javax.servlet.FilterConfig;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.struts2.StrutsConstants;
+import org.apache.struts2.util.ClassLoaderUtils;
+
+import com.opensymphony.xwork2.inject.Inject;
+import com.opensymphony.xwork2.util.ClassLoaderUtil;
+import com.opensymphony.xwork2.util.logging.Logger;
+import com.opensymphony.xwork2.util.logging.LoggerFactory;
+
+public class DefaultStaticContentLoader implements StaticContentLoader {
+ /**
+ * Provide a logging instance.
+ */
+ private Logger log;
+
+ /**
+ * Store set of path prefixes to use with static resources.
+ */
+ protected String[] pathPrefixes;
+
+ /**
+ * Store state of StrutsConstants.STRUTS_SERVE_STATIC_CONTENT setting.
+ */
+ protected boolean serveStatic;
+
+ /**
+ * Store state of StrutsConstants.STRUTS_SERVE_STATIC_BROWSER_CACHE setting.
+ */
+ protected boolean serveStaticBrowserCache;
+
+ /**
+ * Provide a formatted date for setting heading information when caching static content.
+ */
+ protected final Calendar lastModifiedCal = Calendar.getInstance();
+
+ /**
+ * Store state of StrutsConstants.STRUTS_I18N_ENCODING setting.
+ */
+ protected String encoding;
+
+
+ /**
+ * Modify state of StrutsConstants.STRUTS_SERVE_STATIC_CONTENT setting.
+ *
+ * @param val
+ * New setting
+ */
+ @Inject(StrutsConstants.STRUTS_SERVE_STATIC_CONTENT)
+ public void setServeStaticContent(String val) {
+ serveStatic = "true".equals(val);
+ }
+
+ /**
+ * Modify state of StrutsConstants.STRUTS_SERVE_STATIC_BROWSER_CACHE
+ * setting.
+ *
+ * @param val
+ * New setting
+ */
+ @Inject(StrutsConstants.STRUTS_SERVE_STATIC_BROWSER_CACHE)
+ public void setServeStaticBrowserCache(String val) {
+ serveStaticBrowserCache = "true".equals(val);
+ }
+
+ /**
+ * Modify state of StrutsConstants.STRUTS_I18N_ENCODING setting.
+ * @param val New setting
+ */
+ @Inject(StrutsConstants.STRUTS_I18N_ENCODING)
+ public void setEncoding(String val) {
+ encoding = val;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.struts2.dispatcher.StaticResourceLoader#setFilterConfig(javax.servlet.FilterConfig)
+ */
+ public void setFilterConfig(FilterConfig filterConfig) {
+ String param = filterConfig.getInitParameter("packages");
+ String packages = getAdditionalPackages();
+ if (param != null) {
+ packages = param + " " + packages;
+ }
+ this.pathPrefixes = parse(packages);
+ initLogging(filterConfig);
+ }
+
+ protected String getAdditionalPackages() {
+ return "org.apache.struts2.static template org.apache.struts2.interceptor.debugging static";
+ }
+
+ /**
+ * Create a string array from a comma-delimited list of packages.
+ *
+ * @param packages
+ * A comma-delimited String listing packages
+ * @return A string array of packages
+ */
+ protected String[] parse(String packages) {
+ if (packages == null) {
+ return null;
+ }
+ List<String> pathPrefixes = new ArrayList<String>();
+
+ StringTokenizer st = new StringTokenizer(packages, ", \n\t");
+ while (st.hasMoreTokens()) {
+ String pathPrefix = st.nextToken().replace('.', '/');
+ if (!pathPrefix.endsWith("/")) {
+ pathPrefix += "/";
+ }
+ pathPrefixes.add(pathPrefix);
+ }
+
+ return pathPrefixes.toArray(new String[pathPrefixes.size()]);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.struts2.dispatcher.StaticResourceLoader#findStaticResource(java.lang.String,
+ * javax.servlet.http.HttpServletRequest,
+ * javax.servlet.http.HttpServletResponse)
+ */
+ public void findStaticResource(String path, HttpServletRequest request, HttpServletResponse response)
+ throws IOException {
+ String name = cleanupPath(path);
+ if (!name.endsWith(".class")) {
+ for (String pathPrefix : pathPrefixes) {
+ InputStream is = findInputStream(buildPath(name, pathPrefix));
+ if (is != null) {
+ process(is, path, request, response);
+ return;
+ }
+ }
+ }
+
+ response.sendError(HttpServletResponse.SC_NOT_FOUND);
+ }
+
+ 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();
+ }
+ return;
+ }
+ }
+
+ private void initLogging(FilterConfig 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) {
+ System.err.println("Unable to instantiate logger factory: "+factoryName+", using default");
+ e.printStackTrace();
+ } catch (IllegalAccessException e) {
+ System.err.println("Unable to access logger factory: "+factoryName+", using default");
+ e.printStackTrace();
+ } catch (ClassNotFoundException e) {
+ System.err.println("Unable to locate logger factory class: "+factoryName+", using default");
+ e.printStackTrace();
+ }
+ }
+
+ log = LoggerFactory.getLogger(FilterDispatcher.class);
+
+ }
+
+ /**
+ * 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 InputStream findInputStream(String path) throws IOException {
+ return ClassLoaderUtil.getResourceAsStream(path, getClass());
+ }
+
+ /**
+ * @param name resource name
+ * @param packagePrefix The package prefix to use to locate the resource
+ * @return full path
+ * @throws 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);
+ }
+
+
+
+ /**
+ * Determine the content type for the resource name.
+ *
+ * @param name The resource name
+ * @return The mime type
+ */
+ protected String getContentType(String name) {
+ // NOT using the code provided activation.jar to avoid adding yet another dependency
+ // this is generally OK, since these are the main files we server up
+ if (name.endsWith(".js")) {
+ return "text/javascript";
+ } else if (name.endsWith(".css")) {
+ return "text/css";
+ } else if (name.endsWith(".html")) {
+ return "text/html";
+ } else if (name.endsWith(".txt")) {
+ return "text/plain";
+ } else if (name.endsWith(".gif")) {
+ return "image/gif";
+ } else if (name.endsWith(".jpg") || name.endsWith(".jpeg")) {
+ return "image/jpeg";
+ } else if (name.endsWith(".png")) {
+ return "image/png";
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Copy bytes from the input stream to the output stream.
+ *
+ * @param input
+ * The input stream
+ * @param output
+ * The output stream
+ * @throws IOException
+ * If anything goes wrong
+ */
+ protected void copy(InputStream input, OutputStream output) throws IOException {
+ final byte[] buffer = new byte[4096];
+ int n;
+ while (-1 != (n = input.read(buffer))) {
+ output.write(buffer, 0, n);
+ }
+ output.flush();
+ }
+
+ public boolean canHandle(String resourcePath) {
+ return serveStatic && (resourcePath.startsWith("/struts") || resourcePath.startsWith("/static"));
+ }
+
+ /**
+ * @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);
+ }
+}
Modified: struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/FilterDispatcher.java
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/FilterDispatcher.java?rev=653471&r1=653470&r2=653471&view=diff
==============================================================================
--- struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/FilterDispatcher.java (original)
+++ struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/FilterDispatcher.java Mon May 5 06:09:50 2008
@@ -157,31 +157,6 @@
private Logger log;
/**
- * Store set of path prefixes to use with static resources.
- */
- private String[] pathPrefixes;
-
- /**
- * Provide a formatted date for setting heading information when caching static content.
- */
- private final Calendar lastModifiedCal = Calendar.getInstance();
-
- /**
- * Store state of StrutsConstants.STRUTS_SERVE_STATIC_CONTENT setting.
- */
- private boolean serveStatic;
-
- /**
- * Store state of StrutsConstants.STRUTS_SERVE_STATIC_BROWSER_CACHE setting.
- */
- private boolean serveStaticBrowserCache;
-
- /**
- * Store state of StrutsConstants.STRUTS_I18N_ENCODING setting.
- */
- private String encoding;
-
- /**
* Provide ActionMapper instance, set by injection.
*/
private ActionMapper actionMapper;
@@ -197,6 +172,11 @@
protected Dispatcher dispatcher;
/**
+ * Loads stattic resources, set by injection
+ */
+ protected StaticContentLoader staticResourceLoader;
+
+ /**
* Initializes the filter by creating a default dispatcher
* and setting the default packages for static resources.
*
@@ -212,12 +192,7 @@
dispatcher.init();
dispatcher.getContainer().inject(this);
- String param = filterConfig.getInitParameter("packages");
- String packages = "org.apache.struts2.static template org.apache.struts2.interceptor.debugging";
- if (param != null) {
- packages = param + " " + packages;
- }
- this.pathPrefixes = parse(packages);
+ staticResourceLoader.setFilterConfig(filterConfig);
} finally {
ActionContext.setContext(null);
}
@@ -282,38 +257,16 @@
}
/**
- * Modify state of StrutsConstants.STRUTS_SERVE_STATIC_CONTENT setting.
- *
- * @param val New setting
- */
- @Inject(StrutsConstants.STRUTS_SERVE_STATIC_CONTENT)
- public void setServeStaticContent(String val) {
- serveStatic = "true".equals(val);
- }
-
- /**
- * Modify state of StrutsConstants.STRUTS_SERVE_STATIC_BROWSER_CACHE setting.
- *
- * @param val New setting
- */
- @Inject(StrutsConstants.STRUTS_SERVE_STATIC_BROWSER_CACHE)
- public void setServeStaticBrowserCache(String val) {
- serveStaticBrowserCache = "true".equals(val);
- }
-
- /**
- * Modify state of StrutsConstants.STRUTS_I18N_ENCODING setting.
- *
- * @param val New setting
+ * Modify state of StrutsConstants.STRUTS_STATIC_CONTENT_LOADER setting.
+ * @param staticResourceLoader val New setting
*/
- @Inject(StrutsConstants.STRUTS_I18N_ENCODING)
- public void setEncoding(String val) {
- encoding = val;
+ @Inject
+ public void setStaticResourceLoader(StaticContentLoader staticResourceLoader) {
+ this.staticResourceLoader = staticResourceLoader;
}
/**
* Modify ActionMapper instance.
- *
* @param mapper New instance
*/
@Inject
@@ -384,31 +337,6 @@
}
/**
- * Create a string array from a comma-delimited list of packages.
- *
- * @param packages A comma-delimited String listing packages
- * @return A string array of packages
- */
- protected String[] parse(String packages) {
- if (packages == null) {
- return null;
- }
- List<String> pathPrefixes = new ArrayList<String>();
-
- StringTokenizer st = new StringTokenizer(packages, ", \n\t");
- while (st.hasMoreTokens()) {
- String pathPrefix = st.nextToken().replace('.', '/');
- if (!pathPrefix.endsWith("/")) {
- pathPrefix += "/";
- }
- pathPrefixes.add(pathPrefix);
- }
-
- return pathPrefixes.toArray(new String[pathPrefixes.size()]);
- }
-
-
- /**
* Process an action or handle a request a static resource.
* <p/>
* The filter tries to match the request to an action mapping.
@@ -456,9 +384,8 @@
resourcePath = request.getPathInfo();
}
- if (serveStatic && resourcePath.startsWith("/struts")) {
- String name = resourcePath.substring("/struts".length());
- findStaticResource(name, request, response);
+ if (staticResourceLoader.canHandle(resourcePath)) {
+ staticResourceLoader.findStaticResource(resourcePath, request, response);
} else {
// this is a normal request, let it pass through
chain.doFilter(request, response);
@@ -477,137 +404,4 @@
}
}
}
-
- /**
- * Locate a static resource and copy directly to the response,
- * setting the appropriate caching headers.
- *
- * @param name The resource name
- * @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);
- 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();
- }
- return;
- }
- }
- }
-
- response.sendError(HttpServletResponse.SC_NOT_FOUND);
- }
-
- /**
- * Determine the content type for the resource name.
- *
- * @param name The resource name
- * @return The mime type
- */
- protected String getContentType(String name) {
- // NOT using the code provided activation.jar to avoid adding yet another dependency
- // this is generally OK, since these are the main files we server up
- if (name.endsWith(".js")) {
- return "text/javascript";
- } else if (name.endsWith(".css")) {
- return "text/css";
- } else if (name.endsWith(".html")) {
- return "text/html";
- } else if (name.endsWith(".txt")) {
- return "text/plain";
- } else if (name.endsWith(".gif")) {
- return "image/gif";
- } else if (name.endsWith(".jpg") || name.endsWith(".jpeg")) {
- return "image/jpeg";
- } else if (name.endsWith(".png")) {
- return "image/png";
- } else {
- return null;
- }
- }
-
- /**
- * Copy bytes from the input stream to the output stream.
- *
- * @param input The input stream
- * @param output The output stream
- * @throws IOException If anything goes wrong
- */
- protected void copy(InputStream input, OutputStream output) throws IOException {
- final byte[] buffer = new byte[4096];
- int n;
- while (-1 != (n = input.read(buffer))) {
- output.write(buffer, 0, n);
- }
- output.flush();
- }
-
- /**
- * Look for a static resource in the classpath.
- *
- * @param name The resource name
- * @param packagePrefix The package prefix to use to locate the resource
- * @return The inputstream of the resource
- * @throws IOException If there is a problem locating the resource
- */
- protected InputStream findInputStream(String name, String packagePrefix) throws IOException {
- String resourcePath;
- if (packagePrefix.endsWith("/") && name.startsWith("/")) {
- resourcePath = packagePrefix + name.substring(1);
- } else {
- resourcePath = packagePrefix + name;
- }
-
- resourcePath = URLDecoder.decode(resourcePath, encoding);
-
- return ClassLoaderUtil.getResourceAsStream(resourcePath, getClass());
- }
}
Added: struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/StaticContentLoader.java
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/StaticContentLoader.java?rev=653471&view=auto
==============================================================================
--- struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/StaticContentLoader.java (added)
+++ struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/StaticContentLoader.java Mon May 5 06:09:50 2008
@@ -0,0 +1,64 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.struts2.dispatcher;
+
+import java.io.IOException;
+
+import javax.servlet.FilterConfig;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * Interface for loading static resources, based on a path
+ *
+ */
+public interface StaticContentLoader {
+
+ /**
+ * @param path
+ * Requested resource path
+ * @return true if this loader is able to load this type of resource, false otherwise
+ */
+ public boolean canHandle(String path);
+
+ /**
+ * @param filterConfig
+ * The filter configuration
+ */
+ public abstract void setFilterConfig(FilterConfig filterConfig);
+
+ /**
+ * Locate a static resource and copy directly to the response, setting the
+ * appropriate caching headers.
+ *
+ * @param name
+ * The resource name
+ * @param request
+ * The request
+ * @param response
+ * The response
+ * @throws IOException
+ * If anything goes wrong
+ */
+ public abstract void findStaticResource(String path, HttpServletRequest request, HttpServletResponse response)
+ throws IOException;
+
+}
\ No newline at end of file
Modified: struts/struts2/trunk/core/src/main/resources/struts-default.xml
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/resources/struts-default.xml?rev=653471&r1=653470&r2=653471&view=diff
==============================================================================
--- struts/struts2/trunk/core/src/main/resources/struts-default.xml (original)
+++ struts/struts2/trunk/core/src/main/resources/struts-default.xml Mon May 5 06:09:50 2008
@@ -95,6 +95,8 @@
<bean class="org.apache.struts2.views.jsp.ui.OgnlTool" />
+ <bean type="org.apache.struts2.dispatcher.StaticContentLoader" class="org.apache.struts2.dispatcher.DefaultStaticContentLoader" name="struts" />
+
<!-- Silly workarounds for OGNL since there is currently no way to flush its internal caches -->
<bean type="ognl.PropertyAccessor" name="java.util.ArrayList" class="com.opensymphony.xwork2.ognl.accessor.XWorkListPropertyAccessor" />
<bean type="ognl.PropertyAccessor" name="java.util.HashSet" class="com.opensymphony.xwork2.ognl.accessor.XWorkCollectionPropertyAccessor" />