1 /
55
56 package org.apache.poi.poifs.filesystem;
57
58 import java.io.*;
59
60 import java.util.*;
61
62 import org.apache.poi.poifs.common.POIFSConstants;
63 import org.apache.poi.poifs.dev.POIFSViewable;
64 import org.apache.poi.poifs.property.DirectoryProperty;
65 import org.apache.poi.poifs.property.DocumentProperty;
66 import org.apache.poi.poifs.property.Property;
67 import org.apache.poi.poifs.property.PropertyTable;
68 import org.apache.poi.poifs.storage.BATBlock;
69 import org.apache.poi.poifs.storage.BlockAllocationTableReader;
70 import org.apache.poi.poifs.storage.BlockAllocationTableWriter;
71 import org.apache.poi.poifs.storage.BlockList;
72 import org.apache.poi.poifs.storage.BlockWritable;
73 import org.apache.poi.poifs.storage.HeaderBlockReader;
74 import org.apache.poi.poifs.storage.HeaderBlockWriter;
75 import org.apache.poi.poifs.storage.RawDataBlock;
76 import org.apache.poi.poifs.storage.RawDataBlockList;
77 import org.apache.poi.poifs.storage.SmallBlockTableReader;
78 import org.apache.poi.poifs.storage.SmallBlockTableWriter;
79 import org.apache.poi.poifs.storage.SmallDocumentBlock;
80
81
87
88 public class POIFSFileSystem
89 implements POIFSViewable
90 {
91 private PropertyTable _property_table;
92 private List _documents;
93 private DirectoryNode _root;
94
95
98
99 public POIFSFileSystem()
100 {
101 _property_table = new PropertyTable();
102 _documents = new ArrayList();
103 _root = null;
104 }
105
106
113
114 public POIFSFileSystem(final InputStream stream)
115 throws IOException
116 {
117 this();
118
119
120 HeaderBlockReader header_block_reader = new HeaderBlockReader(stream);
121
122
123 RawDataBlockList data_blocks = new RawDataBlockList(stream);
124
125
126
127 new BlockAllocationTableReader(header_block_reader.getBATCount(),
128 header_block_reader.getBATArray(),
129 header_block_reader.getXBATCount(),
130 header_block_reader.getXBATIndex(),
131 data_blocks);
132
133
134 PropertyTable properties =
135 new PropertyTable(header_block_reader.getPropertyStart(),
136 data_blocks);
137
138
139 processProperties(SmallBlockTableReader
140 .getSgetRootumentBlocks(data_blocks, properties
141 .getRgetSBATStartheader_block_reader .getSgetChildren, data_blocks, properties.getRoot()
142 .getChildren(), null);
143 }
144
145
156
157 public DocumentEntry createDocument(final InputStream stream,
158 final String name)
159 throws IOException
160 {
161 return getRoot().createDocument(name, stream);
162 }
163
164
176
177 public DocumentEntry createDocument(final String name, final int size,
178 final POIFSWriterListener writer)
179 throws IOException
180 {
181 return getRoot().createDocument(name, size, writer);
182 }
183
184
193
194 public DirectoryEntry createDirectory(final String name)
195 throws IOException
196 {
197 return getRoot().createDirectory(name);
198 }
199
200
208
209 public void writeFilesystem(final OutputStream stream)
210 throws IOException
211 {
212
213
214 _property_table.preWrite();
215
216
217 SmallBlockTableWriter sbtw =
218 new SmallBlockTableWriter(_documents, _property_table.getRoot());
219
220
221 BlockAllocationTableWriter bat =
222 new BlockAllocationTableWriter();
223
224
225
226 List bm_objects = new ArrayList();
227
228 bm_objects.addAll(_documents);
229 bm_objects.add(_property_table);
230 bm_objects.add(sbtw);
231 bm_objects.add(sbtw.getSBAT());
232
233
234
235 Iterator iter = bm_objects.iterator();
236
237 while (iter.hasNext())
238 {
239 BATManaged bmo = ( BATManaged ) iter.next();
240 int block_count = bmo.countBlocks();
241
242 if (block_count != 0)
243 {
244 bmo.setStartBlock(bat.allocateSpace(block_count));
245 }
246 else
247 {
248
249
250
251
252 }
253 }
254
255
256
257 int batStartBlock = bat.createBlocks();
258
259
260 HeaderBlockWriter header_block_writer = new HeaderBlockWriter();
261 BATBlock[] xbat_blocks =
262 header_block_writer.setBATBlocks(bat.countBlocks(),
263 batStartBlock);
264
265
266 header_block_writer.setPropertyStart(_property_table.getStartBlock());
267
268
269 header_block_writer.setSBATStart(sbtw.getSBAT().getStartBlock());
270
271
272
273
274
275
276 List writers = new ArrayList();
277
278 writers.add(header_block_writer);
279 writers.addAll(_documents);
280 writers.add(_property_table);
281 writers.add(sbtw);
282 writers.add(sbtw.getSBAT());
283 writers.add(bat);
284 for (int j = 0; j < xbat_blocks.length; j++)
285 {
286 writers.add(xbat_blocks[ j ]);
287 }
288
289
290 iter = writers.iterator();
291 while (iter.hasNext())
292 {
293 BlockWritable writer = ( BlockWritable ) iter.next();
294
295 writer.writeBlocks(stream);
296 }
297 }
298
299
307
308 public static void main(String args[])
309 throws IOException
310 {
311 if (args.length != 2)
312 {
313 System.err.println(
314 "two arguments required: input filename and output filename");
315 System.exit(1);
316 }
317 FileInputStream istream = new FileInputStream(args[ 0 ]);
318 FileOutputStream ostream = new FileOutputStream(args[ 1 ]);
319
320 new POIFSFileSystem(istream).writeFilesystem(ostream);
321 istream.close();
322 ostream.close();
323 }
324
325
330
331 public DirectoryEntry getRoot()
332 {
333 if (_root == null)
334 {
335 _root = new DirectoryNode(_property_table.getRoot(), this, null);
336 }
337 return _root;
338 }
339
340
350
351 public DocumentInputStream createDocumentInputStream(
352 final String documentName)
353 throws IOException
354 {
355 Entry document = getRoot().getEntry(documentName);
356
357 if (!document.isDocumentEntry())
358 {
359 throw new IOException("Entry '" + documentName
360 + "' is not a DocumentEntry");
361 }
362 return new DocumentInputStream(( DocumentEntry ) document);
363 }
364
365
370
371 void addDocument(final POIFSDocument document)
372 {
373 _documents.add(document);
374 _property_table.addProperty(document.getDocumentProperty());
375 }
376
377
382
383 void addDirectory(final DirectoryProperty directory)
384 {
385 _property_table.addProperty(directory);
386 }
387
388
393
394 void remove(EntryNode entry)
395 {
396 _property_table.removeProperty(entry.getProperty());
397 if (entry.isDocumentEntry())
398 {
399 _documents.remove((( DocumentNode ) entry).getDocument());
400 }
401 }
402
403 private void processProperties(final BlockList small_blocks,
404 final BlockList big_blocks,
405 final Iterator properties,
406 final DirectoryNode dir)
407 throws IOException
408 {
409 while (properties.hasNext())
410 {
411 Property property = ( Property ) properties.next();
412 String name = property.getName();
413 DirectoryNode parent = (dir == null)
414 ? (( DirectoryNode ) getRoot())
415 : dir;
416
417 if (property.isDirectory())
418 {
419 DirectoryNode new_dir =
420 ( DirectoryNode ) parent.createDirectory(name);
421
422 processProperties(
423 small_blocks, big_blocks,
424 (( DirectoryProperty ) property).getChildren(), new_dir);
425 }
426 else
427 {
428 int startBlock = property.getStartBlock();
429 int size = property.getSize();
430 POIFSDocument document = null;
431
432 if (property.shouldUseSmallBlocks())
433 {
434 document =
435 new POIFSDocumentfetchBlocksnamesmall_blocks .fetchBlocks(startBlock), size);
436 }
437 else
438 {
439 document =
440 new POIFSDocument(name,
441 big_blocks.fetchBlocks(startBlock),
442 size);
443 }
444 parent.createDocument(document);
445 }
446 }
447 }
448
449
450
451
457
458 public Object [] getViewableArray()
459 {
460 if (preferArray())
461 {
462 return (( POIFSViewable ) getRoot()).getViewableArray();
463 }
464 else
465 {
466 return new Object[ 0 ];
467 }
468 }
469
470
477
478 public Iterator getViewableIterator()
479 {
480 if (!preferArray())
481 {
482 return (( POIFSViewable ) getRoot()).getViewableIterator();
483 }
484 else
485 {
486 return Collections.EMPTY_LIST.iterator();
487 }
488 }
489
490
497
498 public boolean preferArray()
499 {
500 return (( POIFSViewable ) getRoot()).preferArray();
501 }
502
503
509
510 public String getShortDescription()
511 {
512 return "POIFS FileSystem";
513 }
514
515
516 }
517
518