Index: java/org/apache/coyote/http11/Http11Protocol.java
===================================================================
--- java/org/apache/coyote/http11/Http11Protocol.java	(revision 1392028)
+++ java/org/apache/coyote/http11/Http11Protocol.java	(working copy)
@@ -173,6 +173,7 @@
             processor.setDisableUploadTimeout(proto.getDisableUploadTimeout());
             processor.setCompressionMinSize(proto.getCompressionMinSize());
             processor.setCompression(proto.getCompression());
+            processor.setCompressionFilters(proto.getCompressionFilters());
             processor.setNoCompressionUserAgents(proto.getNoCompressionUserAgents());
             processor.setCompressableMimeTypes(proto.getCompressableMimeTypes());
             processor.setRestrictedUserAgents(proto.getRestrictedUserAgents());
Index: java/org/apache/coyote/http11/AbstractHttp11Processor.java
===================================================================
--- java/org/apache/coyote/http11/AbstractHttp11Processor.java	(revision 1392028)
+++ java/org/apache/coyote/http11/AbstractHttp11Processor.java	(working copy)
@@ -18,6 +18,7 @@
 
 import java.io.IOException;
 import java.io.InterruptedIOException;
+import java.util.LinkedList;
 import java.util.Locale;
 import java.util.StringTokenizer;
 import java.util.concurrent.atomic.AtomicBoolean;
@@ -261,6 +262,12 @@
     protected UpgradeInbound upgradeInbound = null;
 
 
+    /**
+     * Filters suitable for compressing output.
+     */
+    protected CompressionFilter[] compressionFilters = null;
+
+
     public AbstractHttp11Processor(AbstractEndpoint endpoint) {
         super(endpoint);
     }
@@ -368,7 +375,81 @@
     }
 
 
+    public CompressionFilter[] getCompressionFilters() {
+        if (compressionFilters == null) {
+            compressionFilters = new CompressionFilter[0];
+        }
+        return compressionFilters;
+    }
+
+
+    public void setCompressionFilters(String compressionFilters) {
+        if (compressionFilters == null) {
+            // support gzip by default
+            this.compressionFilters = new CompressionFilter[] { new GzipOutputFilter() };
+        } else {
+            StringTokenizer st = new StringTokenizer(compressionFilters, ",");
+
+            LinkedList<CompressionFilter> compressionFilterList = new LinkedList<CompressionFilter>();
+
+            while (st.hasMoreTokens()) {
+                String className = st.nextToken().trim();
+
+                try {
+                    Object obj = Class.forName(className).newInstance();
+                    if (obj instanceof CompressionFilter) {
+                        CompressionFilter compressionFilter = (CompressionFilter) obj;
+                        compressionFilterList.add(compressionFilter);
+                    } else {
+                        getLog().error(sm.getString("http11processor.compression.invalidclass", className));
+                    }
+                } catch (Exception e) {
+                    getLog().error(sm.getString("http11processor.compression.instantiationfailed", className), e);
+                }
+            }
+
+            if (compressionFilterList.isEmpty() && getLog().isWarnEnabled()) {
+                getLog().warn(sm.getString("http11processor.compression.nofilters"));
+            }
+
+            this.compressionFilters = compressionFilterList.toArray(new CompressionFilter[compressionFilterList.size()]);
+        }
+    }
+
+
+    protected boolean isContentEncodingCompressable(MessageBytes contentEncoding) {
+        if (contentEncoding != null) {
+            for (CompressionFilter filter : getCompressionFilters()) {
+                if (contentEncoding.indexOf(filter.getContentEncoding()) != -1) {
+                    return false;
+                }
+            }
+        }
+        
+        return true;
+    }
+
+
     /**
+     * Tests whether there is a suitable filter available according to the requests &quot;Accept-Encoding&quot;-Header.
+     *
+     * @return A filter to be used for compression, <code>null</code> otherwise.
+     */
+    protected CompressionFilter findCompressionFilterForAcceptEncoding(MessageBytes acceptEncoding) {
+        if (acceptEncoding == null || getCompressionFilters().length == 0) {
+            return null;
+        } else {
+            for (CompressionFilter filter : getCompressionFilters()) {
+                if (acceptEncoding.indexOf(filter.getContentEncoding()) != -1) {
+                    return filter;
+                }
+            }
+            return null;
+        }
+    }
+
+
+    /**
      * General use method
      *
      * @param sArray the StringArray
@@ -546,8 +627,7 @@
         MessageBytes contentEncodingMB =
             response.getMimeHeaders().getValue("Content-Encoding");
 
-        if ((contentEncodingMB != null)
-            && (contentEncodingMB.indexOf("gzip") != -1)) {
+        if (!isContentEncodingCompressable(contentEncodingMB)) {
             return false;
         }
 
@@ -574,21 +654,23 @@
     /**
      * Check if compression should be used for this resource. Already checked
      * that the resource could be compressed if the client supports it.
+     * Returns a CompressionFilter in case a suitable compression could be found, <code>null</code> otherwise.
      */
