You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by or...@apache.org on 2016/09/20 12:01:20 UTC

svn commit: r1761561 - in /qpid/java/trunk: broker-core/src/main/java/org/apache/qpid/server/queue/ broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/ broker-plugins/management-http/src/main/java/org/apache/qpid/serv...

Author: orudyy
Date: Tue Sep 20 12:01:20 2016
New Revision: 1761561

URL: http://svn.apache.org/viewvc?rev=1761561&view=rev
Log:
QPID-7408: Replace GZIPOutputStreamAdapter with GunzipOutputStream extending InflaterOutputStream

Added:
    qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/GunzipOutputStream.java
    qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/LimitingOutputStream.java
    qpid/java/trunk/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/GunzipOutputStreamTest.java
      - copied, changed from r1761411, qpid/java/trunk/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/GZIPOutputStreamAdapterTest.java
Removed:
    qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/GZIPOutputStreamAdapter.java
    qpid/java/trunk/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/GZIPOutputStreamAdapterTest.java
Modified:
    qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/queue/AbstractQueue.java
    qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/AbstractServlet.java

Modified: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/queue/AbstractQueue.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/queue/AbstractQueue.java?rev=1761561&r1=1761560&r2=1761561&view=diff
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/queue/AbstractQueue.java (original)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/queue/AbstractQueue.java Tue Sep 20 12:01:20 2016
@@ -110,6 +110,7 @@ import org.apache.qpid.server.util.Serve
 import org.apache.qpid.server.util.StateChangeListener;
 import org.apache.qpid.server.virtualhost.VirtualHostUnavailableException;
 import org.apache.qpid.transport.TransportException;
+import org.apache.qpid.util.GZIPUtils;
 
 public abstract class AbstractQueue<X extends AbstractQueue<X>>
         extends AbstractConfiguredObject<X>
