KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > pdfbox > pdmodel > common > PDStream


1 /**
2  * Copyright (c) 2004-2005, www.pdfbox.org
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice,
9  * this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright notice,
11  * this list of conditions and the following disclaimer in the documentation
12  * and/or other materials provided with the distribution.
13  * 3. Neither the name of pdfbox; nor the names of its
14  * contributors may be used to endorse or promote products derived from this
15  * software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
24  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  *
28  * http://www.pdfbox.org
29  *
30  */

31 package org.pdfbox.pdmodel.common;
32
33 import java.io.ByteArrayInputStream JavaDoc;
34 import java.io.ByteArrayOutputStream JavaDoc;
35 import java.io.IOException JavaDoc;
36 import java.io.InputStream JavaDoc;
37 import java.io.OutputStream JavaDoc;
38
39 import java.util.ArrayList JavaDoc;
40 import java.util.Iterator JavaDoc;
41 import java.util.List JavaDoc;
42 import java.util.Map JavaDoc;
43
44 import org.pdfbox.cos.COSArray;
45 import org.pdfbox.cos.COSBase;
46 import org.pdfbox.cos.COSDictionary;
47 import org.pdfbox.cos.COSName;
48 import org.pdfbox.cos.COSStream;
49
50 import org.pdfbox.filter.Filter;
51 import org.pdfbox.filter.FilterManager;
52
53 import org.pdfbox.pdmodel.PDDocument;
54
55 import org.pdfbox.pdmodel.common.filespecification.PDFileSpecification;
56
57 /**
58  * A PDStream represents a stream in a PDF document. Streams are tied to a single
59  * PDF document.
60  *
61  * @author <a HREF="mailto:ben@benlitchfield.com">Ben Litchfield</a>
62  * @version $Revision: 1.16 $
63  */

