ant-notifications mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From bode...@apache.org
Subject svn commit: r1350882 - in /ant/core/trunk: WHATSNEW src/main/org/apache/tools/bzip2/CBZip2InputStream.java
Date Sat, 16 Jun 2012 08:08:52 GMT
Author: bodewig
Date: Sat Jun 16 08:08:51 2012
New Revision: 1350882

URL: http://svn.apache.org/viewvc?rev=1350882&view=rev
Log:
Merge bzip2 input from Compress, bringing support for files with multiple streams

Modified:
    ant/core/trunk/WHATSNEW
    ant/core/trunk/src/main/org/apache/tools/bzip2/CBZip2InputStream.java

Modified: ant/core/trunk/WHATSNEW
URL: http://svn.apache.org/viewvc/ant/core/trunk/WHATSNEW?rev=1350882&r1=1350881&r2=1350882&view=diff
==============================================================================
--- ant/core/trunk/WHATSNEW (original)
+++ ant/core/trunk/WHATSNEW Sat Jun 16 08:08:51 2012
@@ -52,6 +52,9 @@ Other changes:
  * merged the TAR package from Commons Compress, it can now read
    archives using POSIX extension headers and STAR extensions.
 
+ * merged the BZIP2 package from Commons Compress, it can now
+   optionally read files that contain multiple streams properly.
+
 Changes from Ant 1.8.3 TO Ant 1.8.4
 ===================================
 

