You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

DocumentBlock.java 6.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. /* ====================================================================
  2. Licensed to the Apache Software Foundation (ASF) under one or more
  3. contributor license agreements. See the NOTICE file distributed with
  4. this work for additional information regarding copyright ownership.
  5. The ASF licenses this file to You under the Apache License, Version 2.0
  6. (the "License"); you may not use this file except in compliance with
  7. the License. You may obtain a copy of the License at
  8. http://www.apache.org/licenses/LICENSE-2.0
  9. Unless required by applicable law or agreed to in writing, software
  10. distributed under the License is distributed on an "AS IS" BASIS,
  11. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. See the License for the specific language governing permissions and
  13. limitations under the License.
  14. ==================================================================== */
  15. package org.apache.poi.poifs.storage;
  16. import java.io.IOException;
  17. import java.io.InputStream;
  18. import java.io.OutputStream;
  19. import java.util.Arrays;
  20. import org.apache.poi.poifs.common.POIFSBigBlockSize;
  21. import org.apache.poi.poifs.common.POIFSConstants;
  22. import org.apache.poi.util.IOUtils;
  23. /**
  24. * A block of document data.
  25. *
  26. * @author Marc Johnson (mjohnson at apache dot org)
  27. */
  28. public final class DocumentBlock extends BigBlock {
  29. private static final byte _default_value = ( byte ) 0xFF;
  30. private byte[] _data;
  31. private int _bytes_read;
  32. /**
  33. * create a document block from a raw data block
  34. *
  35. * @param block the raw data block
  36. *
  37. * @exception IOException
  38. */
  39. public DocumentBlock(final RawDataBlock block)
  40. throws IOException
  41. {
  42. super(
  43. block.getBigBlockSize() == POIFSConstants.SMALLER_BIG_BLOCK_SIZE ?
  44. POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS :
  45. POIFSConstants.LARGER_BIG_BLOCK_SIZE_DETAILS
  46. );
  47. _data = block.getData();
  48. _bytes_read = _data.length;
  49. }
  50. /**
  51. * Create a single instance initialized with data.
  52. *
  53. * @param stream the InputStream delivering the data.
  54. *
  55. * @exception IOException
  56. */
  57. public DocumentBlock(final InputStream stream, POIFSBigBlockSize bigBlockSize)
  58. throws IOException
  59. {
  60. this(bigBlockSize);
  61. int count = IOUtils.readFully(stream, _data);
  62. _bytes_read = (count == -1) ? 0
  63. : count;
  64. }
  65. /**
  66. * Create a single instance initialized with default values
  67. */
  68. private DocumentBlock(POIFSBigBlockSize bigBlockSize)
  69. {
  70. super(bigBlockSize);
  71. _data = new byte[ bigBlockSize.getBigBlockSize() ];
  72. Arrays.fill(_data, _default_value);
  73. }
  74. /**
  75. * Get the number of bytes read for this block
  76. *
  77. * @return bytes read into the block
  78. */
  79. public int size()
  80. {
  81. return _bytes_read;
  82. }
  83. /**
  84. * Was this a partially read block?
  85. *
  86. * @return true if the block was only partially filled with data
  87. */
  88. public boolean partiallyRead()
  89. {
  90. return _bytes_read != bigBlockSize.getBigBlockSize();
  91. }
  92. /**
  93. * @return the fill byte used
  94. */
  95. public static byte getFillByte()
  96. {
  97. return _default_value;
  98. }
  99. /**
  100. * convert a single long array into an array of DocumentBlock
  101. * instances
  102. *
  103. * @param array the byte array to be converted
  104. * @param size the intended size of the array (which may be smaller)
  105. *
  106. * @return an array of DocumentBlock instances, filled from the
  107. * input array
  108. */
  109. public static DocumentBlock [] convert(final POIFSBigBlockSize bigBlockSize,
  110. final byte [] array,
  111. final int size)
  112. {
  113. DocumentBlock[] rval =
  114. new DocumentBlock[ (size + bigBlockSize.getBigBlockSize() - 1) / bigBlockSize.getBigBlockSize() ];
  115. int offset = 0;
  116. for (int k = 0; k < rval.length; k++)
  117. {
  118. rval[ k ] = new DocumentBlock(bigBlockSize);
  119. if (offset < array.length)
  120. {
  121. int length = Math.min(bigBlockSize.getBigBlockSize(),
  122. array.length - offset);
  123. System.arraycopy(array, offset, rval[ k ]._data, 0, length);
  124. if (length != bigBlockSize.getBigBlockSize())
  125. {
  126. Arrays.fill(rval[ k ]._data, length,
  127. bigBlockSize.getBigBlockSize(),
  128. _default_value);
  129. }
  130. }
  131. else
  132. {
  133. Arrays.fill(rval[ k ]._data, _default_value);
  134. }
  135. offset += bigBlockSize.getBigBlockSize();
  136. }
  137. return rval;
  138. }
  139. public static DataInputBlock getDataInputBlock(DocumentBlock[] blocks, int offset) {
  140. if(blocks == null || blocks.length == 0) {
  141. return null;
  142. }
  143. // Key things about the size of the block
  144. POIFSBigBlockSize bigBlockSize = blocks[0].bigBlockSize;
  145. int BLOCK_SHIFT = bigBlockSize.getHeaderValue();
  146. int BLOCK_SIZE = bigBlockSize.getBigBlockSize();
  147. int BLOCK_MASK = BLOCK_SIZE - 1;
  148. // Now do the offset lookup
  149. int firstBlockIndex = offset >> BLOCK_SHIFT;
  150. int firstBlockOffset= offset & BLOCK_MASK;
  151. return new DataInputBlock(blocks[firstBlockIndex]._data, firstBlockOffset);
  152. }
  153. /* ********** START extension of BigBlock ********** */
  154. /**
  155. * Write the block's data to an OutputStream
  156. *
  157. * @param stream the OutputStream to which the stored data should
  158. * be written
  159. *
  160. * @exception IOException on problems writing to the specified
  161. * stream
  162. */
  163. void writeData(final OutputStream stream)
  164. throws IOException
  165. {
  166. doWriteData(stream, _data);
  167. }
  168. /* ********** END extension of BigBlock ********** */
  169. } // end public class DocumentBlock