You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by tc...@apache.org on 2008/07/07 02:28:49 UTC
svn commit: r674372 [4/6] - in /commons/sandbox/compress/branches/redesign:
./ src/ src/main/ src/main/java/ src/main/java/org/
src/main/java/org/apache/ src/main/java/org/apache/commons/
src/main/java/org/apache/commons/compress/ src/main/java/org/apa...
Added: commons/sandbox/compress/branches/redesign/src/main/java/org/apache/commons/compress/archivers/zip/ZipOutputStream.java
URL: http://svn.apache.org/viewvc/commons/sandbox/compress/branches/redesign/src/main/java/org/apache/commons/compress/archivers/zip/ZipOutputStream.java?rev=674372&view=auto
==============================================================================
--- commons/sandbox/compress/branches/redesign/src/main/java/org/apache/commons/compress/archivers/zip/ZipOutputStream.java (added)
+++ commons/sandbox/compress/branches/redesign/src/main/java/org/apache/commons/compress/archivers/zip/ZipOutputStream.java Sun Jul 6 17:28:46 2008
@@ -0,0 +1,731 @@
+/*
+ * 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.commons.compress.archivers.zip;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.Hashtable;
+import java.util.zip.CRC32;
+import java.util.zip.Deflater;
+import java.util.zip.DeflaterOutputStream;
+import java.util.zip.ZipException;
+
+/**
+ * Reimplementation of {@link java.util.zip.ZipOutputStream
+ * java.util.zip.ZipOutputStream} that does handle the extended functionality of
+ * this package, especially internal/external file attributes and extra fields
+ * with different layouts for local file data and central directory entries. <p>
+ *
+ * This implementation will use a Data Descriptor to store size and CRC
+ * information for DEFLATED entries, this means, you don't need to calculate
+ * them yourself. Unfortunately this is not possible for the STORED method, here
+ * setting the CRC and uncompressed size information is required before {@link
+ * #putNextEntry putNextEntry} will be called.</p>
+ *
+ * @author <a href="stefan.bodewig@epost.de">Stefan Bodewig</a>
+ * @version $Revision: 437550 $
+ */
+public class ZipOutputStream
+ extends DeflaterOutputStream
+{
+ /**
+ * Helper, a 0 as ZipShort.
+ *
+ * @since 1.1
+ */
+ private static final byte[] ZERO = {0, 0};
+
+ /**
+ * Helper, a 0 as ZipLong.
+ *
+ * @since 1.1
+ */
+ private static final byte[] LZERO = {0, 0, 0, 0};
+
+ /**
+ * Compression method for deflated entries.
+ *
+ * @since 1.1
+ */
+ public static final int DEFLATED = ZipEntry.DEFLATED;
+
+ /**
+ * Compression method for deflated entries.
+ *
+ * @since 1.1
+ */
+ public static final int STORED = ZipEntry.STORED;
+
+ /*
+ * Various ZIP constants
+ */
+ /**
+ * local file header signature
+ *
+ * @since 1.1
+ */
+ protected static final ZipLong LFH_SIG = new ZipLong( 0X04034B50L );
+ /**
+ * data descriptor signature
+ *
+ * @since 1.1
+ */
+ protected static final ZipLong DD_SIG = new ZipLong( 0X08074B50L );
+ /**
+ * central file header signature
+ *
+ * @since 1.1
+ */
+ protected static final ZipLong CFH_SIG = new ZipLong( 0X02014B50L );
+ /**
+ * end of central dir signature
+ *
+ * @since 1.1
+ */
+ protected static final ZipLong EOCD_SIG = new ZipLong( 0X06054B50L );
+
+ /**
+ * Smallest date/time ZIP can handle.
+ *
+ * @since 1.1
+ */
+ private static final ZipLong DOS_TIME_MIN = new ZipLong( 0x00002100L );
+
+ /**
+ * The file comment.
+ *
+ * @since 1.1
+ */
+ private String m_comment = "";
+
+ /**
+ * Compression level for next entry.
+ *
+ * @since 1.1
+ */
+ private int m_level = Deflater.DEFAULT_COMPRESSION;
+
+ /**
+ * Default compression method for next entry.
+ *
+ * @since 1.1
+ */
+ private int m_method = DEFLATED;
+
+ /**
+ * List of ZipEntries written so far.
+ *
+ * @since 1.1
+ */
+ private final ArrayList m_entries = new ArrayList();
+
+ /**
+ * CRC instance to avoid parsing DEFLATED data twice.
+ *
+ * @since 1.1
+ */
+ private final CRC32 m_crc = new CRC32();
+
+ /**
+ * Count the bytes written to out.
+ *
+ * @since 1.1
+ */
+ private long m_written;
+
+ /**
+ * Data for current entry started here.
+ *
+ * @since 1.1
+ */
+ private long m_dataStart;
+
+ /**
+ * Start of central directory.
+ *
+ * @since 1.1
+ */
+ private ZipLong m_cdOffset = new ZipLong( 0 );
+
+ /**
+ * Length of central directory.
+ *
+ * @since 1.1
+ */
+ private ZipLong m_cdLength = new ZipLong( 0 );
+
+ /**
+ * Holds the offsets of the LFH starts for each entry
+ *
+ * @since 1.1
+ */
+ private final Hashtable m_offsets = new Hashtable();
+
+ /**
+ * The encoding to use for filenames and the file comment. <p>
+ *
+ * For a list of possible values see <a
+ * href="http://java.sun.com/products/jdk/1.2/docs/guide/internat/encoding.doc.html">
+ * http://java.sun.com/products/jdk/1.2/docs/guide/internat/encoding.doc.html
+ * </a>. Defaults to the platform's default character encoding.</p>
+ *
+ * @since 1.3
+ */
+ private String m_encoding;
+
+ /**
+ * Current entry.
+ *
+ * @since 1.1
+ */
+ private ZipArchiveEntry m_entry;
+
+ /**
+ * Creates a new ZIP OutputStream filtering the underlying stream.
+ *
+ * @param output the output stream to write to
+ * @since 1.1
+ */
+ public ZipOutputStream( final OutputStream output )
+ {
+ super( output, new Deflater( Deflater.DEFAULT_COMPRESSION, true ) );
+ }
+
+ /**
+ * Convert a Date object to a DOS date/time field. <p>
+ *
+ * Stolen from InfoZip's <code>fileio.c</code></p>
+ *
+ * @param time Description of Parameter
+ * @return Description of the Returned Value
+ * @since 1.1
+ */
+ protected static ZipLong toDosTime( Date time )
+ {
+ Calendar cal = Calendar.getInstance();
+ cal.setTime( time );
+ int year = cal.get(Calendar.YEAR);
+ int month = cal.get(Calendar.MONTH) + 1;
+ if( year < 1980 )
+ {
+ return DOS_TIME_MIN;
+ }
+ long value = ( ( year - 1980 ) << 25 )
+ | ( month << 21 )
+ | ( cal.get(Calendar.DAY_OF_MONTH) << 16 )
+ | ( cal.get(Calendar.HOUR_OF_DAY) << 11 )
+ | ( cal.get(Calendar.MINUTE) << 5 )
+ | ( cal.get(Calendar.SECOND) >> 1 );
+
+ byte[] result = new byte[ 4 ];
+ result[ 0 ] = (byte)( ( value & 0xFF ) );
+ result[ 1 ] = (byte)( ( value & 0xFF00 ) >> 8 );
+ result[ 2 ] = (byte)( ( value & 0xFF0000 ) >> 16 );
+ result[ 3 ] = (byte)( ( value & 0xFF000000l ) >> 24 );
+ return new ZipLong( result );
+ }
+
+ /**
+ * Set the file comment.
+ *
+ * @param comment The new Comment value
+ * @since 1.1
+ */
+ public void setComment( String comment )
+ {
+ m_comment = comment;
+ }
+
+ /**
+ * The encoding to use for filenames and the file comment. <p>
+ *
+ * For a list of possible values see <a
+ * href="http://java.sun.com/products/jdk/1.2/docs/guide/internat/encoding.doc.html">
+ * http://java.sun.com/products/jdk/1.2/docs/guide/internat/encoding.doc.html
+ * </a>. Defaults to the platform's default character encoding.</p>
+ *
+ * @param encoding The new Encoding value
+ * @since 1.3
+ */
+ public void setEncoding( String encoding )
+ {
+ m_encoding = encoding;
+ }
+
+ /**
+ * Sets the compression level for subsequent entries. <p>
+ *
+ * Default is Deflater.DEFAULT_COMPRESSION.</p>
+ *
+ * @param level The new Level value
+ * @since 1.1
+ */
+ public void setLevel( int level )
+ {
+ m_level = level;
+ }
+
+ /**
+ * Sets the default compression method for subsequent entries. <p>
+ *
+ * Default is DEFLATED.</p>
+ *
+ * @param method The new Method value
+ * @since 1.1
+ */
+ public void setMethod( final int method )
+ {
+ m_method = method;
+ }
+
+ /**
+ * The encoding to use for filenames and the file comment.
+ *
+ * @return null if using the platform's default character encoding.
+ * @since 1.3
+ */
+ public String getEncoding()
+ {
+ return m_encoding;
+ }
+
+ /**
+ * Writes all necessary data for this entry.
+ *
+ * @throws IOException if an IO failure causes operation to fail
+ * @since 1.1
+ */
+ public void closeEntry()
+ throws IOException
+ {
+ if( m_entry == null )
+ {
+ return;
+ }
+
+ long realCrc = m_crc.getValue();
+ m_crc.reset();
+
+ if( m_entry.getMethod() == DEFLATED )
+ {
+ def.finish();
+ while( !def.finished() )
+ {
+ deflate();
+ }
+
+ m_entry.setSize( def.getTotalIn() );
+ m_entry.setComprSize( def.getTotalOut() );
+ m_entry.setCrc( realCrc );
+
+ def.reset();
+
+ m_written += m_entry.getCompressedSize();
+ }
+ else
+ {
+ if( m_entry.getCrc() != realCrc )
+ {
+ throw new ZipException( "bad CRC checksum for entry "
+ + m_entry.getName() + ": "
+ + Long.toHexString( m_entry.getCrc() )
+ + " instead of "
+ + Long.toHexString( realCrc ) );
+ }
+
+ if( m_entry.getSize() != m_written - m_dataStart )
+ {
+ throw new ZipException( "bad size for entry "
+ + m_entry.getName() + ": "
+ + m_entry.getSize()
+ + " instead of "
+ + ( m_written - m_dataStart ) );
+ }
+
+ }
+
+ writeDataDescriptor( m_entry );
+ m_entry = null;
+ }
+
+ /*
+ * Found out by experiment, that DeflaterOutputStream.close()
+ * will call finish() - so we don't need to override close
+ * ourselves.
+ */
+ /**
+ * Finishs writing the contents and closes this as well as the underlying
+ * stream.
+ *
+ * @throws IOException if an IO failure causes operation to fail
+ * @since 1.1
+ */
+ public void finish()
+ throws IOException
+ {
+ closeEntry();
+ m_cdOffset = new ZipLong( m_written );
+ final int size = m_entries.size();
+ for( int i = 0; i < size; i++ )
+ {
+ final ZipArchiveEntry entry = (ZipArchiveEntry)m_entries.get( i );
+ writeCentralFileHeader( entry );
+ }
+ m_cdLength = new ZipLong( m_written - m_cdOffset.getValue() );
+ writeCentralDirectoryEnd();
+ m_offsets.clear();
+ m_entries.clear();
+ }
+
+ /**
+ * Begin writing next entry.
+ *
+ * @param entry the entry
+ * @throws IOException if an IO failure causes operation to fail
+ * @since 1.1
+ */
+ public void putNextEntry( final ZipArchiveEntry entry )
+ throws IOException
+ {
+ closeEntry();
+
+ m_entry = entry;
+ m_entries.add( m_entry );
+
+ if( m_entry.getMethod() == -1 )
+ {// not specified
+ m_entry.setMethod( m_method );
+ }
+
+ if( m_entry.getTime() == -1 )
+ {// not specified
+ m_entry.setTime( System.currentTimeMillis() );
+ }
+
+ if( m_entry.getMethod() == STORED )
+ {
+ if( m_entry.getSize() == -1 )
+ {
+ throw new ZipException( "uncompressed size is required for STORED method" );
+ }
+ if( m_entry.getCrc() == -1 )
+ {
+ throw new ZipException( "crc checksum is required for STORED method" );
+ }
+ m_entry.setComprSize( m_entry.getSize() );
+ }
+ else
+ {
+ def.setLevel( m_level );
+ }
+ writeLocalFileHeader( m_entry );
+ }
+
+ /**
+ * Writes bytes to ZIP entry. <p>
+ *
+ * Override is necessary to support STORED entries, as well as calculationg
+ * CRC automatically for DEFLATED entries.</p>
+ *
+ * @param buffer the buffer to write to
+ * @param offset the offset to write to
+ * @param length the length of data to write
+ * @exception IOException if an IO error causes operation to fail
+ */
+ public void write( final byte[] buffer,
+ final int offset,
+ final int length )
+ throws IOException
+ {
+ if( m_entry.getMethod() == DEFLATED )
+ {
+ super.write( buffer, offset, length );
+ }
+ else
+ {
+ out.write( buffer, offset, length );
+ m_written += length;
+ }
+ m_crc.update( buffer, offset, length );
+ }
+
+ /**
+ * Retrieve the bytes for the given String in the encoding set for this
+ * Stream.
+ *
+ * @param name the name to decode
+ * @return the bytes for string
+ * @exception ZipException if fail to retrieve bytes for specified string
+ * @since 1.3
+ */
+ protected byte[] getBytes( String name )
+ throws ZipException
+ {
+ if( m_encoding == null )
+ {
+ return name.getBytes();
+ }
+ else
+ {
+ try
+ {
+ return name.getBytes( m_encoding );
+ }
+ catch( UnsupportedEncodingException uee )
+ {
+ throw new ZipException( uee.getMessage() );
+ }
+ }
+ }
+
+ /**
+ * Writes the "End of central dir record"
+ *
+ * @exception IOException when an IO erro causes operation to fail
+ * @since 1.1
+ */
+ protected void writeCentralDirectoryEnd()
+ throws IOException
+ {
+ out.write( EOCD_SIG.getBytes() );
+
+ // disk numbers
+ out.write( ZERO );
+ out.write( ZERO );
+
+ // number of entries
+ byte[] num = ( new ZipShort( m_entries.size() ) ).getBytes();
+ out.write( num );
+ out.write( num );
+
+ // length and location of CD
+ out.write( m_cdLength.getBytes() );
+ out.write( m_cdOffset.getBytes() );
+
+ // ZIP file comment
+ byte[] data = getBytes( m_comment );
+ out.write( ( new ZipShort( data.length ) ).getBytes() );
+ out.write( data );
+ }
+
+ /**
+ * Writes the central file header entry
+ *
+ * @param entry the zip entry
+ * @throws IOException when an IO error causes operation to fail
+ * @since 1.1
+ */
+ protected void writeCentralFileHeader( final ZipArchiveEntry entry )
+ throws IOException
+ {
+ out.write( CFH_SIG.getBytes() );
+ m_written += 4;
+
+ // version made by
+ out.write( ( new ZipShort( 20 ) ).getBytes() );
+ m_written += 2;
+
+ // version needed to extract
+ // general purpose bit flag
+ if( entry.getMethod() == DEFLATED )
+ {
+ // requires version 2 as we are going to store length info
+ // in the data descriptor
+ out.write( ( new ZipShort( 20 ) ).getBytes() );
+
+ // bit3 set to signal, we use a data descriptor
+ out.write( ( new ZipShort( 8 ) ).getBytes() );
+ }
+ else
+ {
+ out.write( ( new ZipShort( 10 ) ).getBytes() );
+ out.write( ZERO );
+ }
+ m_written += 4;
+
+ // compression method
+ out.write( ( new ZipShort( entry.getMethod() ) ).getBytes() );
+ m_written += 2;
+
+ // last mod. time and date
+ out.write( toDosTime( new Date( entry.getTime() ) ).getBytes() );
+ m_written += 4;
+
+ // CRC
+ // compressed length
+ // uncompressed length
+ out.write( ( new ZipLong( entry.getCrc() ) ).getBytes() );
+ out.write( ( new ZipLong( entry.getCompressedSize() ) ).getBytes() );
+ out.write( ( new ZipLong( entry.getSize() ) ).getBytes() );
+ m_written += 12;
+
+ // file name length
+ byte[] name = getBytes( entry.getName() );
+ out.write( ( new ZipShort( name.length ) ).getBytes() );
+ m_written += 2;
+
+ // extra field length
+ byte[] extra = entry.getCentralDirectoryExtra();
+ out.write( ( new ZipShort( extra.length ) ).getBytes() );
+ m_written += 2;
+
+ // file comment length
+ String comm = entry.getComment();
+ if( comm == null )
+ {
+ comm = "";
+ }
+ byte[] comment = getBytes( comm );
+ out.write( ( new ZipShort( comment.length ) ).getBytes() );
+ m_written += 2;
+
+ // disk number start
+ out.write( ZERO );
+ m_written += 2;
+
+ // internal file attributes
+ out.write( ( new ZipShort( entry.getInternalAttributes() ) ).getBytes() );
+ m_written += 2;
+
+ // external file attributes
+ out.write( ( new ZipLong( entry.getExternalAttributes() ) ).getBytes() );
+ m_written += 4;
+
+ // relative offset of LFH
+ out.write( ( (ZipLong)m_offsets.get( entry ) ).getBytes() );
+ m_written += 4;
+
+ // file name
+ out.write( name );
+ m_written += name.length;
+
+ // extra field
+ out.write( extra );
+ m_written += extra.length;
+
+ // file comment
+ out.write( comment );
+ m_written += comment.length;
+ }
+
+ /**
+ * Writes the data descriptor entry
+ *
+ * @param ze Description of Parameter
+ * @throws IOException if an IO failure causes operation to fail
+ * @since 1.1
+ */
+ protected void writeDataDescriptor( ZipArchiveEntry ze )
+ throws IOException
+ {
+ if( ze.getMethod() != DEFLATED )
+ {
+ return;
+ }
+ out.write( DD_SIG.getBytes() );
+ out.write( ( new ZipLong( m_entry.getCrc() ) ).getBytes() );
+ out.write( ( new ZipLong( m_entry.getCompressedSize() ) ).getBytes() );
+ out.write( ( new ZipLong( m_entry.getSize() ) ).getBytes() );
+ m_written += 16;
+ }
+
+ /**
+ * Writes the local file header entry
+ *
+ * @param entry the zip entry
+ * @exception IOException when an IO error causes operation to fail
+ * @since 1.1
+ */
+ protected void writeLocalFileHeader( final ZipArchiveEntry entry )
+ throws IOException
+ {
+ m_offsets.put( entry, new ZipLong( m_written ) );
+
+ out.write( LFH_SIG.getBytes() );
+ m_written += 4;
+
+ // version needed to extract
+ // general purpose bit flag
+ if( entry.getMethod() == DEFLATED )
+ {
+ // requires version 2 as we are going to store length info
+ // in the data descriptor
+ out.write( ( new ZipShort( 20 ) ).getBytes() );
+
+ // bit3 set to signal, we use a data descriptor
+ out.write( ( new ZipShort( 8 ) ).getBytes() );
+ }
+ else
+ {
+ out.write( ( new ZipShort( 10 ) ).getBytes() );
+ out.write( ZERO );
+ }
+ m_written += 4;
+
+ // compression method
+ out.write( ( new ZipShort( entry.getMethod() ) ).getBytes() );
+ m_written += 2;
+
+ // last mod. time and date
+ out.write( toDosTime( new Date( entry.getTime() ) ).getBytes() );
+ m_written += 4;
+
+ // CRC
+ // compressed length
+ // uncompressed length
+ if( entry.getMethod() == DEFLATED )
+ {
+ out.write( LZERO );
+ out.write( LZERO );
+ out.write( LZERO );
+ }
+ else
+ {
+ out.write( ( new ZipLong( entry.getCrc() ) ).getBytes() );
+ out.write( ( new ZipLong( entry.getSize() ) ).getBytes() );
+ out.write( ( new ZipLong( entry.getSize() ) ).getBytes() );
+ }
+ m_written += 12;
+
+ // file name length
+ byte[] name = getBytes( entry.getName() );
+ out.write( ( new ZipShort( name.length ) ).getBytes() );
+ m_written += 2;
+
+ // extra field length
+ byte[] extra = entry.getLocalFileDataExtra();
+ out.write( ( new ZipShort( extra.length ) ).getBytes() );
+ m_written += 2;
+
+ // file name
+ out.write( name );
+ m_written += name.length;
+
+ // extra field
+ out.write( extra );
+ m_written += extra.length;
+
+ m_dataStart = m_written;
+ }
+
+}
Added: commons/sandbox/compress/branches/redesign/src/main/java/org/apache/commons/compress/archivers/zip/ZipShort.java
URL: http://svn.apache.org/viewvc/commons/sandbox/compress/branches/redesign/src/main/java/org/apache/commons/compress/archivers/zip/ZipShort.java?rev=674372&view=auto
==============================================================================
--- commons/sandbox/compress/branches/redesign/src/main/java/org/apache/commons/compress/archivers/zip/ZipShort.java (added)
+++ commons/sandbox/compress/branches/redesign/src/main/java/org/apache/commons/compress/archivers/zip/ZipShort.java Sun Jul 6 17:28:46 2008
@@ -0,0 +1,118 @@
+/*
+ * 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.commons.compress.archivers.zip;
+
+/**
+ * Utility class that represents a two byte integer with conversion rules for
+ * the big endian byte order of ZIP files.
+ *
+ * @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a>
+ * @version $Revision: 155439 $
+ */
+public final class ZipShort implements Cloneable
+{
+ private int m_value;
+
+ /**
+ * Create instance from a number.
+ *
+ * @param value Description of Parameter
+ * @since 1.1
+ */
+ public ZipShort( int value )
+ {
+ this.m_value = value;
+ }
+
+ /**
+ * Create instance from bytes.
+ *
+ * @param bytes Description of Parameter
+ * @since 1.1
+ */
+ public ZipShort( byte[] bytes )
+ {
+ this( bytes, 0 );
+ }
+
+ /**
+ * Create instance from the two bytes starting at offset.
+ *
+ * @param bytes Description of Parameter
+ * @param offset Description of Parameter
+ * @since 1.1
+ */
+ public ZipShort( byte[] bytes, int offset )
+ {
+ m_value = ( bytes[ offset + 1 ] << 8 ) & 0xFF00;
+ m_value += ( bytes[ offset ] & 0xFF );
+ }
+
+ /**
+ * Get value as two bytes in big endian byte order.
+ *
+ * @return The Bytes value
+ * @since 1.1
+ */
+ public byte[] getBytes()
+ {
+ byte[] result = new byte[ 2 ];
+ result[ 0 ] = (byte)( m_value & 0xFF );
+ result[ 1 ] = (byte)( ( m_value & 0xFF00 ) >> 8 );
+ return result;
+ }
+
+ /**
+ * Get value as Java int.
+ *
+ * @return The Value value
+ * @since 1.1
+ */
+ public int getValue()
+ {
+ return m_value;
+ }
+
+ /**
+ * Override to make two instances with same value equal.
+ *
+ * @param o Description of Parameter
+ * @return Description of the Returned Value
+ * @since 1.1
+ */
+ public boolean equals( Object o )
+ {
+ if( o == null || !( o instanceof ZipShort ) )
+ {
+ return false;
+ }
+ return m_value == ( (ZipShort)o ).getValue();
+ }
+
+ /**
+ * Override to make two instances with same value equal.
+ *
+ * @return Description of the Returned Value
+ * @since 1.1
+ */
+ public int hashCode()
+ {
+ return m_value;
+ }
+}
Added: commons/sandbox/compress/branches/redesign/src/main/java/org/apache/commons/compress/changes/Change.java
URL: http://svn.apache.org/viewvc/commons/sandbox/compress/branches/redesign/src/main/java/org/apache/commons/compress/changes/Change.java?rev=674372&view=auto
==============================================================================
--- commons/sandbox/compress/branches/redesign/src/main/java/org/apache/commons/compress/changes/Change.java (added)
+++ commons/sandbox/compress/branches/redesign/src/main/java/org/apache/commons/compress/changes/Change.java Sun Jul 6 17:28:46 2008
@@ -0,0 +1,15 @@
+/**
+ *
+ */
+package org.apache.commons.compress.changes;
+
+import org.apache.commons.compress.archivers.ArchiveInputStream;
+
+/**
+ * @author Cy
+ *
+ */
+interface Change {
+ // public void perform(ArchiveInputStream input);
+ public int type();
+}
Added: commons/sandbox/compress/branches/redesign/src/main/java/org/apache/commons/compress/changes/ChangeSet.java
URL: http://svn.apache.org/viewvc/commons/sandbox/compress/branches/redesign/src/main/java/org/apache/commons/compress/changes/ChangeSet.java?rev=674372&view=auto
==============================================================================
--- commons/sandbox/compress/branches/redesign/src/main/java/org/apache/commons/compress/changes/ChangeSet.java (added)
+++ commons/sandbox/compress/branches/redesign/src/main/java/org/apache/commons/compress/changes/ChangeSet.java Sun Jul 6 17:28:46 2008
@@ -0,0 +1,49 @@
+/*
+ * 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.commons.compress.changes;
+
+import java.io.InputStream;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import org.apache.commons.compress.archivers.ArchiveEntry;
+
+
+public final class ChangeSet {
+
+ private final Set changes = new LinkedHashSet();
+
+ public static final int CHANGE_TYPE_DELETE = 1;
+ public static final int CHANGE_TYPE_ADD = 2;
+
+
+ public void delete( final String pFilename ) {
+ changes.add(new DeleteChange(pFilename));
+ }
+
+ public void move( final String pFrom, final String pTo ) {
+ }
+
+ public void add( final ArchiveEntry pEntry, final InputStream pInput) {
+ }
+
+ public Set asSet() {
+ return changes;
+ }
+}
Added: commons/sandbox/compress/branches/redesign/src/main/java/org/apache/commons/compress/changes/ChangeWorker.java
URL: http://svn.apache.org/viewvc/commons/sandbox/compress/branches/redesign/src/main/java/org/apache/commons/compress/changes/ChangeWorker.java?rev=674372&view=auto
==============================================================================
--- commons/sandbox/compress/branches/redesign/src/main/java/org/apache/commons/compress/changes/ChangeWorker.java (added)
+++ commons/sandbox/compress/branches/redesign/src/main/java/org/apache/commons/compress/changes/ChangeWorker.java Sun Jul 6 17:28:46 2008
@@ -0,0 +1,79 @@
+/*
+ * 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.commons.compress.changes;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Iterator;
+
+import org.apache.commons.compress.archivers.ArchiveEntry;
+import org.apache.commons.compress.archivers.ArchiveInputStream;
+import org.apache.commons.compress.archivers.ArchiveOutputStream;
+import org.apache.commons.compress.utils.IOUtils;
+
+/**
+ * Performs the operations of a change set
+ */
+public class ChangeWorker {
+ private ChangeWorker() {
+ // nothing to do
+ }
+
+ /**
+ * TODO
+ * @param changes
+ * @param in
+ * @param out
+ * @throws IOException
+ */
+ public static void perform(ChangeSet changes, ArchiveInputStream in, ArchiveOutputStream out) throws IOException {
+ ArchiveEntry entry = null;
+ while((entry = in.getNextEntry()) != null) {
+ System.out.println(entry.getName());
+ boolean copy = true;
+
+ for (Iterator it = changes.asSet().iterator(); it.hasNext();) {
+ Change change = (Change)it.next();
+
+ if(change.type() == ChangeSet.CHANGE_TYPE_DELETE) {
+ DeleteChange delete = ((DeleteChange)change);
+ if(entry.getName() != null &&
+ entry.getName().equals(delete.targetFile())) {
+ copy = false;
+ }
+ }
+ }
+
+ if(copy) {
+ // copy archive
+ // TODO: unsafe long to int
+ System.out.println("Copy: " + entry.getName());
+ long size = entry.getSize();
+ out.putArchiveEntry(entry);
+ IOUtils.copy((InputStream)in, out, (int)size);
+ out.closeArchiveEntry();
+ }
+
+
+ System.out.println("---");
+ }
+ // add operation stuff
+ out.close();
+ }
+}
Added: commons/sandbox/compress/branches/redesign/src/main/java/org/apache/commons/compress/changes/DeleteChange.java
URL: http://svn.apache.org/viewvc/commons/sandbox/compress/branches/redesign/src/main/java/org/apache/commons/compress/changes/DeleteChange.java?rev=674372&view=auto
==============================================================================
--- commons/sandbox/compress/branches/redesign/src/main/java/org/apache/commons/compress/changes/DeleteChange.java (added)
+++ commons/sandbox/compress/branches/redesign/src/main/java/org/apache/commons/compress/changes/DeleteChange.java Sun Jul 6 17:28:46 2008
@@ -0,0 +1,37 @@
+/**
+ *
+ */
+package org.apache.commons.compress.changes;
+
+import org.apache.commons.compress.archivers.ArchiveInputStream;
+
+/**
+ * Implementation for a delete operation
+ */
+class DeleteChange implements Change {
+ private String filename = null;
+
+ /**
+ * Constructor. Takes the filename of the file to be deleted
+ * from the stream as argument.
+ * @param pFilename the filename of the file to delete
+ */
+ public DeleteChange(final String pFilename) {
+ if(pFilename == null) {
+ throw new NullPointerException();
+ }
+ filename = pFilename;
+ }
+
+ public void perform(ArchiveInputStream input) {
+ System.out.println("PERFORMING DELETE");
+ }
+
+ public String targetFile() {
+ return filename;
+ }
+
+ public int type() {
+ return ChangeSet.CHANGE_TYPE_DELETE;
+ }
+}
Added: commons/sandbox/compress/branches/redesign/src/main/java/org/apache/commons/compress/compressors/CompressorException.java
URL: http://svn.apache.org/viewvc/commons/sandbox/compress/branches/redesign/src/main/java/org/apache/commons/compress/compressors/CompressorException.java?rev=674372&view=auto
==============================================================================
--- commons/sandbox/compress/branches/redesign/src/main/java/org/apache/commons/compress/compressors/CompressorException.java (added)
+++ commons/sandbox/compress/branches/redesign/src/main/java/org/apache/commons/compress/compressors/CompressorException.java Sun Jul 6 17:28:46 2008
@@ -0,0 +1,28 @@
+/**
+ *
+ */
+package org.apache.commons.compress.compressors;
+
+/**
+ *
+ */
+public class CompressorException extends Exception {
+ /* Serial */
+ private static final long serialVersionUID = -2770299103090672278L;
+
+ public CompressorException() {
+ super();
+ }
+
+ public CompressorException(String arg0, Throwable arg1) {
+ super(arg0, arg1);
+ }
+
+ public CompressorException(String arg0) {
+ super(arg0);
+ }
+
+ public CompressorException(Throwable arg0) {
+ super(arg0);
+ }
+}
Added: commons/sandbox/compress/branches/redesign/src/main/java/org/apache/commons/compress/compressors/CompressorInputStream.java
URL: http://svn.apache.org/viewvc/commons/sandbox/compress/branches/redesign/src/main/java/org/apache/commons/compress/compressors/CompressorInputStream.java?rev=674372&view=auto
==============================================================================
--- commons/sandbox/compress/branches/redesign/src/main/java/org/apache/commons/compress/compressors/CompressorInputStream.java (added)
+++ commons/sandbox/compress/branches/redesign/src/main/java/org/apache/commons/compress/compressors/CompressorInputStream.java Sun Jul 6 17:28:46 2008
@@ -0,0 +1,25 @@
+/*
+ * 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.commons.compress.compressors;
+
+import java.io.InputStream;
+
+public abstract class CompressorInputStream extends InputStream {
+ // TODO
+}
Added: commons/sandbox/compress/branches/redesign/src/main/java/org/apache/commons/compress/compressors/CompressorOutputStream.java
URL: http://svn.apache.org/viewvc/commons/sandbox/compress/branches/redesign/src/main/java/org/apache/commons/compress/compressors/CompressorOutputStream.java?rev=674372&view=auto
==============================================================================
--- commons/sandbox/compress/branches/redesign/src/main/java/org/apache/commons/compress/compressors/CompressorOutputStream.java (added)
+++ commons/sandbox/compress/branches/redesign/src/main/java/org/apache/commons/compress/compressors/CompressorOutputStream.java Sun Jul 6 17:28:46 2008
@@ -0,0 +1,26 @@
+/*
+ * 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.commons.compress.compressors;
+
+import java.io.OutputStream;
+
+
+public abstract class CompressorOutputStream extends OutputStream {
+ // TODO
+}
Added: commons/sandbox/compress/branches/redesign/src/main/java/org/apache/commons/compress/compressors/CompressorStreamFactory.java
URL: http://svn.apache.org/viewvc/commons/sandbox/compress/branches/redesign/src/main/java/org/apache/commons/compress/compressors/CompressorStreamFactory.java?rev=674372&view=auto
==============================================================================
--- commons/sandbox/compress/branches/redesign/src/main/java/org/apache/commons/compress/compressors/CompressorStreamFactory.java (added)
+++ commons/sandbox/compress/branches/redesign/src/main/java/org/apache/commons/compress/compressors/CompressorStreamFactory.java Sun Jul 6 17:28:46 2008
@@ -0,0 +1,97 @@
+package org.apache.commons.compress.compressors;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.commons.compress.archivers.ArchiveException;
+import org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream;
+import org.apache.commons.compress.compressors.bzip2.BZip2CompressorOutputStream;
+import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream;
+import org.apache.commons.compress.compressors.gzip.GzipCompressorOutputStream;
+
+public class CompressorStreamFactory {
+ final Map inputStreamClasses = new HashMap();
+ final Map outputStreamClasses = new HashMap();
+
+ public CompressorStreamFactory() throws CompressorException {
+ registerInputStream("gz", GzipCompressorInputStream.class);
+ registerOutputStream("gz", GzipCompressorOutputStream.class);
+ registerInputStream("bzip2", BZip2CompressorInputStream.class);
+ registerOutputStream("bzip2", BZip2CompressorOutputStream.class);
+
+ }
+
+ public void registerInputStream( final String name, final Class stream ) throws CompressorException {
+ if (CompressorInputStream.class.isAssignableFrom(stream) && !(stream.isInterface())) {
+ inputStreamClasses.put(name, stream);
+ } else {
+ throw new CompressorException("Compressor does not implement the CompressorInputStream interface.");
+ }
+ }
+
+ public void registerOutputStream( final String name, final Class stream ) throws CompressorException {
+ if (CompressorOutputStream.class.isAssignableFrom(stream) && !(stream.isInterface())) {
+ outputStreamClasses.put(name, stream);
+ } else {
+ throw new CompressorException("Compressor does not implement the CompressorOutputStream interface.");
+ }
+ }
+
+ public CompressorInputStream createCompressorInputStream( final String name, final InputStream out ) throws CompressorException {
+ try {
+ final Class clazz = (Class) inputStreamClasses.get(name);
+
+ if (clazz == null) {
+ throw new CompressorException("CompressorFactory could not create instance");
+ }
+
+ final Class[] params = { InputStream.class };
+ final Constructor constructor = clazz.getConstructor(params);
+ final Object[] initargs = { out };
+ return (CompressorInputStream) constructor.newInstance(initargs);
+ } catch (InstantiationException e) {
+ throw new CompressorException("CompressorFactory could not create instance", e);
+ } catch (IllegalAccessException e) {
+ throw new CompressorException("CompressorFactory could not create instance", e);
+ } catch (SecurityException e) {
+ throw new CompressorException("CompressorFactory could not create instance", e);
+ } catch (NoSuchMethodException e) {
+ throw new CompressorException("CompressorFactory could not create instance", e);
+ } catch (IllegalArgumentException e) {
+ throw new CompressorException("CompressorFactory could not create instance", e);
+ } catch (InvocationTargetException e) {
+ throw new CompressorException("CompressorFactory could not create instance", e);
+ }
+ }
+
+ public CompressorOutputStream createCompressorOutputStream( final String name, final OutputStream out ) throws ArchiveException {
+ try {
+ final Class clazz = (Class) outputStreamClasses.get(name);
+
+ if (clazz == null) {
+ throw new ArchiveException("CompressorFactory could not create instance");
+ }
+
+ final Class[] params = { OutputStream.class };
+ final Constructor constructor = clazz.getConstructor(params);
+ final Object[] initargs = { out };
+ return (CompressorOutputStream) constructor.newInstance(initargs);
+ } catch (InstantiationException e) {
+ throw new ArchiveException("CompressorFactory could not create instance", e);
+ } catch (IllegalAccessException e) {
+ throw new ArchiveException("CompressorFactory could not create instance", e);
+ } catch (SecurityException e) {
+ throw new ArchiveException("CompressorFactory could not create instance", e);
+ } catch (NoSuchMethodException e) {
+ throw new ArchiveException("CompressorFactory could not create instance", e);
+ } catch (IllegalArgumentException e) {
+ throw new ArchiveException("CompressorFactory could not create instance", e);
+ } catch (InvocationTargetException e) {
+ throw new ArchiveException("CompressorFactory could not create instance", e);
+ }
+ }
+}
Added: commons/sandbox/compress/branches/redesign/src/main/java/org/apache/commons/compress/compressors/bzip2/BZip2CompressorInputStream.java
URL: http://svn.apache.org/viewvc/commons/sandbox/compress/branches/redesign/src/main/java/org/apache/commons/compress/compressors/bzip2/BZip2CompressorInputStream.java?rev=674372&view=auto
==============================================================================
--- commons/sandbox/compress/branches/redesign/src/main/java/org/apache/commons/compress/compressors/bzip2/BZip2CompressorInputStream.java (added)
+++ commons/sandbox/compress/branches/redesign/src/main/java/org/apache/commons/compress/compressors/bzip2/BZip2CompressorInputStream.java Sun Jul 6 17:28:46 2008
@@ -0,0 +1,841 @@
+/*
+ * 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.commons.compress.compressors.bzip2;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.commons.compress.compressors.CompressorInputStream;
+
+/*
+ * This package is based on the work done by Keiron Liddle, Aftex Software
+ * <ke...@aftexsw.com> to whom the Ant project is very grateful for his great
+ * code.
+ */
+
+/**
+ * An input stream that decompresses from the BZip2 format (without the file
+ * header chars) to be read as any other stream.
+ *
+ * @author <a href="mailto:keiron@aftexsw.com">Keiron Liddle</a>
+ */
+public class BZip2CompressorInputStream extends CompressorInputStream implements BZip2Constants {
+
+ private static void cadvise() {
+ System.out.println("CRC Error");
+ //throw new CCoruptionError();
+ }
+
+ private static void badBGLengths() {
+ cadvise();
+ }
+
+ private static void bitStreamEOF() {
+ cadvise();
+ }
+
+ private static void compressedStreamEOF() {
+ cadvise();
+ }
+
+ private void makeMaps() {
+ int i;
+ nInUse = 0;
+ for (i = 0; i < 256; i++) {
+ if (inUse[i]) {
+ seqToUnseq[nInUse] = (char) i;
+ unseqToSeq[i] = (char) nInUse;
+ nInUse++;
+ }
+ }
+ }
+
+ /*
+ index of the last char in the block, so
+ the block size == last + 1.
+ */
+ private int last;
+
+ /*
+ index in zptr[] of original string after sorting.
+ */
+ private int origPtr;
+
+ /*
+ always: in the range 0 .. 9.
+ The current block size is 100000 * this number.
+ */
+ private int blockSize100k;
+
+ private boolean blockRandomised;
+
+ private int bsBuff;
+ private int bsLive;
+ private CRC mCrc = new CRC();
+
+ private boolean[] inUse = new boolean[256];
+ private int nInUse;
+
+ private char[] seqToUnseq = new char[256];
+ private char[] unseqToSeq = new char[256];
+
+ private char[] selector = new char[MAX_SELECTORS];
+ private char[] selectorMtf = new char[MAX_SELECTORS];
+
+ private int[] tt;
+ private char[] ll8;
+
+ /*
+ freq table collected to save a pass over the data
+ during decompression.
+ */
+ private int[] unzftab = new int[256];
+
+ private int[][] limit = new int[N_GROUPS][MAX_ALPHA_SIZE];
+ private int[][] base = new int[N_GROUPS][MAX_ALPHA_SIZE];
+ private int[][] perm = new int[N_GROUPS][MAX_ALPHA_SIZE];
+ private int[] minLens = new int[N_GROUPS];
+
+ private InputStream bsStream;
+
+ private boolean streamEnd = false;
+
+ private int currentChar = -1;
+
+ private static final int START_BLOCK_STATE = 1;
+ private static final int RAND_PART_A_STATE = 2;
+ private static final int RAND_PART_B_STATE = 3;
+ private static final int RAND_PART_C_STATE = 4;
+ private static final int NO_RAND_PART_A_STATE = 5;
+ private static final int NO_RAND_PART_B_STATE = 6;
+ private static final int NO_RAND_PART_C_STATE = 7;
+
+ private int currentState = START_BLOCK_STATE;
+
+ private int storedBlockCRC, storedCombinedCRC;
+ private int computedBlockCRC, computedCombinedCRC;
+
+ int i2, count, chPrev, ch2;
+ int i, tPos;
+ int rNToGo = 0;
+ int rTPos = 0;
+ int j2;
+ char z;
+
+ public BZip2CompressorInputStream(InputStream zStream) {
+ ll8 = null;
+ tt = null;
+ bsSetStream(zStream);
+ initialize();
+ initBlock();
+ setupBlock();
+ }
+
+ public int read() {
+ if (streamEnd) {
+ return -1;
+ } else {
+ int retChar = currentChar;
+ switch(currentState) {
+ case START_BLOCK_STATE:
+ break;
+ case RAND_PART_A_STATE:
+ break;
+ case RAND_PART_B_STATE:
+ setupRandPartB();
+ break;
+ case RAND_PART_C_STATE:
+ setupRandPartC();
+ break;
+ case NO_RAND_PART_A_STATE:
+ break;
+ case NO_RAND_PART_B_STATE:
+ setupNoRandPartB();
+ break;
+ case NO_RAND_PART_C_STATE:
+ setupNoRandPartC();
+ break;
+ default:
+ break;
+ }
+ return retChar;
+ }
+ }
+
+ private void initialize() {
+ char magic3, magic4;
+ magic3 = bsGetUChar();
+ magic4 = bsGetUChar();
+ if (magic3 != 'h' || magic4 < '1' || magic4 > '9') {
+ bsFinishedWithStream();
+ streamEnd = true;
+ return;
+ }
+
+ setDecompressStructureSizes(magic4 - '0');
+ computedCombinedCRC = 0;
+ }
+
+ private void initBlock() {
+ char magic1, magic2, magic3, magic4;
+ char magic5, magic6;
+ magic1 = bsGetUChar();
+ magic2 = bsGetUChar();
+ magic3 = bsGetUChar();
+ magic4 = bsGetUChar();
+ magic5 = bsGetUChar();
+ magic6 = bsGetUChar();
+ if (magic1 == 0x17 && magic2 == 0x72 && magic3 == 0x45
+ && magic4 == 0x38 && magic5 == 0x50 && magic6 == 0x90) {
+ complete();
+ return;
+ }
+
+ if (magic1 != 0x31 || magic2 != 0x41 || magic3 != 0x59
+ || magic4 != 0x26 || magic5 != 0x53 || magic6 != 0x59) {
+ badBlockHeader();
+ streamEnd = true;
+ return;
+ }
+
+ storedBlockCRC = bsGetInt32();
+
+ if (bsR(1) == 1) {
+ blockRandomised = true;
+ } else {
+ blockRandomised = false;
+ }
+
+ // currBlockNo++;
+ getAndMoveToFrontDecode();
+
+ mCrc.initialiseCRC();
+ currentState = START_BLOCK_STATE;
+ }
+
+ private void endBlock() {
+ computedBlockCRC = mCrc.getFinalCRC();
+ /* A bad CRC is considered a fatal error. */
+ if (storedBlockCRC != computedBlockCRC) {
+ crcError();
+ }
+
+ computedCombinedCRC = (computedCombinedCRC << 1)
+ | (computedCombinedCRC >>> 31);
+ computedCombinedCRC ^= computedBlockCRC;
+ }
+
+ private void complete() {
+ storedCombinedCRC = bsGetInt32();
+ if (storedCombinedCRC != computedCombinedCRC) {
+ crcError();
+ }
+
+ bsFinishedWithStream();
+ streamEnd = true;
+ }
+
+ private static void blockOverrun() {
+ cadvise();
+ }
+
+ private static void badBlockHeader() {
+ cadvise();
+ }
+
+ private static void crcError() {
+ cadvise();
+ }
+
+ private void bsFinishedWithStream() {
+ try {
+ if (this.bsStream != null) {
+ if (this.bsStream != System.in) {
+ this.bsStream.close();
+ this.bsStream = null;
+ }
+ }
+ } catch (IOException ioe) {
+ //ignore
+ }
+ }
+
+ private void bsSetStream(InputStream f) {
+ bsStream = f;
+ bsLive = 0;
+ bsBuff = 0;
+ }
+
+ private int bsR(int n) {
+ int v;
+ while (bsLive < n) {
+ int zzi;
+ char thech = 0;
+ try {
+ thech = (char) bsStream.read();
+ } catch (IOException e) {
+ compressedStreamEOF();
+ }
+ if (thech == -1) {
+ compressedStreamEOF();
+ }
+ zzi = thech;
+ bsBuff = (bsBuff << 8) | (zzi & 0xff);
+ bsLive += 8;
+ }
+
+ v = (bsBuff >> (bsLive - n)) & ((1 << n) - 1);
+ bsLive -= n;
+ return v;
+ }
+
+ private char bsGetUChar() {
+ return (char) bsR(8);
+ }
+
+ private int bsGetint() {
+ int u = 0;
+ u = (u << 8) | bsR(8);
+ u = (u << 8) | bsR(8);
+ u = (u << 8) | bsR(8);
+ u = (u << 8) | bsR(8);
+ return u;
+ }
+
+ private int bsGetIntVS(int numBits) {
+ return (int) bsR(numBits);
+ }
+
+ private int bsGetInt32() {
+ return (int) bsGetint();
+ }
+
+ private void hbCreateDecodeTables(int[] limit, int[] base,
+ int[] perm, char[] length,
+ int minLen, int maxLen, int alphaSize) {
+ int pp, i, j, vec;
+
+ pp = 0;
+ for (i = minLen; i <= maxLen; i++) {
+ for (j = 0; j < alphaSize; j++) {
+ if (length[j] == i) {
+ perm[pp] = j;
+ pp++;
+ }
+ }
+ }
+
+ for (i = 0; i < MAX_CODE_LEN; i++) {
+ base[i] = 0;
+ }
+ for (i = 0; i < alphaSize; i++) {
+ base[length[i] + 1]++;
+ }
+
+ for (i = 1; i < MAX_CODE_LEN; i++) {
+ base[i] += base[i - 1];
+ }
+
+ for (i = 0; i < MAX_CODE_LEN; i++) {
+ limit[i] = 0;
+ }
+ vec = 0;
+
+ for (i = minLen; i <= maxLen; i++) {
+ vec += (base[i + 1] - base[i]);
+ limit[i] = vec - 1;
+ vec <<= 1;
+ }
+ for (i = minLen + 1; i <= maxLen; i++) {
+ base[i] = ((limit[i - 1] + 1) << 1) - base[i];
+ }
+ }
+
+ private void recvDecodingTables() {
+ char len[][] = new char[N_GROUPS][MAX_ALPHA_SIZE];
+ int i, j, t, nGroups, nSelectors, alphaSize;
+ int minLen, maxLen;
+ boolean[] inUse16 = new boolean[16];
+
+ /* Receive the mapping table */
+ for (i = 0; i < 16; i++) {
+ if (bsR(1) == 1) {
+ inUse16[i] = true;
+ } else {
+ inUse16[i] = false;
+ }
+ }
+
+ for (i = 0; i < 256; i++) {
+ inUse[i] = false;
+ }
+
+ for (i = 0; i < 16; i++) {
+ if (inUse16[i]) {
+ for (j = 0; j < 16; j++) {
+ if (bsR(1) == 1) {
+ inUse[i * 16 + j] = true;
+ }
+ }
+ }
+ }
+
+ makeMaps();
+ alphaSize = nInUse + 2;
+
+ /* Now the selectors */
+ nGroups = bsR(3);
+ nSelectors = bsR(15);
+ for (i = 0; i < nSelectors; i++) {
+ j = 0;
+ while (bsR(1) == 1) {
+ j++;
+ }
+ selectorMtf[i] = (char) j;
+ }
+
+ /* Undo the MTF values for the selectors. */
+ {
+ char[] pos = new char[N_GROUPS];
+ char tmp, v;
+ for (v = 0; v < nGroups; v++) {
+ pos[v] = v;
+ }
+
+ for (i = 0; i < nSelectors; i++) {
+ v = selectorMtf[i];
+ tmp = pos[v];
+ while (v > 0) {
+ pos[v] = pos[v - 1];
+ v--;
+ }
+ pos[0] = tmp;
+ selector[i] = tmp;
+ }
+ }
+
+ /* Now the coding tables */
+ for (t = 0; t < nGroups; t++) {
+ int curr = bsR(5);
+ for (i = 0; i < alphaSize; i++) {
+ while (bsR(1) == 1) {
+ if (bsR(1) == 0) {
+ curr++;
+ } else {
+ curr--;
+ }
+ }
+ len[t][i] = (char) curr;
+ }
+ }
+
+ /* Create the Huffman decoding tables */
+ for (t = 0; t < nGroups; t++) {
+ minLen = 32;
+ maxLen = 0;
+ for (i = 0; i < alphaSize; i++) {
+ if (len[t][i] > maxLen) {
+ maxLen = len[t][i];
+ }
+ if (len[t][i] < minLen) {
+ minLen = len[t][i];
+ }
+ }
+ hbCreateDecodeTables(limit[t], base[t], perm[t], len[t], minLen,
+ maxLen, alphaSize);
+ minLens[t] = minLen;
+ }
+ }
+
+ private void getAndMoveToFrontDecode() {
+ char[] yy = new char[256];
+ int i, j, nextSym, limitLast;
+ int EOB, groupNo, groupPos;
+
+ limitLast = baseBlockSize * blockSize100k;
+ origPtr = bsGetIntVS(24);
+
+ recvDecodingTables();
+ EOB = nInUse + 1;
+ groupNo = -1;
+ groupPos = 0;
+
+ /*
+ Setting up the unzftab entries here is not strictly
+ necessary, but it does save having to do it later
+ in a separate pass, and so saves a block's worth of
+ cache misses.
+ */
+ for (i = 0; i <= 255; i++) {
+ unzftab[i] = 0;
+ }
+
+ for (i = 0; i <= 255; i++) {
+ yy[i] = (char) i;
+ }
+
+ last = -1;
+
+ {
+ int zt, zn, zvec, zj;
+ if (groupPos == 0) {
+ groupNo++;
+ groupPos = G_SIZE;
+ }
+ groupPos--;
+ zt = selector[groupNo];
+ zn = minLens[zt];
+ zvec = bsR(zn);
+ while (zvec > limit[zt][zn]) {
+ zn++;
+ {
+ {
+ while (bsLive < 1) {
+ int zzi;
+ char thech = 0;
+ try {
+ thech = (char) bsStream.read();
+ } catch (IOException e) {
+ compressedStreamEOF();
+ }
+ if (thech == -1) {
+ compressedStreamEOF();
+ }
+ zzi = thech;
+ bsBuff = (bsBuff << 8) | (zzi & 0xff);
+ bsLive += 8;
+ }
+ }
+ zj = (bsBuff >> (bsLive - 1)) & 1;
+ bsLive--;
+ }
+ zvec = (zvec << 1) | zj;
+ }
+ nextSym = perm[zt][zvec - base[zt][zn]];
+ }
+
+ while (true) {
+
+ if (nextSym == EOB) {
+ break;
+ }
+
+ if (nextSym == RUNA || nextSym == RUNB) {
+ char ch;
+ int s = -1;
+ int N = 1;
+ do {
+ if (nextSym == RUNA) {
+ s = s + (0 + 1) * N;
+ } else if (nextSym == RUNB) {
+ s = s + (1 + 1) * N;
+ }
+ N = N * 2;
+ {
+ int zt, zn, zvec, zj;
+ if (groupPos == 0) {
+ groupNo++;
+ groupPos = G_SIZE;
+ }
+ groupPos--;
+ zt = selector[groupNo];
+ zn = minLens[zt];
+ zvec = bsR(zn);
+ while (zvec > limit[zt][zn]) {
+ zn++;
+ {
+ {
+ while (bsLive < 1) {
+ int zzi;
+ char thech = 0;
+ try {
+ thech = (char) bsStream.read();
+ } catch (IOException e) {
+ compressedStreamEOF();
+ }
+ if (thech == -1) {
+ compressedStreamEOF();
+ }
+ zzi = thech;
+ bsBuff = (bsBuff << 8) | (zzi & 0xff);
+ bsLive += 8;
+ }
+ }
+ zj = (bsBuff >> (bsLive - 1)) & 1;
+ bsLive--;
+ }
+ zvec = (zvec << 1) | zj;
+ }
+ nextSym = perm[zt][zvec - base[zt][zn]];
+ }
+ } while (nextSym == RUNA || nextSym == RUNB);
+
+ s++;
+ ch = seqToUnseq[yy[0]];
+ unzftab[ch] += s;
+
+ while (s > 0) {
+ last++;
+ ll8[last] = ch;
+ s--;
+ }
+
+ if (last >= limitLast) {
+ blockOverrun();
+ }
+ continue;
+ } else {
+ char tmp;
+ last++;
+ if (last >= limitLast) {
+ blockOverrun();
+ }
+
+ tmp = yy[nextSym - 1];
+ unzftab[seqToUnseq[tmp]]++;
+ ll8[last] = seqToUnseq[tmp];
+
+ /*
+ This loop is hammered during decompression,
+ hence the unrolling.
+
+ for (j = nextSym-1; j > 0; j--) yy[j] = yy[j-1];
+ */
+
+ j = nextSym - 1;
+ for (; j > 3; j -= 4) {
+ yy[j] = yy[j - 1];
+ yy[j - 1] = yy[j - 2];
+ yy[j - 2] = yy[j - 3];
+ yy[j - 3] = yy[j - 4];
+ }
+ for (; j > 0; j--) {
+ yy[j] = yy[j - 1];
+ }
+
+ yy[0] = tmp;
+ {
+ int zt, zn, zvec, zj;
+ if (groupPos == 0) {
+ groupNo++;
+ groupPos = G_SIZE;
+ }
+ groupPos--;
+ zt = selector[groupNo];
+ zn = minLens[zt];
+ zvec = bsR(zn);
+ while (zvec > limit[zt][zn]) {
+ zn++;
+ {
+ {
+ while (bsLive < 1) {
+ int zzi;
+ char thech = 0;
+ try {
+ thech = (char) bsStream.read();
+ } catch (IOException e) {
+ compressedStreamEOF();
+ }
+ zzi = thech;
+ bsBuff = (bsBuff << 8) | (zzi & 0xff);
+ bsLive += 8;
+ }
+ }
+ zj = (bsBuff >> (bsLive - 1)) & 1;
+ bsLive--;
+ }
+ zvec = (zvec << 1) | zj;
+ }
+ nextSym = perm[zt][zvec - base[zt][zn]];
+ }
+ continue;
+ }
+ }
+ }
+
+ private void setupBlock() {
+ int[] cftab = new int[257];
+ char ch;
+
+ cftab[0] = 0;
+ for (i = 1; i <= 256; i++) {
+ cftab[i] = unzftab[i - 1];
+ }
+ for (i = 1; i <= 256; i++) {
+ cftab[i] += cftab[i - 1];
+ }
+
+ for (i = 0; i <= last; i++) {
+ ch = (char) ll8[i];
+ tt[cftab[ch]] = i;
+ cftab[ch]++;
+ }
+ cftab = null;
+
+ tPos = tt[origPtr];
+
+ count = 0;
+ i2 = 0;
+ ch2 = 256; /* not a char and not EOF */
+
+ if (blockRandomised) {
+ rNToGo = 0;
+ rTPos = 0;
+ setupRandPartA();
+ } else {
+ setupNoRandPartA();
+ }
+ }
+
+ private void setupRandPartA() {
+ if (i2 <= last) {
+ chPrev = ch2;
+ ch2 = ll8[tPos];
+ tPos = tt[tPos];
+ if (rNToGo == 0) {
+ rNToGo = rNums[rTPos];
+ rTPos++;
+ if (rTPos == 512) {
+ rTPos = 0;
+ }
+ }
+ rNToGo--;
+ ch2 ^= (int) ((rNToGo == 1) ? 1 : 0);
+ i2++;
+
+ currentChar = ch2;
+ currentState = RAND_PART_B_STATE;
+ mCrc.updateCRC(ch2);
+ } else {
+ endBlock();
+ initBlock();
+ setupBlock();
+ }
+ }
+
+ private void setupNoRandPartA() {
+ if (i2 <= last) {
+ chPrev = ch2;
+ ch2 = ll8[tPos];
+ tPos = tt[tPos];
+ i2++;
+
+ currentChar = ch2;
+ currentState = NO_RAND_PART_B_STATE;
+ mCrc.updateCRC(ch2);
+ } else {
+ endBlock();
+ initBlock();
+ setupBlock();
+ }
+ }
+
+ private void setupRandPartB() {
+ if (ch2 != chPrev) {
+ currentState = RAND_PART_A_STATE;
+ count = 1;
+ setupRandPartA();
+ } else {
+ count++;
+ if (count >= 4) {
+ z = ll8[tPos];
+ tPos = tt[tPos];
+ if (rNToGo == 0) {
+ rNToGo = rNums[rTPos];
+ rTPos++;
+ if (rTPos == 512) {
+ rTPos = 0;
+ }
+ }
+ rNToGo--;
+ z ^= ((rNToGo == 1) ? 1 : 0);
+ j2 = 0;
+ currentState = RAND_PART_C_STATE;
+ setupRandPartC();
+ } else {
+ currentState = RAND_PART_A_STATE;
+ setupRandPartA();
+ }
+ }
+ }
+
+ private void setupRandPartC() {
+ if (j2 < (int) z) {
+ currentChar = ch2;
+ mCrc.updateCRC(ch2);
+ j2++;
+ } else {
+ currentState = RAND_PART_A_STATE;
+ i2++;
+ count = 0;
+ setupRandPartA();
+ }
+ }
+
+ private void setupNoRandPartB() {
+ if (ch2 != chPrev) {
+ currentState = NO_RAND_PART_A_STATE;
+ count = 1;
+ setupNoRandPartA();
+ } else {
+ count++;
+ if (count >= 4) {
+ z = ll8[tPos];
+ tPos = tt[tPos];
+ currentState = NO_RAND_PART_C_STATE;
+ j2 = 0;
+ setupNoRandPartC();
+ } else {
+ currentState = NO_RAND_PART_A_STATE;
+ setupNoRandPartA();
+ }
+ }
+ }
+
+ private void setupNoRandPartC() {
+ if (j2 < (int) z) {
+ currentChar = ch2;
+ mCrc.updateCRC(ch2);
+ j2++;
+ } else {
+ currentState = NO_RAND_PART_A_STATE;
+ i2++;
+ count = 0;
+ setupNoRandPartA();
+ }
+ }
+
+ private void setDecompressStructureSizes(int newSize100k) {
+ if (!(0 <= newSize100k && newSize100k <= 9 && 0 <= blockSize100k
+ && blockSize100k <= 9)) {
+ // throw new IOException("Invalid block size");
+ }
+
+ blockSize100k = newSize100k;
+
+ if (newSize100k == 0) {
+ return;
+ }
+
+ int n = baseBlockSize * newSize100k;
+ ll8 = new char[n];
+ tt = new int[n];
+ }
+}
+