]> source.dussan.org Git - poi.git/commitdiff
Initial HDGF support for streams, plus tests
authorNick Burch <nick@apache.org>
Mon, 18 Jun 2007 20:24:39 +0000 (20:24 +0000)
committerNick Burch <nick@apache.org>
Mon, 18 Jun 2007 20:24:39 +0000 (20:24 +0000)
git-svn-id: https://svn.apache.org/repos/asf/jakarta/poi/trunk@548476 13f79535-47bb-0310-9956-ffa450edef68

src/scratchpad/src/org/apache/poi/hdgf/streams/CompressedStreamStore.java [new file with mode: 0644]
src/scratchpad/src/org/apache/poi/hdgf/streams/Stream.java [new file with mode: 0644]
src/scratchpad/src/org/apache/poi/hdgf/streams/StreamStore.java [new file with mode: 0644]
src/scratchpad/src/org/apache/poi/hdgf/streams/UnknownStream.java [new file with mode: 0644]
src/scratchpad/testcases/org/apache/poi/hdgf/streams/TestStreamBasics.java [new file with mode: 0644]

diff --git a/src/scratchpad/src/org/apache/poi/hdgf/streams/CompressedStreamStore.java b/src/scratchpad/src/org/apache/poi/hdgf/streams/CompressedStreamStore.java
new file mode 100644 (file)
index 0000000..7edb389
--- /dev/null
@@ -0,0 +1,62 @@
+/**
+ * 
+ */
+package org.apache.poi.hdgf.streams;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+
+import org.apache.poi.hdgf.LZW4HDGF;
+
+class CompressedStreamStore extends StreamStore {
+       /** The raw, compressed contents */
+       private byte[] compressedContents;
+       /** 
+        * We're not sure what this is, but it comes before the
+        *  real contents in the de-compressed data
+        */
+       private byte[] blockHeader = new byte[4];
+       
+       protected byte[] _getCompressedContents() { return compressedContents; }
+       protected byte[] _getBlockHeader() { return blockHeader; }
+       
+       /**
+        * Creates a new compressed StreamStore, which will handle
+        *  the decompression.
+        */
+       protected CompressedStreamStore(byte[] data, int offset, int length) throws IOException {
+               this(decompress(data,offset,length));
+               
+               compressedContents = new byte[length];
+               System.arraycopy(data, offset, compressedContents, 0, length);
+       }
+       /**
+        * Handles passing the de-compressed data onto our superclass.
+        */
+       private CompressedStreamStore(byte[][] decompressedData) {
+               super(decompressedData[1], 0, decompressedData[1].length);
+               blockHeader = decompressedData[0];
+       }
+
+       /**
+        * Decompresses the given data, returning it as header + contents
+        */
+       public static byte[][] decompress(byte[] data, int offset, int length) throws IOException {
+               ByteArrayInputStream bais = new ByteArrayInputStream(data, offset, length);
+               
+               // Decompress
+               LZW4HDGF lzw = new LZW4HDGF();
+               byte[] decompressed = lzw.decode(bais);
+               
+               // Split into header and contents
+               byte[][] ret = new byte[2][];
+               ret[0] = new byte[4];
+               ret[1] = new byte[decompressed.length - 4];
+               
+               System.arraycopy(decompressed, 0, ret[0], 0, 4);
+               System.arraycopy(decompressed, 4, ret[1], 0, ret[1].length);
+               
+               // All done
+               return ret;
+       }
+}
\ No newline at end of file
diff --git a/src/scratchpad/src/org/apache/poi/hdgf/streams/Stream.java b/src/scratchpad/src/org/apache/poi/hdgf/streams/Stream.java
new file mode 100644 (file)
index 0000000..b5291bb
--- /dev/null
@@ -0,0 +1,75 @@
+/* ====================================================================
+   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.poi.hdgf.streams;
+
+import java.io.IOException;
+
+import org.apache.poi.hdgf.pointers.Pointer;
+
+/**
+ * Base of all Streams within a HDGF document.
+ * Streams are what hold the data (the metadata of a stream
+ *  is held in the pointer that points to the stream).
+ * A stream may be stored compressed or un-compressed on the
+ *  disk, but that doesn't appear to change their use.
+ */
+public abstract class Stream {
+       private Pointer pointer;
+       private StreamStore store;
+       
+       public Pointer getPointer() { return pointer; }
+       protected StreamStore getStore() { return store; }
+       
+       /**
+        * Creates a new Stream, having already used the pointer
+        *  to build a store 
+        */
+       protected Stream(Pointer pointer, StreamStore store) {
+               this.pointer = pointer;
+               this.store = store;
+       }
+       
+       /**
+        * Uses the pointer to locate a Stream within the document
+        *  data, and creates it.
+        * @param pointer The Pointer to create a stream for
+        * @param documentData The raw document data
+        */
+       public static Stream createStream(Pointer pointer, byte[] documentData) {
+               // Create the store
+               StreamStore store;
+               if(pointer.destinationCompressed()) {
+                       try {
+                               store = new CompressedStreamStore(
+                                       documentData, pointer.getOffset(), pointer.getLength()
+                               );
+                       } catch(IOException e) {
+                               // Should never occur
+                               throw new IllegalStateException(e);
+                       }
+               } else {
+                       store = new StreamStore(
+                                       documentData, pointer.getOffset(), pointer.getLength()
+                       );
+               }
+               
+               // Figure out what sort of Stream to create, and create it
+               
+               // Give up and return a generic one
+               return new UnknownStream(pointer, store);
+       }
+}
diff --git a/src/scratchpad/src/org/apache/poi/hdgf/streams/StreamStore.java b/src/scratchpad/src/org/apache/poi/hdgf/streams/StreamStore.java
new file mode 100644 (file)
index 0000000..0ce1b6b
--- /dev/null
@@ -0,0 +1,20 @@
+package org.apache.poi.hdgf.streams;
+
+/**
+ * Holds the representation of the stream on-disk, and
+ *  handles de-compressing it as required.
+ * In future, may also handle writing it back out again
+ */
+class StreamStore {
+       private byte[] contents;
+       
+       /**
+        * Creates a new, non compressed Stream Store
+        */
+       protected StreamStore(byte[] data, int offset, int length) {
+               contents = new byte[length];
+               System.arraycopy(data, offset, contents, 0, length);
+       }
+       
+       protected byte[] getContents() { return contents; }
+}
\ No newline at end of file
diff --git a/src/scratchpad/src/org/apache/poi/hdgf/streams/UnknownStream.java b/src/scratchpad/src/org/apache/poi/hdgf/streams/UnknownStream.java
new file mode 100644 (file)
index 0000000..d7eef9b
--- /dev/null
@@ -0,0 +1,29 @@
+/* ====================================================================
+   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.poi.hdgf.streams;
+
+import org.apache.poi.hdgf.pointers.Pointer;
+
+/**
+ * A placeholder for a stream where we don't known anything 
+ *  about how to process / handle it
+ */
+public class UnknownStream extends Stream {
+       protected UnknownStream(Pointer pointer, StreamStore store) {
+               super(pointer, store);
+       }
+}
diff --git a/src/scratchpad/testcases/org/apache/poi/hdgf/streams/TestStreamBasics.java b/src/scratchpad/testcases/org/apache/poi/hdgf/streams/TestStreamBasics.java
new file mode 100644 (file)
index 0000000..81ab4e5
--- /dev/null
@@ -0,0 +1,127 @@
+package org.apache.poi.hdgf.streams;
+
+import org.apache.poi.hdgf.pointers.Pointer;
+import org.apache.poi.hdgf.pointers.PointerV6;
+
+import junit.framework.TestCase;
+
+public class TestStreamBasics extends TestCase {
+       /** The header from when compressedStream is decompressed */
+       public static final byte[] compressedStreamDCHeader = new byte[] {
+               -60, 2, 0, 0
+       };
+       public static final byte[] compressedStream = new byte[] {
+               123, -60, 2, -21, -16, 1, 0, 0, -72, -13, -16, 78, -32, -5, 1, 
+               0, 3, -21, -16, 10, 5, 4, -21, -16, 21, 9, -21, -16, 103, -21, 
+               -16, 34, -36, -1, 52, 15, 70, 15, 120, 88, 15, -7, -2, -28, -9, 
+               -123, 21, 0, 44, -122, 1, -4, 104, 15, -24, -13, 40, -98, 32, 
+               78, 102, -67, -1, -2, -30, 64, 40, -67, -113, -73, 116, -98, 
+               -85, 2, 66, 123, 9, 109, -85, 2, -89, 14, -56, -69, -83, -79, 
+               -34, -3, 120, 110, 75, -9, -10, 20, -6, -25, -12, 22, -21, -16, 
+               -12, -81, 67, 1, -128, -70, -21, -16, 84, -21, -16, 70, 0, 23, 
+               -21, -16, 76, 47, -40, 79, 1, -44, -21, -16, 32, 3, 18, 12, 17, 
+               -43, -68, 17, 16, -8, 21, 22, -1, -21, -16, -84, -1, -35, 79, 
+               -9, -10, 96, 0, 46, -21, -16, 44, -39, -41, 79, 1, 119, -13, 
+               -16, -106, -13, -16, 84, 0, 125, 26, -21, -16, 68, -38, 79, 1, 
+               17, 10, 0, -97, 50, 10, 0, 0, -42, -108, 15, 118, 31, 0, -3, 29, 
+               -21, -16, -100, -25, 79, 1, -18, 97, -36, 76, 16, -21, -16, 86, 
+               0, 36, -5, 1, -5, 79, 63, 1, -124, 98, 0, 0, 28, 3, 20, -34, -3, 
+               125, 33, -21, -16, 100, -4, 79, 1, -92, -91, 16, -22, 24, 19, 41, 
+               -21, -16, -44, -59, 16, 108, 100, 0, -21, 0, 71, -105, 18, 39, 85, 
+               17, -3, 79, 1, 95, -108, 113, 0, 0, 104, 3, 18, 49, 49, 17, -1, 64, 
+               85, 1, 0, 114, 0, 0, -93, -36, -21, -16, 100, 31, 0, 0, -40, -21, 
+               -16, -92, 66, 127, 85, 1, 98, 119, 0, 0, -48, 79, 18, -3, 50, -17, 
+               1, 67, 85, 1, 81, -127, 0, -41, 0, 14, 6, 4, 17, 63, -63, 17, 68, 
+               85, -65, 1, 30, -120, 0, 0, 42, 79, 18, 68, 126, -21, -16, -76, 69, 
+               85, 1, 102, -119, 72, 37, 0, 97, 33 };
+       public static final byte[] uncompressedStream = new byte[] {
+               0, 1, 0, 0, -72, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+               0, 0, 0, 0, 0, 1, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 
+               0, 9, 0, 0, 0, 103, 0, 0, 0, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+               -123, 21, 0, 44, -123, 21, 0, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, -98, 32, 78, 102, -67, 
+               -2, -30, 64, 40, -67, -113, -73, 116, -67, -2, -30, 64, 40, 66, 
+               123, 9, 109, -67, -2, -30, 64, 40, -98, 32, 78, 102, -67, -2, -30, 
+               64, 40, -67, -113, -73, 116, -67, -2, -30, 64, -56, -83, -79, 0, 0, 
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120, 110, 75, 1, 0, 0, 0, 
+               0, 0, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 22, 0, 0, 0, -12, -81, 67, 
+               1, -128, 0, 0, 0, 84, 0, 0, 0, 70, 0, 23, 0, 0, 0, 76, -40, 79, 1, 
+               -44, 0, 0, 0, 32, 0, 0, 0, 84, 0, 23, 0, 0, 0, -68, -40, 79, 1, -8, 
+               0, 0, 0, 32, 0, 0, 0, 84, 0, -1, 0, 0, 0, -84, -1, 79, 1, 0, 0, 0, 
+               0, 0, 0, 0, 0, 96, 0, 46, 0, 0, 0, 44, -39, 79, 1, 119, 1, 0, 0, 
+               -106, 1, 0, 0, 84, 0, 26, 0, 0, 0, 68, -38, 79, 1, 17, 3, 0, 0, 
+               50, 10, 0, 0, -42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+               29, 0, 0, 0, -100, -25, 79, 1, -18, 97, 0, 0, -106, 0, 0, 0, 86, 0, 
+               36, 0, 0, 0, -12, -5, 79, 1, -124, 98, 0, 0, 28, 0, 0, 0, 84, 0, 0, 
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 100, 
+               -4, 79, 1, -92, 98, 0, 0, 32, 0, 0, 0, 84, 0, 41, 0, 0, 0, -44, -4, 
+               79, 1, 108, 100, 0, 0, 71, 0, 0, 0, 86, 0, 39, 0, 0, 0, 68, -3, 79, 
+               1, -108, 113, 0, 0, 104, 0, 0, 0, 84, 0, 49, 0, 0, 0, -84, 64, 85, 
+               1, 0, 114, 0, 0, -93, 0, 0, 0, -42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+               0, 0, 0, 0, 0, 0, 0, 0, 0, -40, 0, 0, 0, -92, 66, 85, 1, 98, 119, 
+               0, 0, -48, 1, 0, 0, 84, 0, 50, 0, 0, 0, 20, 67, 85, 1, 81, -127, 
+               0, 0, 14, 6, 0, 0, 84, 0, 63, 0, 0, 0, 100, 68, 85, 1, 30, -120, 
+               0, 0, 42, 1, 0, 0, 84, 0, 68, 0, 0, 0, -76, 69, 85, 1, 102, -119, 
+               0, 0, 42, 1, 0, 0, 84, 0, 0, 0, 0, 0
+       };
+
+       public void testCompressedStream() {
+               // Create a fake pointer
+               Pointer ptr = new TestPointer(true, 0, compressedStream.length, -1, (short)-1);
+               // Now the stream
+               Stream stream = Stream.createStream(ptr, compressedStream);
+               
+               // Check
+               assertNotNull(stream.getPointer());
+               assertNotNull(stream.getStore());
+               assertTrue(stream.getStore() instanceof StreamStore);
+               assertTrue(stream.getStore() instanceof CompressedStreamStore);
+               assertTrue(stream instanceof UnknownStream);
+               
+               // Check the stream store
+               CompressedStreamStore ss = (CompressedStreamStore)stream.getStore();
+               assertEquals(4, ss._getBlockHeader().length);
+               assertEquals(compressedStream.length, ss._getCompressedContents().length);
+               assertEquals(uncompressedStream.length, ss.getContents().length);
+               
+               for(int i=0; i<uncompressedStream.length; i++) {
+                       assertEquals(uncompressedStream[i], ss.getContents()[i]);
+               }
+       }
+       
+       public void testUncompressedStream() {
+               // Create a fake pointer
+               Pointer ptr = new TestPointer(false, 0, uncompressedStream.length, -1, (short)-1);
+               // Now the stream
+               Stream stream = Stream.createStream(ptr, uncompressedStream);
+               
+               // Check
+               assertNotNull(stream.getPointer());
+               assertNotNull(stream.getStore());
+               assertTrue(stream.getStore() instanceof StreamStore);
+               assertFalse(stream.getStore() instanceof CompressedStreamStore);
+               assertTrue(stream instanceof UnknownStream);
+       }
+       
+       public static class TestPointer extends Pointer {
+               private boolean compressed;
+               public TestPointer(boolean compressed, int offset, int length, int type, short format) {
+                       this.compressed = compressed;
+                       this.offset = offset;
+                       this.length = length;
+                       this.type = type;
+                       this.format = format;
+               }
+
+               public boolean destinationCompressed() { return compressed; }
+               public boolean destinationHasChunks() { return false; }
+               public boolean destinationHasPointers() { return false; }
+               public boolean destinationHasStrings() { return false; }
+               public int getSizeInBytes() { return -1; }
+       }
+}
\ No newline at end of file