Modified: ant/core/trunk/src/main/org/apache/tools/bzip2/CBZip2InputStream.java
URL: http://svn.apache.org/viewvc/ant/core/trunk/src/main/org/apache/tools/bzip2/CBZip2InputStream.java?rev=1350882&r1=1350881&r2=1350882&view=diff
==============================================================================
--- ant/core/trunk/src/main/org/apache/tools/bzip2/CBZip2InputStream.java (original)
+++ ant/core/trunk/src/main/org/apache/tools/bzip2/CBZip2InputStream.java Sat Jun 16 08:08:51
2012
@@ -45,28 +45,6 @@ import java.io.InputStream;
  */
 public class CBZip2InputStream extends InputStream implements BZip2Constants {
 
-    private static void reportCRCError() throws IOException {
-        // The clean way would be to throw an exception.
-        //throw new IOException("crc error");
-
-        // Just print a message, like the previous versions of this class did
-        System.err.println("BZip2 CRC error");
-    }
-
-    private void makeMaps() {
-        final boolean[] inUse   = this.data.inUse;
-        final byte[] seqToUnseq = this.data.seqToUnseq;
-
-        int nInUseShadow = 0;
-
-        for (int i = 0; i < 256; i++) {
-            if (inUse[i])
-                seqToUnseq[nInUseShadow++] = (byte) i;
-        }
-
-        this.nInUse = nInUseShadow;
-    }
-
     /**
      * Index of the last char in the block, so the block size == last + 1.
      */
@@ -92,6 +70,7 @@ public class CBZip2InputStream extends I
     private int nInUse;
 
     private InputStream in;
+    private final boolean decompressConcatenated;
 
     private int currentChar = -1;
 
@@ -129,7 +108,8 @@ public class CBZip2InputStream extends I
 
     /**
      * Constructs a new CBZip2InputStream which decompresses bytes read from
-     * the specified stream.
+     * the specified stream. This doesn't suppprt decompressing
+     * concatenated .bz2 files.
      *
      * <p>Although BZip2 headers are marked with the magic
      * <tt>"Bz"</tt> this constructor expects the next byte in the
@@ -143,12 +123,46 @@ public class CBZip2InputStream extends I
      *  if <tt>in == null</tt>
      */
     public CBZip2InputStream(final InputStream in) throws IOException {
+        this(in, false);
+    }
+
+    /**
+     * Constructs a new CBZip2InputStream which decompresses bytes
+     * read from the specified stream.
+     *
+     * <p>Although BZip2 headers are marked with the magic
+     * <tt>"Bz"</tt> this constructor expects the next byte in the
+     * stream to be the first one after the magic.  Thus callers have
+     * to skip the first two bytes. Otherwise this constructor will
+     * throw an exception. </p>
+     *
+     * @param in the InputStream from which this object should be created
+     * @param decompressConcatenated
+     *                     if true, decompress until the end of the input;
+     *                     if false, stop after the first .bz2 stream and
+     *                     leave the input position to point to the next
+     *                     byte after the .bz2 stream
+     *
+     * @throws IOException
+     *             if the stream content is malformed or an I/O error occurs.
+     * @throws NullPointerException
+     *             if <tt>in == null</tt>
+     */
+    public CBZip2InputStream(final InputStream in,
+                             final boolean decompressConcatenated)
+            throws IOException {
         super();
 
         this.in = in;
-        init();
+        this.decompressConcatenated = decompressConcatenated;
+
+        init(true);
+        initBlock();
+        setupBlock();
     }
 
+    /** {@inheritDoc} */
+    @Override
     public int read() throws IOException {
         if (this.in != null) {
             return read0();
@@ -157,6 +171,12 @@ public class CBZip2InputStream extends I
         }
     }
 
+    /*
+     * (non-Javadoc)
+     * 
+     * @see java.io.InputStream#read(byte[], int, int)
+     */
+    @Override
     public int read(final byte[] dest, final int offs, final int len)
         throws IOException {
         if (offs < 0) {
@@ -183,6 +203,21 @@ public class CBZip2InputStream extends I
         return (destOffs == offs) ? -1 : (destOffs - offs);
     }
 
+    private void makeMaps() {
+        final boolean[] inUse   = this.data.inUse;
+        final byte[] seqToUnseq = this.data.seqToUnseq;
+
+        int nInUseShadow = 0;
+
+        for (int i = 0; i < 256; i++) {
+            if (inUse[i]) {
+                seqToUnseq[nInUseShadow++] = (byte) i;
+            }
+        }
+
+        this.nInUse = nInUseShadow;
+    }
+
     private int read0() throws IOException {
         final int retChar = this.currentChar;
 
@@ -222,18 +257,31 @@ public class CBZip2InputStream extends I
         return retChar;
     }
 
-    private void init() throws IOException {
+    private boolean init(boolean isFirstStream) throws IOException {
         if (null == in) {
             throw new IOException("No InputStream");
         }
-        if (in.available() == 0) {
-            throw new IOException("Empty InputStream");
+        
+        if (isFirstStream) {
+            if (in.available() == 0) {
+                throw new IOException("Empty InputStream");
+            }
+        } else {
+            int magic0 = this.in.read();
+            if (magic0 == -1) {
+                return false;
+            }
+            int magic1 = this.in.read();
+            if (magic0 != 'B' || magic1 != 'Z') {
+                throw new IOException("Garbage after a valid BZip2 stream");
+            }
         }
+
         int magic2 = this.in.read();
         if (magic2 != 'h') {
-            throw new IOException("Stream is not BZip2 formatted: expected 'h'"
-                                  + " as first byte but got '" + (char) magic2
-                                  + "'");
+            throw new IOException(isFirstStream
+                    ? "Stream is not in the BZip2 format"
+                    : "Garbage after a valid BZip2 stream");
         }
 
         int blockSize = this.in.read();
@@ -244,32 +292,50 @@ public class CBZip2InputStream extends I
 
         this.blockSize100k = blockSize - '0';
 
-        initBlock();
-        setupBlock();
+        this.bsLive = 0;
+        this.computedCombinedCRC = 0;
+
+        return true;
     }
 
     private void initBlock() throws IOException {
-        char magic0 = bsGetUByte();
-        char magic1 = bsGetUByte();
-        char magic2 = bsGetUByte();
-        char magic3 = bsGetUByte();
-        char magic4 = bsGetUByte();
-        char magic5 = bsGetUByte();
-
-        if (magic0 == 0x17 &&
-            magic1 == 0x72 &&
-            magic2 == 0x45 &&
-            magic3 == 0x38 &&
-            magic4 == 0x50 &&
-            magic5 == 0x90) {
-            complete(); // end of file
-        } else if (magic0 != 0x31 || // '1'
-                   magic1 != 0x41 || // ')'
-                   magic2 != 0x59 || // 'Y'
-                   magic3 != 0x26 || // '&'
-                   magic4 != 0x53 || // 'S'
-                   magic5 != 0x59   // 'Y'
-                   ) {
+        char magic0;
+        char magic1;
+        char magic2;
+        char magic3;
+        char magic4;
+        char magic5;
+
+        while (true) {
+            // Get the block magic bytes.
+            magic0 = bsGetUByte();
+            magic1 = bsGetUByte();
+            magic2 = bsGetUByte();
+            magic3 = bsGetUByte();
+            magic4 = bsGetUByte();
+            magic5 = bsGetUByte();
+
+            // If isn't end of stream magic, break out of the loop.
+            if (magic0 != 0x17 || magic1 != 0x72 || magic2 != 0x45
+                    || magic3 != 0x38 || magic4 != 0x50 || magic5 != 0x90) {
+                break;
+            }
+
+            // End of stream was reached. Check the combined CRC and
+            // advance to the next .bz2 stream if decoding concatenated
+            // streams.
+            if (complete()) {
+                return;
+            }
+        }
+
+        if (magic0 != 0x31 || // '1'
+            magic1 != 0x41 || // ')'
+            magic2 != 0x59 || // 'Y'
+            magic3 != 0x26 || // '&'
+            magic4 != 0x53 || // 'S'
+            magic5 != 0x59 // 'Y'
+            ) {
             this.currentState = EOF;
             throw new IOException("bad block header");
         } else {
@@ -313,7 +379,7 @@ public class CBZip2InputStream extends I
         this.computedCombinedCRC ^= this.computedBlockCRC;
     }
 
-    private void complete() throws IOException {
+    private boolean complete() throws IOException {
         this.storedCombinedCRC = bsGetInt();
         this.currentState = EOF;
         this.data = null;
@@ -321,8 +387,13 @@ public class CBZip2InputStream extends I
         if (this.storedCombinedCRC != this.computedCombinedCRC) {
             reportCRCError();
         }
+
+        // Look for the next .bz2 stream if decompressing
+        // concatenated files.
+        return !decompressConcatenated || !init(false);
     }
 
+    @Override
     public void close() throws IOException {
         InputStream inShadow = this.in;
         if (inShadow != null) {
@@ -978,5 +1049,14 @@ public class CBZip2InputStream extends I
         }
 
     }
+
+    private static void reportCRCError() throws IOException {
+        // The clean way would be to throw an exception.
+        //throw new IOException("crc error");
+
+        // Just print a message, like the previous versions of this class did
+        System.err.println("BZip2 CRC error");
+    }
+
 }
 



Mime
View raw message