KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > poi > poifs > filesystem > POIFSDocument


1
2 /* ====================================================================
3    Copyright 2002-2004 Apache Software Foundation
4
5    Licensed under the Apache License, Version 2.0 (the "License");
6    you may not use this file except in compliance with the License.
7    You may obtain a copy of the License at
8
9        http://www.apache.org/licenses/LICENSE-2.0
10
11    Unless required by applicable law or agreed to in writing, software
12    distributed under the License is distributed on an "AS IS" BASIS,
13    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14    See the License for the specific language governing permissions and
15    limitations under the License.
16 ==================================================================== */

17         
18
19 package org.apache.poi.poifs.filesystem;
20
21 import java.io.*;
22
23 import java.util.*;
24
25 import org.apache.poi.poifs.common.POIFSConstants;
26 import org.apache.poi.poifs.dev.POIFSViewable;
27 import org.apache.poi.poifs.property.DocumentProperty;
28 import org.apache.poi.poifs.property.Property;
29 import org.apache.poi.poifs.storage.BlockWritable;
30 import org.apache.poi.poifs.storage.ListManagedBlock;
31 import org.apache.poi.poifs.storage.DocumentBlock;
32 import org.apache.poi.poifs.storage.RawDataBlock;
33 import org.apache.poi.poifs.storage.SmallDocumentBlock;
34 import org.apache.poi.util.HexDump;
35
36 /**
37  * This class manages a document in the POIFS filesystem.
38  *
39  * @author Marc Johnson (mjohnson at apache dot org)
40  */

