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.*;
021:
022: import java.util.*;
023:
024: import org.apache.poi.poifs.common.POIFSConstants;
025: import org.apache.poi.poifs.filesystem.OfficeXmlFileException;
026: import org.apache.poi.util.IOUtils;
027: import org.apache.poi.util.IntegerField;
028: import org.apache.poi.util.LittleEndian;
029: import org.apache.poi.util.LittleEndianConsts;
030: import org.apache.poi.util.LongField;
031: import org.apache.poi.util.ShortField;
032:
033: /**
034: * The block containing the archive header
035: *
036: * @author Marc Johnson (mjohnson at apache dot org)
037: */
038:
039: public class HeaderBlockReader implements HeaderBlockConstants {
040:
041: // number of big block allocation table blocks (int)
042: private IntegerField _bat_count;
043:
044: // start of the property set block (int index of the property set
045: // chain's first big block)
046: private IntegerField _property_start;
047:
048: // start of the small block allocation table (int index of small
049: // block allocation table's first big block)
050: private IntegerField _sbat_start;
051:
052: // big block index for extension to the big block allocation table
053: private IntegerField _xbat_start;
054: private IntegerField _xbat_count;
055: private byte[] _data;
056:
057: /**
058: * create a new HeaderBlockReader from an InputStream
059: *
060: * @param stream the source InputStream
061: *
062: * @exception IOException on errors or bad data
063: */
064:
065: public HeaderBlockReader(final InputStream stream)
066: throws IOException {
067: _data = new byte[POIFSConstants.BIG_BLOCK_SIZE];
068: int byte_count = IOUtils.readFully(stream, _data);
069:
070: if (byte_count != POIFSConstants.BIG_BLOCK_SIZE) {
071: if (byte_count == -1)
072: //Cant have -1 bytes read in the error message!
073: byte_count = 0;
074: String type = " byte" + ((byte_count == 1) ? ("") : ("s"));
075:
076: throw new IOException("Unable to read entire header; "
077: + byte_count + type + " read; expected "
078: + POIFSConstants.BIG_BLOCK_SIZE + " bytes");
079: }
080:
081: // verify signature
082: LongField signature = new LongField(_signature_offset, _data);
083:
084: if (signature.get() != _signature) {
085: // Is it one of the usual suspects?
086: if (_data[0] == 0x50 && _data[1] == 0x4b
087: && _data[2] == 0x03 && _data[3] == 0x04) {
088: throw new OfficeXmlFileException(
089: "The supplied data appears to be in the Office 2007+ XML. POI only supports OLE2 Office documents");
090: }
091:
092: // Give a generic error
093: throw new IOException("Invalid header signature; read "
094: + signature.get() + ", expected " + _signature);
095: }
096: _bat_count = new IntegerField(_bat_count_offset, _data);
097: _property_start = new IntegerField(_property_start_offset,
098: _data);
099: _sbat_start = new IntegerField(_sbat_start_offset, _data);
100: _xbat_start = new IntegerField(_xbat_start_offset, _data);
101: _xbat_count = new IntegerField(_xbat_count_offset, _data);
102: }
103:
104: /**
105: * get start of Property Table
106: *
107: * @return the index of the first block of the Property Table
108: */
109:
110: public int getPropertyStart() {
111: return _property_start.get();
112: }
113:
114: /**
115: * @return start of small block allocation table
116: */
117:
118: public int getSBATStart() {
119: return _sbat_start.get();
120: }
121:
122: /**
123: * @return number of BAT blocks
124: */
125:
126: public int getBATCount() {
127: return _bat_count.get();
128: }
129:
130: /**
131: * @return BAT array
132: */
133:
134: public int[] getBATArray() {
135: int[] result = new int[_max_bats_in_header];
136: int offset = _bat_array_offset;
137:
138: for (int j = 0; j < _max_bats_in_header; j++) {
139: result[j] = LittleEndian.getInt(_data, offset);
140: offset += LittleEndianConsts.INT_SIZE;
141: }
142: return result;
143: }
144:
145: /**
146: * @return XBAT count
147: */
148:
149: public int getXBATCount() {
150: return _xbat_count.get();
151: }
152:
153: /**
154: * @return XBAT index
155: */
156:
157: public int getXBATIndex() {
158: return _xbat_start.get();
159: }
160: } // end public class HeaderBlockReader
|