-    private boolean useCompression() {
+    private CompressionFilter findCompressionFilter() {
 
         // Check if browser support gzip encoding
         MessageBytes acceptEncodingMB =
             request.getMimeHeaders().getValue("accept-encoding");
 
-        if ((acceptEncodingMB == null)
-            || (acceptEncodingMB.indexOf("gzip") == -1)) {
-            return false;
+        CompressionFilter result = findCompressionFilterForAcceptEncoding(acceptEncodingMB);
+
+        if (result == null) {
+            return null;
         }
 
         // If force mode, always compress (test purposes only)
         if (compressionLevel == 2) {
-            return true;
+            return null;
         }
 
         // Check for incompatible Browser
@@ -600,12 +682,12 @@
 
                 if (noCompressionUserAgents != null &&
                         noCompressionUserAgents.matcher(userAgentValue).matches()) {
-                        return false;
+                        return null;
                 }
             }
         }
 
-        return true;
+        return result;
     }
 
 
@@ -1358,14 +1440,14 @@
 
         // Check for compression
         boolean isCompressable = false;
-        boolean useCompression = false;
+        CompressionFilter compressionFilter = null;
         if (entityBody && (compressionLevel > 0) && !sendingWithSendfile) {
             isCompressable = isCompressable();
             if (isCompressable) {
-                useCompression = useCompression();
+                compressionFilter = findCompressionFilter();
             }
             // Change content-length to -1 to force chunking
-            if (useCompression) {
+            if (compressionFilter != null) {
                 response.setContentLength(-1);
             }
         }
@@ -1407,9 +1489,9 @@
             }
         }
 
-        if (useCompression) {
-            getOutputBuffer().addActiveFilter(outputFilters[Constants.GZIP_FILTER]);
-            headers.setValue("Content-Encoding").setString("gzip");
+        if (compressionFilter != null) {
+            getOutputBuffer().addActiveFilter(compressionFilter);
+            headers.setValue("Content-Encoding").setString(compressionFilter.getContentEncoding());
         }
         // If it might be compressed, set the Vary header
         if (isCompressable) {
Index: java/org/apache/coyote/http11/CompressionFilter.java
===================================================================
--- java/org/apache/coyote/http11/CompressionFilter.java	(revision 0)
+++ java/org/apache/coyote/http11/CompressionFilter.java	(revision 0)
@@ -0,0 +1,37 @@
+/*
+ *  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.coyote.http11;
+
+import org.apache.tomcat.util.buf.MessageBytes;
+
+/**
+ * A spezialized filter for output compression.
+ * 
+ * @author Florian Fray
+ */
+public interface CompressionFilter extends OutputFilter {
+
+
+    /**
+     * Returns a valid value for a &quot;Content-Encoding&quot;-Header.
+     * Must not return <code>null</code>.
+     */
+    String getContentEncoding();
+
+
+}
Index: java/org/apache/coyote/http11/LocalStrings.properties
===================================================================
--- java/org/apache/coyote/http11/LocalStrings.properties	(revision 1392028)
+++ java/org/apache/coyote/http11/LocalStrings.properties	(working copy)
@@ -21,6 +21,9 @@
 http11protocol.proto.socketexception.info=SocketException reading request, ignored
 http11protocol.start=Starting Coyote HTTP/1.1 on {0}
 
+http11processor.compression.instantiationfailed=Could not instantiate CompressionFilter from class {0}. Ignoring compression filter.
+http11processor.compression.invalidclass=Class {0} is not implementing CompressionFilter. Ignoring compression filter.
+http11processor.compression.nofilters=All compression filters are invalid, so Tomcat will not support any output compression.
 http11processor.regexp.error=Error parsing regular expression {0}
 http11processor.filter.unknown=Unknown filter {0}
 http11processor.filter.error=Error intializing filter {0}
Index: java/org/apache/coyote/http11/AbstractHttp11Protocol.java
===================================================================
--- java/org/apache/coyote/http11/AbstractHttp11Protocol.java	(revision 1392028)
+++ java/org/apache/coyote/http11/AbstractHttp11Protocol.java	(working copy)
@@ -92,6 +92,11 @@
     public void setCompression(String valueS) { compression = valueS; }
 
 
+    private String compressionFilters = null;
+    public String getCompressionFilters() { return compressionFilters; }
+    public void setCompressionFilters(String valueS) { compressionFilters = valueS; }
+
+
     private String noCompressionUserAgents = null;
     public String getNoCompressionUserAgents() {
         return noCompressionUserAgents;
Index: java/org/apache/coyote/http11/filters/GzipOutputFilter.java
===================================================================
--- java/org/apache/coyote/http11/filters/GzipOutputFilter.java	(revision 1392028)
+++ java/org/apache/coyote/http11/filters/GzipOutputFilter.java	(working copy)
@@ -24,14 +24,16 @@
 import org.apache.coyote.OutputBuffer;
 import org.apache.coyote.Response;
 import org.apache.coyote.http11.OutputFilter;
+import org.apache.coyote.http11.CompressionFilter;
 import org.apache.tomcat.util.buf.ByteChunk;
+import org.apache.tomcat.util.buf.MessageBytes;
 
 /**
  * Gzip output filter.
  * 
  * @author Remy Maucherat
  */
-public class GzipOutputFilter implements OutputFilter {
+public class GzipOutputFilter implements CompressionFilter {
 
 
     /**
@@ -154,6 +156,14 @@
     }
 
 
+    // ------------------------------------------- CompressionFilter Methods
+
+    @Override
+    public String getContentEncoding() {
+        return "gzip";
+    }
+
+
     // ------------------------------------------- FakeOutputStream Inner Class
 
 
