You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

PDFInfo.java 9.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one or more
  3. * contributor license agreements. See the NOTICE file distributed with
  4. * this work for additional information regarding copyright ownership.
  5. * The ASF licenses this file to You under the Apache License, Version 2.0
  6. * (the "License"); you may not use this file except in compliance with
  7. * the License. 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. /* $Id$ */
  18. package org.apache.fop.pdf;
  19. import java.io.ByteArrayOutputStream;
  20. import java.io.IOException;
  21. import java.util.Date;
  22. import java.util.LinkedHashMap;
  23. import java.util.Map;
  24. import java.util.TimeZone;
  25. import org.apache.xmlgraphics.util.DateFormatUtil;
  26. /**
  27. * class representing an /Info object
  28. */
  29. public class PDFInfo extends PDFObject {
  30. /** The standard keys in the Document Information Dictionary */
  31. public static enum StandardKey {
  32. TITLE("Title"),
  33. AUTHOR("Author"),
  34. SUBJECT("Subject"),
  35. KEYWORDS("Keywords"),
  36. CREATOR("Creator"),
  37. PRODUCER("Producer"),
  38. CREATION_DATE("CreationDate"),
  39. MOD_DATE("ModDate"),
  40. TRAPPED("Trapped");
  41. private final String name;
  42. private StandardKey(String name) {
  43. this.name = name;
  44. }
  45. /**
  46. * Returns the standard key that corresponds to the given name.
  47. *
  48. * @param name key name
  49. * @return the key whose name exactly matches the given name (case-sensitive)
  50. */
  51. public static StandardKey get(String name) {
  52. for (StandardKey key : values()) {
  53. if (key.name.equals(name)) {
  54. return key;
  55. }
  56. }
  57. return null;
  58. }
  59. /**
  60. * Returns the name of this key.
  61. *
  62. * @return the name as it would appear in the Info dictionary without the leading slash
  63. */
  64. public String getName() {
  65. return name;
  66. }
  67. }
  68. /**
  69. * the application producing the PDF
  70. */
  71. private String producer;
  72. private String title;
  73. private String author;
  74. private String subject;
  75. private String keywords;
  76. private Date creationDate;
  77. private Date modDate;
  78. private Map<PDFName, String> customProperties;
  79. /**
  80. * the name of the application that created the
  81. * original document before converting to PDF
  82. */
  83. private String creator;
  84. /** @return the producer of the document or null if not set */
  85. public String getProducer() {
  86. return this.producer;
  87. }
  88. /**
  89. * set the producer string
  90. *
  91. * @param producer the producer string
  92. */
  93. public void setProducer(String producer) {
  94. this.producer = producer;
  95. }
  96. /** @return the creator of the document or null if not set */
  97. public String getCreator() {
  98. return this.creator;
  99. }
  100. /**
  101. * set the creator string
  102. *
  103. * @param creator the document creator
  104. */
  105. public void setCreator(String creator) {
  106. this.creator = creator;
  107. }
  108. /** @return the title string */
  109. public String getTitle() {
  110. return this.title;
  111. }
  112. /**
  113. * set the title string
  114. *
  115. * @param t the document title
  116. */
  117. public void setTitle(String t) {
  118. this.title = t;
  119. }
  120. /** @return the author of the document or null if not set */
  121. public String getAuthor() {
  122. return this.author;
  123. }
  124. /**
  125. * set the author string
  126. *
  127. * @param a the document author
  128. */
  129. public void setAuthor(String a) {
  130. this.author = a;
  131. }
  132. /** @return the subject of the document or null if not set */
  133. public String getSubject() {
  134. return this.subject;
  135. }
  136. /**
  137. * set the subject string
  138. *
  139. * @param s the document subject
  140. */
  141. public void setSubject(String s) {
  142. this.subject = s;
  143. }
  144. /** @return the keywords for the document or null if not set */
  145. public String getKeywords() {
  146. return this.keywords;
  147. }
  148. /**
  149. * set the keywords string
  150. *
  151. * @param k the keywords for this document
  152. */
  153. public void setKeywords(String k) {
  154. this.keywords = k;
  155. }
  156. /**
  157. * @return last set creation date
  158. */
  159. public Date getCreationDate() {
  160. return creationDate;
  161. }
  162. /**
  163. * @param date Date to store in the PDF as creation date. Use null to force current system date.
  164. */
  165. public void setCreationDate(Date date) {
  166. creationDate = date;
  167. }
  168. /** @return last modification date
  169. */
  170. public Date getModDate() {
  171. return this.modDate;
  172. }
  173. /**
  174. * Sets the date of the last modification.
  175. * @param date the last modification date or null if there are no modifications
  176. */
  177. public void setModDate(Date date) {
  178. this.modDate = date;
  179. }
  180. /**
  181. * {@inheritDoc}
  182. */
  183. public byte[] toPDF() {
  184. PDFProfile profile = getDocumentSafely().getProfile();
  185. ByteArrayOutputStream bout = new ByteArrayOutputStream(128);
  186. try {
  187. bout.write(encode("<<\n"));
  188. if (title != null && title.length() > 0) {
  189. bout.write(encode("/Title "));
  190. bout.write(encodeText(this.title));
  191. bout.write(encode("\n"));
  192. } else {
  193. profile.verifyTitleAbsent();
  194. }
  195. if (author != null) {
  196. bout.write(encode("/Author "));
  197. bout.write(encodeText(this.author));
  198. bout.write(encode("\n"));
  199. }
  200. if (subject != null) {
  201. bout.write(encode("/Subject "));
  202. bout.write(encodeText(this.subject));
  203. bout.write(encode("\n"));
  204. }
  205. if (keywords != null) {
  206. bout.write(encode("/Keywords "));
  207. bout.write(encodeText(this.keywords));
  208. bout.write(encode("\n"));
  209. }
  210. if (creator != null) {
  211. bout.write(encode("/Creator "));
  212. bout.write(encodeText(this.creator));
  213. bout.write(encode("\n"));
  214. }
  215. bout.write(encode("/Producer "));
  216. bout.write(encodeText(this.producer));
  217. bout.write(encode("\n"));
  218. // creation date in form (D:YYYYMMDDHHmmSSOHH'mm')
  219. if (creationDate == null) {
  220. creationDate = new Date();
  221. }
  222. bout.write(encode("/CreationDate "));
  223. bout.write(encodeString(formatDateTime(creationDate)));
  224. bout.write(encode("\n"));
  225. if (profile.isModDateRequired() && this.modDate == null) {
  226. this.modDate = this.creationDate;
  227. }
  228. if (this.modDate != null) {
  229. bout.write(encode("/ModDate "));
  230. bout.write(encodeString(formatDateTime(modDate)));
  231. bout.write(encode("\n"));
  232. }
  233. if (profile.isPDFXActive()) {
  234. bout.write(encode("/GTS_PDFXVersion "));
  235. bout.write(encodeString(profile.getPDFXMode().getName()));
  236. bout.write(encode("\n"));
  237. }
  238. if (profile.isTrappedEntryRequired()) {
  239. bout.write(encode("/Trapped /False\n"));
  240. }
  241. if (customProperties != null) {
  242. for (Map.Entry<PDFName, String> entry : customProperties.entrySet()) {
  243. entry.getKey().output(bout);
  244. bout.write(encode(" "));
  245. bout.write(encodeText(entry.getValue()));
  246. bout.write(encode("\n"));
  247. }
  248. }
  249. bout.write(encode(">>"));
  250. } catch (IOException ioe) {
  251. log.error("Ignored I/O exception", ioe);
  252. }
  253. return bout.toByteArray();
  254. }
  255. /**
  256. * Formats a date/time according to the PDF specification (D:YYYYMMDDHHmmSSOHH'mm').
  257. * @param time date/time value to format
  258. * @param tz the time zone
  259. * @return the requested String representation
  260. */
  261. protected static String formatDateTime(final Date time, TimeZone tz) {
  262. return DateFormatUtil.formatPDFDate(time, tz);
  263. }
  264. /**
  265. * Formats a date/time according to the PDF specification. (D:YYYYMMDDHHmmSSOHH'mm').
  266. * @param time date/time value to format
  267. * @return the requested String representation
  268. */
  269. protected static String formatDateTime(final Date time) {
  270. return formatDateTime(time, TimeZone.getDefault());
  271. }
  272. /**
  273. * Adds a custom property to this Info dictionary.
  274. */
  275. public void put(String key, String value) {
  276. StandardKey standardKey = StandardKey.get(key);
  277. if (standardKey != null) {
  278. throw new IllegalArgumentException(key + " is a reserved keyword");
  279. }
  280. if (customProperties == null) {
  281. customProperties = new LinkedHashMap<PDFName, String>();
  282. }
  283. customProperties.put(new PDFName(key), value);
  284. }
  285. }