001: /* ====================================================================
002: Licensed to the Apache Software Foundation (ASF) under one or more
003: contributor license agreements. See the NOTICE file distributed with
004: this work for additional information regarding copyright ownership.
005: The ASF licenses this file to You under the Apache License, Version 2.0
006: (the "License"); you may not use this file except in compliance with
007: the License. You may obtain a copy of the License at
008:
009: http://www.apache.org/licenses/LICENSE-2.0
010:
011: Unless required by applicable law or agreed to in writing, software
012: distributed under the License is distributed on an "AS IS" BASIS,
013: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: See the License for the specific language governing permissions and
015: limitations under the License.
016: ==================================================================== */
017: package org.apache.poi.hdgf.streams;
018:
019: import java.io.ByteArrayInputStream;
020: import java.io.IOException;
021:
022: import org.apache.poi.hdgf.HDGFLZW;
023:
024: /**
025: * A StreamStore where the data on-disk is compressed,
026: * using the crazy Visio LZW
027: */
028: public class CompressedStreamStore extends StreamStore {
029: /** The raw, compressed contents */
030: private byte[] compressedContents;
031: /**
032: * We're not sure what this is, but it comes before the
033: * real contents in the de-compressed data
034: */
035: private byte[] blockHeader = new byte[4];
036: private boolean blockHeaderInContents = false;
037:
038: protected byte[] _getCompressedContents() {
039: return compressedContents;
040: }
041:
042: protected byte[] _getBlockHeader() {
043: return blockHeader;
044: }
045:
046: /**
047: * Creates a new compressed StreamStore, which will handle
048: * the decompression.
049: */
050: protected CompressedStreamStore(byte[] data, int offset, int length)
051: throws IOException {
052: this (decompress(data, offset, length));
053:
054: compressedContents = new byte[length];
055: System.arraycopy(data, offset, compressedContents, 0, length);
056: }
057:
058: /**
059: * Handles passing the de-compressed data onto our superclass.
060: */
061: private CompressedStreamStore(byte[][] decompressedData) {
062: super (decompressedData[1], 0, decompressedData[1].length);
063: blockHeader = decompressedData[0];
064: }
065:
066: /**
067: * Some kinds of streams expect their 4 byte header to be
068: * on the front of the contents.
069: * They can call this to have it sorted.
070: */
071: protected void copyBlockHeaderToContents() {
072: if (blockHeaderInContents)
073: return;
074:
075: prependContentsWith(blockHeader);
076: blockHeaderInContents = true;
077: }
078:
079: /**
080: * Decompresses the given data, returning it as header + contents
081: */
082: public static byte[][] decompress(byte[] data, int offset,
083: int length) throws IOException {
084: ByteArrayInputStream bais = new ByteArrayInputStream(data,
085: offset, length);
086:
087: // Decompress
088: HDGFLZW lzw = new HDGFLZW();
089: byte[] decompressed = lzw.decode(bais);
090:
091: // Split into header and contents
092: byte[][] ret = new byte[2][];
093: ret[0] = new byte[4];
094: ret[1] = new byte[decompressed.length - 4];
095:
096: System.arraycopy(decompressed, 0, ret[0], 0, 4);
097: System.arraycopy(decompressed, 4, ret[1], 0, ret[1].length);
098:
099: // All done
100: return ret;
101: }
102: }
|