Fehler durch mehrfaches Mappen des AcceleratorFilters auf ein URI behandelt
[percentcodec] / cachecontrol / src / main / java / de / halbekunst / juplo / cachecontrol / AcceleratorFilter.java
index f0037bf..8e63222 100644 (file)
@@ -27,6 +27,7 @@ import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowire;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Configurable;
+import org.springframework.beans.factory.annotation.Qualifier;
 
 
 
@@ -46,7 +47,7 @@ public class AcceleratorFilter implements Filter {
 
 
   @Autowired CacheControl cacheControl;
-  @Autowired(required=false) Integer defaultBufferSize = DEFAULT_BUFFER_SIZE;
+  @Autowired(required=false) @Qualifier("defaultBufferSize") Integer defaultBufferSize = DEFAULT_BUFFER_SIZE;
   @Autowired String eTag;
   @Autowired Boolean weak;
   @Autowired Long lastModified;
@@ -61,21 +62,36 @@ public class AcceleratorFilter implements Filter {
       return;
     }
 
-    // TODO: Das macht so wahrscheinlich keinen Sinn...
-    /** Prüfen, ob es sich um eine Anfrage für einen JSP-Include handelt */
-    if (request.getAttribute(REQUEST_URI_ATTRIBUTE) != null) {
-      log.debug("Includes cannot be accelerated");
-      chain.doFilter(request, response);
-      return;
-    }
-
     HttpServletRequest httpRequest = (HttpServletRequest)request;
     HttpServletResponse httpResponse = (HttpServletResponse)response;
-    AccelerationWrapper wrapper = new AccelerationWrapper(httpRequest, httpResponse);
+
+    AccelerationWrapper wrapper;
+
+    wrapper = (AccelerationWrapper)request.getAttribute(AcceleratorFilter.RESPONSE_WRAPPER);
+    if (wrapper != null) {
+      if (wrapper.getFilter() == this) {
+        /** Ignore multiple mappings of the same filter-instance */
+        log.warn("Ignoring multiple mappings on same URL: {}", httpRequest.getRequestURI());
+        chain.doFilter(request, response);
+        return;
+      }
+      else {
+        log.error("Only one instance of AcceleratorFilter must be mapped to any URL: {}", httpRequest.getRequestURI());
+        httpResponse.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Only one instance of AcceleratorFilter must be mapped to any URL!");
+        return;
+      }
+    }
+
+    wrapper = new AccelerationWrapper(httpRequest, httpResponse);
     httpRequest.setAttribute(RESPONSE_WRAPPER, wrapper);
     cacheControl.init(wrapper);
-    chain.doFilter(request, wrapper);
-    wrapper.finish();
+    try {
+      chain.doFilter(request, wrapper);
+      wrapper.finish();
+    }
+    catch (NotModifiedException nm) {
+      log.trace("Not modified: {}", httpRequest.getRequestURI());
+    }
   }
 
   @Override
@@ -145,6 +161,10 @@ public class AcceleratorFilter implements Filter {
     }
 
 
+    private AcceleratorFilter getFilter() {
+      return AcceleratorFilter.this;
+    }
+
     private void finish() throws IOException {
       flushBuffer();
       out.close();
@@ -332,6 +352,7 @@ public class AcceleratorFilter implements Filter {
        */
       response.reset();
       pos = 0;
+      size = 0;
       stream = null;
       writer = null;
     }
@@ -342,8 +363,6 @@ public class AcceleratorFilter implements Filter {
         writer.flush();
       else if (stream != null)
         stream.flush();
-
-      out.flush();
     }
 
     @Override
@@ -648,9 +667,17 @@ public class AcceleratorFilter implements Filter {
       public void write(int i) throws IOException {
         if (pos == bufferSize) {
           out().write(buffer);
-          pos = 0;
           committed = true;
-          cacheControl.decorate(request, response, this);
+          /** Dekoration nur beim ersten Schreib-Schub anstoßen */
+          if (pos == size) {
+            if (!cacheControl.decorate(request, response)) {
+              zipped = false;
+              os = null;
+              pos = 0;
+              throw new NotModifiedException();
+            }
+          }
+          pos = 0;
         }
         buffer[pos++] = (byte) i;
         size++;
@@ -662,7 +689,15 @@ public class AcceleratorFilter implements Filter {
           return;
 
         committed = true;
-        cacheControl.decorate(request, response, this);
+        /** Dekoration nur beim ersten Schreib-Schub anstoßen */
+        if (pos == size) {
+          if (!cacheControl.decorate(request, response)) {
+            zipped = false;
+            os = null;
+            pos = 0;
+            throw new NotModifiedException();
+          }
+        }
         out().write(buffer, 0, pos);
         out().flush();
         pos = 0;
@@ -673,7 +708,8 @@ public class AcceleratorFilter implements Filter {
         if (size == 0) {
           committed = true;
           zipped = false;
-          cacheControl.decorate(request, response, this);
+          if (!cacheControl.decorate(request, response))
+            throw new NotModifiedException();
           sos.close();
         }
         else {
@@ -684,3 +720,5 @@ public class AcceleratorFilter implements Filter {
     }
   }
 }
+
+class NotModifiedException extends IOException {}
\ No newline at end of file