Author: cschneider
Date: Wed Feb  1 10:30:19 2012
New Revision: 1239041

URL: http://svn.apache.org/viewvc?rev=1239041&view=rev
Log:
CXF-4081 Move gzip feature to core

Added:
    cxf/trunk/rt/core/src/main/java/org/apache/cxf/transport/
    cxf/trunk/rt/core/src/main/java/org/apache/cxf/transport/common/
    cxf/trunk/rt/core/src/main/java/org/apache/cxf/transport/common/gzip/
    
cxf/trunk/rt/core/src/main/java/org/apache/cxf/transport/common/gzip/GZIPFeature.java
    
cxf/trunk/rt/core/src/main/java/org/apache/cxf/transport/common/gzip/GZIPInInterceptor.java
    
cxf/trunk/rt/core/src/main/java/org/apache/cxf/transport/common/gzip/GZIPOutInterceptor.java
    
cxf/trunk/rt/core/src/main/java/org/apache/cxf/transport/common/gzip/Messages.properties
    cxf/trunk/rt/core/src/test/java/org/apache/cxf/transport/common/
    cxf/trunk/rt/core/src/test/java/org/apache/cxf/transport/common/gzip/
    
cxf/trunk/rt/core/src/test/java/org/apache/cxf/transport/common/gzip/GZIPAcceptEncodingTest.java
Removed:
    cxf/trunk/rt/transports/common/
Modified:
    cxf/trunk/osgi/karaf/features/src/main/resources/features.xml
    
cxf/trunk/rt/core/src/main/java/org/apache/cxf/service/factory/AnnotationsFactoryBeanListener.java
    cxf/trunk/rt/pom.xml
    cxf/trunk/rt/transports/jms/pom.xml

Modified: cxf/trunk/osgi/karaf/features/src/main/resources/features.xml
URL: 
http://svn.apache.org/viewvc/cxf/trunk/osgi/karaf/features/src/main/resources/features.xml?rev=1239041&r1=1239040&r2=1239041&view=diff
==============================================================================
--- cxf/trunk/osgi/karaf/features/src/main/resources/features.xml (original)
+++ cxf/trunk/osgi/karaf/features/src/main/resources/features.xml Wed Feb  1 
10:30:19 2012
@@ -99,7 +99,6 @@
         <bundle 
start-level='40'>mvn:org.apache.cxf/cxf-api/${project.version}</bundle>
         <bundle 
start-level='40'>mvn:org.apache.cxf/cxf-rt-core/${project.version}</bundle>
         <bundle 
start-level='40'>mvn:org.apache.cxf/cxf-rt-management/${project.version}</bundle>
 
-               <bundle 
start-level='40'>mvn:org.apache.cxf/cxf-rt-transports-common/${project.version}</bundle>
 
         <bundle 
start-level='40'>mvn:org.apache.cxf.karaf/cxf-karaf-commands/${project.version}</bundle>
     </feature>
     <feature name="cxf-ws-policy" version="${project.version}" 
resolver='(obr)'>

Modified: 
cxf/trunk/rt/core/src/main/java/org/apache/cxf/service/factory/AnnotationsFactoryBeanListener.java
URL: 
http://svn.apache.org/viewvc/cxf/trunk/rt/core/src/main/java/org/apache/cxf/service/factory/AnnotationsFactoryBeanListener.java?rev=1239041&r1=1239040&r2=1239041&view=diff
==============================================================================
--- 
cxf/trunk/rt/core/src/main/java/org/apache/cxf/service/factory/AnnotationsFactoryBeanListener.java
 (original)
+++ 
cxf/trunk/rt/core/src/main/java/org/apache/cxf/service/factory/AnnotationsFactoryBeanListener.java
 Wed Feb  1 10:30:19 2012
@@ -60,6 +60,7 @@ import org.apache.cxf.service.model.Bind
 import org.apache.cxf.service.model.FaultInfo;
 import org.apache.cxf.service.model.InterfaceInfo;
 import org.apache.cxf.service.model.OperationInfo;
