You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commons-dev@ws.apache.org by ve...@apache.org on 2009/06/05 09:41:46 UTC

svn commit: r781934 - in /webservices/commons/trunk/modules/tcpmon/modules/tcpmon-core/src: main/java/org/apache/ws/commons/tcpmon/core/filter/ main/java/org/apache/ws/commons/tcpmon/core/filter/http/ main/java/org/apache/ws/commons/tcpmon/core/filter/...

Author: veithen
Date: Fri Jun  5 07:41:45 2009
New Revision: 781934

URL: http://svn.apache.org/viewvc?rev=781934&view=rev
Log:
Added support for gzip content-encoding.

Added:
    webservices/commons/trunk/modules/tcpmon/modules/tcpmon-core/src/main/java/org/apache/ws/commons/tcpmon/core/filter/zip/GZIPEncoder.java   (with props)
    webservices/commons/trunk/modules/tcpmon/modules/tcpmon-core/src/test/java/org/apache/ws/commons/tcpmon/core/filter/zip/GZIPEncoderTest.java   (with props)
Modified:
    webservices/commons/trunk/modules/tcpmon/modules/tcpmon-core/src/main/java/org/apache/ws/commons/tcpmon/core/filter/StreamUtil.java
    webservices/commons/trunk/modules/tcpmon/modules/tcpmon-core/src/main/java/org/apache/ws/commons/tcpmon/core/filter/http/HttpFilter.java

Modified: webservices/commons/trunk/modules/tcpmon/modules/tcpmon-core/src/main/java/org/apache/ws/commons/tcpmon/core/filter/StreamUtil.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/tcpmon/modules/tcpmon-core/src/main/java/org/apache/ws/commons/tcpmon/core/filter/StreamUtil.java?rev=781934&r1=781933&r2=781934&view=diff
==============================================================================
--- webservices/commons/trunk/modules/tcpmon/modules/tcpmon-core/src/main/java/org/apache/ws/commons/tcpmon/core/filter/StreamUtil.java (original)
+++ webservices/commons/trunk/modules/tcpmon/modules/tcpmon-core/src/main/java/org/apache/ws/commons/tcpmon/core/filter/StreamUtil.java Fri Jun  5 07:41:45 2009
@@ -16,8 +16,6 @@
 
 package org.apache.ws.commons.tcpmon.core.filter;
 
-import java.io.IOException;
-import java.io.InputStream;
 import java.io.UnsupportedEncodingException;
 
 /**
@@ -113,4 +111,26 @@
     public static int readUShort(Stream stream) {
         return stream.get(1) << 8 | stream.get(0);
     }
+    
+    /**
+     * Insert an integer in little endian byte order.
+     * 
+     * @param stream
+     * @param i
+     */
+    public static void insertInt(Stream stream, int i) {
+        insertShort(stream, i & 0xffff);
+        insertShort(stream, (i >> 16) & 0xffff);
+    }
+
+    /**
+     * Insert a short integer in little endian byte order.
+     * 
+     * @param stream
+     * @param s
+     */
+    public static void insertShort(Stream stream, int s) {
+        stream.insert((byte)(s & 0xff));
+        stream.insert((byte)((s >> 8) & 0xff));
+    }
 }

Modified: webservices/commons/trunk/modules/tcpmon/modules/tcpmon-core/src/main/java/org/apache/ws/commons/tcpmon/core/filter/http/HttpFilter.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/tcpmon/modules/tcpmon-core/src/main/java/org/apache/ws/commons/tcpmon/core/filter/http/HttpFilter.java?rev=781934&r1=781933&r2=781934&view=diff
==============================================================================
--- webservices/commons/trunk/modules/tcpmon/modules/tcpmon-core/src/main/java/org/apache/ws/commons/tcpmon/core/filter/http/HttpFilter.java (original)
+++ webservices/commons/trunk/modules/tcpmon/modules/tcpmon-core/src/main/java/org/apache/ws/commons/tcpmon/core/filter/http/HttpFilter.java Fri Jun  5 07:41:45 2009
@@ -30,6 +30,8 @@
 import org.apache.ws.commons.tcpmon.core.filter.StreamFilter;
 import org.apache.ws.commons.tcpmon.core.filter.StreamUtil;
 import org.apache.ws.commons.tcpmon.core.filter.mime.ContentFilterFactory;