@@ -2791,18 +2792,16 @@ public abstract class AbstractQueue<X ex
         public void write(OutputStream outputStream) throws IOException
         {
             ServerMessage message = _messageReference.getMessage();
-            int length = (int) (_limit == UNLIMITED ? message.getSize() : _limit);
+            int length = (int) ((_limit == UNLIMITED || GZIPUtils.GZIP_CONTENT_ENCODING.equals(getContentEncoding())) ? message.getSize() : _limit);
             Collection<QpidByteBuffer> content = message.getContent(0, length);
             try
             {
                 for (QpidByteBuffer b : content)
                 {
-
                     int len = b.remaining();
                     byte[] data = new byte[len];
                     b.get(data);
                     outputStream.write(data);
-
                 }
             }
             finally

Added: qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/GunzipOutputStream.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/GunzipOutputStream.java?rev=1761561&view=auto
==============================================================================
--- qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/GunzipOutputStream.java (added)
+++ qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/GunzipOutputStream.java Tue Sep 20 12:01:20 2016
@@ -0,0 +1,305 @@
+/*
+ * 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.qpid.server.management.plugin;
+
+import java.io.ByteArrayInputStream;
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Arrays;
+import java.util.EnumSet;
+import java.util.zip.CRC32;
+import java.util.zip.CheckedOutputStream;
+import java.util.zip.Deflater;
+import java.util.zip.Inflater;
+import java.util.zip.InflaterOutputStream;
+
+public class GunzipOutputStream extends InflaterOutputStream
+{
+    private final GZIPHeader _header = new GZIPHeader();
+    private final GZIPTrailer _trailer = new GZIPTrailer();
+    private final byte[] _singleByteArray = new byte[1];
+    private StreamState _streamState = StreamState.HEADER_PARSING;
+    private final CRC32 _crc;
+
+    public GunzipOutputStream(final OutputStream targetOutputStream)
+    {
+        super(new CheckedOutputStream(targetOutputStream, new CRC32()), new Inflater(true));
+        _crc = (CRC32)((CheckedOutputStream)out).getChecksum();
+    }
+
+    @Override
+    public void write(final byte data[], final int offset, final int length) throws IOException
+    {
+        ByteArrayInputStream bais = new ByteArrayInputStream(data, offset, length);
+        int b;
+        while ((b = bais.read()) != -1)
+        {
+            if (_streamState == StreamState.DONE)
+            {
+                // another member is coming
+                _streamState = StreamState.HEADER_PARSING;
+                _crc.reset();
+                _header.reset();
+                _trailer.reset();
+                inf.reset();
+            }
+
+            if (_streamState == StreamState.HEADER_PARSING)
+            {
+                _header.headerByte(b);
+                if (_header.getState() == HeaderState.DONE)
+                {
+                    _streamState = StreamState.INFLATING;
+                    continue;
+                }
+            }
+
+            if (_streamState == StreamState.INFLATING)
+            {
+                _singleByteArray[0] = (byte) b;
+                super.write(_singleByteArray, 0, 1);
+
+                if (inf.finished())
+                {
+                    _streamState = StreamState.TRAILER_PARSING;
+                    continue;
+                }
+            }
+
+            if (_streamState == StreamState.TRAILER_PARSING)
+            {
+                if (_trailer.trailerByte(b))
+                {
+                    _trailer.verify(_crc);
+                    _streamState = StreamState.DONE;
+                    continue;
+                }
+            }
+        }
+    }
+
+    private enum StreamState
+    {
+        HEADER_PARSING, INFLATING, TRAILER_PARSING, DONE
+    }
+
+    private enum HeaderState
+    {
+        ID1, ID2, CM, FLG, MTIME_0, MTIME_1, MTIME_2, MTIME_3, XFL, OS, XLEN_0, XLEN_1, FEXTRA, FNAME, FCOMMENT, CRC16_0, CRC16_1, DONE
+    }
+
+    private class GZIPHeader
+    {
+        private static final int GZIP_MAGIC_1 = 0x1F;
+        private static final int GZIP_MAGIC_2 = 0x8B;
+        private static final int SUPPORTED_COMPRESSION_METHOD = Deflater.DEFLATED;
+        private HeaderState _state = HeaderState.ID1;
+        private byte _flags;
+        private byte _xlen0;
+        private int _xlen;
+        private int _fExtraCounter;
+
+        private void headerByte(int headerByte) throws IOException
+        {
+            int b = headerByte & 0xff;
+            switch (_state)
+            {
+                case ID1:
+                    if (b != GZIP_MAGIC_1)
+                    {
+                        throw new IOException(String.format("Incorrect first magic byte: got '%X' but expected '%X'",
+                                                            headerByte,
+                                                            GZIP_MAGIC_1));
+                    }
+                    _state = HeaderState.ID2;
+                    break;
+                case ID2:
+                    if (b != GZIP_MAGIC_2)
+                    {
+                        throw new IOException(String.format("Incorrect second magic byte: got '%X' but expected '%X'",
+                                                            headerByte,
+                                                            GZIP_MAGIC_2));
+                    }
+                    _state = HeaderState.CM;
+                    break;
+                case CM:
+                    if (b != SUPPORTED_COMPRESSION_METHOD)
+                    {
+                        throw new IOException(String.format("Unexpected compression method : '%X'", b));
+                    }
+                    _state = HeaderState.FLG;
+                    break;
+                case FLG:
+                    _flags = (byte) b;
+                    _state = HeaderState.MTIME_0;
+                    break;
+                case MTIME_0:
+                    _state = HeaderState.MTIME_1;
+                    break;
+                case MTIME_1:
+                    _state = HeaderState.MTIME_2;
+                    break;
+                case MTIME_2:
+                    _state = HeaderState.MTIME_3;
+                    break;
+                case MTIME_3:
+                    _state = HeaderState.XFL;
+                    break;
+                case XFL:
+                    _state = HeaderState.OS;
+                    break;
+                case OS:
+                    adjustStateAccordingToFlags();
+                    break;
+                case XLEN_0:
+                    _xlen0 = (byte) b;
+                    _state = HeaderState.XLEN_1;
+                    break;
+                case XLEN_1:
+                    _xlen = b << 8 | _xlen0;
+                    _state = HeaderState.FEXTRA;
+                    break;
+                case FEXTRA:
+                    _fExtraCounter++;
+                    if (_fExtraCounter == _xlen)
+                    {
+                        adjustStateAccordingToFlags(HeaderState.XLEN_0);
+                    }
+                    break;
+                case FNAME:
+                    if (b == 0)
+                    {
+                        adjustStateAccordingToFlags(HeaderState.XLEN_0, HeaderState.FNAME);
+                    }
+                    break;
+                case FCOMMENT:
+                    if (b == 0)
+                    {
+                        adjustStateAccordingToFlags(HeaderState.XLEN_0, HeaderState.FNAME, HeaderState.FCOMMENT);
+                    }
+                    break;
+                case CRC16_0:
+                    _state = HeaderState.CRC16_1;
+                    break;
+                case CRC16_1:
+                    _state = HeaderState.DONE;
+                    break;
+                default:
+                    throw new IOException("Unexpected state " + _state);
+            }
+        }
+
+        private void adjustStateAccordingToFlags(HeaderState... previousStates)
+        {
+            EnumSet<HeaderState> previous = previousStates.length == 0
+                    ? EnumSet.noneOf(HeaderState.class)
+                    : EnumSet.copyOf(Arrays.asList(previousStates));
+            if ((_flags & (byte) 4) != 0 && !previous.contains(HeaderState.XLEN_0))
+            {
+                _state = HeaderState.XLEN_0;
+            }
+            else if ((_flags & (byte) 8) != 0 && !previous.contains(HeaderState.FNAME))
+            {
+                _state = HeaderState.FNAME;
+            }
+            else if ((_flags & (byte) 16) != 0 && !previous.contains(HeaderState.FCOMMENT))
+            {
+                _state = HeaderState.FCOMMENT;
+            }
+            else if ((_flags & (byte) 2) != 0 && !previous.contains(HeaderState.CRC16_0))
+            {
+                _state = HeaderState.CRC16_0;
+            }
+            else
+            {
+                _state = HeaderState.DONE;
+            }
+        }
+
+        private HeaderState getState()
+        {
+            return _state;
+        }
+
+        private void reset()
+        {
+            _state = HeaderState.ID1;
+            _flags = 0;
+            _xlen0 = 0;
+            _xlen = 0;
+            _fExtraCounter = 0;
+        }
+    }
+
+    private class GZIPTrailer
+    {
+        private static final int TRAILER_SIZE = 8;
+        private static final long SIZE_MASK = 0xffffffffL;
+        private byte[] _trailerBytes = new byte[TRAILER_SIZE];
+        private int _receivedByteIndex;
+
+        private boolean trailerByte(int b) throws IOException
+        {
+            if (_receivedByteIndex < TRAILER_SIZE)
+            {
+                _trailerBytes[_receivedByteIndex++] = (byte) (b & 0xff);
+                return _receivedByteIndex == TRAILER_SIZE;
+            }
+            else
+            {
+                throw new IOException(
+                        "Received bytes exceeds GZIP trailer length. Multipe memeber support is not implemented");
+            }
+        }
+
+        private void verify(CRC32 crc) throws IOException
+        {
+            try (DataInputStream in = new DataInputStream(new ByteArrayInputStream(_trailerBytes)))
+            {
+                long crc32 = readLittleEndianInt(in);
+                if (crc32 != crc.getValue())
+                {
+                    throw new IOException("crc32 mismatch. Gzip-compressed data is corrupted");
+                }
+                long isize = readLittleEndianInt(in);
+                if (isize != (inf.getBytesWritten() & SIZE_MASK))
+                {
+                    throw new IOException("Uncompressed size mismatch. Gzip-compressed data is corrupted");
+                }
+            }
+        }
+
+        private long readLittleEndianInt(final DataInputStream inData) throws IOException
+        {
+            return inData.readUnsignedByte()
+                   | (inData.readUnsignedByte() << 8)
+                   | (inData.readUnsignedByte() << 16)
+                   | (((long) inData.readUnsignedByte()) << 24);
+        }
+
+        private void reset()
+        {
+            _receivedByteIndex = 0;
+        }
+
+    }
+}

Added: qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/LimitingOutputStream.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/LimitingOutputStream.java?rev=1761561&view=auto
==============================================================================
--- qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/LimitingOutputStream.java (added)
+++ qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/LimitingOutputStream.java Tue Sep 20 12:01:20 2016
@@ -0,0 +1,76 @@
+/*
+ * 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.qpid.server.management.plugin;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+public class LimitingOutputStream extends OutputStream
+{
+    private final OutputStream _outputStream;
+    private final long _limit;
+    private long _counter;
+
+    public LimitingOutputStream(OutputStream outputStream, long limit)
+    {
+        _outputStream = outputStream;
+        _limit = limit;
+    }
+
+    @Override
+    public void write(final int b) throws IOException
+    {
+        if (_counter < _limit)
+        {
+            _outputStream.write(b);
+            _counter++;
+        }
+    }
+
+    @Override
+    public void write(final byte[] b, final int off, final int len) throws IOException
+    {
+        if (_counter < _limit)
+        {
+            int written = Math.min(len, (int)(_limit - _counter));
+            _outputStream.write(b, off, written);
+            _counter += written;
+        }
+    }
+
+    @Override
+    public void write(final byte[] b) throws IOException
+    {
+        write(b, 0, b.length);
+    }
+
+    @Override
+    public void flush() throws IOException
+    {
+        _outputStream.flush();
+    }
+
+    @Override
+    public void close() throws IOException
+    {
+        _outputStream.close();
+    }
+}

Modified: qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/AbstractServlet.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/AbstractServlet.java?rev=1761561&r1=1761560&r2=1761561&view=diff
==============================================================================
--- qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/AbstractServlet.java (original)
+++ qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/AbstractServlet.java Tue Sep 20 12:01:20 2016
@@ -32,6 +32,7 @@ import java.security.PrivilegedException
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.zip.GZIPOutputStream;
 
 import javax.security.auth.Subject;
 import javax.servlet.ServletConfig;
@@ -41,21 +42,21 @@ import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
-import org.apache.qpid.server.model.Content;
-import org.apache.qpid.server.model.CustomRestHeaders;
-import org.apache.qpid.server.model.RestContentHeader;
-
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.SerializationFeature;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import org.apache.qpid.server.management.plugin.GunzipOutputStream;
 import org.apache.qpid.server.management.plugin.HttpManagementConfiguration;
 import org.apache.qpid.server.management.plugin.HttpManagementUtil;
+import org.apache.qpid.server.management.plugin.LimitingOutputStream;
 import org.apache.qpid.server.model.Broker;
 import org.apache.qpid.server.model.ConfiguredObjectJacksonModule;
+import org.apache.qpid.server.model.Content;
+import org.apache.qpid.server.model.CustomRestHeaders;
+import org.apache.qpid.server.model.RestContentHeader;
 import org.apache.qpid.server.util.ConnectionScopedRuntimeException;
-import org.apache.qpid.server.management.plugin.GZIPOutputStreamAdapter;
 
 public abstract class AbstractServlet extends HttpServlet
 {
@@ -328,6 +329,27 @@ public abstract class AbstractServlet ex
             throws IOException
     {
         Map<String, Object> headers = getResponseHeaders(content);
+
+        try (OutputStream os = getOutputStream(request, response, headers))
+        {
+            response.setStatus(HttpServletResponse.SC_OK);
+            for (Map.Entry<String, Object> entry : headers.entrySet())
+            {
+                response.setHeader(entry.getKey(), String.valueOf(entry.getValue()));
+            }
+            content.write(os);
+        }
+        catch (IOException e)
+        {
+            LOGGER.warn("Unexpected exception processing request", e);
+            sendJsonErrorResponse(request, response, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
+        }
+    }
+
+    private OutputStream getOutputStream(final HttpServletRequest request,
+                                         final HttpServletResponse response,
+                                         Map<String, Object> headers) throws IOException
+    {
         boolean isGzipCompressed = GZIP_CONTENT_ENCODING.equals(headers.get(CONTENT_ENCODING_HEADER.toUpperCase()));
         boolean isCompressingAccepted = HttpManagementUtil.isCompressingAccepted(request, _managementConfiguration);
         if (isGzipCompressed && !isCompressingAccepted)
@@ -339,25 +361,35 @@ public abstract class AbstractServlet ex
         {
             limit = Long.parseLong(String.valueOf(headers.get(CONTENT_LIMIT.toUpperCase())));
         }
+        OutputStream stream = response.getOutputStream();
 
-        try (OutputStream os = isGzipCompressed && isCompressingAccepted && limit < 0
-                ? response.getOutputStream()
-                : isGzipCompressed && (!isCompressingAccepted || limit >= 0)
-                        ? new GZIPOutputStreamAdapter(getOutputStream(request, response), limit)
-                        : getOutputStream(request, response))
+        if (isGzipCompressed)
         {
-            response.setStatus(HttpServletResponse.SC_OK);
-            for (Map.Entry<String, Object> entry : headers.entrySet())
+            if (!isCompressingAccepted)
             {
-                response.setHeader(entry.getKey(), String.valueOf(entry.getValue()));
+                if (limit > 0)
+                {
+                    stream = new LimitingOutputStream(stream, limit);
+                }
+                stream = new GunzipOutputStream(stream);
+            }
+            else
+            {
+                if (limit > 0)
+                {
+                    stream = new GunzipOutputStream(new LimitingOutputStream(new GZIPOutputStream(stream), limit));
+                }
             }
-            content.write(os);
         }
-        catch (IOException e)
+        else
         {
-            LOGGER.warn("Unexpected exception processing request", e);
-            sendJsonErrorResponse(request, response, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
+            if (isCompressingAccepted)
+            {
+                stream = new GZIPOutputStream(stream);
+            }
         }
+
+        return stream;
     }
 
     private Map<String, Object> getResponseHeaders(final Object content)

Copied: qpid/java/trunk/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/GunzipOutputStreamTest.java (from r1761411, qpid/java/trunk/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/GZIPOutputStreamAdapterTest.java)
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/GunzipOutputStreamTest.java?p2=qpid/java/trunk/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/GunzipOutputStreamTest.java&p1=qpid/java/trunk/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/GZIPOutputStreamAdapterTest.java&r1=1761411&r2=1761561&rev=1761561&view=diff
==============================================================================
--- qpid/java/trunk/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/GZIPOutputStreamAdapterTest.java (original)
+++ qpid/java/trunk/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/GunzipOutputStreamTest.java Tue Sep 20 12:01:20 2016
@@ -24,37 +24,65 @@ import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.util.zip.GZIPOutputStream;
 
+import javax.xml.bind.DatatypeConverter;
+
 import org.apache.qpid.test.utils.QpidTestCase;
 
 
-public class GZIPOutputStreamAdapterTest extends QpidTestCase
+public class GunzipOutputStreamTest extends QpidTestCase
 {
+    // base64 encoded content of 'gzip -N test.txt' containing text: This is test
+    private static final String GZIP_CONTENT_WITH_EMBEDDED_FILE_NAME =
+            "H4sICIAM4FcAA3Rlc3QudHh0AAvJyCxWAKKS1OISANCadxgMAAAA";
+
+    // base64 encoded content of 'gzip -c -N test.txt > test.txt.gz ; gzip -c -N test1.txt >> test.txt.gz'
+    // containing texts "This is test" and "Another test text" accordingly
+    private static final String GZIP_CONTENT_WITH_MULTIPLE_MEMBERS =
+            "H4sICNoV4VcAA3Rlc3QudHh0AAvJyCxWAKKS1OISANCadxgMAAAA"
+            + "H4sICOQV4VcAA3Rlc3QxLnR4dABzzMsvyUgtUihJLS4BEhUlAHeK0kERAAAA";
+    private static final String TEST_TEXT = "This is test";
+    private static final String TEST_TEXT2 = "Another test text";
 
     public void testDecompressing() throws IOException
     {
         String testText = generateTestText();
         ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
-        GZIPOutputStreamAdapter adapter = new GZIPOutputStreamAdapter(outputStream, 128, -1);
+        GunzipOutputStream adapter = new GunzipOutputStream(outputStream);
 
         compressAndDecompressWithAdapter(testText, adapter);
 
         assertEquals("Unexpected content", testText, new String(outputStream.toByteArray()));
     }
 
-    public void testDecompressingLimited() throws IOException
+    public void testDecompressingWithFileName() throws IOException
     {
-        String testText = generateTestText();
+        byte[] data = DatatypeConverter.parseBase64Binary(GZIP_CONTENT_WITH_EMBEDDED_FILE_NAME);
+
         ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
-        GZIPOutputStreamAdapter adapter = new GZIPOutputStreamAdapter(outputStream, 128, testText.length() / 2);
+        GunzipOutputStream adapter = new GunzipOutputStream(outputStream);
+        adapter.write(data);
 
-        compressAndDecompressWithAdapter(testText, adapter);
+        assertEquals("Unexpected content", TEST_TEXT, new String(outputStream.toByteArray()));
+    }
+
+    public void testDecompressingMultipleMembers() throws IOException
+    {
+        byte[] data = DatatypeConverter.parseBase64Binary(GZIP_CONTENT_WITH_MULTIPLE_MEMBERS);
+
+        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+        GunzipOutputStream adapter = new GunzipOutputStream(outputStream);
+        for (int i = 0; i < data.length; i++)
+        {
+            adapter.write(data[i]);
+        }
 
-        assertEquals("Unexpected content",
-                     testText.substring(0, testText.length() / 2),
-                     new String(outputStream.toByteArray()));
+        StringBuilder expected = new StringBuilder(TEST_TEXT);
+        expected.append(TEST_TEXT2);
+        assertEquals("Unexpected content", expected.toString(), new String(outputStream.toByteArray()));
     }
 
-    private void compressAndDecompressWithAdapter(final String testText, final GZIPOutputStreamAdapter adapter) throws IOException
+    private void compressAndDecompressWithAdapter(final String testText, final GunzipOutputStream adapter)
+            throws IOException
     {
         byte[] data = compress(testText);
         byte[] buffer = new byte[256];
@@ -64,7 +92,7 @@ public class GZIPOutputStreamAdapterTest
         {
             int length = Math.min(remaining, buffer.length);
             System.arraycopy(data, written, buffer, 0, length);
-            adapter.write(buffer);
+            adapter.write(buffer, 0, length);
             written += length;
             remaining -= length;
         }
@@ -86,8 +114,16 @@ public class GZIPOutputStreamAdapterTest
         int i = 0;
         while (sb.length() < 5000)
         {
-            sb.append(" A simple test text ").append(i++);
+            if (i % 2 == 0)
+            {
+                sb.append(TEST_TEXT);
+            }
+            else
+            {
+                sb.append(TEST_TEXT2);
+            }
+            sb.append(" ").append(i++);
         }
         return sb.toString();
     }
-}
\ No newline at end of file
+}



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org