+import org.apache.cxf.transport.common.gzip.GZIPFeature;
 
 /**
  * 
@@ -247,13 +248,8 @@ public class AnnotationsFactoryBeanListe
     private void addGZipSupport(Endpoint ep, Bus bus, GZIP annotation) {
         if (annotation != null) {
             try {
-                Class<?> cls = ClassLoaderUtils
-                    
.loadClass("org.apache.cxf.transport.common.gzip.GZIPFeature",
-                               this.getClass());
-                
-                AbstractFeature feature = (AbstractFeature)cls.newInstance();
-                cls.getMethod("setThreshold", new Class[] {Integer.TYPE})
-                    .invoke(feature, annotation.threshold());
+                GZIPFeature feature = new GZIPFeature();
+                feature.setThreshold(annotation.threshold());
                 feature.initialize(ep, bus);
             } catch (Exception e) {
                 //ignore - just assume it's an unsupported/unknown annotation

Added: 
cxf/trunk/rt/core/src/main/java/org/apache/cxf/transport/common/gzip/GZIPFeature.java
URL: 
http://svn.apache.org/viewvc/cxf/trunk/rt/core/src/main/java/org/apache/cxf/transport/common/gzip/GZIPFeature.java?rev=1239041&view=auto
==============================================================================
--- 
cxf/trunk/rt/core/src/main/java/org/apache/cxf/transport/common/gzip/GZIPFeature.java
 (added)
+++ 
cxf/trunk/rt/core/src/main/java/org/apache/cxf/transport/common/gzip/GZIPFeature.java
 Wed Feb  1 10:30:19 2012
@@ -0,0 +1,101 @@
+/**
+ * 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.cxf.transport.common.gzip;
+
+import java.util.List;
+
+import org.apache.cxf.Bus;
+import org.apache.cxf.common.injection.NoJSR250Annotations;
+import org.apache.cxf.feature.AbstractFeature;
+import org.apache.cxf.interceptor.Interceptor;
+import org.apache.cxf.interceptor.InterceptorProvider;
+import org.apache.cxf.message.Message;
+
+/**
+ * This class is used to control GZIP compression of messages.
+ * Attaching this feature to an endpoint will allow the endpoint to handle
+ * compressed requests, and will cause outgoing responses to be compressed if
+ * the client indicates (via the Accept-Encoding header) that it can handle
+ * them.
+ * <pre>
+ * <![CDATA[
+ * <jaxws:endpoint ...>
+ *   <jaxws:features>
+ *     <bean class="org.apache.cxf.transport.http.gzip.GZIPFeature"/>
+ *   </jaxws:features>
+ * </jaxws:endpoint>
+ * ]]>
+ * </pre>
+ * Attaching this feature to a client will cause outgoing request messages to
+ * be compressed and incoming compressed responses to be uncompressed.  If you
+ * want the service to know that your client can accept compressed responses,
+ * you will also need to set the "AcceptEncoding" value in the relevant HTTP
+ * conduit client configuration.
+ * <pre>
+ * <![CDATA[
+ * <http-conf:conduit 
name="{http://apache.org/hello_world_soap_http}SoapPort.http-conduit";>
+ *   <http-conf:client AcceptEncoding="gzip" />
+ * </http-conf:conduit>
+ * ]]>
+ * </pre>
+ */
+@NoJSR250Annotations
+public class GZIPFeature extends AbstractFeature {
+    private static final GZIPInInterceptor IN = new GZIPInInterceptor();
+    private static final GZIPOutInterceptor OUT = new GZIPOutInterceptor();
+    
+    /**
+     * The compression threshold to pass to the outgoing interceptor.
+     */
+    int threshold = -1;
+    
+    @Override
+    protected void initializeProvider(InterceptorProvider provider, Bus bus) {
+        provider.getInInterceptors().add(IN);
+        if (threshold == -1) {
+            provider.getOutInterceptors().add(OUT);
+            provider.getOutFaultInterceptors().add(OUT);
+        } else {
+            GZIPOutInterceptor out = new GZIPOutInterceptor();
+            out.setThreshold(threshold);
+            remove(provider.getOutInterceptors());
+            remove(provider.getOutFaultInterceptors());
+            provider.getOutInterceptors().add(out);
+            provider.getOutFaultInterceptors().add(out);
+        }
+    }
+
+    private void remove(List<Interceptor<? extends Message>> outInterceptors) {
+        int x = outInterceptors.size();
+        while (x > 0) {
+            --x;
+            if (outInterceptors.get(x) instanceof GZIPOutInterceptor) {
+                outInterceptors.remove(x);
+            }
+        }
+    }
+
+    public void setThreshold(int threshold) {
+        this.threshold = threshold;
+    }
+    
+    public int getThreshold() {
+        return threshold;
+    }    
+}

