You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by tr...@apache.org on 2006/03/12 04:16:36 UTC
svn commit: r385235 - in /directory/trunks/mina: ./ filter-compression/
filter-compression/lib/ filter-compression/src/
filter-compression/src/main/ filter-compression/src/main/java/
filter-compression/src/main/java/org/ filter-compression/src/main/jav...
Author: trustin
Date: Sat Mar 11 19:16:33 2006
New Revision: 385235
URL: http://svn.apache.org/viewcvs?rev=385235&view=rev
Log:
Related issue: DIRMINA-179 (Stream compression support)
* Applied Vinod's patch
** Removed algorithm parameter because ZLib is the only algorithm for now. We'll have to provide an interface such as CompressionAlgorithm and let user provide it as a parameter.
* systemPath in pom.xml doesn't work well with the bundled Eclipse plugin; upgraded to 2.1
Added:
directory/trunks/mina/filter-compression/
directory/trunks/mina/filter-compression/LICENSE.txt (with props)
directory/trunks/mina/filter-compression/NOTICE.txt (with props)
directory/trunks/mina/filter-compression/lib/
directory/trunks/mina/filter-compression/lib/jzlib-1.0.7.jar (with props)
directory/trunks/mina/filter-compression/pom.xml (with props)
directory/trunks/mina/filter-compression/src/
directory/trunks/mina/filter-compression/src/main/
directory/trunks/mina/filter-compression/src/main/java/
directory/trunks/mina/filter-compression/src/main/java/org/
directory/trunks/mina/filter-compression/src/main/java/org/apache/
directory/trunks/mina/filter-compression/src/main/java/org/apache/mina/
directory/trunks/mina/filter-compression/src/main/java/org/apache/mina/filter/
directory/trunks/mina/filter-compression/src/main/java/org/apache/mina/filter/CompressionFilter.java (with props)
directory/trunks/mina/filter-compression/src/main/java/org/apache/mina/filter/support/
directory/trunks/mina/filter-compression/src/main/java/org/apache/mina/filter/support/Zlib.java (with props)
directory/trunks/mina/filter-compression/src/test/
directory/trunks/mina/filter-compression/src/test/java/
directory/trunks/mina/filter-compression/src/test/java/org/
directory/trunks/mina/filter-compression/src/test/java/org/apache/
directory/trunks/mina/filter-compression/src/test/java/org/apache/mina/
directory/trunks/mina/filter-compression/src/test/java/org/apache/mina/filter/
directory/trunks/mina/filter-compression/src/test/java/org/apache/mina/filter/CompressionFilterTest.java (with props)
directory/trunks/mina/filter-compression/src/test/java/org/apache/mina/filter/support/
directory/trunks/mina/filter-compression/src/test/java/org/apache/mina/filter/support/ZlibTest.java (with props)
Modified:
directory/trunks/mina/pom.xml
Added: directory/trunks/mina/filter-compression/LICENSE.txt
URL: http://svn.apache.org/viewcvs/directory/trunks/mina/filter-compression/LICENSE.txt?rev=385235&view=auto
==============================================================================
--- directory/trunks/mina/filter-compression/LICENSE.txt (added)
+++ directory/trunks/mina/filter-compression/LICENSE.txt Sat Mar 11 19:16:33 2006
@@ -0,0 +1,20 @@
+/*
+ * Apache License
+ * Version 2.0, January 2004
+ * http://www.apache.org/licenses/
+ *
+ * Copyright ${pom.inceptionYear} 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.
+ *
+ */
Propchange: directory/trunks/mina/filter-compression/LICENSE.txt
------------------------------------------------------------------------------
svn:executable = *
Added: directory/trunks/mina/filter-compression/NOTICE.txt
URL: http://svn.apache.org/viewcvs/directory/trunks/mina/filter-compression/NOTICE.txt?rev=385235&view=auto
==============================================================================
--- directory/trunks/mina/filter-compression/NOTICE.txt (added)
+++ directory/trunks/mina/filter-compression/NOTICE.txt Sat Mar 11 19:16:33 2006
@@ -0,0 +1,2 @@
+This product includes software developed by
+The Apache Software Foundation (http://www.apache.org/).
Propchange: directory/trunks/mina/filter-compression/NOTICE.txt
------------------------------------------------------------------------------
svn:executable = *
Added: directory/trunks/mina/filter-compression/lib/jzlib-1.0.7.jar
URL: http://svn.apache.org/viewcvs/directory/trunks/mina/filter-compression/lib/jzlib-1.0.7.jar?rev=385235&view=auto
==============================================================================
Binary file - no diff available.
Propchange: directory/trunks/mina/filter-compression/lib/jzlib-1.0.7.jar
------------------------------------------------------------------------------
svn:executable = *
Propchange: directory/trunks/mina/filter-compression/lib/jzlib-1.0.7.jar
------------------------------------------------------------------------------
svn:mime-type = application/octet-stream
Added: directory/trunks/mina/filter-compression/pom.xml
URL: http://svn.apache.org/viewcvs/directory/trunks/mina/filter-compression/pom.xml?rev=385235&view=auto
==============================================================================
--- directory/trunks/mina/filter-compression/pom.xml (added)
+++ directory/trunks/mina/filter-compression/pom.xml Sat Mar 11 19:16:33 2006
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<project>
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.directory.mina</groupId>
+ <artifactId>build</artifactId>
+ <version>0.9.3-SNAPSHOT</version>
+ </parent>
+ <artifactId>mina-filter-compression</artifactId>
+ <name>Apache MINA Stream Compression Filter</name>
+ <packaging>jar</packaging>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>org.apache.directory.mina</groupId>
+ <artifactId>mina-core</artifactId>
+ <version>${pom.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-simple</artifactId>
+ <version>1.0-rc5</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>easymock</groupId>
+ <artifactId>easymock</artifactId>
+ <version>1.2_Java1.3</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>jcraft</groupId>
+ <artifactId>jzlib</artifactId>
+ <version>1.0.7</version>
+ <scope>system</scope>
+ <systemPath>${basedir}/lib/jzlib-1.0.7.jar</systemPath>
+ </dependency>
+
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>1.4</source>
+ <target>1.4</target>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
+
Propchange: directory/trunks/mina/filter-compression/pom.xml
------------------------------------------------------------------------------
svn:executable = *
Added: directory/trunks/mina/filter-compression/src/main/java/org/apache/mina/filter/CompressionFilter.java
URL: http://svn.apache.org/viewcvs/directory/trunks/mina/filter-compression/src/main/java/org/apache/mina/filter/CompressionFilter.java?rev=385235&view=auto
==============================================================================
--- directory/trunks/mina/filter-compression/src/main/java/org/apache/mina/filter/CompressionFilter.java (added)
+++ directory/trunks/mina/filter-compression/src/main/java/org/apache/mina/filter/CompressionFilter.java Sat Mar 11 19:16:33 2006
@@ -0,0 +1,272 @@
+/*
+ * Copyright 2004 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.mina.filter;
+
+import java.io.IOException;
+
+import org.apache.mina.common.ByteBuffer;
+import org.apache.mina.common.IoFilter;
+import org.apache.mina.common.IoFilterAdapter;
+import org.apache.mina.common.IoFilterChain;
+import org.apache.mina.common.IoSession;
+import org.apache.mina.filter.support.Zlib;
+
+/**
+ * An {@link IoFilter} which compresses all data using
+ * <a href="http://www.jcraft.com/jzlib/">JZlib</a>.
+ * Support for the LZW (DLCZ) algorithm is also planned.
+ * <p>
+ * This filter only supports compression using the <tt>PARTIAL FLUSH</tt> method,
+ * since that is the only method useful when doing stream level compression.
+ * <p>
+ * This filter supports compression/decompression of the input and output
+ * channels selectively. It can also be enabled/disabled on the fly.
+ * <p>
+ * This filter does not discard the zlib objects, keeping them around for the
+ * entire life of the filter. This is because the zlib dictionary needs to
+ * be built up over time, which is used during compression and decompression.
+ * Over time, as repetitive data is sent over the wire, the compression efficiency
+ * steadily increases.
+ * <p>
+ * Note that the zlib header is written only once. It is not necessary that
+ * the data received after processing by this filter may not be complete due
+ * to packet fragmentation.
+ * <p>
+ * It goes without saying that the other end of this stream should also have a
+ * compatible compressor/decompressor using the same algorithm.
+ *
+ * @author The Apache Directory Project (mina-dev@directory.apache.org)
+ */
+public class CompressionFilter extends IoFilterAdapter
+{
+ /**
+ * Max compression level. Will give the highest compression ratio, but
+ * will also take more cpu time and is the slowest.
+ */
+ public static final int COMPRESSION_MAX = Zlib.COMPRESSION_MAX;
+
+ /**
+ * Provides the best speed at the price of a low compression ratio.
+ */
+ public static final int COMPRESSION_MIN = Zlib.COMPRESSION_MIN;
+
+ /**
+ * No compression done on the data.
+ */
+ public static final int COMPRESSION_NONE = Zlib.COMPRESSION_NONE;
+
+ /**
+ * The default compression level used. Provides the best balance
+ * between speed and compression
+ */
+ public static final int COMPRESSION_DEFAULT = Zlib.COMPRESSION_DEFAULT;
+
+ /**
+ * A session attribute that stores the {@link Zlib} object used for compression.
+ */
+ private static final String DEFLATER = CompressionFilter.class.getName()
+ + ".Deflater";
+
+ /**
+ * A session attribute that stores the {@link Zlib} object used for decompression.
+ */
+ private static final String INFLATER = CompressionFilter.class.getName()
+ + ".Inflater";
+
+ /**
+ * A flag that allows you to disable compression once.
+ */
+ public static final String DISABLE_COMPRESSION_ONCE = CompressionFilter.class
+ .getName()
+ + ".DisableCompressionOnce";
+
+ private boolean compressInbound = true;
+ private boolean compressOutbound = true;
+ private int compressionLevel;
+
+ /**
+ * Creates a new instance which compresses outboud data and decompresses
+ * inbound data with default compression level.
+ */
+ public CompressionFilter()
+ {
+ this( true, true, COMPRESSION_DEFAULT );
+ }
+
+ /**
+ * Creates a new instance which compresses outboud data and decompresses
+ * inbound data with the specified <tt>compressionLevel</tt>.
+ *
+ * @param compressionLevel the level of compression to be used. Must
+ * be one of {@link #COMPRESSION_DEFAULT},
+ * {@link #COMPRESSION_MAX},
+ * {@link #COMPRESSION_MIN}, and
+ * {@link #COMPRESSION_NONE}.
+ */
+ public CompressionFilter( final int compressionLevel )
+ {
+ this( true, true, compressionLevel );
+ }
+
+ /**
+ * Creates a new instance.
+ *
+ * @param compressInbound <tt>true</tt> if data read is to be decompressed
+ * @param compressOutbound <tt>true</tt> if data written is to be compressed
+ * @param compressionLevel the level of compression to be used. Must
+ * be one of {@link #COMPRESSION_DEFAULT},
+ * {@link #COMPRESSION_MAX},
+ * {@link #COMPRESSION_MIN}, and
+ * {@link #COMPRESSION_NONE}.
+ */
+ public CompressionFilter(
+ final boolean compressInbound,
+ final boolean compressOutbound,
+ final int compressionLevel )
+ {
+ this.compressionLevel = compressionLevel;
+ this.compressInbound = compressInbound;
+ this.compressOutbound = compressOutbound;
+ }
+
+ public void messageReceived( NextFilter nextFilter,
+ IoSession session, Object message ) throws Exception
+ {
+ if( !compressInbound )
+ {
+ nextFilter.messageReceived( session, message );
+ return;
+ }
+
+ Zlib inflater = ( Zlib ) session.getAttribute( INFLATER );
+ if( inflater == null )
+ {
+ throw new IllegalStateException();
+ }
+
+ ByteBuffer inBuffer = ( ByteBuffer ) message;
+ ByteBuffer outBuffer = inflater.inflate( inBuffer );
+
+ nextFilter.messageReceived( session, outBuffer );
+ }
+
+ /*
+ * @see org.apache.mina.common.IoFilter#filterWrite(org.apache.mina.common.IoFilter.NextFilter, org.apache.mina.common.IoSession, org.apache.mina.common.IoFilter.WriteRequest)
+ */
+ public void filterWrite( NextFilter nextFilter,
+ IoSession session, WriteRequest writeRequest ) throws IOException
+ {
+ if( !compressOutbound )
+ {
+ nextFilter.filterWrite( session, writeRequest );
+ return;
+ }
+
+ if( session.containsAttribute( DISABLE_COMPRESSION_ONCE ) )
+ {
+ // Remove the marker attribute because it is temporary.
+ session.removeAttribute( DISABLE_COMPRESSION_ONCE );
+ nextFilter.filterWrite( session, writeRequest );
+ return;
+ }
+
+ Zlib deflater = ( Zlib ) session.getAttribute( DEFLATER );
+ if( deflater == null )
+ {
+ throw new IllegalStateException();
+ }
+
+ ByteBuffer inBuffer = ( ByteBuffer ) writeRequest.getMessage();
+
+ ByteBuffer outBuf = deflater.deflate( inBuffer );
+
+ nextFilter.filterWrite( session, new WriteRequest( outBuf, writeRequest
+ .getFuture() ) );
+ }
+
+ public void onPreAdd( IoFilterChain parent, String name, NextFilter nextFilter ) throws Exception
+ {
+ if( parent.contains( CompressionFilter.class ) )
+ {
+ throw new IllegalStateException( "A filter chain cannot contain more than" +
+ " one Stream Compression filter." );
+ }
+
+ Zlib deflater = new Zlib( compressionLevel, Zlib.MODE_DEFLATER );
+ Zlib inflater = new Zlib( compressionLevel, Zlib.MODE_INFLATER );
+
+ IoSession session = parent.getSession();
+
+ session.setAttribute( DEFLATER, deflater );
+ session.setAttribute( INFLATER, inflater );
+ }
+
+ /**
+ * Returns <tt>true</tt> if incoming data is being compressed.
+ */
+ public boolean isCompressInbound()
+ {
+ return compressInbound;
+ }
+
+ /**
+ * Sets if incoming data has to be compressed.
+ */
+ public void setCompressInbound( boolean compressInbound )
+ {
+ this.compressInbound = compressInbound;
+ }
+
+ /**
+ * Returns <tt>true</tt> if the filter is compressing data being written.
+ */
+ public boolean isCompressOutbound()
+ {
+ return compressOutbound;
+ }
+
+ /**
+ * Set if outgoing data has to be compressed.
+ */
+ public void setCompressOutbound( boolean compressOutbound )
+ {
+ this.compressOutbound = compressOutbound;
+ }
+
+ public void onPostRemove( IoFilterChain parent, String name, NextFilter nextFilter ) throws Exception
+ {
+ super.onPostRemove( parent, name, nextFilter );
+ IoSession session = parent.getSession();
+ if( session == null )
+ {
+ return;
+ }
+
+ Zlib inflater = ( Zlib ) session.getAttribute( INFLATER );
+ Zlib deflater = ( Zlib ) session.getAttribute( DEFLATER );
+ if( deflater != null )
+ {
+ deflater.cleanUp();
+ }
+
+ if( inflater != null )
+ {
+ inflater.cleanUp();
+ }
+ }
+}
Propchange: directory/trunks/mina/filter-compression/src/main/java/org/apache/mina/filter/CompressionFilter.java
------------------------------------------------------------------------------
svn:executable = *
Added: directory/trunks/mina/filter-compression/src/main/java/org/apache/mina/filter/support/Zlib.java
URL: http://svn.apache.org/viewcvs/directory/trunks/mina/filter-compression/src/main/java/org/apache/mina/filter/support/Zlib.java?rev=385235&view=auto
==============================================================================
--- directory/trunks/mina/filter-compression/src/main/java/org/apache/mina/filter/support/Zlib.java (added)
+++ directory/trunks/mina/filter-compression/src/main/java/org/apache/mina/filter/support/Zlib.java Sat Mar 11 19:16:33 2006
@@ -0,0 +1,194 @@
+/*
+ * Copyright 2004 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.mina.filter.support;
+
+import java.io.IOException;
+
+import org.apache.mina.common.ByteBuffer;
+
+import com.jcraft.jzlib.JZlib;
+import com.jcraft.jzlib.ZStream;
+
+/**
+ * A helper class for interfacing with the JZlib library. This class acts both
+ * as a compressor and decompressor, but only as one at a time. The only
+ * flush method supported is <tt>Z_FLUSH_SYNC</tt> also known as <tt>Z_PARTIAL_FLUSH</tt>
+ *
+ * @author The Apache Directory MINA subproject (mina-dev@directory.apache.org)
+ */
+public class Zlib
+{
+ public static final int COMPRESSION_MAX = JZlib.Z_BEST_COMPRESSION;
+ public static final int COMPRESSION_MIN = JZlib.Z_BEST_SPEED;
+ public static final int COMPRESSION_NONE = JZlib.Z_NO_COMPRESSION;
+ public static final int COMPRESSION_DEFAULT = JZlib.Z_DEFAULT_COMPRESSION;
+
+ public static final int MODE_DEFLATER = 1;
+ public static final int MODE_INFLATER = 2;
+
+ private int compressionLevel;
+ private ZStream zStream = null;
+ private int mode = -1;
+
+ /**
+ * @param compressionLevel the level of compression that should be used
+ * @param mode the mode in which the instance will operate. Can be either
+ * of <tt>MODE_DEFLATER</tt> or <tt>MODE_INFLATER</tt>
+ */
+ public Zlib( int compressionLevel, int mode )
+ {
+ switch( compressionLevel )
+ {
+ case COMPRESSION_MAX:
+ case COMPRESSION_MIN:
+ case COMPRESSION_NONE:
+ case COMPRESSION_DEFAULT:
+ this.compressionLevel = compressionLevel;
+ break;
+ default:
+ throw new IllegalArgumentException( "invalid compression level specified" );
+ }
+
+ // create a new instance of ZStream. This will be done only once.
+ zStream = new ZStream();
+
+ switch( mode )
+ {
+ case MODE_DEFLATER:
+ zStream.deflateInit( this.compressionLevel );
+ break;
+ case MODE_INFLATER:
+ zStream.inflateInit();
+ break;
+ default:
+ throw new IllegalArgumentException( "invalid mode specified" );
+ }
+ this.mode = mode;
+ }
+
+ /**
+ * @param inBuffer the {@link ByteBuffer} to be decompressed. The contents
+ * of the buffer are transferred into a local byte array and the buffer is
+ * flipped and returned intact.
+ * @return the decompressed data. If not passed to the MINA methods that
+ * release the buffer automatically, the buffer has to be manually released
+ * @throws IOException if the decompression of the data failed for some reason.
+ */
+ public ByteBuffer inflate( ByteBuffer inBuffer ) throws IOException
+ {
+ if( mode == MODE_DEFLATER )
+ {
+ throw new IllegalStateException( "not initialized as INFLATER" );
+ }
+
+ byte[] inBytes = new byte[ inBuffer.limit() ];
+ inBuffer.get( inBytes ).flip();
+
+ byte[] outBytes = new byte[ inBytes.length * 2 ];
+ ByteBuffer outBuffer = ByteBuffer.allocate( outBytes.length );
+ outBuffer.setAutoExpand( true );
+
+ zStream.next_in = inBytes;
+ zStream.next_in_index = 0;
+ zStream.avail_in = inBytes.length;
+ zStream.next_out = outBytes;
+ zStream.next_out_index = 0;
+ zStream.avail_out = outBytes.length;
+ int retval = 0;
+
+ do
+ {
+ retval = zStream.inflate( JZlib.Z_PARTIAL_FLUSH );
+ switch( retval )
+ {
+ case JZlib.Z_OK:
+ // completed decompression, lets copy data and get out
+ case JZlib.Z_BUF_ERROR:
+ // need more space for output. store current output and get more
+ outBuffer.put( outBytes, 0, zStream.next_out_index );
+ zStream.next_out_index = 0;
+ zStream.avail_out = outBytes.length;
+ break;
+ default:
+ // unknown error
+ outBuffer.release();
+ outBuffer = null;
+ if( zStream.msg == null )
+ throw new IOException( "Unknown error. Error code : " + retval );
+ else
+ throw new IOException( "Unknown error. Error code : " + retval
+ + " and message : " + zStream.msg );
+ }
+ } while( zStream.avail_in > 0 );
+
+ return outBuffer.flip();
+ }
+
+ /**
+ * @param inBuffer the buffer to be compressed. The contents are transferred
+ * into a local byte array and the buffer is flipped and returned intact.
+ * @return the buffer with the compressed data. If not passed to any of the
+ * MINA methods that automatically release the buffer, the buffer has to be
+ * released manually.
+ * @throws IOException if the compression of teh buffer failed for some reason
+ */
+ public ByteBuffer deflate( ByteBuffer inBuffer ) throws IOException
+ {
+ if( mode == MODE_INFLATER )
+ {
+ throw new IllegalStateException( "not initialized as DEFLATER" );
+ }
+
+ byte[] inBytes = new byte[ inBuffer.limit() ];
+ inBuffer.get( inBytes ).flip();
+
+ // according to spec, destination buffer should be 0.1% larger
+ // than source length plus 12 bytes. We add a single byte to safeguard
+ // against rounds that round down to the smaller value
+ int outLen = (int) Math.round( inBytes.length * 1.001 ) + 1 + 12;
+ byte[] outBytes = new byte[ outLen ];
+
+ zStream.next_in = inBytes;
+ zStream.next_in_index = 0;
+ zStream.avail_in = inBytes.length;
+ zStream.next_out = outBytes;
+ zStream.next_out_index = 0;
+ zStream.avail_out = outBytes.length;
+
+ int retval = zStream.deflate( JZlib.Z_SYNC_FLUSH );
+ if( retval != JZlib.Z_OK )
+ {
+ outBytes = null;
+ inBytes = null;
+ throw new IOException( "Compression failed with return value : " + retval );
+ }
+
+ ByteBuffer outBuf = ByteBuffer.wrap( outBytes, 0, zStream.next_out_index );
+
+ return outBuf;
+ }
+
+ /**
+ * Cleans up the resources used by the compression library.
+ */
+ public void cleanUp()
+ {
+ if( zStream != null )
+ zStream.free();
+ }
+}
\ No newline at end of file
Propchange: directory/trunks/mina/filter-compression/src/main/java/org/apache/mina/filter/support/Zlib.java
------------------------------------------------------------------------------
svn:executable = *
Added: directory/trunks/mina/filter-compression/src/test/java/org/apache/mina/filter/CompressionFilterTest.java
URL: http://svn.apache.org/viewcvs/directory/trunks/mina/filter-compression/src/test/java/org/apache/mina/filter/CompressionFilterTest.java?rev=385235&view=auto
==============================================================================
--- directory/trunks/mina/filter-compression/src/test/java/org/apache/mina/filter/CompressionFilterTest.java (added)
+++ directory/trunks/mina/filter-compression/src/test/java/org/apache/mina/filter/CompressionFilterTest.java Sat Mar 11 19:16:33 2006
@@ -0,0 +1,209 @@
+/*
+ * Copyright 2004 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.mina.filter;
+
+import org.apache.mina.common.ByteBuffer;
+import org.apache.mina.common.IoFilterChain;
+import org.apache.mina.common.IoSession;
+import org.apache.mina.common.IoFilter.NextFilter;
+import org.apache.mina.filter.support.Zlib;
+import org.apache.mina.common.IoFilter.WriteRequest;
+import org.easymock.MockControl;
+import org.easymock.AbstractMatcher;
+
+import junit.framework.TestCase;
+
+/**
+ * @author The Apache Directory MINA subproject (mina-dev@directory.apache.org)
+ *
+ */
+public class CompressionFilterTest extends TestCase
+{
+ private MockControl mockSession;
+ private MockControl mockNextFilter;
+ private MockControl mockIoFilterChain;
+ private IoSession session;
+ private NextFilter nextFilter;
+ private IoFilterChain ioFilterChain;
+ private CompressionFilter filter;
+ private Zlib deflater;
+ private Zlib inflater;
+ private Zlib actualDeflater;
+ private Zlib actualInflater;
+
+ // the sample data to be used for testing
+ String strCompress =
+ "The quick brown fox jumps over the lazy dog. " +
+ "The quick brown fox jumps over the lazy dog. " +
+ "The quick brown fox jumps over the lazy dog. " +
+ "The quick brown fox jumps over the lazy dog. " +
+ "The quick brown fox jumps over the lazy dog. " +
+ "The quick brown fox jumps over the lazy dog. " +
+ "The quick brown fox jumps over the lazy dog. " +
+ "The quick brown fox jumps over the lazy dog. " +
+ "The quick brown fox jumps over the lazy dog. " +
+ "The quick brown fox jumps over the lazy dog. " +
+ "The quick brown fox jumps over the lazy dog. " +
+ "The quick brown fox jumps over the lazy dog. " +
+ "The quick brown fox jumps over the lazy dog. " +
+ "The quick brown fox jumps over the lazy dog. " +
+ "The quick brown fox jumps over the lazy dog. " +
+ "The quick brown fox jumps over the lazy dog. " +
+ "The quick brown fox jumps over the lazy dog. " +
+ "The quick brown fox jumps over the lazy dog. " +
+ "The quick brown fox jumps over the lazy dog. " +
+ "The quick brown fox jumps over the lazy dog. " +
+ "The quick brown fox jumps over the lazy dog. " +
+ "The quick brown fox jumps over the lazy dog. " +
+ "The quick brown fox jumps over the lazy dog. " +
+ "The quick brown fox jumps over the lazy dog. " +
+ "The quick brown fox jumps over the lazy dog. ";
+
+ protected void setUp()
+ {
+ // create the necessary mock controls.
+ mockSession = MockControl.createControl( IoSession.class );
+ mockNextFilter = MockControl.createControl( NextFilter.class );
+ mockIoFilterChain = MockControl.createControl( IoFilterChain.class );
+
+ // set the default matcher
+ mockNextFilter.setDefaultMatcher( new DataMatcher() );
+
+ session = ( IoSession ) mockSession.getMock();
+ nextFilter = ( NextFilter ) mockNextFilter.getMock();
+ ioFilterChain = ( IoFilterChain ) mockIoFilterChain.getMock();
+
+ // create an instance of the filter
+ filter = new CompressionFilter( CompressionFilter.COMPRESSION_MAX );
+
+ // deflater and inflater that will be used by the filter
+ deflater = new Zlib( Zlib.COMPRESSION_MAX, Zlib.MODE_DEFLATER );
+ inflater = new Zlib( Zlib.COMPRESSION_MAX, Zlib.MODE_INFLATER );
+
+ // create instances of the deflater and inflater to help test the output
+ actualDeflater = new Zlib( Zlib.COMPRESSION_MAX, Zlib.MODE_DEFLATER );
+ actualInflater = new Zlib( Zlib.COMPRESSION_MAX, Zlib.MODE_INFLATER );
+ }
+
+ public void testCompression() throws Exception
+ {
+ // prepare the input data
+ ByteBuffer buf = ByteBuffer.wrap( strCompress.getBytes( "UTF8" ) );
+ ByteBuffer actualOutput = actualDeflater.deflate( buf );
+ WriteRequest writeRequest = new WriteRequest( buf );
+
+ // record all the mock calls
+ ioFilterChain.contains( CompressionFilter.class );
+ mockIoFilterChain.setReturnValue( false );
+
+ ioFilterChain.getSession();
+ mockIoFilterChain.setReturnValue( session );
+
+ session.setAttribute( CompressionFilter.class.getName() + ".Deflater", deflater );
+ mockSession.setDefaultMatcher( new DataMatcher() );
+ mockSession.setReturnValue( null, MockControl.ONE );
+
+ session.setAttribute( CompressionFilter.class.getName() + ".Inflater", inflater );
+ mockSession.setReturnValue( null, MockControl.ONE );
+
+ session.containsAttribute( CompressionFilter.DISABLE_COMPRESSION_ONCE );
+ mockSession.setReturnValue( false );
+
+ session.getAttribute( CompressionFilter.class.getName() + ".Deflater" );
+ mockSession.setReturnValue( deflater );
+
+ nextFilter.filterWrite( session, new WriteRequest( actualOutput ) );
+
+ // switch to playback mode
+ mockSession.replay();
+ mockIoFilterChain.replay();
+ mockNextFilter.replay();
+
+ // make the actual calls on the filter
+ filter.onPreAdd( ioFilterChain, "CompressionFilter", nextFilter );
+ filter.filterWrite( nextFilter, session, writeRequest );
+
+ // verify that all the calls happened as recorded
+ mockNextFilter.verify();
+
+ assertTrue( true );
+ }
+
+ public void testDecompression() throws Exception
+ {
+ // prepare the input data
+ ByteBuffer buf = ByteBuffer.wrap( strCompress.getBytes( "UTF8" ) );
+ ByteBuffer byteInput = actualDeflater.deflate( buf );
+ ByteBuffer actualOutput = actualInflater.inflate( byteInput );
+
+ // record all the mock calls
+ ioFilterChain.contains( CompressionFilter.class );
+ mockIoFilterChain.setReturnValue( false );
+
+ ioFilterChain.getSession();
+ mockIoFilterChain.setReturnValue( session );
+
+ session.setAttribute( CompressionFilter.class.getName() + ".Deflater", deflater );
+ mockSession.setDefaultMatcher( new DataMatcher() );
+ mockSession.setReturnValue( null, MockControl.ONE );
+
+ session.setAttribute( CompressionFilter.class.getName() + ".Inflater", inflater );
+ mockSession.setReturnValue( null, MockControl.ONE );
+
+ session.getAttribute( CompressionFilter.class.getName() + ".Inflater" );
+ mockSession.setReturnValue( inflater );
+
+ nextFilter.messageReceived( session, actualOutput );
+
+ // switch to playback mode
+ mockSession.replay();
+ mockIoFilterChain.replay();
+ mockNextFilter.replay();
+
+ // make the actual calls on the filter
+ filter.onPreAdd( ioFilterChain, "CompressionFilter", nextFilter );
+ filter.messageReceived( nextFilter, session, byteInput );
+
+ // verify that all the calls happened as recorded
+ mockNextFilter.verify();
+
+ assertTrue( true );
+ }
+
+ /**
+ * A matcher used to check if the actual and expected outputs matched
+ *
+ * @author The Apache Directory MINA subproject (mina-dev@directory.apache.org)
+ */
+ class DataMatcher extends AbstractMatcher
+ {
+ protected boolean argumentMatches( Object arg0, Object arg1 )
+ {
+ // we need to only verify the ByteBuffer output
+ if( arg0 instanceof WriteRequest )
+ {
+ WriteRequest expected = (WriteRequest) arg0;
+ WriteRequest actual = (WriteRequest) arg1;
+ ByteBuffer bExpected = (ByteBuffer) expected.getMessage();
+ ByteBuffer bActual = (ByteBuffer) actual.getMessage();
+ return bExpected.equals( bActual );
+ }
+ return true;
+ }
+ }
+}
Propchange: directory/trunks/mina/filter-compression/src/test/java/org/apache/mina/filter/CompressionFilterTest.java
------------------------------------------------------------------------------
svn:executable = *
Added: directory/trunks/mina/filter-compression/src/test/java/org/apache/mina/filter/support/ZlibTest.java
URL: http://svn.apache.org/viewcvs/directory/trunks/mina/filter-compression/src/test/java/org/apache/mina/filter/support/ZlibTest.java?rev=385235&view=auto
==============================================================================
--- directory/trunks/mina/filter-compression/src/test/java/org/apache/mina/filter/support/ZlibTest.java (added)
+++ directory/trunks/mina/filter-compression/src/test/java/org/apache/mina/filter/support/ZlibTest.java Sat Mar 11 19:16:33 2006
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2004 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.mina.filter.support;
+
+import java.io.IOException;
+import java.nio.charset.Charset;
+
+import org.apache.mina.common.ByteBuffer;
+
+import junit.framework.TestCase;
+
+/**
+ * @author The Apache Directory MINA subproject (mina-dev@directory.apache.org)
+ */
+public class ZlibTest extends TestCase
+{
+ private Zlib deflater = null;
+ private Zlib inflater = null;
+
+ protected void setUp() throws Exception
+ {
+ deflater = new Zlib( Zlib.COMPRESSION_MAX, Zlib.MODE_DEFLATER );
+ inflater = new Zlib( Zlib.COMPRESSION_MAX, Zlib.MODE_INFLATER );
+ }
+
+ public void testCompression() throws Exception
+ {
+ String strInput = "";
+
+ // increase the count to as many as required to generate a long
+ // string for input
+ for( int i = 0; i < 10; i++ )
+ {
+ strInput += "The quick brown fox jumps over the lazy dog. ";
+ }
+ ByteBuffer byteInput = ByteBuffer.wrap( strInput.getBytes( "UTF8" ) );
+
+ // increase the count to have the compression and decompression
+ // done using the same instance of Zlib
+ for( int i = 0; i < 5; i++ )
+ {
+ ByteBuffer byteCompressed = deflater.deflate( byteInput );
+ ByteBuffer byteUncompressed = inflater.inflate( byteCompressed );
+ String strOutput = byteUncompressed.getString( Charset.forName( "UTF8" )
+ .newDecoder() );
+ assertTrue( strOutput.equals( strInput ) );
+ }
+ }
+
+ public void testCorruptedData() throws Exception
+ {
+ String strInput = "Hello World";
+ ByteBuffer byteInput = ByteBuffer.wrap( strInput.getBytes( "UTF8" ) );
+
+ ByteBuffer byteCompressed = deflater.deflate( byteInput );
+ // change the contents to something else. Since this doesn't check
+ // for integrity, it wont throw an exception
+ byteCompressed.put( 5, (byte) 0xa );
+ ByteBuffer byteUncompressed = inflater.inflate( byteCompressed );
+ String strOutput = byteUncompressed.getString( Charset.forName( "UTF8" )
+ .newDecoder() );
+ assertFalse( strOutput.equals( strInput ) );
+ }
+
+ public void testCorruptedHeader() throws Exception
+ {
+ String strInput = "Hello World";
+ ByteBuffer byteInput = ByteBuffer.wrap( strInput.getBytes( "UTF8" ) );
+
+ ByteBuffer byteCompressed = deflater.deflate( byteInput );
+ // write a bad value into the zlib header. Make sure that
+ // the decompression fails
+ byteCompressed.put( 0, (byte) 0xca );
+ try
+ {
+ inflater.inflate( byteCompressed );
+ }
+ catch( IOException e )
+ {
+ assertTrue( true );
+ return;
+ }
+ assertTrue( false );
+ }
+
+ public void testFragments() throws Exception
+ {
+ String strInput = "";
+ for( int i = 0; i < 10; i++ )
+ {
+ strInput += "The quick brown fox jumps over the lazy dog. ";
+ }
+ ByteBuffer byteInput = ByteBuffer.wrap( strInput.getBytes( "UTF8" ) );
+ ByteBuffer byteCompressed = null;
+
+ for( int i = 0; i < 5; i++ )
+ {
+ byteCompressed = deflater.deflate( byteInput );
+ if( i == 0 )
+ {
+ // decompress the first compressed output since it contains
+ // the zlib header, which will not be generated for further
+ // compressions done with the same instance
+ ByteBuffer byteUncompressed = inflater.inflate( byteCompressed );
+ String strOutput = byteUncompressed.getString( Charset.forName( "UTF8" )
+ .newDecoder() );
+ assertTrue( strOutput.equals( strInput ) );
+ }
+ }
+ // check if the last compressed data block can be decompressed
+ // successfully.
+ ByteBuffer byteUncompressed = inflater.inflate( byteCompressed );
+ String strOutput = byteUncompressed.getString( Charset.forName( "UTF8" )
+ .newDecoder() );
+ assertTrue( strOutput.equals( strInput ) );
+ }
+}
Propchange: directory/trunks/mina/filter-compression/src/test/java/org/apache/mina/filter/support/ZlibTest.java
------------------------------------------------------------------------------
svn:executable = *
Modified: directory/trunks/mina/pom.xml
URL: http://svn.apache.org/viewcvs/directory/trunks/mina/pom.xml?rev=385235&r1=385234&r2=385235&view=diff
==============================================================================
--- directory/trunks/mina/pom.xml (original)
+++ directory/trunks/mina/pom.xml Sat Mar 11 19:16:33 2006
@@ -153,6 +153,7 @@
<module>filter-ssl</module>
<module>filter-codec-asn1</module>
<module>filter-codec-netty</module>
+ <module>filter-compression</module>
<module>integration-spring</module>
<module>examples</module>
</modules>
@@ -167,6 +168,7 @@
<module>core</module>
<module>filter-codec-asn1</module>
<module>filter-codec-netty</module>
+ <module>filter-compression</module>
</modules>
<build>
<plugins>
@@ -253,6 +255,11 @@
<finalName>mina-${pom.version}</finalName>
<includeSite>true</includeSite>
</configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-eclipse-plugin</artifactId>
+ <version>2.1</version>
</plugin>
</plugins>
</build>