You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by fm...@apache.org on 2008/01/29 20:51:37 UTC

svn commit: r616499 - /incubator/sling/trunk/launchpad/launchpad-servlets/src/main/java/org/apache/sling/launchpad/servlets/LaunchpadDefaultServlet.java

Author: fmeschbe
Date: Tue Jan 29 11:51:30 2008
New Revision: 616499

URL: http://svn.apache.org/viewvc?rev=616499&view=rev
Log:
SLING-211 Improve streaming of resources by adding LastModified header and
supporting If-Modified-Since

Modified:
    incubator/sling/trunk/launchpad/launchpad-servlets/src/main/java/org/apache/sling/launchpad/servlets/LaunchpadDefaultServlet.java

Modified: incubator/sling/trunk/launchpad/launchpad-servlets/src/main/java/org/apache/sling/launchpad/servlets/LaunchpadDefaultServlet.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/launchpad/launchpad-servlets/src/main/java/org/apache/sling/launchpad/servlets/LaunchpadDefaultServlet.java?rev=616499&r1=616498&r2=616499&view=diff
==============================================================================
--- incubator/sling/trunk/launchpad/launchpad-servlets/src/main/java/org/apache/sling/launchpad/servlets/LaunchpadDefaultServlet.java (original)
+++ incubator/sling/trunk/launchpad/launchpad-servlets/src/main/java/org/apache/sling/launchpad/servlets/LaunchpadDefaultServlet.java Tue Jan 29 11:51:30 2008
@@ -18,6 +18,10 @@
  */
 package org.apache.sling.launchpad.servlets;
 
+import static javax.servlet.http.HttpServletResponse.SC_NOT_MODIFIED;
+import static org.apache.sling.api.servlets.HttpConstants.HEADER_IF_MODIFIED_SINCE;
+import static org.apache.sling.api.servlets.HttpConstants.HEADER_LAST_MODIFIED;
+
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
@@ -27,6 +31,7 @@
 import javax.servlet.Servlet;
 import javax.servlet.ServletConfig;
 import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
 import org.apache.sling.api.SlingHttpServletRequest;