Added: 
cxf/trunk/rt/core/src/main/java/org/apache/cxf/transport/common/gzip/GZIPInInterceptor.java
URL: 
http://svn.apache.org/viewvc/cxf/trunk/rt/core/src/main/java/org/apache/cxf/transport/common/gzip/GZIPInInterceptor.java?rev=1239041&view=auto
==============================================================================
--- 
cxf/trunk/rt/core/src/main/java/org/apache/cxf/transport/common/gzip/GZIPInInterceptor.java
 (added)
+++ 
cxf/trunk/rt/core/src/main/java/org/apache/cxf/transport/common/gzip/GZIPInInterceptor.java
 Wed Feb  1 10:30:19 2012
@@ -0,0 +1,101 @@
+/**
+ * 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.cxf.transport.common.gzip;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.List;
+import java.util.Map;
+import java.util.ResourceBundle;
+import java.util.logging.Logger;
+import java.util.zip.GZIPInputStream;
+
+import org.apache.cxf.common.i18n.BundleUtils;
+import org.apache.cxf.common.logging.LogUtils;
+import org.apache.cxf.helpers.CastUtils;
+import org.apache.cxf.helpers.HttpHeaderHelper;
+import org.apache.cxf.interceptor.AttachmentInInterceptor;
+import org.apache.cxf.interceptor.Fault;
+import org.apache.cxf.message.Message;
+import org.apache.cxf.phase.AbstractPhaseInterceptor;
+import org.apache.cxf.phase.Phase;
+
+/**
+ * CXF interceptor that uncompresses those incoming messages that have "gzip"
+ * content-encoding. An instance of this class should be added as an in and
+ * inFault interceptor on clients that need to talk to a service that returns
+ * gzipped responses or on services that want to accept gzipped requests. For
+ * clients, you probably also want to use
+ * {@link 
org.apache.cxf.transports.http.configuration.HTTPClientPolicy#setAcceptEncoding}
+ * to let the server know you can handle compressed responses. To compress
+ * outgoing messages, see {@link GZIPOutInterceptor}. This class was originally
+ * based on one of the CXF samples (configuration_interceptor).
+ * 
+ * @author Ian Roberts ([email protected])
+ */
+public class GZIPInInterceptor extends AbstractPhaseInterceptor<Message> {
+
+
+    private static final ResourceBundle BUNDLE = 
BundleUtils.getBundle(GZIPInInterceptor.class);
+    private static final Logger LOG = 
LogUtils.getL7dLogger(GZIPInInterceptor.class);
+
+    public GZIPInInterceptor() {
+        super(Phase.RECEIVE);
+        addBefore(AttachmentInInterceptor.class.getName());
+    }
+
+    public void handleMessage(Message message) throws Fault {
+        // check for Content-Encoding header - we are only interested in
+        // messages that say they are gzipped.
+        Map<String, List<String>> protocolHeaders = CastUtils.cast((Map<?, 
?>)message
+            .get(Message.PROTOCOL_HEADERS));
+        if (protocolHeaders != null) {
+            List<String> contentEncoding = 
HttpHeaderHelper.getHeader(protocolHeaders, 
+                                                                      
HttpHeaderHelper.CONTENT_ENCODING);
+            if (contentEncoding == null) {
+                contentEncoding = 
protocolHeaders.get(GZIPOutInterceptor.SOAP_JMS_CONTENTENCODING);
+            }
+            if (contentEncoding != null
+                && (contentEncoding.contains("gzip") || 
contentEncoding.contains("x-gzip"))) {
+                try {
+                    LOG.fine("Uncompressing response");
+                    InputStream is = message.getContent(InputStream.class);
+                    if (is == null) {
+                        return;
+                    }
+
+                    // wrap an unzipping stream around the original one
+                    GZIPInputStream zipInput = new GZIPInputStream(is);
+                    message.setContent(InputStream.class, zipInput);
+
+                    // remove content encoding header as we've now dealt with 
it
+                    for (String key : protocolHeaders.keySet()) {
+                        if (key.equalsIgnoreCase("Content-Encoding")) {
+                            protocolHeaders.remove(key);
+                            break;
+                        }
+                    }
+                } catch (IOException ex) {
+                    throw new Fault(new 
org.apache.cxf.common.i18n.Message("COULD_NOT_UNZIP", BUNDLE), ex);
+                }
+            }
+        }
+    }
+
+}

