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.property;
019:
020: import java.io.IOException;
021: import java.io.OutputStream;
022:
023: import java.util.*;
024:
025: import org.apache.poi.poifs.common.POIFSConstants;
026: import org.apache.poi.poifs.filesystem.BATManaged;
027: import org.apache.poi.poifs.storage.BlockWritable;
028: import org.apache.poi.poifs.storage.PropertyBlock;
029: import org.apache.poi.poifs.storage.RawDataBlock;
030: import org.apache.poi.poifs.storage.RawDataBlockList;
031:
032: /**
033: * This class embodies the Property Table for the filesystem; this is
034: * basically the dsirectory for all of the documents in the
035: * filesystem.
036: *
037: * @author Marc Johnson (mjohnson at apache dot org)
038: */
039:
040: public class PropertyTable implements BATManaged, BlockWritable {
041: private int _start_block;
042: private List _properties;
043: private BlockWritable[] _blocks;
044:
045: /**
046: * Default constructor
047: */
048:
049: public PropertyTable() {
050: _start_block = POIFSConstants.END_OF_CHAIN;
051: _properties = new ArrayList();
052: addProperty(new RootProperty());
053: _blocks = null;
054: }
055:
056: /**
057: * reading constructor (used when we've read in a file and we want
058: * to extract the property table from it). Populates the
059: * properties thoroughly
060: *
061: * @param startBlock the first block of the property table
062: * @param blockList the list of blocks
063: *
064: * @exception IOException if anything goes wrong (which should be
065: * a result of the input being NFG)
066: */
067:
068: public PropertyTable(final int startBlock,
069: final RawDataBlockList blockList) throws IOException {
070: _start_block = POIFSConstants.END_OF_CHAIN;
071: _blocks = null;
072: _properties = PropertyFactory.convertToProperties(blockList
073: .fetchBlocks(startBlock));
074: populatePropertyTree((DirectoryProperty) _properties.get(0));
075: }
076:
077: /**
078: * Add a property to the list of properties we manage
079: *
080: * @param property the new Property to manage
081: */
082:
083: public void addProperty(final Property property) {
084: _properties.add(property);
085: }
086:
087: /**
088: * Remove a property from the list of properties we manage
089: *
090: * @param property the Property to be removed
091: */
092:
093: public void removeProperty(final Property property) {
094: _properties.remove(property);
095: }
096:
097: /**
098: * Get the root property
099: *
100: * @return the root property
101: */
102:
103: public RootProperty getRoot() {
104:
105: // it's always the first element in the List
106: return (RootProperty) _properties.get(0);
107: }
108:
109: /**
110: * Prepare to be written
111: */
112:
113: public void preWrite() {
114: Property[] properties = (Property[]) _properties
115: .toArray(new Property[0]);
116:
117: // give each property its index
118: for (int k = 0; k < properties.length; k++) {
119: properties[k].setIndex(k);
120: }
121:
122: // allocate the blocks for the property table
123: _blocks = PropertyBlock.createPropertyBlockArray(_properties);
124:
125: // prepare each property for writing
126: for (int k = 0; k < properties.length; k++) {
127: properties[k].preWrite();
128: }
129: }
130:
131: /**
132: * Get the start block for the property table
133: *
134: * @return start block index
135: */
136:
137: public int getStartBlock() {
138: return _start_block;
139: }
140:
141: private void populatePropertyTree(DirectoryProperty root)
142: throws IOException {
143: int index = root.getChildIndex();
144:
145: if (!Property.isValidIndex(index)) {
146:
147: // property has no children
148: return;
149: }
150: Stack children = new Stack();
151:
152: children.push(_properties.get(index));
153: while (!children.empty()) {
154: Property property = (Property) children.pop();
155:
156: root.addChild(property);
157: if (property.isDirectory()) {
158: populatePropertyTree((DirectoryProperty) property);
159: }
160: index = property.getPreviousChildIndex();
161: if (Property.isValidIndex(index)) {
162: children.push(_properties.get(index));
163: }
164: index = property.getNextChildIndex();
165: if (Property.isValidIndex(index)) {
166: children.push(_properties.get(index));
167: }
168: }
169: }
170:
171: /* ********** START implementation of BATManaged ********** */
172:
173: /**
174: * Return the number of BigBlock's this instance uses
175: *
176: * @return count of BigBlock instances
177: */
178:
179: public int countBlocks() {
180: return (_blocks == null) ? 0 : _blocks.length;
181: }
182:
183: /**
184: * Set the start block for this instance
185: *
186: * @param index index into the array of BigBlock instances making
187: * up the the filesystem
188: */
189:
190: public void setStartBlock(final int index) {
191: _start_block = index;
192: }
193:
194: /* ********** END implementation of BATManaged ********** */
195: /* ********** START implementation of BlockWritable ********** */
196:
197: /**
198: * Write the storage to an OutputStream
199: *
200: * @param stream the OutputStream to which the stored data should
201: * be written
202: *
203: * @exception IOException on problems writing to the specified
204: * stream
205: */
206:
207: public void writeBlocks(final OutputStream stream)
208: throws IOException {
209: if (_blocks != null) {
210: for (int j = 0; j < _blocks.length; j++) {
211: _blocks[j].writeBlocks(stream);
212: }
213: }
214: }
215:
216: /* ********** END implementation of BlockWritable ********** */
217: } // end public class PropertyTable
|