KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > lowagie > text > pdf > PdfCopy


1 /*
2  * $Id: PdfCopy.java 2760 2007-05-16 11:33:16Z psoares33 $
3  * $Name$
4  *
5  * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
6  *
7  * The contents of this file are subject to the Mozilla Public License Version 1.1
8  * (the "License"); you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at http://www.mozilla.org/MPL/
10  *
11  * Software distributed under the License is distributed on an "AS IS" basis,
12  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13  * for the specific language governing rights and limitations under the License.
14  *
15  * The Original Code is 'iText, a free JAVA-PDF library'.
16  *
17  * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
18  * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
19  * All Rights Reserved.
20  * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
21  * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
22  *
23  * This module by Mark Thompson. Copyright (C) 2002 Mark Thompson
24  *
25  * Contributor(s): all the names of the contributors are added in the source code
26  * where applicable.
27  *
28  * Alternatively, the contents of this file may be used under the terms of the
29  * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
30  * provisions of LGPL are applicable instead of those above. If you wish to
31  * allow use of your version of this file only under the terms of the LGPL
32  * License and not to allow others to use your version of this file under
33  * the MPL, indicate your decision by deleting the provisions above and
34  * replace them with the notice and other provisions required by the LGPL.
35  * If you do not delete the provisions above, a recipient may use your version
36  * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
37  *
38  * This library is free software; you can redistribute it and/or modify it
39  * under the terms of the MPL as stated above or under the terms of the GNU
40  * Library General Public License as published by the Free Software Foundation;
41  * either version 2 of the License, or any later version.
42  *
43  * This library is distributed in the hope that it will be useful, but WITHOUT
44  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
45  * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
46  * details.
47  *
48  * If you didn't download this code from the following link, you should check if
49  * you aren't using an obsolete version:
50  * http://www.lowagie.com/iText/
51  */

52 package com.lowagie.text.pdf;
53
54 import java.io.IOException JavaDoc;
55 import java.io.OutputStream JavaDoc;
56 import java.util.HashMap JavaDoc;
57 import java.util.Iterator JavaDoc;
58 import java.util.List JavaDoc;
59
60 import com.lowagie.text.Document;
61 import com.lowagie.text.DocumentException;
62 import com.lowagie.text.ExceptionConverter;
63
64 /**
65  * Make copies of PDF documents. Documents can be edited after reading and
66  * before writing them out.
67  * @author Mark Thompson
68  */

