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 header_block_writer.setSBATBlockCount(sbtw.getSBATBlockCount());
273
274
275
276
277
278
279 List writers = new ArrayList();
280
281 writers.add(header_block_writer);
282 writers.addAll(_documents);
283 writers.add(_property_table);
284 writers.add(sbtw);
285 writers.add(sbtw.getSBAT());
286 writers.add(bat);
287 for (int j = 0; j < xbat_blocks.length; j++)
288 {
289 writers.add(xbat_blocks[ j ]);
290 }
291
292
293 iter = writers.iterator();
294 while (iter.hasNext())
295 {
296 BlockWritable writer = ( BlockWritable ) iter.next();
297
298 writer.writeBlocks(stream);
299 }
300 }
301
302
310
311 public static void main(String args[])
312 throws IOException
313 {
314 if (args.length != 2)
315 {
316 System.err.println(
317 "two arguments required: input filename and output filename");
318 System.exit(1);
319 }
320 FileInputStream istream = new FileInputStream(args[ 0 ]);
321 FileOutputStream ostream = new FileOutputStream(args[ 1 ]);
322
323 new POIFSFileSystem(istream).writeFilesystem(ostream);
324 istream.close();
325 ostream.close();
326 }
327
328
333
334 public DirectoryEntry getRoot()
335 {
336 if (_root == null)
337 {
338 _root = new DirectoryNode(_property_table.getRoot(), this, null);
339 }
340 return _root;
341 }
342
343
353
354 public DocumentInputStream createDocumentInputStream(
355 final String documentName)
356 throws IOException
357 {
358 Entry document = getRoot().getEntry(documentName);
359
360 if (!document.isDocumentEntry())
361 {
362 throw new IOException("Entry '" + documentName
363 + "' is not a DocumentEntry");
364 }
365 return new DocumentInputStream(( DocumentEntry ) document);
366 }
367
368
373
374 void addDocument(final POIFSDocument document)
375 {
376 _documents.add(document);
377 _property_table.addProperty(document.getDocumentProperty());
378 }
379
380
385
386 void addDirectory(final DirectoryProperty directory)
387 {
388 _property_table.addProperty(directory);
389 }
390
391
396
397 void remove(EntryNode entry)
398 {
399 _property_table.removeProperty(entry.getProperty());
400 if (entry.isDocumentEntry())
401 {
402 _documents.remove((( DocumentNode ) entry).getDocument());
403 }
404 }
405
406 private void processProperties(final BlockList small_blocks,
407 final BlockList big_blocks,
408 final Iterator properties,
409 final DirectoryNode dir)
410 throws IOException
411 {
412 while (properties.hasNext())
413 {
414 Property property = ( Property ) properties.next();
415 String name = property.getName();
416 DirectoryNode parent = (dir == null)
417 ? (( DirectoryNode ) getRoot())
418 : dir;
419
420 if (property.isDirectory())
421 {
422 DirectoryNode new_dir =
423 ( DirectoryNode ) parent.createDirectory(name);
424
425 processProperties(
426 small_blocks, big_blocks,
427 (( DirectoryProperty ) property).getChildren(), new_dir);
428 }
429 else
430 {
431 int startBlock = property.getStartBlock();
432 int size = property.getSize();
433 POIFSDocument document = null;
434
435 if (property.shouldUseSmallBlocks())
436 {
437 document =
438 new POIFSDocumentfetchBlocksnamesmall_blocks .fetchBlocks(startBlock), size);
439 }
440 else
441 {
442 document =
443 new POIFSDocument(name,
444 big_blocks.fetchBlocks(startBlock),
445 size);
446 }
447 parent.createDocument(document);
448 }
449 }
450 }
451
452
453
454
460
461 public Object [] getViewableArray()
462 {
463 if (preferArray())
464 {
465 return (( POIFSViewable ) getRoot()).getViewableArray();
466 }
467 else
468 {
469 return new Object[ 0 ];
470 }
471 }
472
473
480
481 public Iterator getViewableIterator()
482 {
483 if (!preferArray())
484 {
485 return (( POIFSViewable ) getRoot()).getViewableIterator();
486 }
487 else
488 {
489 return Collections.EMPTY_LIST.iterator();
490 }
491 }
492
493
500
501 public boolean preferArray()
502 {
503 return (( POIFSViewable ) getRoot()).preferArray();
504 }
505
506
512
513 public String getShortDescription()
514 {
515 return "POIFS FileSystem";
516 }
517
518
519 }
520
521