KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > pdfbox > cos > COSDocument


1 /**
2  * Copyright (c) 2003-2006, 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.cos;
32
33 import java.io.File JavaDoc;
34 import java.io.IOException JavaDoc;
35
36 import java.util.ArrayList JavaDoc;
37 import java.util.HashMap JavaDoc;
38 import java.util.Iterator JavaDoc;
39 import java.util.List JavaDoc;
40 import java.util.Map JavaDoc;
41
42
43 import org.pdfbox.exceptions.COSVisitorException;
44 import org.pdfbox.io.RandomAccess;
45 import org.pdfbox.io.RandomAccessFile;
46
47 import org.pdfbox.pdfparser.PDFObjectStreamParser;
48 import org.pdfbox.persistence.util.COSObjectKey;
49
50 /**
51  * This is the in-memory representation of the PDF document. You need to call
52  * close() on this object when you are done using it!!
53  *
54  * @author <a HREF="ben@benlitchfield.com">Ben Litchfield</a>
55  * @version $Revision: 1.28 $
56  */

57 public class COSDocument extends COSBase
58 {
59     private float version;
60     
61     /**
62      * added objects (actually preserving original sequence).
63      */

64     private List JavaDoc objects = new ArrayList JavaDoc();
65     
66     /**
67      * a pool of objects read/referenced so far
68      * used to resolve indirect object references.
69      */

70     private Map JavaDoc objectPool = new HashMap JavaDoc();
71
72     /**
73      * Document trailer dictionary.
74      */

75     private COSDictionary trailer;
76
77     /**
78      * This file will store the streams in order to conserve memory.
79      */

80     private RandomAccess scratchFile = null;
81     
82     private File JavaDoc tmpFile = null;
83     
84     private String JavaDoc headerString = "%PDF-1.4";
85
86     /**
87      * Constructor. Uses the java.io.tmpdir value to create a file
88      * to store the streams.
89      *
90      * @throws IOException If there is an error creating the tmp file.
91      */

92     public COSDocument() throws IOException JavaDoc
93     {
94         this( new File JavaDoc( System.getProperty( "java.io.tmpdir" ) ) );
95     }
96
97     /**
98      * Constructor that will create a create a scratch file in the
99      * following directory.
100      *
101      * @param scratchDir The directory to store a scratch file.
102      *
103      * @throws IOException If there is an error creating the tmp file.
104      */

105     public COSDocument( File JavaDoc scratchDir ) throws IOException JavaDoc
106     {
107         tmpFile = File.createTempFile( "pdfbox", "tmp", scratchDir );
108         scratchFile = new RandomAccessFile( tmpFile, "rw" );
109     }
110
111     /**
112      * Constructor that will use the following random access file for storage
113      * of the PDF streams. The client of this method is responsible for deleting
114      * the storage if necessary that this file will write to. The close method
115      * will close the file though.
116      *
117      * @param file The random access file to use for storage.
118      */

119     public COSDocument( RandomAccess file )
120     {
121         scratchFile = file;
122     }
123
124     /**
125      * This will get the scratch file for this document.
126      *
127      * @return The scratch file.
128      */

129     public RandomAccess getScratchFile()
130     {
131         return scratchFile;
132     }
133
134     /**
135      * This will get the first dictionary object by type.
136      *
137      * @param type The type of the object.
138      *
139      * @return This will return an object with the specified type.
140      */

141     public COSObject getObjectByType( String JavaDoc type )
142     {
143         return getObjectByType( COSName.getPDFName( type ) );
144     }
145     
146     /**
147      * This will get the first dictionary object by type.
148      *
149      * @param type The type of the object.
150      *
151      * @return This will return an object with the specified type.
152      */

153     public COSObject getObjectByType( COSName type )
154     {
155         COSObject retval = null;
156         Iterator JavaDoc iter = objects.iterator();
157         while( iter.hasNext() && retval == null)
158         {
159             COSObject object = (COSObject)iter.next();
160
161             COSBase realObject = object.getObject();
162             if( realObject instanceof COSDictionary )
163             {
164                 COSDictionary dic = (COSDictionary)realObject;
165                 COSName objectType = (COSName)dic.getItem( COSName.TYPE );
166                 if( objectType != null && objectType.equals( type ) )
167                 {
168                     retval = object;
169                 }
170             }
171         }
172         return retval;
173     }
174     
175     /**
176      * This will get all dictionary objects by type.
177      *
178      * @param type The type of the object.
179      *
180      * @return This will return an object with the specified type.
181      */

182     public List JavaDoc getObjectsByType( String JavaDoc type )
183     {
184         return getObjectsByType( COSName.getPDFName( type ) );
185     }
186     
187     /**
188      * This will get a dictionary object by type.
189      *
190      * @param type The type of the object.
191      *
192      * @return This will return an object with the specified type.
193      */

194     public List JavaDoc getObjectsByType( COSName type )
195     {
196         List JavaDoc retval = new ArrayList JavaDoc();
197         Iterator JavaDoc iter = objects.iterator();
198         while( iter.hasNext() )
199         {
200             COSObject object = (COSObject)iter.next();
201
202             COSBase realObject = object.getObject();
203             if( realObject instanceof COSDictionary )
204             {
205                 COSDictionary dic = (COSDictionary)realObject;
206                 COSName objectType = (COSName)dic.getItem( COSName.TYPE );
207                 if( objectType != null && objectType.equals( type ) )
208                 {
209                     retval.add( object );
210                 }
211             }
212         }
213         return retval;
214     }
215
216     /**
217      * This will print contents to stdout.
218      */

219     public void print()
220     {
221         Iterator JavaDoc iter = objects.iterator();
222         while( iter.hasNext() )
223         {
224             COSObject object = (COSObject)iter.next();
225             System.out.println( object);
226         }
227     }
228
229     /**
230      * This will set the version of this PDF document.
231      *
232      * @param versionValue The version of the PDF document.
233      */

234     public void setVersion( float versionValue )
235     {
236         version = versionValue;
237     }
238
239     /**
240      * This will get the version of this PDF document.
241      *
242      * @return This documents version.
243      */

244     public float getVersion()
245     {
246         return version;
247     }
248
249     /**
250      * This will tell if this is an encrypted document.
251      *
252      * @return true If this document is encrypted.
253      */

254     public boolean isEncrypted()
255     {
256         boolean encrypted = false;
257         if( trailer != null )
258         {
259             encrypted = trailer.getDictionaryObject( "Encrypt" ) != null;
260         }
261         return encrypted;
262     }
263
264     /**
265      * This will get the encryption dictionary if the document is encrypted or null
266      * if the document is not encrypted.
267      *
268      * @return The encryption dictionary.
269      */

270     public COSDictionary getEncryptionDictionary()
271     {
272         return (COSDictionary)trailer.getDictionaryObject( COSName.getPDFName( "Encrypt" ) );
273     }
274
275     /**
276      * This will set the encryption dictionary, this should only be called when
277      * encypting the document.
278      *
279      * @param encDictionary The encryption dictionary.
280      */

281     public void setEncryptionDictionary( COSDictionary encDictionary )
282     {
283         trailer.setItem( COSName.getPDFName( "Encrypt" ), encDictionary );
284     }
285
286     /**
287      * This will get the document ID.
288      *
289      * @return The document id.
290      */

291     public COSArray getDocumentID()
292     {
293         return (COSArray) getTrailer().getItem(COSName.getPDFName("ID"));
294     }
295
296     /**
297      * This will set the document ID.
298      *
299      * @param id The document id.
300      */

301     public void setDocumentID( COSArray id )
302     {
303         getTrailer().setItem(COSName.getPDFName("ID"), id);
304     }
305
306     /**
307      * This will create an object for this document.
308      *
309      * Create an indirect object out of the direct type and include in the document
310      * for later lookup via document a map from direct object to indirect object
311      * is maintained. this provides better support for manual PDF construction.
312      *
313      * @param base the base object to wrap in an indirect object.
314      *
315      * @return The pdf object that wraps the base, or creates a new one.
316      */

317     /**
318     public COSObject createObject( COSBase base )
319     {
320         COSObject obj = (COSObject)objectMap.get(base);
321         if (obj == null)
322         {
323             obj = new COSObject( base );
324             obj.addTo(this);
325         }
326         return obj;
327     }**/

328
329     /**
330      * This will get the document catalog.
331      *
332      * Maybe this should move to an object at PDFEdit level
333      *
334      * @return catalog is the root of all document activities
335      *
336      * @throws IOException If no catalog can be found.
337      */

338     public COSObject getCatalog() throws IOException JavaDoc
339     {
340         COSObject catalog = getObjectByType( COSName.CATALOG );
341         if( catalog == null )
342         {
343             throw new IOException JavaDoc( "Catalog cannot be found" );
344         }
345         return catalog;
346     }
347
348     /**
349      * This will get a list of all available objects.
350      *
351      * @return A list of all objects.
352      */

353     public List JavaDoc getObjects()
354     {
355         return new ArrayList JavaDoc(objects);
356     }
357
358     /**
359      * This will get the document trailer.
360      *
361      * @return the document trailer dict
362      */

363     public COSDictionary getTrailer()
364     {
365         return trailer;
366     }
367
368     /**
369      * // MIT added, maybe this should not be supported as trailer is a persistence construct.
370      * This will set the document trailer.
371      *
372      * @param newTrailer the document trailer dictionary
373      */

374     public void setTrailer(COSDictionary newTrailer)
375     {
376         trailer = newTrailer;
377     }
378
379     /**
380      * visitor pattern double dispatch method.
381      *
382      * @param visitor The object to notify when visiting this object.
383      * @return any object, depending on the visitor implementation, or null
384      * @throws COSVisitorException If an error occurs while visiting this object.
385      */

386     public Object JavaDoc accept(ICOSVisitor visitor) throws COSVisitorException
387     {
388         return visitor.visitFromDocument( this );
389     }
390
391     /**
392      * This will close all storage and delete the tmp files.
393      *
394      * @throws IOException If there is an error close resources.
395      */

396     public void close() throws IOException JavaDoc
397     {
398         if( scratchFile != null )
399         {
400             scratchFile.close();
401             scratchFile = null;
402         }
403         if( tmpFile != null )
404         {
405             tmpFile.delete();
406             tmpFile = null;
407         }
408     }
409
410     /**
411      * The sole purpose of this is to inform a client of PDFBox that they
412      * did not close the document.
413      */

414     protected void finalize()
415     {
416         if( tmpFile != null || scratchFile != null )
417         {
418             Throwable JavaDoc t = new Throwable JavaDoc( "Warning: You did not close the PDF Document" );
419             t.printStackTrace();
420         }
421     }
422     /**
423      * @return Returns the headerString.
424      */

425     public String JavaDoc getHeaderString()
426     {
427         return headerString;
428     }
429     /**
430      * @param header The headerString to set.
431      */

432     public void setHeaderString(String JavaDoc header)
433     {
434         headerString = header;
435     }
436     
437     /**
438      * This method will search the list of objects for types of ObjStm. If it finds
439      * them then it will parse out all of the objects from the stream that is contains.
440      *
441      * @throws IOException If there is an error parsing the stream.
442      */

443     public void dereferenceObjectStreams() throws IOException JavaDoc
444     {
445         Iterator JavaDoc objStm = getObjectsByType( "ObjStm" ).iterator();
446         while( objStm.hasNext() )
447         {
448             COSObject objStream = (COSObject)objStm.next();
449             COSStream stream = (COSStream)objStream.getObject();
450             PDFObjectStreamParser parser = new PDFObjectStreamParser( stream, this );
451             parser.parse();
452             Iterator JavaDoc compressedObjects = parser.getObjects().iterator();
453             while( compressedObjects.hasNext() )
454             {
455                 COSObject next = (COSObject)compressedObjects.next();
456                 COSObjectKey key = new COSObjectKey( next );
457                 COSObject obj = getObjectFromPool( key );
458                 obj.setObject( next.getObject() );
459             }
460         }
461     }
462     
463     /**
464      * This will add an object to this document.
465      * the method checks if obj is already present as there may be cyclic dependencies
466      *
467      * @param obj The object to add to the document.
468      * @return The object that was actually added to this document, if an object reference already
469      * existed then that will be returned.
470      *
471      * @throws IOException If there is an error adding the object.
472      */

473     public COSObject addObject(COSObject obj) throws IOException JavaDoc
474     {
475         COSObjectKey key = null;
476         if( obj.getObjectNumber() != null )
477         {
478             key = new COSObjectKey( obj );
479         }
480         COSObject fromPool = getObjectFromPool( key );
481         fromPool.setObject( obj.getObject() );
482         return fromPool;
483     }
484     
485     /**
486      * This will get an object from the pool.
487      *
488      * @param key The object key.
489      *
490      * @return The object in the pool or a new one if it has not been parsed yet.
491      *
492      * @throws IOException If there is an error getting the proxy object.
493      */

494     public COSObject getObjectFromPool(COSObjectKey key) throws IOException JavaDoc
495     {
496         COSObject obj = null;
497         if( key != null )
498         {
499             obj = (COSObject) objectPool.get(key);
500         }
501         if (obj == null)
502         {
503             // this was a forward reference, make "proxy" object
504
obj = new COSObject(null);
505             if( key != null )
506             {
507                 obj.setObjectNumber( new COSInteger( key.getNumber() ) );
508                 obj.setGenerationNumber( new COSInteger( key.getGeneration() ) );
509                 objectPool.put(key, obj);
510             }
511             objects.add( obj );
512         }
513         
514         return obj;
515     }
516 }
Popular Tags