64 public class PDStream implements COSObjectable
65 {
66     private COSStream stream;
67     
68     /**
69      * This will create a new PDStream object.
70      */

71     protected PDStream()
72     {
73         //should only be called by PDMemoryStream
74
}
75     
76     /**
77      * This will create a new PDStream object.
78      *
79      * @param document The document that the stream will be part of.
80      */

81     public PDStream( PDDocument document )
82     {
83         stream = new COSStream( document.getDocument().getScratchFile() );
84     }
85     
86     /**
87      * Constructor.
88      *
89      * @param str The stream parameter.
90      */

91     public PDStream( COSStream str )
92     {
93         stream = str;
94     }
95     
96     /**
97      * Constructor. Reads all data from the input stream and embeds it into the
98      * document, this will close the InputStream.
99      *
100      * @param doc The document that will hold the stream.
101      * @param str The stream parameter.
102      * @throws IOException If there is an error creating the stream in the document.
103      */

104     public PDStream( PDDocument doc, InputStream JavaDoc str ) throws IOException JavaDoc
105     {
106         this( doc, str, false );
107     }
108     
109     /**
110      * Constructor. Reads all data from the input stream and embeds it into the
111      * document, this will close the InputStream.
112      *
113      * @param doc The document that will hold the stream.
114      * @param str The stream parameter.
115      * @param filtered True if the stream already has a filter applied.
116      * @throws IOException If there is an error creating the stream in the document.
117      */

118     public PDStream( PDDocument doc, InputStream JavaDoc str, boolean filtered ) throws IOException JavaDoc
119     {
120         OutputStream JavaDoc output = null;
121         try
122         {
123             stream = new COSStream( doc.getDocument().getScratchFile() );
124             if( filtered )
125             {
126                 output = stream.createFilteredStream();
127             }
128             else
129             {
130                 output = stream.createUnfilteredStream();
131             }
132             byte[] buffer = new byte[ 1024 ];
133             int amountRead = -1;
134             while( (amountRead = str.read(buffer)) != -1 )
135             {
136                 output.write( buffer, 0, amountRead );
137             }
138         }
139         finally
140         {
141             if( output != null )
142             {
143                 output.close();
144             }
145             if( str != null )
146             {
147                 str.close();
148             }
149         }
150     }
151     
152     /**
153      * If there are not compression filters on the current stream then this
154      * will add a compression filter, flate compression for example.
155      */

156     public void addCompression()
157     {
158         List JavaDoc filters = getFilters();
159         if( filters == null )
160         {
161             filters = new ArrayList JavaDoc();
162             filters.add( COSName.FLATE_DECODE );
163             setFilters( filters );
164         }
165     }
166     
167     /**
168      * Create a pd stream from either a regular COSStream on a COSArray of cos streams.
169      * @param base Either a COSStream or COSArray.
170      * @return A PDStream or null if base is null.
171      * @throws IOException If there is an error creating the PDStream.
172      */

173     public static PDStream createFromCOS( COSBase base ) throws IOException JavaDoc
174     {
175         PDStream retval = null;
176         if( base instanceof COSStream )
177         {
178             retval = new PDStream( (COSStream)base );
179         }
180         else if( base instanceof COSArray )
181         {
182             retval = new PDStream( new COSStreamArray( (COSArray)base ) );
183         }
184         else
185         {
186             if( base != null )
187             {
188                 throw new IOException JavaDoc( "Contents are unknown type:" + base.getClass().getName() );
189             }
190         }
191         return retval;
192     }
193
194
195     /**
196      * Convert this standard java object to a COS object.
197      *
198      * @return The cos object that matches this Java object.
199      */

200     public COSBase getCOSObject()
201     {
202         return stream;
203     }
204     
205     /**
206      * This will get a stream that can be written to.
207      *
208      * @return An output stream to write data to.
209      *
210      * @throws IOException If an IO error occurs during writing.
211      */

212     public OutputStream JavaDoc createOutputStream() throws IOException JavaDoc
213     {
214         return stream.createUnfilteredStream();
215     }
216     
217     /**
218      * This will get a stream that can be read from.
219      *
220      * @return An input stream that can be read from.
221      *
222      * @throws IOException If an IO error occurs during reading.
223      */

224     public InputStream JavaDoc createInputStream() throws IOException JavaDoc
225     {
226         return stream.getUnfilteredStream();
227     }
228     
229     /**
230      * This will get a stream with some filters applied but not others. This is useful
231      * when doing images, ie filters = [flate,dct], we want to remove flate but leave dct
232      *
233      * @param stopFilters A list of filters to stop decoding at.
234      * @return A stream with decoded data.
235      * @throws IOException If there is an error processing the stream.
236      */

237     public InputStream JavaDoc getPartiallyFilteredStream( List JavaDoc stopFilters ) throws IOException JavaDoc
238     {
239         FilterManager manager = stream.getFilterManager();
240         InputStream JavaDoc is = stream.getFilteredStream();
241         ByteArrayOutputStream JavaDoc os = new ByteArrayOutputStream JavaDoc();
242         List JavaDoc filters = getFilters();
243         Iterator JavaDoc iter = filters.iterator();
244         String JavaDoc nextFilter = null;
245         boolean done = false;
246         while( iter.hasNext() && !done )
247         {
248             os.reset();
249             nextFilter = (String JavaDoc)iter.next();
250             if( stopFilters.contains( nextFilter ) )
251             {
252                 done = true;
253             }
254             else
255             {
256                 Filter filter = manager.getFilter( COSName.getPDFName(nextFilter) );
257                 filter.decode( is, os, stream );
258                 is = new ByteArrayInputStream JavaDoc( os.toByteArray() );
259             }
260         }
261         return is;
262     }
263     
264     /**
265      * Get the cos stream associated with this object.
266      *
267      * @return The cos object that matches this Java object.
268      */

269     public COSStream getStream()
270     {
271         return stream;
272     }
273     
274     /**
275      * This will get the length of the filtered/compressed stream. This is readonly in the
276      * PD Model and will be managed by this class.
277      *
278      * @return The length of the filtered stream.
279      */

280     public int getLength()
281     {
282         return stream.getInt( "Length", 0 );
283     }
284     
285     /**
286      * This will get the list of filters that are associated with this stream. Or
287      * null if there are none.
288      * @return A list of all encoding filters to apply to this stream.
289      */

290     public List JavaDoc getFilters()
291     {
292         List JavaDoc retval = null;
293         COSBase filters = stream.getFilters();
294         if( filters instanceof COSName )
295         {
296             COSName name = (COSName)filters;
297             retval = new COSArrayList( name.getName(), name, stream, "Filter" );
298         }
299         else if( filters instanceof COSArray )
300         {
301             retval = COSArrayList.convertCOSNameCOSArrayToList( (COSArray)filters );
302         }
303         return retval;
304     }
305     
306     /**
307      * This will set the filters that are part of this stream.
308      *
309      * @param filters The filters that are part of this stream.
310      */

311     public void setFilters( List JavaDoc filters )
312     {
313         COSBase obj = COSArrayList.convertStringListToCOSNameCOSArray( filters );
314         stream.setItem( "Filter", obj );
315     }
316     
317     /**
318      * Get the list of decode parameters. Each entry in the list will refer to
319      * an entry in the filters list.
320      *
321      * @return The list of decode parameters.
322      *
323      * @throws IOException if there is an error retrieving the parameters.
324      */

325     public List JavaDoc getDecodeParams() throws IOException JavaDoc
326     {
327         List JavaDoc retval = null;
328         
329         COSBase dp = stream.getDictionaryObject( "DecodeParms" );
330         if( dp == null )
331         {
332             //See PDF Ref 1.5 implementation note 7, the DP is sometimes used instead.
333
dp = stream.getDictionaryObject( "DP" );
334         }
335         if( dp instanceof COSDictionary )
336         {
337             Map JavaDoc map = COSDictionaryMap.convertBasicTypesToMap( (COSDictionary)dp );
338             retval = new COSArrayList(map, dp, stream, "DecodeParams" );
339         }
340         else if( dp instanceof COSArray )
341         {
342             COSArray array = (COSArray)dp;
343             List JavaDoc actuals = new ArrayList JavaDoc();
344             for( int i=0; i<array.size(); i++ )
345             {
346                 actuals.add(
347                     COSDictionaryMap.convertBasicTypesToMap(
348                         (COSDictionary)array.getObject( i ) ) );
349             }
350             retval = new COSArrayList(actuals, array);
351         }
352         
353         return retval;
354     }
355     
356     /**
357      * This will set the list of decode params.
358      *
359      * @param decodeParams The list of decode params.
360      */

361     public void setDecodeParams( List JavaDoc decodeParams )
362     {
363         stream.setItem(
364             "DecodeParams", COSArrayList.converterToCOSArray( decodeParams ) );
365     }
366     
367     /**
368      * This will get the file specification for this stream. This is only
369      * required for external files.
370      *
371      * @return The file specification.
372      *
373      * @throws IOException If there is an error creating the file spec.
374      */

375     public PDFileSpecification getFile() throws IOException JavaDoc
376     {
377         COSBase f = stream.getDictionaryObject( "F" );
378         PDFileSpecification retval = PDFileSpecification.createFS( f );
379         return retval;
380     }
381     
382     /**
383      * Set the file specification.
384      * @param f The file specification.
385      */

386     public void setFile( PDFileSpecification f )
387     {
388         stream.setItem( "F", f );
389     }
390     
391     /**
392      * This will get the list of filters that are associated with this stream. Or
393      * null if there are none.
394      * @return A list of all encoding filters to apply to this stream.
395      */

396     public List JavaDoc getFileFilters()
397     {
398         List JavaDoc retval = null;
399         COSBase filters = stream.getDictionaryObject( "FFilter" );
400         if( filters instanceof COSName )
401         {
402             COSName name = (COSName)filters;
403             retval = new COSArrayList( name.getName(), name, stream, "FFilter" );
404         }
405         else if( filters instanceof COSArray )
406         {
407             retval = COSArrayList.convertCOSNameCOSArrayToList( (COSArray)filters );
408         }
409         return retval;
410     }
411     
412     /**
413      * This will set the filters that are part of this stream.
414      *
415      * @param filters The filters that are part of this stream.
416      */

417     public void setFileFilters( List JavaDoc filters )
418     {
419         COSBase obj = COSArrayList.convertStringListToCOSNameCOSArray( filters );
420         stream.setItem( "FFilter", obj );
421     }
422     
423     /**
424      * Get the list of decode parameters. Each entry in the list will refer to
425      * an entry in the filters list.
426      *
427      * @return The list of decode parameters.
428      *
429      * @throws IOException if there is an error retrieving the parameters.
430      */

431     public List JavaDoc getFileDecodeParams() throws IOException JavaDoc
432     {
433         List JavaDoc retval = null;
434         
435         COSBase dp = stream.getDictionaryObject( "FDecodeParms" );
436         if( dp instanceof COSDictionary )
437         {
438             Map JavaDoc map = COSDictionaryMap.convertBasicTypesToMap( (COSDictionary)dp );
439             retval = new COSArrayList(map, dp, stream, "FDecodeParams" );
440         }
441         else if( dp instanceof COSArray )
442         {
443             COSArray array = (COSArray)dp;
444             List JavaDoc actuals = new ArrayList JavaDoc();
445             for( int i=0; i<array.size(); i++ )
446             {
447                 actuals.add(
448                     COSDictionaryMap.convertBasicTypesToMap(
449                         (COSDictionary)array.getObject( i ) ) );
450             }
451             retval = new COSArrayList(actuals, array);
452         }
453         
454         return retval;
455     }
456     
457     /**
458      * This will set the list of decode params.
459      *
460      * @param decodeParams The list of decode params.
461      */

462     public void setFileDecodeParams( List JavaDoc decodeParams )
463     {
464         stream.setItem(
465             "FDecodeParams", COSArrayList.converterToCOSArray( decodeParams ) );
466     }
467     
468     /**
469      * This will copy the stream into a byte array.
470      *
471      * @return The byte array of the filteredStream
472      * @throws IOException When getFilteredStream did not work
473      */

474     public byte[] getByteArray() throws IOException JavaDoc
475     {
476         ByteArrayOutputStream JavaDoc output = new ByteArrayOutputStream JavaDoc();
477         byte[] buf = new byte[1024];
478         InputStream JavaDoc is = null;
479         try
480         {
481             is = createInputStream();
482             int amountRead = -1;
483             while( (amountRead = is.read( buf )) != -1)
484             {
485                 output.write( buf, 0, amountRead );
486             }
487         }
488         finally
489         {
490             if( is != null )
491             {
492                 is.close();
493             }
494         }
495         return output.toByteArray();
496     }
497     
498     /**
499      * A convenience method to get this stream as a string. Uses
500      * the default system encoding.
501      *
502      * @return a String representation of this (input) stream, with the
503      * platform default encoding.
504      *
505      * @throws IOException if there is an error while converting the stream
506      * to a string.
507      */

508     public String JavaDoc getInputStreamAsString() throws IOException JavaDoc
509     {
510         byte[] bStream = getByteArray();
511         return new String JavaDoc(bStream);
512     }
513     
514     /**
515      * Get the metadata that is part of the document catalog. This will
516      * return null if there is no meta data for this object.
517      *
518      * @return The metadata for this object.
519      */

520     public PDMetadata getMetadata()
521     {
522         PDMetadata retval = null;
523         COSStream mdStream = (COSStream)stream.getDictionaryObject( "Metadata" );
524         if( mdStream != null )
525         {
526             retval = new PDMetadata( mdStream );
527         }
528         return retval;
529     }
530     
531     /**
532      * Set the metadata for this object. This can be null.
533      *
534      * @param meta The meta data for this object.
535      */

536     public void setMetadata( PDMetadata meta )
537     {
538         stream.setItem( "Metadata", meta );
539     }
540 }
Popular Tags