41
42 public class POIFSDocument
43     implements BATManaged, BlockWritable, POIFSViewable
44 {
45     private DocumentProperty _property;
46     private int _size;
47
48     // one of these stores will be valid
49
private SmallBlockStore _small_store;
50     private BigBlockStore _big_store;
51
52     /**
53      * Constructor from large blocks
54      *
55      * @param name the name of the POIFSDocument
56      * @param blocks the big blocks making up the POIFSDocument
57      * @param length the actual length of the POIFSDocument
58      *
59      * @exception IOException
60      */

61
62     public POIFSDocument(final String JavaDoc name, final RawDataBlock [] blocks,
63                          final int length)
64         throws IOException
65     {
66         _size = length;
67         _big_store = new BigBlockStore(blocks);
68         _property = new DocumentProperty(name, _size);
69         _small_store = new SmallBlockStore(new BlockWritable[ 0 ]);
70         _property.setDocument(this);
71     }
72
73     /**
74      * Constructor from small blocks
75      *
76      * @param name the name of the POIFSDocument
77      * @param blocks the small blocks making up the POIFSDocument
78      * @param length the actual length of the POIFSDocument
79      */

80
81     public POIFSDocument(final String JavaDoc name,
82                          final SmallDocumentBlock [] blocks, final int length)
83     {
84         _size = length;
85         try
86         {
87             _big_store = new BigBlockStore(new RawDataBlock[ 0 ]);
88         }
89         catch (IOException ignored)
90         {
91
92             // can't happen with that constructor
93
}
94         _property = new DocumentProperty(name, _size);
95         _small_store = new SmallBlockStore(blocks);
96         _property.setDocument(this);
97     }
98
99     /**
100      * Constructor from small blocks
101      *
102      * @param name the name of the POIFSDocument
103      * @param blocks the small blocks making up the POIFSDocument
104      * @param length the actual length of the POIFSDocument
105      *
106      * @exception IOException
107      */

108
109     public POIFSDocument(final String JavaDoc name, final ListManagedBlock [] blocks,
110                          final int length)
111         throws IOException
112     {
113         _size = length;
114         _property = new DocumentProperty(name, _size);
115         _property.setDocument(this);
116         if (Property.isSmall(_size))
117         {
118             _big_store = new BigBlockStore(new RawDataBlock[ 0 ]);
119             _small_store = new SmallBlockStore(blocks);
120         }
121         else
122         {
123             _big_store = new BigBlockStore(blocks);
124             _small_store = new SmallBlockStore(new BlockWritable[ 0 ]);
125         }
126     }
127
128     /**
129      * Constructor
130      *
131      * @param name the name of the POIFSDocument
132      * @param stream the InputStream we read data from
133      *
134      * @exception IOException thrown on read errors
135      */

136
137     public POIFSDocument(final String JavaDoc name, final InputStream stream)
138         throws IOException
139     {
140         List blocks = new ArrayList();
141
142         _size = 0;
143         while (true)
144         {
145             DocumentBlock block = new DocumentBlock(stream);
146             int blockSize = block.size();
147
148             if (blockSize > 0)
149             {
150                 blocks.add(block);
151                 _size += blockSize;
152             }
153             if (block.partiallyRead())
154             {
155                 break;
156             }
157         }
158         DocumentBlock[] bigBlocks =
159             ( DocumentBlock [] ) blocks.toArray(new DocumentBlock[ 0 ]);
160
161         _big_store = new BigBlockStore(bigBlocks);
162         _property = new DocumentProperty(name, _size);
163         _property.setDocument(this);
164         if (_property.shouldUseSmallBlocks())
165         {
166             _small_store =
167                 new SmallBlockStore(SmallDocumentBlock.convert(bigBlocks,
168                     _size));
169             _big_store = new BigBlockStore(new DocumentBlock[ 0 ]);
170         }
171         else
172         {
173             _small_store = new SmallBlockStore(new BlockWritable[ 0 ]);
174         }
175     }
176
177     /**
178      * Constructor
179      *
180      * @param name the name of the POIFSDocument
181      * @param size the length of the POIFSDocument
182      * @param path the path of the POIFSDocument
183      * @param writer the writer who will eventually write the document
184      * contents
185      *
186      * @exception IOException thrown on read errors
187      */

188
189     public POIFSDocument(final String JavaDoc name, final int size,
190                          final POIFSDocumentPath path,
191                          final POIFSWriterListener writer)
192         throws IOException
193     {
194         _size = size;
195         _property = new DocumentProperty(name, _size);
196         _property.setDocument(this);
197         if (_property.shouldUseSmallBlocks())
198         {
199             _small_store = new SmallBlockStore(path, name, size, writer);
200             _big_store = new BigBlockStore(new Object JavaDoc[ 0 ]);
201         }
202         else
203         {
204             _small_store = new SmallBlockStore(new BlockWritable[ 0 ]);
205             _big_store = new BigBlockStore(path, name, size, writer);
206         }
207     }
208
209     /**
210      * return the array of SmallDocumentBlocks used
211      *
212      * @return array of SmallDocumentBlocks; may be empty, cannot be null
213      */

214
215     public BlockWritable [] getSmallBlocks()
216     {
217         return _small_store.getBlocks();
218     }
219
220     /**
221      * @return size of the document
222      */

223
224     public int getSize()
225     {
226         return _size;
227     }
228
229     /**
230      * read data from the internal stores
231      *
232      * @param buffer the buffer to write to
233      * @param offset the offset into our storage to read from
234      */

235
236     void read(final byte [] buffer, final int offset)
237     {
238         if (_property.shouldUseSmallBlocks())
239         {
240             SmallDocumentBlock.read(_small_store.getBlocks(), buffer, offset);
241         }
242         else
243         {
244             DocumentBlock.read(_big_store.getBlocks(), buffer, offset);
245         }
246     }
247
248     /**
249      * Get the DocumentProperty
250      *
251      * @return the instance's DocumentProperty
252      */

253
254     DocumentProperty getDocumentProperty()
255     {
256         return _property;
257     }
258
259     /* ********** START implementation of BlockWritable ********** */
260
261     /**
262      * Write the storage to an OutputStream
263      *
264      * @param stream the OutputStream to which the stored data should
265      * be written
266      *
267      * @exception IOException on problems writing to the specified
268      * stream
269      */

270
271     public void writeBlocks(final OutputStream stream)
272         throws IOException
273     {
274         _big_store.writeBlocks(stream);
275     }
276
277     /* ********** END implementation of BlockWritable ********** */
278     /* ********** START implementation of BATManaged ********** */
279
280     /**
281      * Return the number of BigBlock's this instance uses
282      *
283      * @return count of BigBlock instances
284      */

285
286     public int countBlocks()
287     {
288         return _big_store.countBlocks();
289     }
290
291     /**
292      * Set the start block for this instance
293      *
294      * @param index index into the array of blocks making up the
295      * filesystem
296      */

297
298     public void setStartBlock(final int index)
299     {
300         _property.setStartBlock(index);
301     }
302
303     /* ********** END implementation of BATManaged ********** */
304     /* ********** START begin implementation of POIFSViewable ********** */
305
306     /**
307      * Get an array of objects, some of which may implement
308      * POIFSViewable
309      *
310      * @return an array of Object; may not be null, but may be empty
311      */

312
313     public Object JavaDoc [] getViewableArray()
314     {
315         Object JavaDoc[] results = new Object JavaDoc[ 1 ];
316         String JavaDoc result;
317
318         try
319         {
320             ByteArrayOutputStream output = new ByteArrayOutputStream();
321             BlockWritable[] blocks = null;
322
323             if (_big_store.isValid())
324             {
325                 blocks = _big_store.getBlocks();
326             }
327             else if (_small_store.isValid())
328             {
329                 blocks = _small_store.getBlocks();
330             }
331             if (blocks != null)
332             {
333                 for (int k = 0; k < blocks.length; k++)
334                 {
335                     blocks[ k ].writeBlocks(output);
336                 }
337                 byte[] data = output.toByteArray();
338
339                 if (data.length > _property.getSize())
340                 {
341                     byte[] tmp = new byte[ _property.getSize() ];
342
343                     System.arraycopy(data, 0, tmp, 0, tmp.length);
344                     data = tmp;
345                 }
346                 output = new ByteArrayOutputStream();
347                 HexDump.dump(data, 0, output, 0);
348                 result = output.toString();
349             }
350             else
351             {
352                 result = "<NO DATA>";
353             }
354         }
355         catch (IOException e)
356         {
357             result = e.getMessage();
358         }
359         results[ 0 ] = result;
360         return results;
361     }
362
363     /**
364      * Get an Iterator of objects, some of which may implement
365      * POIFSViewable
366      *
367      * @return an Iterator; may not be null, but may have an empty
368      * back end store
369      */

370
371     public Iterator getViewableIterator()
372     {
373         return Collections.EMPTY_LIST.iterator();
374     }
375
376     /**
377      * Give viewers a hint as to whether to call getViewableArray or
378      * getViewableIterator
379      *
380      * @return true if a viewer should call getViewableArray, false if
381      * a viewer should call getViewableIterator
382      */

383
384     public boolean preferArray()
385     {
386         return true;
387     }
388
389     /**
390      * Provides a short description of the object, to be used when a
391      * POIFSViewable object has not provided its contents.
392      *
393      * @return short description
394      */

395
396     public String JavaDoc getShortDescription()
397     {
398         StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
399
400         buffer.append("Document: \"").append(_property.getName())
401             .append("\"");
402         buffer.append(" size = ").append(getSize());
403         return buffer.toString();
404     }
405
406     /* ********** END begin implementation of POIFSViewable ********** */
407     private class SmallBlockStore
408     {
409         private SmallDocumentBlock[] smallBlocks;
410         private POIFSDocumentPath path;
411         private String JavaDoc name;
412         private int size;
413         private POIFSWriterListener writer;
414
415         /**
416          * Constructor
417          *
418          * @param blocks blocks to construct the store from
419          */

420
421         SmallBlockStore(final Object JavaDoc [] blocks)
422         {
423             smallBlocks = new SmallDocumentBlock[ blocks.length ];
424             for (int j = 0; j < blocks.length; j++)
425             {
426                 smallBlocks[ j ] = ( SmallDocumentBlock ) blocks[ j ];
427             }
428             this.path = null;
429             this.name = null;
430             this.size = -1;
431             this.writer = null;
432         }
433
434         /**
435          * Constructor for a small block store that will be written
436          * later
437          *
438          * @param path path of the document
439          * @param name name of the document
440          * @param size length of the document
441          * @param writer the object that will eventually write the document
442          */

443
444         SmallBlockStore(final POIFSDocumentPath path, final String JavaDoc name,
445                         final int size, final POIFSWriterListener writer)
446         {
447             smallBlocks = new SmallDocumentBlock[ 0 ];
448             this.path = path;
449             this.name = name;
450             this.size = size;
451             this.writer = writer;
452         }
453
454         /**
455          * @return true if this store is a valid source of data
456          */

457
458         boolean isValid()
459         {
460             return ((smallBlocks.length > 0) || (writer != null));
461         }
462
463         /**
464          * @return the SmallDocumentBlocks
465          */

466
467         BlockWritable [] getBlocks()
468         {
469             if (isValid() && (writer != null))
470             {
471                 ByteArrayOutputStream stream =
472                     new ByteArrayOutputStream(size);
473                 DocumentOutputStream dstream =
474                     new DocumentOutputStream(stream, size);
475
476                 writer.processPOIFSWriterEvent(new POIFSWriterEvent(dstream,
477                         path, name, size));
478                 smallBlocks = SmallDocumentBlock.convert(stream.toByteArray(),
479                                                          size);
480             }
481             return smallBlocks;
482         }
483     } // end private class SmallBlockStore
484

485     private class BigBlockStore
486     {
487         private DocumentBlock[] bigBlocks;
488         private POIFSDocumentPath path;
489         private String JavaDoc name;
490         private int size;
491         private POIFSWriterListener writer;
492
493         /**
494          * Constructor
495          *
496          * @param blocks the blocks making up the store
497          *
498          * @exception IOException on I/O error
499          */

500
501         BigBlockStore(final Object JavaDoc [] blocks)
502             throws IOException
503         {
504             bigBlocks = new DocumentBlock[ blocks.length ];
505             for (int j = 0; j < blocks.length; j++)
506             {
507                 if (blocks[ j ] instanceof DocumentBlock)
508                 {
509                     bigBlocks[ j ] = ( DocumentBlock ) blocks[ j ];
510                 }
511                 else
512                 {
513                     bigBlocks[ j ] =
514                         new DocumentBlock(( RawDataBlock ) blocks[ j ]);
515                 }
516             }
517             this.path = null;
518             this.name = null;
519             this.size = -1;
520             this.writer = null;
521         }
522
523         /**
524          * Constructor for a big block store that will be written
525          * later
526          *
527          * @param path path of the document
528          * @param name name of the document
529          * @param size length of the document
530          * @param writer the object that will eventually write the
531          * document
532          */

533
534         BigBlockStore(final POIFSDocumentPath path, final String JavaDoc name,
535                       final int size, final POIFSWriterListener writer)
536         {
537             bigBlocks = new DocumentBlock[ 0 ];
538             this.path = path;
539             this.name = name;
540             this.size = size;
541             this.writer = writer;
542         }
543
544         /**
545          * @return true if this store is a valid source of data
546          */

547
548         boolean isValid()
549         {
550             return ((bigBlocks.length > 0) || (writer != null));
551         }
552
553         /**
554          * @return the DocumentBlocks
555          */

556
557         DocumentBlock [] getBlocks()
558         {
559             if (isValid() && (writer != null))
560             {
561                 ByteArrayOutputStream stream =
562                     new ByteArrayOutputStream(size);
563                 DocumentOutputStream dstream =
564                     new DocumentOutputStream(stream, size);
565
566                 writer.processPOIFSWriterEvent(new POIFSWriterEvent(dstream,
567                         path, name, size));
568                 bigBlocks = DocumentBlock.convert(stream.toByteArray(), size);
569             }
570             return bigBlocks;
571         }
572
573         /**
574          * write the blocks to a stream
575          *
576          * @param stream the stream to which the data is to be written
577          *
578          * @exception IOException on error
579          */

580
581         void writeBlocks(OutputStream stream)
582             throws IOException
583         {
584             if (isValid())
585             {
586                 if (writer != null)
587                 {
588                     DocumentOutputStream dstream =
589                         new DocumentOutputStream(stream, size);
590
591                     writer.processPOIFSWriterEvent(
592                         new POIFSWriterEvent(dstream, path, name, size));
593                     dstream.writeFiller(countBlocks()
594                                         * POIFSConstants
595                                             .BIG_BLOCK_SIZE, DocumentBlock
596                                             .getFillByte());
597                 }
598                 else
599                 {
600                     for (int k = 0; k < bigBlocks.length; k++)
601                     {
602                         bigBlocks[ k ].writeBlocks(stream);
603                     }
604                 }
605             }
606         }
607
608         /**
609          * @return number of big blocks making up this document
610          */

611
612         int countBlocks()
613         {
614             int rval = 0;
615
616             if (isValid())
617             {
618                 if (writer != null)
619                 {
620                     rval = (size + POIFSConstants.BIG_BLOCK_SIZE - 1)
621                            / POIFSConstants.BIG_BLOCK_SIZE;
622                 }
623                 else
624                 {
625                     rval = bigBlocks.length;
626                 }
627             }
628             return rval;
629         }
630     } // end private class BigBlockStore
631
} // end class POIFSDocument
632

633
Popular Tags