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:
018: package org.apache.poi.poifs.storage;
019:
020: import java.io.IOException;
021: import java.io.InputStream;
022: import java.io.OutputStream;
023:
024: import java.util.Arrays;
025:
026: import org.apache.poi.poifs.common.POIFSConstants;
027: import org.apache.poi.util.IOUtils;
028: import org.apache.poi.util.IntegerField;
029: import org.apache.poi.util.LittleEndian;
030: import org.apache.poi.util.LittleEndianConsts;
031:
032: /**
033: * A block of document data.
034: *
035: * @author Marc Johnson (mjohnson at apache dot org)
036: */
037:
038: public class DocumentBlock extends BigBlock {
039: private static final byte _default_value = (byte) 0xFF;
040: private byte[] _data;
041: private int _bytes_read;
042:
043: /**
044: * create a document block from a raw data block
045: *
046: * @param block the raw data block
047: *
048: * @exception IOException
049: */
050:
051: public DocumentBlock(final RawDataBlock block) throws IOException {
052: _data = block.getData();
053: _bytes_read = _data.length;
054: }
055:
056: /**
057: * Create a single instance initialized with data.
058: *
059: * @param stream the InputStream delivering the data.
060: *
061: * @exception IOException
062: */
063:
064: public DocumentBlock(final InputStream stream) throws IOException {
065: this ();
066: int count = IOUtils.readFully(stream, _data);
067:
068: _bytes_read = (count == -1) ? 0 : count;
069: }
070:
071: /**
072: * Create a single instance initialized with default values
073: */
074:
075: private DocumentBlock() {
076: _data = new byte[POIFSConstants.BIG_BLOCK_SIZE];
077: Arrays.fill(_data, _default_value);
078: }
079:
080: /**
081: * Get the number of bytes read for this block
082: *
083: * @return bytes read into the block
084: */
085:
086: public int size() {
087: return _bytes_read;
088: }
089:
090: /**
091: * Was this a partially read block?
092: *
093: * @return true if the block was only partially filled with data
094: */
095:
096: public boolean partiallyRead() {
097: return _bytes_read != POIFSConstants.BIG_BLOCK_SIZE;
098: }
099:
100: /**
101: * @return the fill byte used
102: */
103:
104: public static byte getFillByte() {
105: return _default_value;
106: }
107:
108: /**
109: * convert a single long array into an array of DocumentBlock
110: * instances
111: *
112: * @param array the byte array to be converted
113: * @param size the intended size of the array (which may be smaller)
114: *
115: * @return an array of DocumentBlock instances, filled from the
116: * input array
117: */
118:
119: public static DocumentBlock[] convert(final byte[] array,
120: final int size) {
121: DocumentBlock[] rval = new DocumentBlock[(size
122: + POIFSConstants.BIG_BLOCK_SIZE - 1)
123: / POIFSConstants.BIG_BLOCK_SIZE];
124: int offset = 0;
125:
126: for (int k = 0; k < rval.length; k++) {
127: rval[k] = new DocumentBlock();
128: if (offset < array.length) {
129: int length = Math.min(POIFSConstants.BIG_BLOCK_SIZE,
130: array.length - offset);
131:
132: System.arraycopy(array, offset, rval[k]._data, 0,
133: length);
134: if (length != POIFSConstants.BIG_BLOCK_SIZE) {
135: Arrays.fill(rval[k]._data, length,
136: POIFSConstants.BIG_BLOCK_SIZE,
137: _default_value);
138: }
139: } else {
140: Arrays.fill(rval[k]._data, _default_value);
141: }
142: offset += POIFSConstants.BIG_BLOCK_SIZE;
143: }
144: return rval;
145: }
146:
147: /**
148: * read data from an array of DocumentBlocks
149: *
150: * @param blocks the blocks to read from
151: * @param buffer the buffer to write the data into
152: * @param offset the offset into the array of blocks to read from
153: */
154:
155: public static void read(final DocumentBlock[] blocks,
156: final byte[] buffer, final int offset) {
157: int firstBlockIndex = offset / POIFSConstants.BIG_BLOCK_SIZE;
158: int firstBlockOffset = offset % POIFSConstants.BIG_BLOCK_SIZE;
159: int lastBlockIndex = (offset + buffer.length - 1)
160: / POIFSConstants.BIG_BLOCK_SIZE;
161:
162: if (firstBlockIndex == lastBlockIndex) {
163: System.arraycopy(blocks[firstBlockIndex]._data,
164: firstBlockOffset, buffer, 0, buffer.length);
165: } else {
166: int buffer_offset = 0;
167:
168: System.arraycopy(blocks[firstBlockIndex]._data,
169: firstBlockOffset, buffer, buffer_offset,
170: POIFSConstants.BIG_BLOCK_SIZE - firstBlockOffset);
171: buffer_offset += POIFSConstants.BIG_BLOCK_SIZE
172: - firstBlockOffset;
173: for (int j = firstBlockIndex + 1; j < lastBlockIndex; j++) {
174: System.arraycopy(blocks[j]._data, 0, buffer,
175: buffer_offset, POIFSConstants.BIG_BLOCK_SIZE);
176: buffer_offset += POIFSConstants.BIG_BLOCK_SIZE;
177: }
178: System.arraycopy(blocks[lastBlockIndex]._data, 0, buffer,
179: buffer_offset, buffer.length - buffer_offset);
180: }
181: }
182:
183: /* ********** START extension of BigBlock ********** */
184:
185: /**
186: * Write the block's data to an OutputStream
187: *
188: * @param stream the OutputStream to which the stored data should
189: * be written
190: *
191: * @exception IOException on problems writing to the specified
192: * stream
193: */
194:
195: void writeData(final OutputStream stream) throws IOException {
196: doWriteData(stream, _data);
197: }
198:
199: /* ********** END extension of BigBlock ********** */
200: } // end public class DocumentBlock
|