diff --git a/spring-faces/src/main/java/org/springframework/faces/ui/resource/FlowResourceHelper.java b/spring-faces/src/main/java/org/springframework/faces/ui/resource/FlowResourceHelper.java index a481a9ba..c6116da2 100644 --- a/spring-faces/src/main/java/org/springframework/faces/ui/resource/FlowResourceHelper.java +++ b/spring-faces/src/main/java/org/springframework/faces/ui/resource/FlowResourceHelper.java @@ -113,8 +113,6 @@ public class FlowResourceHelper { return; } - RequestContext requestContext = RequestContextHolder.getRequestContext(); - ResponseWriter writer = facesContext.getResponseWriter(); writer.startElement("script", null); diff --git a/spring-faces/src/main/java/org/springframework/faces/ui/resource/ResourceServlet.java b/spring-faces/src/main/java/org/springframework/faces/ui/resource/ResourceServlet.java new file mode 100644 index 00000000..1900ec38 --- /dev/null +++ b/spring-faces/src/main/java/org/springframework/faces/ui/resource/ResourceServlet.java @@ -0,0 +1,127 @@ +package org.springframework.faces.ui.resource; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLConnection; +import java.util.HashMap; +import java.util.Map; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.util.ClassUtils; + +/** + * Special action for resolving and rendering static resources from within a JAR file. + * + * @author Jeremy Grelle + */ +public class ResourceServlet extends HttpServlet { + + private static final String HTTP_CONTENT_LENGTH_HEADER = "Content-Length"; + + private static final String HTTP_LAST_MODIFIED_HEADER = "Last-Modified"; + + private static final String HTTP_EXPIRES_HEADER = "Expires"; + + private static final String HTTP_CACHE_CONTROL_HEADER = "Cache-Control"; + + private Map defaultMimeTypes = new HashMap(); + { + defaultMimeTypes.put(".css", "text/css"); + defaultMimeTypes.put(".gif", "image/gif"); + defaultMimeTypes.put(".ico", "image/vnd.microsoft.icon"); + defaultMimeTypes.put(".jpeg", "image/jpeg"); + defaultMimeTypes.put(".jpg", "image/jpeg"); + defaultMimeTypes.put(".js", "text/javascript"); + defaultMimeTypes.put(".png", "image/png"); + } + + protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + + URL resource = getRequestResourceURL(request); + + if (resource == null) { + response.setStatus(HttpServletResponse.SC_NOT_FOUND); + return; + } + + URLConnection resourceConn = resource.openConnection(); + long lastModified = resourceConn.getLastModified(); + + String mimeType = getServletContext().getMimeType(resource.getPath()); + if (mimeType == null) { + String extension = resource.getPath().substring(resource.getPath().lastIndexOf('.')); + mimeType = (String) defaultMimeTypes.get(extension); + } + response.setContentType(mimeType); + + response.setHeader(HTTP_CONTENT_LENGTH_HEADER, Long.toString(resourceConn.getContentLength())); + response.setDateHeader(HTTP_LAST_MODIFIED_HEADER, lastModified); + configureCaching(response, 31556926); + + InputStream in = resourceConn.getInputStream(); + OutputStream out = response.getOutputStream(); + try { + byte[] buffer = new byte[1024]; + while (in.available() > 0) { + int len = in.read(buffer); + out.write(buffer, 0, len); + } + } finally { + in.close(); + out.close(); + } + } + + protected long getLastModified(HttpServletRequest request) { + URL resource; + try { + resource = getRequestResourceURL(request); + } catch (MalformedURLException e) { + return -1; + } + + if (resource == null) { + return -1; + } + + URLConnection resourceConn; + try { + resourceConn = resource.openConnection(); + } catch (IOException e) { + return -1; + } + return resourceConn.getLastModified(); + } + + private URL getRequestResourceURL(HttpServletRequest request) throws MalformedURLException { + String localResourcePath = request.getPathInfo().toString(); + String jarResourcePath = "META-INF" + request.getPathInfo().toString(); + + URL resource; + + resource = getServletContext().getResource(localResourcePath); + if (resource == null) { + resource = ClassUtils.getDefaultClassLoader().getResource(jarResourcePath); + } + + return resource; + } + + /** + * Set HTTP headers to allow caching for the given number of seconds. + * @param seconds number of seconds into the future that the response should be cacheable for + */ + private void configureCaching(HttpServletResponse response, int seconds) { + // HTTP 1.0 header + response.setDateHeader(HTTP_EXPIRES_HEADER, System.currentTimeMillis() + seconds * 1000L); + // HTTP 1.1 header + response.setHeader(HTTP_CACHE_CONTROL_HEADER, "max-age=" + seconds); + } +}