001: /*
002: * Copyright (c) 2007, intarsys consulting GmbH
003: *
004: * Redistribution and use in source and binary forms, with or without
005: * modification, are permitted provided that the following conditions are met:
006: *
007: * - Redistributions of source code must retain the above copyright notice,
008: * this list of conditions and the following disclaimer.
009: *
010: * - Redistributions in binary form must reproduce the above copyright notice,
011: * this list of conditions and the following disclaimer in the documentation
012: * and/or other materials provided with the distribution.
013: *
014: * - Neither the name of intarsys nor the names of its contributors may be used
015: * to endorse or promote products derived from this software without specific
016: * prior written permission.
017: *
018: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
019: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
020: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
021: * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
022: * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
023: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
024: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
025: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
026: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
027: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
028: * POSSIBILITY OF SUCH DAMAGE.
029: */
030: package de.intarsys.pdf.pd;
031:
032: import java.io.IOException;
033: import java.util.ArrayList;
034: import java.util.HashMap;
035: import java.util.HashSet;
036: import java.util.Iterator;
037: import java.util.List;
038: import java.util.Map;
039: import java.util.Set;
040:
041: import de.intarsys.pdf.cds.CDSDate;
042: import de.intarsys.pdf.cds.CDSNameTreeNode;
043: import de.intarsys.pdf.cos.COSArray;
044: import de.intarsys.pdf.cos.COSBasedObject;
045: import de.intarsys.pdf.cos.COSCatalog;
046: import de.intarsys.pdf.cos.COSDictionary;
047: import de.intarsys.pdf.cos.COSDocument;
048: import de.intarsys.pdf.cos.COSInfoDict;
049: import de.intarsys.pdf.cos.COSName;
050: import de.intarsys.pdf.cos.COSObject;
051: import de.intarsys.pdf.cos.COSRuntimeException;
052: import de.intarsys.pdf.cos.COSStream;
053: import de.intarsys.pdf.cos.COSString;
054: import de.intarsys.pdf.crypt.IAccessPermissions;
055: import de.intarsys.pdf.crypt.ISystemSecurityHandler;
056: import de.intarsys.pdf.parser.COSLoadError;
057: import de.intarsys.pdf.parser.COSLoadException;
058: import de.intarsys.pdf.st.EnumWriteMode;
059: import de.intarsys.pdf.st.STDocument;
060: import de.intarsys.tools.attribute.IAttributeSupport;
061: import de.intarsys.tools.locator.ILocator;
062: import de.intarsys.tools.locator.ILocatorSupport;
063:
064: /**
065: * The PD Level representation of a PDF Document. PD Level objects provide the
066: * PDF semantics on top of the COS objects.
067: *
068: * <p>
069: * A PDDocument object should not be shared between threads without thought.
070: * Some clients may store information along with the PDDocument extensions in a
071: * non thread safe manner.
072: * </p>
073: *
074: */
075: public class PDDocument implements IAdditionalActionSupport,
076: IAttributeSupport, ILocatorSupport {
077: // supported additional action triggers
078: public static final Set CATALOG_ACTION_TRIGGERS;
079:
080: public static final COSName DK_OpenAction = COSName
081: .constant("OpenAction"); //$NON-NLS-1$
082:
083: public static final COSName DK_Perms = COSName.constant("Perms"); //$NON-NLS-1$
084:
085: public static final COSName CN_Perms_DocMDP = COSName
086: .constant("DocMDP"); //$NON-NLS-1$
087:
088: public static final COSName CN_Perms_UR = COSName.constant("UR"); //$NON-NLS-1$
089:
090: static {
091: CATALOG_ACTION_TRIGGERS = new HashSet(6);
092: CATALOG_ACTION_TRIGGERS.add("DC"); //$NON-NLS-1$
093: CATALOG_ACTION_TRIGGERS.add("WS"); //$NON-NLS-1$
094: CATALOG_ACTION_TRIGGERS.add("DS"); //$NON-NLS-1$
095: CATALOG_ACTION_TRIGGERS.add("WP"); //$NON-NLS-1$
096: CATALOG_ACTION_TRIGGERS.add("DP"); //$NON-NLS-1$
097: }
098:
099: /**
100: * create a pd document based on a cos level object
101: *
102: * @param doc
103: * COSDocument to base this PDDocument on
104: *
105: * @return A new PDDocument object.
106: * @throws COSLoadException
107: */
108: public static PDDocument createFromCos(COSDocument doc)
109: throws COSLoadException {
110: PDDocument result = (PDDocument) doc
111: .getAttribute(PDDocument.class);
112: if (result == null) {
113: result = new PDDocument(doc);
114: result.initializeFromCos();
115: result.checkConsistency();
116: doc.setAttribute(PDDocument.class, result);
117: }
118: return result;
119: }
120:
121: public static PDDocument createFromLocator(ILocator locator)
122: throws IOException, COSLoadException {
123: return createFromCos(COSDocument.createFromLocator(locator));
124: }
125:
126: /**
127: * create a PDDocument from scratch
128: *
129: * @return A new PDDocument.
130: */
131: public static PDDocument createNew() {
132: PDDocument result = new PDDocument();
133: result.initializeFromScratch();
134: result.setAttribute(PDDocument.class, result);
135: return result;
136: }
137:
138: // some low level cos representations
139: // the underlying COSDocument object
140: private COSDocument cosDoc;
141:
142: protected PDDocument() {
143: this (COSDocument.createNew());
144: }
145:
146: /**
147: * PDDocument constructor.
148: *
149: * @param newDoc
150: * The COS document representing the receiver.
151: */
152: protected PDDocument(COSDocument newDoc) {
153: super ();
154: cosDoc = newDoc;
155: }
156:
157: /*
158: * (non-Javadoc)
159: *
160: * @see de.intarsys.pdf.pd.IActionContainer#addAction(de.intarsys.pdf.pd.PDAction)
161: */
162: public void addAction(PDAction action) {
163: addOpenAction(action);
164: }
165:
166: /**
167: * Add a {@link PDAction} to be exceuted when this is opened.
168: *
169: * @param newAction
170: * The new {@link PDAction}
171: */
172: public void addOpenAction(PDAction newAction) {
173: if (newAction == null) {
174: return;
175: }
176: if (getOpenAction() != null) {
177: getOpenAction().addNext(newAction);
178: } else {
179: setOpenAction(newAction);
180: }
181: }
182:
183: /**
184: * Add a page object to this documents root page tree.
185: *
186: * @param newNode
187: * The page to be added
188: */
189: public void addPageNode(PDPageNode newNode) {
190: getPageTree().addNode(newNode);
191: }
192:
193: /**
194: * Add a page object to this document after the designated page.
195: *
196: * @param newNode
197: * the page to be added
198: * @param destination
199: * The page after the new one is inserted
200: */
201: public void addPageNodeAfter(PDPageNode newNode,
202: PDPageNode destination) {
203: if (destination == null) {
204: getPageTree().addNode(newNode);
205: } else {
206: destination.getParent().addNodeAfter(newNode, destination);
207: }
208: }
209:
210: protected void checkConsistency() throws COSLoadError {
211: if (getCatalog() == null) {
212: throw new COSLoadError("Catalog missing"); //$NON-NLS-1$
213: }
214: if (getPageTree() == null) {
215: throw new COSLoadError("Page tree missing"); //$NON-NLS-1$
216: }
217: }
218:
219: /**
220: * Close the document. Accessing a documents content is undefined after
221: * <code>close</code>.
222: *
223: * @throws IOException
224: */
225: public void close() throws IOException {
226: cosDoc.close();
227: }
228:
229: protected void collectAnnotations(List result) {
230: getPageTree().collectAnnotations(result);
231: }
232:
233: /**
234: * Make a deep copy of the receiver.
235: *
236: * @return the object copied recursively
237: */
238: public PDDocument copyDeep() {
239: try {
240: return PDDocument.createFromCos(cosGetDoc().copyDeep());
241: } catch (COSLoadException e) {
242: throw new COSRuntimeException(e);
243: }
244: }
245:
246: /**
247: * The COS level implementation of the document
248: *
249: * @return The underlying COSDocument
250: */
251: public COSDocument cosGetDoc() {
252: return cosDoc;
253: }
254:
255: /**
256: * The permissions dictionary of the document.
257: *
258: * @return The permissions dictionary of the document.
259: */
260: public COSDictionary cosGetPermissionsDict() {
261: COSCatalog catalog = getCatalog();
262: if (catalog == null) {
263: return null;
264: }
265: return catalog.cosGetField(DK_Perms).asDictionary();
266: }
267:
268: /**
269: * The piece info dictionary of the document.
270: *
271: * @return The piece info dictionary of the document.
272: */
273: public COSDictionary cosGetPieceInfoDict() {
274: COSCatalog catalog = getCatalog();
275: if (catalog == null) {
276: return null;
277: }
278: return catalog.cosGetField(COSCatalog.DK_PieceInfo)
279: .asDictionary();
280: }
281:
282: /**
283: * The uri dictionary of the document.
284: *
285: * @return The uri dictionary of the document.
286: */
287: public COSDictionary cosGetURI() {
288: COSCatalog catalog = getCatalog();
289: if (catalog == null) {
290: return null;
291: }
292: return catalog.cosGetField(COSCatalog.DK_URI).asDictionary();
293: }
294:
295: /**
296: * Set the permissions dictionary of the document.
297: *
298: * @param permsDict
299: * the new permission dictionary
300: */
301: public void cosSetPermissionsDict(COSDictionary permsDict) {
302: COSCatalog catalog = getCatalog();
303: if (catalog == null) {
304: return;
305: }
306: permsDict.beIndirect();
307: catalog.cosSetField(DK_Perms, permsDict);
308: }
309:
310: /**
311: * Set the piece info dictionary of the document.
312: *
313: * @param dict
314: * the new piece info dictionary
315: */
316: public void cosSetPieceInfoDict(COSDictionary dict) {
317: COSCatalog catalog = getCatalog();
318: if (catalog == null) {
319: return;
320: }
321: dict.beIndirect();
322: catalog.cosSetField(COSCatalog.DK_PieceInfo, dict);
323: }
324:
325: /**
326: * create an AcroForm in a PDF Document.
327: *
328: * @return the acro form just created
329: *
330: * @throws IllegalStateException
331: */
332: public PDAcroForm createAcroForm() {
333: if (getAcroForm() != null) {
334: throw new IllegalStateException(
335: "AcroForm already available"); //$NON-NLS-1$
336: }
337: PDAcroForm acroForm = (PDAcroForm) PDAcroForm.META.createNew();
338: PDResources formResources = (PDResources) PDResources.META
339: .createNew();
340: acroForm.setDefaultResources(formResources);
341: setAcroForm(acroForm);
342: return acroForm;
343: }
344:
345: /**
346: * create a new page tree for this document. tha page tree must still be
347: * added to the document or a page tree to get visible.
348: *
349: * @return the PDPageTree created
350: */
351: public PDPageTree createPageTree() {
352: PDPageTree result = (PDPageTree) PDPageTree.META.createNew();
353: return result;
354: }
355:
356: /**
357: * Simple delegate to COSDocument.getAccessPermissions()
358: *
359: * @return document access permissions
360: */
361: public IAccessPermissions getAccessPermissions() {
362: return cosGetDoc().getAccessPermissions();
363: }
364:
365: /**
366: * read an AcroForm from a PDF Document. return null if no AcroForm is
367: * available.
368: *
369: * @return the acro form of the document or null
370: */
371: public PDAcroForm getAcroForm() {
372: COSCatalog catalog = getCatalog();
373: if (catalog == null) {
374: return null;
375: }
376: return (PDAcroForm) PDAcroForm.META.createFromCos(catalog
377: .cosGetField(COSCatalog.DK_AcroForm));
378: }
379:
380: public PDAdditionalActions getAdditionalActions() {
381: COSDictionary aa = null;
382: COSCatalog catalog = getCatalog();
383: if (catalog != null) {
384: aa = catalog.cosGetField(DK_AA).asDictionary();
385: }
386: return (PDAdditionalActions) PDAdditionalActions.META
387: .createFromCos(aa);
388: }
389:
390: public List getAnnotations() {
391: List result = new ArrayList();
392: collectAnnotations(result);
393: return result;
394: }
395:
396: public PDApplicationData getApplicationData(String name) {
397: COSDictionary pid = cosGetPieceInfoDict();
398: if (pid == null) {
399: return null;
400: }
401: COSName cosName = COSName.create(name);
402: COSDictionary pi = pid.get(cosName).asDictionary();
403: if (pi == null) {
404: return null;
405: }
406: return (PDApplicationData) PDApplicationData.META
407: .createFromCos(pi);
408: }
409:
410: /*
411: * (non-Javadoc)
412: *
413: * @see de.intarsys.tools.component.IAttributeSupport#getAttribute(java.lang.Object)
414: */
415: public Object getAttribute(Object key) {
416: return cosDoc.getAttribute(key);
417: }
418:
419: public String getAuthor() {
420: return getDocumentInfoString(COSInfoDict.DK_Author);
421: }
422:
423: /**
424: * lookup the catalog dictionary in a document
425: *
426: * @return the document catalog object
427: */
428: public COSCatalog getCatalog() {
429: return cosGetDoc().getCatalog();
430: }
431:
432: public CDSDate getCreationDate() {
433: if (getInfoDict() == null) {
434: return null;
435: }
436: return getInfoDict().getCreationDate();
437: }
438:
439: public String getCreationDateString() {
440: return getDocumentInfoString(COSInfoDict.DK_CreationDate);
441: }
442:
443: public String getCreator() {
444: return getDocumentInfoString(COSInfoDict.DK_Creator);
445: }
446:
447: protected String getDocumentInfoString(COSName name) {
448: COSInfoDict infoDict = cosGetDoc().getInfoDict();
449: if (infoDict == null) {
450: return null;
451: }
452: COSObject obj = infoDict.cosGetField(name);
453: return obj.isNull() ? null : obj.stringValue();
454: }
455:
456: /**
457: * Get the info dictionary containing metadata.
458: *
459: * @return The info dictionary containing metadata.
460: */
461: public COSInfoDict getInfoDict() {
462: return cosGetDoc().getInfoDict();
463: }
464:
465: public String getKeywords() {
466: return getDocumentInfoString(COSInfoDict.DK_Keywords);
467: }
468:
469: public ILocator getLocator() {
470: return cosDoc.getLocator();
471: }
472:
473: public String getMetadata() {
474: COSCatalog catalog = getCatalog();
475: if (catalog == null) {
476: return null;
477: }
478: COSStream metadata = catalog
479: .cosGetField(COSCatalog.DK_Metadata).asStream();
480: if (metadata == null) {
481: return null;
482: }
483: byte[] bytes = metadata.getEncodedBytes();
484: return new String(bytes);
485: }
486:
487: public CDSDate getModDate() {
488: if (getInfoDict() == null) {
489: return null;
490: }
491: return getInfoDict().getModDate();
492: }
493:
494: public String getModDateString() {
495: return getDocumentInfoString(COSInfoDict.DK_ModDate);
496: }
497:
498: public String getName() {
499: return cosDoc.getName();
500: }
501:
502: public PDAction getOpenAction() {
503: COSCatalog catalog = getCatalog();
504: if (catalog == null) {
505: return null;
506: }
507:
508: COSObject openAction = catalog.cosGetField(DK_OpenAction);
509: if (openAction.isNull()) {
510: return null;
511: }
512: if (openAction instanceof COSDictionary) {
513: return (PDAction) PDAction.META.createFromCos(openAction);
514: }
515: if (openAction instanceof COSArray) {
516: return (PDAction) PDActionGoTo.META
517: .createFromCos(openAction);
518: }
519: return null;
520: }
521:
522: public PDOutline getOutline() {
523: return (PDOutline) PDOutline.META.createFromCos(getCatalog()
524: .cosGetOutline());
525: }
526:
527: public PDOutputIntent getOutputIntent(COSName oiName) {
528: List outputIntents = getOutputIntents();
529: if (outputIntents != null) {
530: for (Iterator iter = outputIntents.iterator(); iter
531: .hasNext();) {
532: PDOutputIntent element = (PDOutputIntent) iter.next();
533: COSObject keys = element
534: .cosGetField(PDOutputIntent.DK_S);
535: if (keys != null) {
536: if (keys.equals(oiName)) {
537: return element;
538: }
539: }
540: }
541: }
542: return null;
543: }
544:
545: public List getOutputIntents() {
546: COSArray oi = null;
547: COSCatalog catalog = getCatalog();
548: if (catalog != null) {
549: oi = catalog.cosGetField(COSCatalog.DK_OutputIntents)
550: .asArray();
551: if (oi != null) {
552: List result = new ArrayList();
553: Iterator i = oi.iterator();
554: while (i.hasNext()) {
555: COSBasedObject pdObject = PDOutputIntent.META
556: .createFromCos((COSObject) i.next());
557: if (pdObject != null) {
558: result.add(pdObject);
559: }
560: }
561: return result;
562: }
563: }
564: return null;
565: }
566:
567: /**
568: * return the documents root page tree
569: *
570: * @return the root page tree of the document
571: */
572: public PDPageTree getPageTree() {
573: return (PDPageTree) PDPageNode.META.createFromCos(getCatalog()
574: .cosGetField(COSCatalog.DK_Pages));
575: }
576:
577: /**
578: * Shortcut to a signature dictionary in the document permissions
579: * dictionary. Valid keys are "DocMDP" and "UR". If the permissions
580: * dictionary doesn't exist, then null is returned. If no signature
581: * dictionary under the specified key exists, null is returned.
582: *
583: * @param key
584: * key which should be ether "DocMDP" or "UR"
585: *
586: * @return returns a signature dictionary referenced by the specified key or
587: * null if ether no permissions dictionary exists or no signature
588: * dictionary to the key exists.
589: */
590: public PDSignature getPermissions(COSName key) {
591: COSDictionary perms = cosGetPermissionsDict();
592: if (perms == null) {
593: return null;
594: }
595: COSDictionary sigDict = perms.get(key).asDictionary();
596: if (sigDict == null) {
597: return null;
598: }
599: return (PDSignature) PDSignature.META.createFromCos(sigDict);
600: }
601:
602: public String getProducer() {
603: return getDocumentInfoString(COSInfoDict.DK_Producer);
604: }
605:
606: public String getSubject() {
607: return getDocumentInfoString(COSInfoDict.DK_Subject);
608: }
609:
610: /*
611: * (non-Javadoc)
612: *
613: * @see de.intarsys.pdf.pd.IAdditionalActionSupport#getSupportedTriggerEvents()
614: */
615: public Set getSupportedTriggerEvents() {
616: return CATALOG_ACTION_TRIGGERS;
617: }
618:
619: public String getTitle() {
620: return getDocumentInfoString(COSInfoDict.DK_Title);
621: }
622:
623: public String getTrapped() {
624: if (getInfoDict() == null) {
625: return null;
626: }
627: return getInfoDict().getTrapped();
628: }
629:
630: /**
631: * The write mode to be used when the document is written the next time. If
632: * defined this overrides any hint that is used when saving the document.
633: * The write mode is reset after each "save".
634: *
635: * @return The write mode to be used when the document is written.
636: */
637: public EnumWriteMode getWriteModeHint() {
638: return cosDoc.getWriteModeHint();
639: }
640:
641: /**
642: * initialize the object when created based on its cos representation
643: */
644: protected void initializeFromCos() {
645: //
646: }
647:
648: /**
649: * initialize the object when created from scratch (in memory)
650: */
651: protected void initializeFromScratch() {
652: PDPageTree pageTree = (PDPageTree) PDPageTree.META.createNew();
653: cosDoc.getCatalog().cosSetField(COSCatalog.DK_Pages,
654: pageTree.cosGetObject());
655: }
656:
657: public boolean isDirty() {
658: return cosDoc.isDirty();
659: }
660:
661: /**
662: * Lookup if this document is encrypted, means it has a security handler.
663: *
664: * @return true if the document has an {@link ISystemSecurityHandler}
665: */
666: public boolean isEncrypted() {
667: return cosDoc.isEncrypted();
668: }
669:
670: public boolean isNew() {
671: return cosDoc.isNew();
672: }
673:
674: public boolean isReadOnly() {
675: return cosDoc.isReadOnly();
676: }
677:
678: /**
679: * <code>true</code> if the document should be saved in an incremental way
680: * only. This is for example the case when the document contains digital
681: * signatures.
682: *
683: * @return <code>true</code> if the document should be saved in an
684: * incremental way only.
685: */
686: public boolean isPreferIncrementalSave() {
687: // we don't like full save of encrypted documents
688: if (isEncrypted()) {
689: return true;
690: }
691: // there is a hint with the form not to do a full save
692: if (isAppendOnly()) {
693: return true;
694: }
695: // sometimes the hint is not set - check harder
696: return isSigned();
697: }
698:
699: /**
700: * <code>true</code> if the document has a flag to prefere incremental
701: * save.
702: *
703: * @return <code>true</code> if the document should be saved in an
704: * incremental way only.
705: */
706: public boolean isAppendOnly() {
707: if (getAcroForm() == null) {
708: return false;
709: }
710: return getAcroForm().getSigFlags().isAppendOnly();
711: }
712:
713: /**
714: * <code>true</code> if the document contains digital signatures. This
715: * should be reflected in the SigFlags entry of the form - but who knows...
716: *
717: * @return <code>true</code> if the document contains digital signatures.
718: *
719: */
720: public boolean isSigned() {
721: if (getAcroForm() == null) {
722: return false;
723: }
724: return getAcroForm().isSigned();
725: }
726:
727: public COSObject lookupDestination(String name) {
728: COSCatalog catalog = getCatalog();
729: COSObject destination = null;
730: COSDictionary dests = catalog.cosGetDests();
731: if (dests != null) {
732: destination = dests.get(COSName.create(name));
733: }
734: if (destination == null) {
735: COSDictionary names = catalog.cosGetNames();
736: if (names != null) {
737: COSDictionary destsDict = names
738: .get(COSCatalog.DK_Dests).asDictionary();
739: if (destsDict != null) {
740: CDSNameTreeNode destsTree = CDSNameTreeNode
741: .createFromCos(destsDict);
742: destination = destsTree.get(COSString.create(name));
743: }
744: }
745: }
746: return destination.isNull() ? null : destination;
747: }
748:
749: public void removeApplicationData(String name) {
750: COSDictionary pid = cosGetPieceInfoDict();
751: if (pid == null) {
752: return;
753: }
754: COSName cosName = COSName.create(name);
755: pid.remove(cosName);
756: }
757:
758: /*
759: * (non-Javadoc)
760: *
761: * @see de.intarsys.tools.component.IAttributeSupport#removeAttribute(java.lang.Object)
762: */
763: public Object removeAttribute(Object key) {
764: return cosDoc.removeAttribute(key);
765: }
766:
767: public void restore(ILocator locator) throws IOException,
768: COSLoadException {
769: cosGetDoc().restore(locator);
770: }
771:
772: public void save() throws IOException {
773: save(getLocator(), null);
774: }
775:
776: public void save(ILocator locator) throws IOException {
777: save(locator, null);
778: }
779:
780: public void save(ILocator locator, Map options) throws IOException {
781: Map actualOptions = options;
782: if (actualOptions == null) {
783: actualOptions = new HashMap();
784: }
785: if (isPreferIncrementalSave()) {
786: // request an incremental write if possible
787: actualOptions.put(STDocument.OPTION_WRITEMODEHINT,
788: EnumWriteMode.INCREMENTAL);
789: } else {
790: EnumWriteMode mode = (EnumWriteMode) actualOptions
791: .get(STDocument.OPTION_WRITEMODEHINT);
792: if (mode == null || mode.isUndefined()) {
793: // we have no write mode predefined
794: if ((locator != null) && (locator != getLocator())) {
795: // this is "save as..."
796: actualOptions.put(STDocument.OPTION_WRITEMODEHINT,
797: EnumWriteMode.FULL);
798: }
799: }
800: }
801: cosDoc.save(locator, actualOptions);
802: }
803:
804: /**
805: * Set AcroForm in PDF Document.
806: *
807: */
808: public void setAcroForm(PDAcroForm form) {
809: COSCatalog catalog = getCatalog();
810: if (catalog == null) {
811: return;
812: }
813: catalog.setFieldObject(COSCatalog.DK_AcroForm, form);
814: }
815:
816: /*
817: * (non-Javadoc)
818: *
819: * @see de.intarsys.pdf.pd.IAdditionalActionSupport#setActions(de.intarsys.pdf.pd.PDAdditionalActions)
820: */
821: public void setAdditionalActions(PDAdditionalActions actions) {
822: COSCatalog catalog = getCatalog();
823: if (catalog != null) {
824: catalog.setFieldObject(DK_AA, actions);
825: }
826: }
827:
828: public void setApplicationData(String name, PDApplicationData data) {
829: COSDictionary pid = cosGetPieceInfoDict();
830: if (pid == null) {
831: pid = COSDictionary.create();
832: cosSetPieceInfoDict(pid);
833: }
834: COSName cosName = COSName.create(name);
835: if (data == null) {
836: pid.remove(cosName);
837: } else {
838: pid.put(cosName, data.cosGetDict());
839: }
840: }
841:
842: /*
843: * (non-Javadoc)
844: *
845: * @see de.intarsys.tools.component.IAttributeSupport#setAttribute(java.lang.Object,
846: * java.lang.Object)
847: */
848: public Object setAttribute(Object key, Object o) {
849: return cosDoc.setAttribute(key, o);
850: }
851:
852: public void setAuthor(String value) {
853: setDocumentInfo(COSInfoDict.DK_Author, value);
854: }
855:
856: public void setCreationDateString(String value) {
857: setDocumentInfo(COSInfoDict.DK_CreationDate, value);
858: }
859:
860: public void setCreator(String value) {
861: setDocumentInfo(COSInfoDict.DK_Creator, value);
862: }
863:
864: public void setDocumentInfo(COSName name, String value) {
865: COSInfoDict infoDict = cosGetDoc().getInfoDict();
866: if (infoDict == null) {
867: infoDict = (COSInfoDict) COSInfoDict.META.createNew();
868: cosGetDoc().setInfoDict(infoDict);
869: }
870: infoDict.setFieldString(name, value);
871: }
872:
873: /**
874: * Set the info dictionary containing metadata.
875: *
876: * @param infoDict
877: * The info dictionary containing metadata.
878: */
879: public void setInfoDict(COSInfoDict infoDict) {
880: cosGetDoc().setInfoDict(infoDict);
881: }
882:
883: public void setKeywords(String value) {
884: setDocumentInfo(COSInfoDict.DK_Keywords, value);
885: }
886:
887: public void setModDateString(String value) {
888: setDocumentInfo(COSInfoDict.DK_ModDate, value);
889: }
890:
891: public void setName(String name) {
892: cosDoc.setName(name);
893: }
894:
895: public void setOpenAction(PDAction newAction) {
896: COSCatalog catalog = getCatalog();
897: if (catalog == null) {
898: return;
899: }
900: catalog.setFieldObject(DK_OpenAction, newAction);
901: }
902:
903: public void setOutline(PDOutline outline) {
904: getCatalog().cosSetOutline(outline.cosGetDict());
905: }
906:
907: public void setPageTree(PDPageTree newTree) {
908: getCatalog().setFieldObject(COSCatalog.DK_Pages, newTree);
909: }
910:
911: public void setPermissions(COSName name, PDSignature signature) {
912: COSDictionary perms = cosGetPermissionsDict();
913: if (perms == null) {
914: perms = COSDictionary.create();
915: cosSetPermissionsDict(perms);
916: }
917: COSDictionary sigDict = signature.cosGetDict();
918: sigDict.beIndirect();
919: perms.put(name, sigDict);
920: }
921:
922: public void setProducer(String value) {
923: setDocumentInfo(COSInfoDict.DK_Producer, value);
924: }
925:
926: public void setSubject(String value) {
927: setDocumentInfo(COSInfoDict.DK_Subject, value);
928: }
929:
930: public void setTitle(String value) {
931: setDocumentInfo(COSInfoDict.DK_Title, value);
932: }
933:
934: public void setTrapped(String value) {
935: if (getInfoDict() == null) {
936: return;
937: }
938: getInfoDict().setTrapped(value);
939: }
940:
941: /**
942: * The write mode to be used when the document is written the next time. If
943: * defined this overrides any hint that is used when saving the document.
944: * The write mode is reset after each "save".
945: *
946: * @param writeMode
947: * The write mode to be used when the document is written.
948: */
949: public void setWriteModeHint(EnumWriteMode writeMode) {
950: cosDoc.setWriteModeHint(writeMode);
951: }
952: }
|