| /* ==================================================================== |
| Licensed to the Apache Software Foundation (ASF) under one or more |
| contributor license agreements. See the NOTICE file distributed with |
| this work for additional information regarding copyright ownership. |
| The ASF licenses this file to You under the Apache License, Version 2.0 |
| (the "License"); you may not use this file except in compliance with |
| the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| ==================================================================== */ |
| |
| package org.apache.poi.poifs.storage; |
| |
| import java.io.ByteArrayInputStream; |
| import java.io.IOException; |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| import org.apache.poi.poifs.common.POIFSConstants; |
| import org.apache.poi.util.LittleEndian; |
| import org.apache.poi.util.LittleEndianConsts; |
| |
| /** |
| * Class LocalRawDataBlockList |
| * |
| * @author Marc Johnson(mjohnson at apache dot org) |
| */ |
| public final class LocalRawDataBlockList extends RawDataBlockList { |
| private final List<RawDataBlock> _list; |
| private RawDataBlock[] _array; |
| |
| public LocalRawDataBlockList() |
| throws IOException |
| { |
| super(new ByteArrayInputStream(new byte[ 0 ]), POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS); |
| _list = new ArrayList<RawDataBlock>(); |
| _array = null; |
| } |
| |
| /** |
| * create and a new XBAT block |
| * |
| * @param start index of first BAT block |
| * @param end index of last BAT block |
| * @param chain index of next XBAT block |
| */ |
| public void createNewXBATBlock(final int start, final int end, |
| final int chain) |
| throws IOException |
| { |
| byte[] data = new byte[ 512 ]; |
| int offset = 0; |
| |
| for (int k = start; k <= end; k++) |
| { |
| LittleEndian.putInt(data, offset, k); |
| offset += LittleEndianConsts.INT_SIZE; |
| } |
| while (offset != 508) |
| { |
| LittleEndian.putInt(data, offset, -1); |
| offset += LittleEndianConsts.INT_SIZE; |
| } |
| LittleEndian.putInt(data, offset, chain); |
| add(new RawDataBlock(new ByteArrayInputStream(data))); |
| } |
| |
| /** |
| * create a BAT block and add it to the list |
| * |
| * @param start_index initial index for the block list |
| */ |
| public void createNewBATBlock(final int start_index) |
| throws IOException |
| { |
| byte[] data = new byte[ 512 ]; |
| int offset = 0; |
| |
| for (int j = 0; j < 128; j++) |
| { |
| int index = start_index + j; |
| |
| if (index % 256 == 0) |
| { |
| LittleEndian.putInt(data, offset, -1); |
| } |
| else if (index % 256 == 255) |
| { |
| LittleEndian.putInt(data, offset, -2); |
| } |
| else |
| { |
| LittleEndian.putInt(data, offset, index + 1); |
| } |
| offset += LittleEndianConsts.INT_SIZE; |
| } |
| add(new RawDataBlock(new ByteArrayInputStream(data))); |
| } |
| |
| /** |
| * fill the list with dummy blocks |
| * |
| * @param count of blocks |
| */ |
| public void fill(final int count) |
| throws IOException |
| { |
| int limit = 128 * count; |
| |
| for (int j = _list.size(); j < limit; j++) |
| { |
| add(new RawDataBlock(new ByteArrayInputStream(new byte[ 0 ]))); |
| } |
| } |
| |
| /** |
| * add a new block |
| * |
| * @param block new block to add |
| */ |
| public void add(RawDataBlock block) |
| { |
| _list.add(block); |
| } |
| |
| /** |
| * override of remove method |
| * |
| * @param index of block to be removed |
| * |
| * @return desired block |
| */ |
| @Override |
| public ListManagedBlock remove(final int index) |
| throws IOException |
| { |
| ensureArrayExists(); |
| RawDataBlock rvalue = null; |
| |
| try |
| { |
| rvalue = _array[ index ]; |
| if (rvalue == null) |
| { |
| throw new IOException("index " + index + " is null"); |
| } |
| _array[ index ] = null; |
| } |
| catch (ArrayIndexOutOfBoundsException ignored) |
| { |
| throw new IOException("Cannot remove block[ " + index |
| + " ]; out of range"); |
| } |
| return rvalue; |
| } |
| |
| /** |
| * remove the specified block from the list |
| * |
| * @param index the index of the specified block; if the index is |
| * out of range, that's ok |
| */ |
| @Override |
| public void zap(final int index) |
| { |
| ensureArrayExists(); |
| if ((index >= 0) && (index < _array.length)) |
| { |
| _array[ index ] = null; |
| } |
| } |
| |
| private void ensureArrayExists() |
| { |
| if (_array == null) |
| { |
| _array = _list.toArray(new RawDataBlock[ 0 ]); |
| } |
| } |
| |
| @Override |
| public int blockCount() { |
| return _list.size(); |
| } |
| } |