+import org.apache.ws.commons.tcpmon.core.filter.zip.GZIPDecoder;
+import org.apache.ws.commons.tcpmon.core.filter.zip.GZIPEncoder;
 
 /**
  * Base class for {@link HttpRequestFilter} and {@link HttpResponseFilter}.
@@ -40,15 +42,15 @@
     private static final int STATE_CONTENT = 2;
     private static final int STATE_COMPLETE = 3;
 
-    private final boolean decodeTransferEncoding;
+    private final boolean decode;
     private int state = STATE_FIRST_LINE;
     private final Headers headers = new Headers();
     private ContentFilterFactory contentFilterFactory;
     private EntityProcessor transferDecoder;
     private StreamFilter[] contentFilterChain;
     
-    public HttpFilter(boolean decodeTransferEncoding) {
-        this.decodeTransferEncoding = decodeTransferEncoding;
+    public HttpFilter(boolean decode) {
+        this.decode = decode;
     }
     
     public void setContentFilterFactory(ContentFilterFactory contentFilterFactory) {
@@ -97,7 +99,7 @@
                 case STATE_CONTENT: {
                     if (transferDecoder != null) {
                         Stream decoderStream =
-                                decodeTransferEncoding ? stream : new ReadOnlyStream(stream);
+                                decode ? stream : new ReadOnlyStream(stream);
                         if (transferDecoder.process(decoderStream)) {
                             state = STATE_COMPLETE;
                             if (contentFilterChain != null) {
@@ -130,6 +132,8 @@
         boolean hasEntity = false;
         boolean discardHeaders = false;
         StreamFilter transferEncoder = null;
+        StreamFilter contentDecoder = null;
+        StreamFilter contentEncoder = null;
         for (Iterator it = headers.iterator(); it.hasNext(); ) {
             Header header = (Header)it.next();
             String name = header.getName();
@@ -155,6 +159,11 @@
                         // If the content type is unparseable, just continue
                     }
                 }
+            } else if (name.equalsIgnoreCase("Content-Encoding")) {
+                if (value.equals("gzip")) {
+                    contentDecoder = new GZIPDecoder();
+                    contentEncoder = new GZIPEncoder();
+                }
             }
         }
         
@@ -170,15 +179,29 @@
         
         if (hasEntity) {
             if (contentFilterChain != null) {
-                if (transferEncoder != null && !decodeTransferEncoding) {
-                    stream.pushFilter(transferEncoder);
+                if (!decode) {
+                    if (transferEncoder != null) {
+                        stream.pushFilter(transferEncoder);
+                    }
+                    if (contentEncoder != null) {
+                        stream.pushFilter(contentEncoder);
+                    }
                 }
                 for (int i=contentFilterChain.length-1; i>=0; i--) {
                     stream.pushFilter(contentFilterChain[i]);
                 }
+                if (contentDecoder != null) {
+                    stream.pushFilter(contentDecoder);
+                }
             } else {
-                if (transferDecoder != null && !decodeTransferEncoding) {
-                    transferDecoder = new ReadOnlyEntityProcessorWrapper(transferDecoder);
+                if (decode) {
+                    if (contentDecoder != null) {
+                        stream.pushFilter(contentDecoder);
+                    }
+                } else {
+                    if (transferDecoder != null) {
+                        transferDecoder = new ReadOnlyEntityProcessorWrapper(transferDecoder);
+                    }
                 }
             }
             state = STATE_CONTENT;

Added: webservices/commons/trunk/modules/tcpmon/modules/tcpmon-core/src/main/java/org/apache/ws/commons/tcpmon/core/filter/zip/GZIPEncoder.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/tcpmon/modules/tcpmon-core/src/main/java/org/apache/ws/commons/tcpmon/core/filter/zip/GZIPEncoder.java?rev=781934&view=auto
==============================================================================
--- webservices/commons/trunk/modules/tcpmon/modules/tcpmon-core/src/main/java/org/apache/ws/commons/tcpmon/core/filter/zip/GZIPEncoder.java (added)
+++ webservices/commons/trunk/modules/tcpmon/modules/tcpmon-core/src/main/java/org/apache/ws/commons/tcpmon/core/filter/zip/GZIPEncoder.java Fri Jun  5 07:41:45 2009
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2004,2005 The Apache Software Foundation.
+ *
+ * Licensed 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.ws.commons.tcpmon.core.filter.zip;
+
+import java.util.zip.CRC32;
+import java.util.zip.Deflater;
+
+import org.apache.ws.commons.tcpmon.core.filter.Stream;
+import org.apache.ws.commons.tcpmon.core.filter.StreamFilter;
+import org.apache.ws.commons.tcpmon.core.filter.StreamUtil;
+
+public class GZIPEncoder implements StreamFilter {
+    private static final byte[] header = { 0x1f, (byte)0x8b, 8, 0, 0, 0, 0, 0, 0, -1 };
+    
+    private final Deflater deflater;
+    private final CRC32 crc = new CRC32();
+    private final byte[] inBuffer = new byte[256];
+    private final byte[] outBuffer = new byte[256];
+    private boolean isStart = true;
+    
+    public GZIPEncoder() {
+        this.deflater = new Deflater(Deflater.DEFAULT_COMPRESSION, true);
+    }
+
+    public void invoke(Stream stream) {
+        if (isStart) {
+            stream.insert(header, 0, 10);
+            isStart = false;
+        }
+        do {
+            int in = Math.min(inBuffer.length, stream.available());
+            stream.read(inBuffer, 0, in);
+            deflater.setInput(inBuffer, 0, in);
+            stream.discard(in);
+            if (stream.isEndOfStream()) {
+                deflater.finish();
+            }
+            crc.update(inBuffer, 0, in);
+            while (true) {
+                int out = deflater.deflate(outBuffer);
+                if (out > 0) {
+                    stream.insert(outBuffer, 0, out);
+                } else {
+                    break;
+                }
+            }
+        } while (stream.available() > 0);
+        if (stream.isEndOfStream()) {
+            // Write trailer
+            StreamUtil.insertInt(stream, (int)crc.getValue());
+            StreamUtil.insertInt(stream, deflater.getTotalIn());
+        }
+    }
+}

Propchange: webservices/commons/trunk/modules/tcpmon/modules/tcpmon-core/src/main/java/org/apache/ws/commons/tcpmon/core/filter/zip/GZIPEncoder.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: webservices/commons/trunk/modules/tcpmon/modules/tcpmon-core/src/test/java/org/apache/ws/commons/tcpmon/core/filter/zip/GZIPEncoderTest.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/tcpmon/modules/tcpmon-core/src/test/java/org/apache/ws/commons/tcpmon/core/filter/zip/GZIPEncoderTest.java?rev=781934&view=auto
==============================================================================
--- webservices/commons/trunk/modules/tcpmon/modules/tcpmon-core/src/test/java/org/apache/ws/commons/tcpmon/core/filter/zip/GZIPEncoderTest.java (added)
+++ webservices/commons/trunk/modules/tcpmon/modules/tcpmon-core/src/test/java/org/apache/ws/commons/tcpmon/core/filter/zip/GZIPEncoderTest.java Fri Jun  5 07:41:45 2009
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2004,2005 The Apache Software Foundation.
+ *
+ * Licensed 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.ws.commons.tcpmon.core.filter.zip;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.OutputStream;
+import java.util.Arrays;
+import java.util.Random;
+import java.util.zip.GZIPInputStream;
+
+import junit.framework.TestCase;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.ws.commons.tcpmon.core.filter.Pipeline;
+import org.apache.ws.commons.tcpmon.core.filter.Tee;
+
+public class GZIPEncoderTest extends TestCase {
+    public void test() throws Exception {
+        byte[] content = new byte[10000];
+        Random random = new Random();
+        random.nextBytes(content);
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        Pipeline pipeline = new Pipeline();
+        pipeline.addFilter(new GZIPEncoder());
+        pipeline.addFilter(new Tee(baos));
+        OutputStream out = pipeline.getOutputStream();
+        out.write(content);
+        out.close();
+        byte[] content2 = IOUtils.toByteArray(new GZIPInputStream(new ByteArrayInputStream(baos.toByteArray())));
+        assertTrue(Arrays.equals(content, content2));
+    }
+}

Propchange: webservices/commons/trunk/modules/tcpmon/modules/tcpmon-core/src/test/java/org/apache/ws/commons/tcpmon/core/filter/zip/GZIPEncoderTest.java
------------------------------------------------------------------------------
    svn:eol-style = native