@@ -68,53 +73,59 @@
  *  
  */
 public class LaunchpadDefaultServlet extends SlingAllMethodsServlet {
-    
+
     private Servlet postServlet;
+
     private Servlet defaultGetServlet;
+
     private Servlet ujaxInfoServlet;
+
     private Map<String, Servlet> getServlets;
-    
+
     @Override
     public void init(ServletConfig config) throws ServletException {
-        
+
         super.init(config);
-        
+
         // setup our "internal" servlets
         postServlet = new UjaxPostServlet();
         postServlet.init(config);
-        
+
         ujaxInfoServlet = new UjaxInfoServlet();
         ujaxInfoServlet.init(config);
-        
+
         defaultGetServlet = new PlainTextRendererServlet("text/plain");
-        
+
         getServlets = new HashMap<String, Servlet>();
         getServlets.put("html", new DefaultHtmlRendererServlet("text/html"));
         getServlets.put("json", new JsonRendererServlet("application/json"));
         getServlets.put("txt", defaultGetServlet);
     }
 
-    protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) throws IOException, ServletException {
+    protected void doGet(SlingHttpServletRequest request,
+            SlingHttpServletResponse response) throws IOException,
+            ServletException {
         final Resource resource = request.getResource();
 
-        if(request.getPathInfo().startsWith(UjaxInfoServlet.PATH_PREFIX)) {
+        if (request.getPathInfo().startsWith(UjaxInfoServlet.PATH_PREFIX)) {
             ujaxInfoServlet.service(request, response);
             return;
         }
-        
+
         // cannot handle the request for missing resources
         if (resource instanceof NonExistingResource) {
-            response.sendError(HttpServletResponse.SC_NOT_FOUND,"Resource not found at path " + resource.getPath());
+            response.sendError(HttpServletResponse.SC_NOT_FOUND,
+                "Resource not found at path " + resource.getPath());
             return;
         }
-        
+
         // render using a servlet or binary streaming
         Servlet s = defaultGetServlet;
         InputStream stream = null;
         final String ext = request.getRequestPathInfo().getExtension();
-        if(ext!=null && ext.length() > 0) {
-            // if there is an extension, lookup our getServlets 
-            s = getServlets.get(ext); 
+        if (ext != null && ext.length() > 0) {
+            // if there is an extension, lookup our getServlets
+            s = getServlets.get(ext);
         } else {
             // no extension means we're addressing a static file directly
             // check whether the resource adapts to a stream, spool then
@@ -122,63 +133,102 @@
         }
 
         // render using stream, s, or fail
-        if(stream != null) {
-            stream(response, resource, stream);
-        } else if(s!=null) {
+        if (stream != null) {
+            stream(request, response, resource, stream);
+        } else if (s != null) {
             s.service(request, response);
         } else {
-            response.sendError(
-                    HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
-                    "No default renderer found for extension='" + ext + "'"
-            );
+            response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
+                "No default renderer found for extension='" + ext + "'");
         }
     }
 
-    protected void doPost(SlingHttpServletRequest request, SlingHttpServletResponse response) 
-    throws ServletException,IOException {
+    protected void doPost(SlingHttpServletRequest request,
+            SlingHttpServletResponse response) throws ServletException,
+            IOException {
         postServlet.service(request, response);
     }
-    
+
     /** Stream the Resource to response */
-    private void stream(HttpServletResponse response, Resource resource,
-            InputStream stream) throws IOException {
-        
+    private void stream(HttpServletRequest request,
+            HttpServletResponse response, Resource resource, InputStream stream)
+            throws IOException {
+
         ResourceMetadata meta = resource.getResourceMetadata();
-        
-        final String defaultContentType = "application/octet-stream";
-        String contentType = (String) meta.get(ResourceMetadata.CONTENT_TYPE);
-        if (contentType == null || defaultContentType.equals(contentType)) {
-            // if repository doesn't provide a content-type, or provides the default one,
-            // try to do better using our servlet context
-            final String ct = getServletContext().getMimeType(resource.getPath());
-            if(ct!=null) {
-                contentType = ct;
+
+        // check the last modification time and If-Modified-Since header
+        Long modifTime = (Long) meta.get(ResourceMetadata.MODIFICATION_TIME);
+        if (unmodified(request, modifTime)) {
+
+            response.setStatus(SC_NOT_MODIFIED);
+
+        } else {
+
+            if (modifTime != null) {    
+                response.setDateHeader(HEADER_LAST_MODIFIED, modifTime);
             }
-        }
-        if (contentType != null) {
-            response.setContentType(contentType);
-        }
-        
-        String encoding = (String) meta.get(ResourceMetadata.CHARACTER_ENCODING);
-        if (encoding != null) {
-            response.setCharacterEncoding(encoding);
-        }
-        
-        try {
-            OutputStream out = response.getOutputStream();
-            
-            byte[] buf = new byte[1024];
-            int rd;
-            while ( (rd=stream.read(buf)) >= 0) {
-                out.write(buf, 0, rd);
+
+            final String defaultContentType = "application/octet-stream";
+            String contentType = (String) meta.get(ResourceMetadata.CONTENT_TYPE);
+            if (contentType == null || defaultContentType.equals(contentType)) {
+                // if repository doesn't provide a content-type, or provides the
+                // default one,
+                // try to do better using our servlet context
+                final String ct = getServletContext().getMimeType(
+                    resource.getPath());
+                if (ct != null) {
+                    contentType = ct;
+                }
+            }
+            if (contentType != null) {
+                response.setContentType(contentType);
+            }
+
+            String encoding = (String) meta.get(ResourceMetadata.CHARACTER_ENCODING);
+            if (encoding != null) {
+                response.setCharacterEncoding(encoding);
             }
-            
-        } finally {
+
             try {
-                stream.close();
-            } catch (IOException ignore) {
-                // don't care
+                OutputStream out = response.getOutputStream();
+
+                byte[] buf = new byte[1024];
+                int rd;
+                while ((rd = stream.read(buf)) >= 0) {
+                    out.write(buf, 0, rd);
+                }
+
+            } finally {
+                try {
+                    stream.close();
+                } catch (IOException ignore) {
+                    // don't care
+                }
             }
         }
     }
+
+    /**
+     * Returns <code>true</code> if the request has a
+     * <code>If-Modified-Since</code> header whose date value is later than
+     * the last modification time given as <code>modifTime</code>.
+     * 
+     * @param request The <code>ComponentRequest</code> checked for the
+     *            <code>If-Modified-Since</code> header.
+     * @param modifTime The last modification time to compare the header to.
+     * @return <code>true</code> if the <code>modifTime</code> is less than
+     *         or equal to the time of the <code>If-Modified-Since</code>
+     *         header.
+     */
+    private boolean unmodified(HttpServletRequest request, Long modifTime) {
+        if (modifTime != null) {
+            long modTime = modifTime / 1000; // seconds
+            long ims = request.getDateHeader(HEADER_IF_MODIFIED_SINCE) / 1000;
+            return modTime <= ims;
+        }
+        
+        // we have no modification time value, assume modified
+        return false;
+    }
+
 }