From: Nick Burch Date: Mon, 18 Jun 2007 20:24:39 +0000 (+0000) Subject: Initial HDGF support for streams, plus tests X-Git-Tag: REL_3_0_1_RC3~15 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=4fef51784c62ad4b28051283b8c5b85f267938b9;p=poi.git Initial HDGF support for streams, plus tests git-svn-id: https://svn.apache.org/repos/asf/jakarta/poi/trunk@548476 13f79535-47bb-0310-9956-ffa450edef68 --- 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 index 0000000000..7edb389025 --- /dev/null +++ b/src/scratchpad/src/org/apache/poi/hdgf/streams/CompressedStreamStore.java @@ -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 index 0000000000..b5291bb74c --- /dev/null +++ b/src/scratchpad/src/org/apache/poi/hdgf/streams/Stream.java @@ -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 index 0000000000..0ce1b6be34 --- /dev/null +++ b/src/scratchpad/src/org/apache/poi/hdgf/streams/StreamStore.java @@ -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 index 0000000000..d7eef9b554 --- /dev/null +++ b/src/scratchpad/src/org/apache/poi/hdgf/streams/UnknownStream.java @@ -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 index 0000000000..81ab4e5c64 --- /dev/null +++ b/src/scratchpad/testcases/org/apache/poi/hdgf/streams/TestStreamBasics.java @@ -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