69
70 public class PdfCopy extends PdfWriter {
71     /**
72      * This class holds information about indirect references, since they are
73      * renumbered by iText.
74      */

75     static class IndirectReferences {
76         PdfIndirectReference theRef;
77         boolean hasCopied;
78         IndirectReferences(PdfIndirectReference ref) {
79             theRef = ref;
80             hasCopied = false;
81         }
82         void setCopied() { hasCopied = true; }
83         boolean getCopied() { return hasCopied; }
84         PdfIndirectReference getRef() { return theRef; }
85     };
86     protected HashMap JavaDoc indirects;
87     protected HashMap JavaDoc indirectMap;
88     protected int currentObjectNum = 1;
89     protected PdfReader reader;
90     protected PdfIndirectReference acroForm;
91     protected List JavaDoc newBookmarks;
92     
93     /**
94      * A key to allow us to hash indirect references
95      */

96     protected static class RefKey {
97         int num;
98         int gen;
99         RefKey(int num, int gen) {
100             this.num = num;
101             this.gen = gen;
102         }
103         RefKey(PdfIndirectReference ref) {
104             num = ref.getNumber();
105             gen = ref.getGeneration();
106         }
107         RefKey(PRIndirectReference ref) {
108             num = ref.getNumber();
109             gen = ref.getGeneration();
110         }
111         public int hashCode() {
112             return (gen<<16)+num;
113         }
114         public boolean equals(Object JavaDoc o) {
115             if (!(o instanceof RefKey)) return false;
116             RefKey other = (RefKey)o;
117             return this.gen == other.gen && this.num == other.num;
118         }
119         public String JavaDoc toString() {
120             return Integer.toString(num) + ' ' + gen;
121         }
122     }
123     
124     /**
125      * Constructor
126      * @param document
127      * @param os outputstream
128      */

129     public PdfCopy(Document document, OutputStream JavaDoc os) throws DocumentException {
130         super(new PdfDocument(), os);
131         document.addDocListener(pdf);
132         pdf.addWriter(this);
133         indirectMap = new HashMap JavaDoc();
134     }
135     
136     public void open() {
137         super.open();
138     }
139
140     /**
141      * Grabs a page from the input document
142      * @param reader the reader of the document
143      * @param pageNumber which page to get
144      * @return the page
145      */

146     public PdfImportedPage getImportedPage(PdfReader reader, int pageNumber) {
147         if (currentPdfReaderInstance != null) {
148             if (currentPdfReaderInstance.getReader() != reader) {
149                 try {
150                     currentPdfReaderInstance.getReader().close();
151                     currentPdfReaderInstance.getReaderFile().close();
152                 }
153                 catch (IOException JavaDoc ioe) {
154                     // empty on purpose
155
}
156                 currentPdfReaderInstance = reader.getPdfReaderInstance(this);
157             }
158         }
159         else {
160             currentPdfReaderInstance = reader.getPdfReaderInstance(this);
161         }
162         return currentPdfReaderInstance.getImportedPage(pageNumber);
163     }
164     
165     
166     /**
167      * Translate a PRIndirectReference to a PdfIndirectReference
168      * In addition, translates the object numbers, and copies the
169      * referenced object to the output file.
170      * NB: PRIndirectReferences (and PRIndirectObjects) really need to know what
171      * file they came from, because each file has its own namespace. The translation
172      * we do from their namespace to ours is *at best* heuristic, and guaranteed to
173      * fail under some circumstances.
174      */

175     protected PdfIndirectReference copyIndirect(PRIndirectReference in) throws IOException JavaDoc, BadPdfFormatException {
176         PdfIndirectReference theRef;
177         RefKey key = new RefKey(in);
178         IndirectReferences iRef = (IndirectReferences)indirects.get(key);
179         if (iRef != null) {
180             theRef = iRef.getRef();
181             if (iRef.getCopied()) {
182                 return theRef;
183             }
184         }
185         else {
186             theRef = body.getPdfIndirectReference();
187             iRef = new IndirectReferences(theRef);
188             indirects.put(key, iRef);
189         }
190         PdfObject obj = PdfReader.getPdfObjectRelease(in);
191         if (obj != null && obj.isDictionary()) {
192             PdfName type = (PdfName)PdfReader.getPdfObjectRelease(((PdfDictionary)obj).get(PdfName.TYPE));
193             if (type != null && PdfName.PAGE.equals(type)) {
194                 return theRef;
195             }
196         }
197         iRef.setCopied();
198         obj = copyObject(obj);
199         addToBody(obj, theRef);
200         return theRef;
201     }
202     
203     /**
204      * Translate a PRDictionary to a PdfDictionary. Also translate all of the
205      * objects contained in it.
206      */

207     protected PdfDictionary copyDictionary(PdfDictionary in)
208     throws IOException JavaDoc, BadPdfFormatException {
209         PdfDictionary out = new PdfDictionary();
210         PdfName type = (PdfName)PdfReader.getPdfObjectRelease(in.get(PdfName.TYPE));
211         
212         for (Iterator JavaDoc it = in.getKeys().iterator(); it.hasNext();) {
213             PdfName key = (PdfName)it.next();
214             PdfObject value = in.get(key);
215             // System.out.println("Copy " + key);
216
if (type != null && PdfName.PAGE.equals(type)) {
217                 if (!key.equals(PdfName.B) && !key.equals(PdfName.PARENT))
218                     out.put(key, copyObject(value));
219             }
220             else
221                 out.put(key, copyObject(value));
222         }
223         return out;
224     }
225     
226     /**
227      * Translate a PRStream to a PdfStream. The data part copies itself.
228      */

229     protected PdfStream copyStream(PRStream in) throws IOException JavaDoc, BadPdfFormatException {
230         PRStream out = new PRStream(in, null);
231         
232         for (Iterator JavaDoc it = in.getKeys().iterator(); it.hasNext();) {
233             PdfName key = (PdfName) it.next();
234             PdfObject value = in.get(key);
235             out.put(key, copyObject(value));
236         }
237         
238         return out;
239     }
240     
241     
242     /**
243      * Translate a PRArray to a PdfArray. Also translate all of the objects contained
244      * in it
245      */

246     protected PdfArray copyArray(PdfArray in) throws IOException JavaDoc, BadPdfFormatException {
247         PdfArray out = new PdfArray();
248         
249         for (Iterator JavaDoc i = in.getArrayList().iterator(); i.hasNext();) {
250             PdfObject value = (PdfObject)i.next();
251             out.add(copyObject(value));
252         }
253         return out;
254     }
255     
256     /**
257      * Translate a PR-object to a Pdf-object
258      */

259     protected PdfObject copyObject(PdfObject in) throws IOException JavaDoc,BadPdfFormatException {
260         if (in == null)
261             return PdfNull.PDFNULL;
262         switch (in.type) {
263             case PdfObject.DICTIONARY:
264                 // System.out.println("Dictionary: " + in.toString());
265
return copyDictionary((PdfDictionary)in);
266             case PdfObject.INDIRECT:
267                 return copyIndirect((PRIndirectReference)in);
268             case PdfObject.ARRAY:
269                 return copyArray((PdfArray)in);
270             case PdfObject.NUMBER:
271             case PdfObject.NAME:
272             case PdfObject.STRING:
273             case PdfObject.NULL:
274             case PdfObject.BOOLEAN:
275                 return in;
276             case PdfObject.STREAM:
277                 return copyStream((PRStream)in);
278                 // return in;
279
default:
280                 if (in.type < 0) {
281                     String JavaDoc lit = ((PdfLiteral)in).toString();
282                     if (lit.equals("true") || lit.equals("false")) {
283                         return new PdfBoolean(lit);
284                     }
285                     return new PdfLiteral(lit);
286                 }
287                 System.out.println("CANNOT COPY type " + in.type);
288                 return null;
289         }
290     }
291     
292     /**
293      * convenience method. Given an importedpage, set our "globals"
294      */

295     protected int setFromIPage(PdfImportedPage iPage) {
296         int pageNum = iPage.getPageNumber();
297         PdfReaderInstance inst = currentPdfReaderInstance = iPage.getPdfReaderInstance();
298         reader = inst.getReader();
299         setFromReader(reader);
300         return pageNum;
301     }
302     
303     /**
304      * convenience method. Given a reader, set our "globals"
305      */

306     protected void setFromReader(PdfReader reader) {
307         this.reader = reader;
308         indirects = (HashMap JavaDoc)indirectMap.get(reader);
309         if (indirects == null) {
310             indirects = new HashMap JavaDoc();
311             indirectMap.put(reader,indirects);
312             PdfDictionary catalog = reader.getCatalog();
313             PRIndirectReference ref = null;
314             PdfObject o = catalog.get(PdfName.ACROFORM);
315             if (o == null || o.type() != PdfObject.INDIRECT)
316                 return;
317             ref = (PRIndirectReference)o;
318             if (acroForm == null) acroForm = body.getPdfIndirectReference();
319             indirects.put(new RefKey(ref), new IndirectReferences(acroForm));
320         }
321     }
322     /**
323      * Add an imported page to our output
324      * @param iPage an imported page
325      * @throws IOException, BadPdfFormatException
326      */

327     public void addPage(PdfImportedPage iPage) throws IOException JavaDoc, BadPdfFormatException {
328         int pageNum = setFromIPage(iPage);
329         
330         PdfDictionary thePage = reader.getPageN(pageNum);
331         PRIndirectReference origRef = reader.getPageOrigRef(pageNum);
332         reader.releasePage(pageNum);
333         RefKey key = new RefKey(origRef);
334         PdfIndirectReference pageRef;
335         IndirectReferences iRef = (IndirectReferences)indirects.get(key);
336         if (iRef != null && !iRef.getCopied()) {
337             pageReferences.add(iRef.getRef());
338             iRef.setCopied();
339         }
340         pageRef = getCurrentPage();
341         if (iRef == null) {
342             iRef = new IndirectReferences(pageRef);
343             indirects.put(key, iRef);
344         }
345         iRef.setCopied();
346         PdfDictionary newPage = copyDictionary(thePage);
347         root.addPage(newPage);
348         ++currentPageNumber;
349     }
350     
351     /**
352      * Copy the acroform for an input document. Note that you can only have one,
353      * we make no effort to merge them.
354      * @param reader The reader of the input file that is being copied
355      * @throws IOException, BadPdfFormatException
356      */

357     public void copyAcroForm(PdfReader reader) throws IOException JavaDoc, BadPdfFormatException {
358         setFromReader(reader);
359         
360         PdfDictionary catalog = reader.getCatalog();
361         PRIndirectReference hisRef = null;
362         PdfObject o = catalog.get(PdfName.ACROFORM);
363         if (o != null && o.type() == PdfObject.INDIRECT)
364             hisRef = (PRIndirectReference)o;
365         if (hisRef == null) return; // bugfix by John Englar
366
RefKey key = new RefKey(hisRef);
367         PdfIndirectReference myRef;
368         IndirectReferences iRef = (IndirectReferences)indirects.get(key);
369         if (iRef != null) {
370             acroForm = myRef = iRef.getRef();
371         }
372         else {
373             acroForm = myRef = body.getPdfIndirectReference();
374             iRef = new IndirectReferences(myRef);
375             indirects.put(key, iRef);
376         }
377         if (! iRef.getCopied()) {
378             iRef.setCopied();
379             PdfDictionary theForm = copyDictionary((PdfDictionary)PdfReader.getPdfObject(hisRef));
380             addToBody(theForm, myRef);
381         }
382     }
383     
384     /*
385      * the getCatalog method is part of PdfWriter.
386      * we wrap this so that we can extend it
387      */

388     protected PdfDictionary getCatalog(PdfIndirectReference rootObj) {
389         try {
390             PdfDictionary theCat = pdf.getCatalog(rootObj);
391             if (acroForm != null) theCat.put(PdfName.ACROFORM, acroForm);
392             if (newBookmarks == null || newBookmarks.isEmpty())
393                 return theCat;
394             PdfDictionary top = new PdfDictionary();
395             PdfIndirectReference topRef = getPdfIndirectReference();
396             Object JavaDoc kids[] = SimpleBookmark.iterateOutlines(this, topRef, newBookmarks, false);
397             top.put(PdfName.FIRST, (PdfIndirectReference)kids[0]);
398             top.put(PdfName.LAST, (PdfIndirectReference)kids[1]);
399             top.put(PdfName.COUNT, new PdfNumber(((Integer JavaDoc)kids[2]).intValue()));
400             addToBody(top, topRef);
401             theCat.put(PdfName.OUTLINES, topRef);
402             return theCat;
403         }
404         catch (IOException JavaDoc e) {
405             throw new ExceptionConverter(e);
406         }
407     }
408     
409     /**
410      * Sets the bookmarks. The list structure is defined in
411      * <CODE>SimpleBookmark#</CODE>.
412      * @param outlines the bookmarks or <CODE>null</CODE> to remove any
413      */

414     public void setOutlines(List JavaDoc outlines) {
415         newBookmarks = outlines;
416     }
417
418     /**
419      * Signals that the <CODE>Document</CODE> was closed and that no other
420      * <CODE>Elements</CODE> will be added.
421      * <P>
422      * The pages-tree is built and written to the outputstream.
423      * A Catalog is constructed, as well as an Info-object,
424      * the referencetable is composed and everything is written
425      * to the outputstream embedded in a Trailer.
426      */

427     
428     public synchronized void close() {
429         if (open) {
430             PdfReaderInstance ri = currentPdfReaderInstance;
431             pdf.close();
432             super.close();
433             if (ri != null) {
434                 try {
435                     ri.getReader().close();
436                     ri.getReaderFile().close();
437                 }
438                 catch (IOException JavaDoc ioe) {
439                     // empty on purpose
440
}
441             }
442         }
443     }
444     PdfIndirectReference add(PdfImage pdfImage, PdfIndirectReference fixedRef) throws PdfException { return null; }
445     public PdfIndirectReference add(PdfOutline outline) { return null; }
446     public void addAnnotation(PdfAnnotation annot) { }
447     PdfIndirectReference add(PdfPage page, PdfContents contents) throws PdfException { return null; }
448
449     public void freeReader(PdfReader reader) throws IOException JavaDoc {
450         indirectMap.remove(reader);
451         if (currentPdfReaderInstance != null) {
452             if (currentPdfReaderInstance.getReader() == reader) {
453                 try {
454                     currentPdfReaderInstance.getReader().close();
455                     currentPdfReaderInstance.getReaderFile().close();
456                 }
457                 catch (IOException JavaDoc ioe) {
458                     // empty on purpose
459
}
460                 currentPdfReaderInstance = null;
461             }
462         }
463     }
464 }
Popular Tags