1 2 /* ==================================================================== 3 * The Apache Software License, Version 1.1 4 * 5 * Copyright (c) 2002 The Apache Software Foundation. All rights 6 * reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in 17 * the documentation and/or other materials provided with the 18 * distribution. 19 * 20 * 3. The end-user documentation included with the redistribution, 21 * if any, must include the following acknowledgment: 22 * "This product includes software developed by the 23 * Apache Software Foundation (http://www.apache.org/)." 24 * Alternately, this acknowledgment may appear in the software itself, 25 * if and wherever such third-party acknowledgments normally appear. 26 * 27 * 4. The names "Apache" and "Apache Software Foundation" and 28 * "Apache POI" must not be used to endorse or promote products 29 * derived from this software without prior written permission. For 30 * written permission, please contact apache@apache.org. 31 * 32 * 5. Products derived from this software may not be called "Apache", 33 * "Apache POI", nor may "Apache" appear in their name, without 34 * prior written permission of the Apache Software Foundation. 35 * 36 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 37 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 38 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 39 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR 40 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 41 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 42 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 43 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 44 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 45 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 46 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 47 * SUCH DAMAGE. 48 * ==================================================================== 49 * 50 * This software consists of voluntary contributions made by many 51 * individuals on behalf of the Apache Software Foundation. For more 52 * information on the Apache Software Foundation, please see 53 * <http://www.apache.org/>. 54 */ 55 56 package org.apache.poi.poifs.storage; 57 58 import java.io.IOException; 59 import java.io.InputStream; 60 import java.io.OutputStream; 61 62 import java.util.Arrays; 63 64 import org.apache.poi.poifs.common.POIFSConstants; 65 import org.apache.poi.util.IntegerField; 66 import org.apache.poi.util.LittleEndian; 67 import org.apache.poi.util.LittleEndianConsts; 68 69 /** 70 * A block of document data. 71 * 72 * @author Marc Johnson (mjohnson at apache dot org) 73 */ 74 75 public class DocumentBlock 76 extends BigBlock 77 { 78 private static final byte _default_value = ( byte ) 0xFF; 79 private byte[] _data; 80 private int _bytes_read; 81 82 /** 83 * create a document block from a raw data block 84 * 85 * @param block the raw data block 86 * 87 * @exception IOException 88 */ 89 90 public DocumentBlock(final RawDataBlock block) 91 throws IOException 92 { 93 _data = block.getData(); 94 _bytes_read = _data.length; 95 } 96 97 /** 98 * Create a single instance initialized with data. 99 * 100 * @param stream the InputStream delivering the data. 101 * 102 * @exception IOException 103 */ 104 105 public DocumentBlock(final InputStream stream) 106 throws IOException 107 { 108 this(); 109 int count = stream.read(_data); 110 111 _bytes_read = (count == -1) ? 0 112 : count; 113 } 114 115 /** 116 * Create a single instance initialized with default values 117 */ 118 119 private DocumentBlock() 120 { 121 _data = new byte[ POIFSConstants.BIG_BLOCK_SIZE ]; 122 Arrays.fill(_data, _default_value); 123 } 124 125 /** 126 * Get the number of bytes read for this block 127 * 128 * @return bytes read into the block 129 */ 130 131 public int size() 132 { 133 return _bytes_read; 134 } 135 136 /** 137 * Was this a partially read block? 138 * 139 * @return true if the block was only partially filled with data 140 */ 141 142 public boolean partiallyRead() 143 { 144 return _bytes_read != POIFSConstants.BIG_BLOCK_SIZE; 145 } 146 147 /** 148 * @return the fill byte used 149 */ 150 151 public static byte getFillByte() 152 { 153 return _default_value; 154 } 155 156 /** 157 * convert a single long array into an array of DocumentBlock 158 * instances 159 * 160 * @param array the byte array to be converted 161 * @param size the intended size of the array (which may be smaller) 162 * 163 * @return an array of DocumentBlock instances, filled from the 164 * input array 165 */ 166 167 public static DocumentBlock [] convert(final byte [] array, 168 final int size) 169 { 170 DocumentBlock[] rval = 171 new DocumentBlock[ (size + POIFSConstants.BIG_BLOCK_SIZE - 1) / POIFSConstants.BIG_BLOCK_SIZE ]; 172 int offset = 0; 173 174 for (int k = 0; k < rval.length; k++) 175 { 176 rval[ k ] = new DocumentBlock(); 177 if (offset < array.length) 178 { 179 int length = Math.min(POIFSConstants.BIG_BLOCK_SIZE, 180 array.length - offset); 181 182 System.arraycopy(array, offset, rval[ k ]._data, 0, length); 183 if (length != POIFSConstants.BIG_BLOCK_SIZE) 184 { 185 Arrays.fill(rval[ k ]._data, length, 186 POIFSConstants.BIG_BLOCK_SIZE, 187 _default_value); 188 } 189 } 190 else 191 { 192 Arrays.fill(rval[ k ]._data, _default_value); 193 } 194 offset += POIFSConstants.BIG_BLOCK_SIZE; 195 } 196 return rval; 197 } 198 199 /** 200 * read data from an array of DocumentBlocks 201 * 202 * @param blocks the blocks to read from 203 * @param buffer the buffer to write the data into 204 * @param offset the offset into the array of blocks to read from 205 */ 206 207 public static void read(final DocumentBlock [] blocks, 208 final byte [] buffer, final int offset) 209 { 210 int firstBlockIndex = offset / POIFSConstants.BIG_BLOCK_SIZE; 211 int firstBlockOffset = offset % POIFSConstants.BIG_BLOCK_SIZE; 212 int lastBlockIndex = (offset + buffer.length - 1) 213 / POIFSConstants.BIG_BLOCK_SIZE; 214 215 if (firstBlockIndex == lastBlockIndex) 216 { 217 System.arraycopy(blocks[ firstBlockIndex ]._data, 218 firstBlockOffset, buffer, 0, buffer.length); 219 } 220 else 221 { 222 int buffer_offset = 0; 223 224 System.arraycopy(blocks[ firstBlockIndex ]._data, 225 firstBlockOffset, buffer, buffer_offset, 226 POIFSConstants.BIG_BLOCK_SIZE 227 - firstBlockOffset); 228 buffer_offset += POIFSConstants.BIG_BLOCK_SIZE - firstBlockOffset; 229 for (int j = firstBlockIndex + 1; j < lastBlockIndex; j++) 230 { 231 System.arraycopy(blocks[ j ]._data, 0, buffer, buffer_offset, 232 POIFSConstants.BIG_BLOCK_SIZE); 233 buffer_offset += POIFSConstants.BIG_BLOCK_SIZE; 234 } 235 System.arraycopy(blocks[ lastBlockIndex ]._data, 0, buffer, 236 buffer_offset, buffer.length - buffer_offset); 237 } 238 } 239 240 /* ********** START extension of BigBlock ********** */ 241 242 /** 243 * Write the block's data to an OutputStream 244 * 245 * @param stream the OutputStream to which the stored data should 246 * be written 247 * 248 * @exception IOException on problems writing to the specified 249 * stream 250 */ 251 252 void writeData(final OutputStream stream) 253 throws IOException 254 { 255 doWriteData(stream, _data); 256 } 257 258 /* ********** END extension of BigBlock ********** */ 259 } // end public class DocumentBlock 260 261