Added: 
cxf/trunk/rt/core/src/main/java/org/apache/cxf/transport/common/gzip/GZIPOutInterceptor.java
URL: 
http://svn.apache.org/viewvc/cxf/trunk/rt/core/src/main/java/org/apache/cxf/transport/common/gzip/GZIPOutInterceptor.java?rev=1239041&view=auto
==============================================================================
--- 
cxf/trunk/rt/core/src/main/java/org/apache/cxf/transport/common/gzip/GZIPOutInterceptor.java
 (added)
+++ 
cxf/trunk/rt/core/src/main/java/org/apache/cxf/transport/common/gzip/GZIPOutInterceptor.java
 Wed Feb  1 10:30:19 2012
@@ -0,0 +1,323 @@
+/**
+ * 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.cxf.transport.common.gzip;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.ResourceBundle;
+import java.util.TreeMap;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.zip.GZIPOutputStream;
+
+import org.apache.cxf.common.i18n.BundleUtils;
+import org.apache.cxf.common.logging.LogUtils;
+import org.apache.cxf.helpers.CastUtils;
+import org.apache.cxf.helpers.HttpHeaderHelper;
+import org.apache.cxf.interceptor.Fault;
+import org.apache.cxf.interceptor.MessageSenderInterceptor;
+import org.apache.cxf.io.AbstractThresholdOutputStream;
+import org.apache.cxf.message.Exchange;
+import org.apache.cxf.message.Message;
+import org.apache.cxf.phase.AbstractPhaseInterceptor;
+import org.apache.cxf.phase.Phase;
+
+/**
+ * CXF interceptor that compresses outgoing messages using gzip and sets the
+ * HTTP Content-Encoding header appropriately. An instance of this class should
+ * be added as an out interceptor on clients that need to talk to a service 
that
+ * accepts gzip-encoded requests or on a service that wants to be able to 
return
+ * compressed responses. In server mode, the interceptor only compresses
+ * responses if the client indicated (via an Accept-Encoding header on the
+ * request) that it can understand them. To handle gzip-encoded input messages,
+ * see {@link GZIPInInterceptor}. This interceptor supports a compression
+ * {@link #threshold} (default 1kB) - messages smaller than this threshold will
+ * not be compressed. To force compression of all messages, set the threshold 
to
+ * 0. This class was originally based on one of the CXF samples
+ * (configuration_interceptor).
+ * 
+ * @author Ian Roberts ([email protected])
+ */
+public class GZIPOutInterceptor extends AbstractPhaseInterceptor<Message> {
+
+    /**
+     * Enum giving the possible values for whether we should gzip a particular
+     * message.
+     */
+    public static enum UseGzip {
+        NO, YES, FORCE
+    }
+
+    /**
+     * Key under which we store the original output stream on the message, for
+     * use by the ending interceptor.
+     */
+    public static final String ORIGINAL_OUTPUT_STREAM_KEY = 
GZIPOutInterceptor.class.getName()
+                                                            + 
".originalOutputStream";
+
+    /**
+     * Key under which we store an indication of whether compression is
+     * permitted or required, for use by the ending interceptor.
+     */
+    public static final String USE_GZIP_KEY = 
GZIPOutInterceptor.class.getName() + ".useGzip";
+
+    /**
+     * Key under which we store the name which should be used for the
+     * content-encoding of the outgoing message. Typically "gzip" but may be
+     * "x-gzip" if we are processing a response message and this is the name
+     * given by the client in Accept-Encoding.
+     */
+    public static final String GZIP_ENCODING_KEY = 
GZIPOutInterceptor.class.getName() + ".gzipEncoding";
+    
+    public static final String SOAP_JMS_CONTENTENCODING = 
"SOAPJMS_contentEncoding";
+
+    private static final ResourceBundle BUNDLE = 
BundleUtils.getBundle(GZIPOutInterceptor.class);
+    private static final Logger LOG = 
LogUtils.getL7dLogger(GZIPOutInterceptor.class);
+
+
+    /**
+     * Compression threshold in bytes - messages smaller than this will not be
+     * compressed.
+     */
+    private int threshold = 1024;
+
+    public GZIPOutInterceptor() {
+        super(Phase.PREPARE_SEND);
+        addAfter(MessageSenderInterceptor.class.getName());
+    }
+    public GZIPOutInterceptor(int threshold) {
+        super(Phase.PREPARE_SEND);
+        addAfter(MessageSenderInterceptor.class.getName());
+        this.threshold = threshold;
+    }
+
+    public void setThreshold(int threshold) {
+        this.threshold = threshold;
+    }
+
+    public int getThreshold() {
+        return threshold;
+    }
+
+    public void handleMessage(Message message) throws Fault {
+        UseGzip use = gzipPermitted(message);
+        if (use != UseGzip.NO) {
+            // remember the original output stream, we will write compressed
+            // data to this later
+            OutputStream os = message.getContent(OutputStream.class);
+            if (os == null) {
+                return;
+            }
+            message.put(ORIGINAL_OUTPUT_STREAM_KEY, os);
+            message.put(USE_GZIP_KEY, use);
+
+            // new stream to cache the message
+            GZipThresholdOutputStream cs 
+                = new GZipThresholdOutputStream(threshold,
+                                                os,
+                                                use == UseGzip.FORCE,
+                                                message);
+            message.setContent(OutputStream.class, cs);
+        }
+    }
+
+    /**
+     * Checks whether we can, cannot or must use gzip compression on this 
output
+     * message. Gzip is always permitted if the message is a client request. If
+     * the message is a server response we check the Accept-Encoding header of
+     * the corresponding request message - with no Accept-Encoding we assume
+     * that gzip is not permitted. For the full gory details, see <a
+     * 
href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.3";>section
+     * 14.3 of RFC 2616</a> (HTTP 1.1).
+     * 
+     * @param message the outgoing message.
+     * @return whether to attempt gzip compression for this message.
+     * @throws Fault if the Accept-Encoding header does not allow any encoding
+     *                 that we can support (identity, gzip or x-gzip).
+     */
+    private UseGzip gzipPermitted(Message message) throws Fault {
+        UseGzip permitted = UseGzip.NO;
+        if (Boolean.TRUE.equals(message.get(Message.REQUESTOR_ROLE))) {
+            LOG.fine("Requestor role, so gzip enabled");
+            permitted = UseGzip.YES;
+            message.put(GZIP_ENCODING_KEY, "gzip");
+            addHeader(message, "Accept-Encoding", "gzip;q=1.0, identity; 
q=0.5, *;q=0"); 
+        } else {
+            LOG.fine("Response role, checking accept-encoding");
+            Exchange exchange = message.getExchange();
+            Message request = exchange.getInMessage();
+            Map<String, List<String>> requestHeaders = CastUtils.cast((Map<?, 
?>)request
+                .get(Message.PROTOCOL_HEADERS));
+            if (requestHeaders != null) {
+                List<String> acceptEncodingHeader = 
CastUtils.cast(HttpHeaderHelper
+                    .getHeader(requestHeaders, 
HttpHeaderHelper.ACCEPT_ENCODING));
+                List<String> jmsEncodingHeader = 
CastUtils.cast(requestHeaders.get(SOAP_JMS_CONTENTENCODING));
+                if (jmsEncodingHeader != null && 
jmsEncodingHeader.contains("gzip")) {
+                    permitted = UseGzip.YES;
+                    message.put(GZIP_ENCODING_KEY, "gzip");
+                }
+                if (acceptEncodingHeader != null) {
+                    if (LOG.isLoggable(Level.FINE)) {
+                        LOG.fine("Accept-Encoding header: " + 
acceptEncodingHeader);
+                    }
+                    // Accept-Encoding is a comma separated list of entries, so
+                    // we split it into its component parts and build two
+                    // lists, one with all the "q=0" encodings and the other
+                    // with the rest (no q, or q=<non-zero>).
+                    List<String> zeros = new ArrayList<String>(3);
+                    List<String> nonZeros = new ArrayList<String>(3);
+
+                    // regular expression that matches any encoding with a
+                    // q-value of 0 (or 0.0, 0.00, etc.).
+                    Pattern zeroQ = Pattern.compile(";\\s*q=0(?:\\.0+)?$");
+                    for (String headerLine : acceptEncodingHeader) {
+                        String[] encodings = 
headerLine.trim().split("[,\\s]*,\\s*");
+
+                        for (String enc : encodings) {
+                            Matcher m = zeroQ.matcher(enc);
+                            if (m.find()) {
+                                zeros.add(enc.substring(0, m.start()));
+                            } else if (enc.indexOf(';') >= 0) {
+                                nonZeros.add(enc.substring(0, 
enc.indexOf(';')));
+                            } else {
+                                nonZeros.add(enc);
+                            }
+                        }
+                    }
+
+                    // identity encoding is permitted if (a) it is not
+                    // specifically disabled by an identity;q=0 and (b) if
+                    // there is a *;q=0 then there is also an explicit
+                    // identity[;q=<non-zero>]
+                    //
+                    // [x-]gzip is permitted if (a) there is an explicit
+                    // [x-]gzip[;q=<non-zero>], or (b) there is a
+                    // *[;q=<non-zero>] and no [x-]gzip;q=0 to disable it.
+                    boolean identityEnabled = !zeros.contains("identity")
+                                              && (!zeros.contains("*") || 
nonZeros.contains("identity"));
+                    boolean gzipEnabled = nonZeros.contains("gzip")
+                                          || (nonZeros.contains("*") && 
!zeros.contains("gzip"));
+                    boolean xGzipEnabled = nonZeros.contains("x-gzip")
+                                           || (nonZeros.contains("*") && 
!zeros.contains("x-gzip"));
+
+                    if (identityEnabled && !gzipEnabled && !xGzipEnabled) {
+                        permitted = UseGzip.NO;
+                    } else if (identityEnabled && gzipEnabled) {
+                        permitted = UseGzip.YES;
+                        message.put(GZIP_ENCODING_KEY, "gzip");
+                    } else if (identityEnabled && xGzipEnabled) {
+                        permitted = UseGzip.YES;
+                        message.put(GZIP_ENCODING_KEY, "x-gzip");
+                    } else if (!identityEnabled && gzipEnabled) {
+                        permitted = UseGzip.FORCE;
+                        message.put(GZIP_ENCODING_KEY, "gzip");
+                    } else if (!identityEnabled && xGzipEnabled) {
+                        permitted = UseGzip.FORCE;
+                        message.put(GZIP_ENCODING_KEY, "x-gzip");
+                    } else {
+                        throw new Fault(new 
org.apache.cxf.common.i18n.Message("NO_SUPPORTED_ENCODING",
+                                                                               
BUNDLE));
+                    }
+                } else {
+                    LOG.fine("No accept-encoding header");
+                }
+            }
+        }
+
+        if (LOG.isLoggable(Level.FINE)) {
+            LOG.fine("gzip permitted: " + permitted);
+        }
+        return permitted;
+    }
+    
+    static class GZipThresholdOutputStream extends 
AbstractThresholdOutputStream {
+        Message message;
+        
+        public GZipThresholdOutputStream(int t, OutputStream orig,
+                                         boolean force, Message msg) {
+            super(t);
+            super.wrappedStream = orig;
+            message = msg;
+            if (force) {
+                setupGZip();
+            }
+        }
+        
+        private void setupGZip() {
+            
+        }
+
+        @Override
+        public void thresholdNotReached() {
+            //nothing
+            LOG.fine("Message is smaller than compression threshold, not 
compressing.");
+        }
+
+        @Override
+        public void thresholdReached() throws IOException {
+            LOG.fine("Compressing message.");
+            // Set the Content-Encoding HTTP header
+            String enc = (String)message.get(GZIP_ENCODING_KEY);
+            addHeader(message, "Content-Encoding", enc);
+            // if this is a response message, add the Vary header
+            if (!Boolean.TRUE.equals(message.get(Message.REQUESTOR_ROLE))) {
+                addHeader(message, "Vary", "Accept-Encoding");
+            } 
+
+            // gzip the result
+            GZIPOutputStream zipOutput = new GZIPOutputStream(wrappedStream);
+            wrappedStream = zipOutput;
+        }
+    }
+    
+    /**
+     * Adds a value to a header. If the given header name is not currently
+     * set in the message, an entry is created with the given single value.
+     * If the header is already set, the value is appended to the first
+     * element of the list, following a comma.
+     * 
+     * @param message the message
+     * @param name the header to set
+     * @param value the value to add
+     */
+    private static void addHeader(Message message, String name, String value) {
+        Map<String, List<String>> protocolHeaders = CastUtils.cast((Map<?, 
?>)message
+            .get(Message.PROTOCOL_HEADERS));
+        if (protocolHeaders == null) {
+            protocolHeaders = new TreeMap<String, 
List<String>>(String.CASE_INSENSITIVE_ORDER);
+            message.put(Message.PROTOCOL_HEADERS, protocolHeaders);
+        }
+        List<String> header = 
CastUtils.cast((List<?>)protocolHeaders.get(name));
+        if (header == null) {
+            header = new ArrayList<String>();
+            protocolHeaders.put(name, header);
+        }
+        if (header.size() == 0) {
+            header.add(value);
+        } else {
+            header.set(0, header.get(0) + "," + value);
+        }
+    }    
+
+}

Added: 
cxf/trunk/rt/core/src/main/java/org/apache/cxf/transport/common/gzip/Messages.properties
URL: 
http://svn.apache.org/viewvc/cxf/trunk/rt/core/src/main/java/org/apache/cxf/transport/common/gzip/Messages.properties?rev=1239041&view=auto
==============================================================================
--- 
cxf/trunk/rt/core/src/main/java/org/apache/cxf/transport/common/gzip/Messages.properties
 (added)
+++ 
cxf/trunk/rt/core/src/main/java/org/apache/cxf/transport/common/gzip/Messages.properties
 Wed Feb  1 10:30:19 2012
@@ -0,0 +1,23 @@
+#
+#
+#    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.
+#
+#
+COULD_NOT_UNZIP=Could not unzip compressed message.
+COULD_NOT_ZIP=Could not compress message.
+NO_SUPPORTED_ENCODING=No supported content encodings available.

Added: 
cxf/trunk/rt/core/src/test/java/org/apache/cxf/transport/common/gzip/GZIPAcceptEncodingTest.java
URL: 
http://svn.apache.org/viewvc/cxf/trunk/rt/core/src/test/java/org/apache/cxf/transport/common/gzip/GZIPAcceptEncodingTest.java?rev=1239041&view=auto
==============================================================================
--- 
cxf/trunk/rt/core/src/test/java/org/apache/cxf/transport/common/gzip/GZIPAcceptEncodingTest.java
 (added)
+++ 
cxf/trunk/rt/core/src/test/java/org/apache/cxf/transport/common/gzip/GZIPAcceptEncodingTest.java
 Wed Feb  1 10:30:19 2012
@@ -0,0 +1,139 @@
+/**
+ * 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.cxf.transport.common.gzip;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+import org.apache.cxf.helpers.HttpHeaderHelper;
+import org.apache.cxf.interceptor.Fault;
+import org.apache.cxf.interceptor.InterceptorChain;
+import org.apache.cxf.message.Exchange;
+import org.apache.cxf.message.ExchangeImpl;
+import org.apache.cxf.message.Message;
+import org.apache.cxf.message.MessageImpl;
+import org.easymock.EasyMock;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import static 
org.apache.cxf.transport.common.gzip.GZIPOutInterceptor.UseGzip.FORCE;
+import static 
org.apache.cxf.transport.common.gzip.GZIPOutInterceptor.UseGzip.YES;
+
+/**
+ * Test for the parsing of Accept-Encoding by the GZIPOutInterceptor. For
+ * Accept-Encoding values that enable gzip we expect an extra interceptor to be
+ * added to the out message, and the {@link GZIPOutInterceptor#USE_GZIP_KEY} to
+ * be set correctly. For Accept-Encoding values that do not enable gzip the
+ * interceptor should not be added.
+ */
+public class GZIPAcceptEncodingTest extends Assert {
+
+    private GZIPOutInterceptor interceptor;
+    private Message inMessage;
+    private Message outMessage;
+    private InterceptorChain outInterceptors;
+
+    @Before
+    public void setUp() throws Exception {
+        interceptor = new GZIPOutInterceptor();
+        inMessage = new MessageImpl();
+        outMessage = new MessageImpl();
+        Exchange exchange = new ExchangeImpl();
+        exchange.setInMessage(inMessage);
+        inMessage.setExchange(exchange);
+        inMessage.setContent(InputStream.class, new ByteArrayInputStream(new 
byte[0]));
+        exchange.setOutMessage(outMessage);
+        outMessage.setExchange(exchange);
+        outMessage.setContent(OutputStream.class, new ByteArrayOutputStream());
+        outInterceptors = EasyMock.createMock(InterceptorChain.class);
+        outMessage.setInterceptorChain(outInterceptors);
+    }
+
+    @Test
+    public void testNoAcceptEncoding() throws Exception {
+        EasyMock.replay(outInterceptors);
+        interceptor.handleMessage(outMessage);
+    }
+
+    @Test
+    public void testAcceptGzip() throws Exception {
+        singleTest("gzip", true, YES, "gzip");
+    }
+
+    @Test
+    public void testAcceptXGzip() throws Exception {
+        singleTest("x-gzip, x-compress", true, YES, "x-gzip");
+    }
+
+    @Test
+    public void testAcceptStar() throws Exception {
+        singleTest("*", true, YES, "gzip");
+    }
+
+    @Test
+    public void testAcceptOnlyGzip() throws Exception {
+        singleTest("gzip, identity; q=0", true, FORCE, "gzip");
+    }
+
+    @Test
+    public void testOnlyIdentitySupported() throws Exception {
+        singleTest("deflate", false, null, null);
+    }
+
+    @Test
+    public void testGzipExplicitlyDisabled() throws Exception {
+        singleTest("gzip; q=0.00", false, null, null);
+    }
+
+    @Test(expected = Fault.class)
+    public void testNoValidEncodings() throws Exception {
+        EasyMock.replay();
+        setAcceptEncoding("*;q=0, deflate;q=0.5");
+        interceptor.handleMessage(outMessage);
+    }
+
+    private void singleTest(String encoding, boolean expectEndingInterceptor,
+                            GZIPOutInterceptor.UseGzip expectedUseGzip, String 
expectedGzipEncoding)
+        throws Exception {
+
+        EasyMock.replay(outInterceptors);
+        setAcceptEncoding(encoding);
+        interceptor.handleMessage(outMessage);
+        assertSame("Wrong value of " + GZIPOutInterceptor.USE_GZIP_KEY, 
expectedUseGzip, outMessage
+            .get(GZIPOutInterceptor.USE_GZIP_KEY));
+        assertEquals("Wrong value of " + GZIPOutInterceptor.GZIP_ENCODING_KEY, 
expectedGzipEncoding,
+                     outMessage.get(GZIPOutInterceptor.GZIP_ENCODING_KEY));
+    }
+
+    private void setAcceptEncoding(String enc) {
+        Map<String, List<String>> protocolHeaders 
+            = new TreeMap<String, List<String>>(String.CASE_INSENSITIVE_ORDER);
+        
protocolHeaders.put(HttpHeaderHelper.getHeaderKey(HttpHeaderHelper.ACCEPT_ENCODING),
 Collections
+            .singletonList(enc));
+        inMessage.put(Message.PROTOCOL_HEADERS, protocolHeaders);
+    }
+}

Modified: cxf/trunk/rt/pom.xml
URL: 
http://svn.apache.org/viewvc/cxf/trunk/rt/pom.xml?rev=1239041&r1=1239040&r2=1239041&view=diff
==============================================================================
--- cxf/trunk/rt/pom.xml (original)
+++ cxf/trunk/rt/pom.xml Wed Feb  1 10:30:19 2012
@@ -45,7 +45,6 @@
         <module>frontend/jaxws</module>
         <module>frontend/jaxrs</module>
         <module>frontend/js</module>
-        <module>transports/common</module>
         <module>transports/http</module>
         <module>transports/http-jetty</module>
         <module>transports/jms</module>

Modified: cxf/trunk/rt/transports/jms/pom.xml
URL: 
http://svn.apache.org/viewvc/cxf/trunk/rt/transports/jms/pom.xml?rev=1239041&r1=1239040&r2=1239041&view=diff
==============================================================================
--- cxf/trunk/rt/transports/jms/pom.xml (original)
+++ cxf/trunk/rt/transports/jms/pom.xml Wed Feb  1 10:30:19 2012
@@ -60,11 +60,6 @@
         </dependency>
         <dependency>
             <groupId>org.apache.cxf</groupId>
-            <artifactId>cxf-rt-transports-common</artifactId>
-            <version>${project.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.cxf</groupId>
             <artifactId>cxf-rt-management</artifactId>
             <version>${project.version}</version>
         </dependency>


Reply via email to