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 [EMAIL PROTECTED] com.opensymphony.xwork2.util.PatternMatcher} 
implementation class */
     public static final String STRUTS_PATTERNMATCHER = "struts.patternMatcher";
 
+    /** The [EMAIL PROTECTED] 
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" />


Reply via email to