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.

FOUserAgent.java 18KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608
  1. /*
  2. * Copyright 1999-2005 The Apache Software Foundation.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. /* $Id$ */
  17. package org.apache.fop.apps;
  18. // Java
  19. import java.io.File;
  20. import java.io.IOException;
  21. import java.net.URL;
  22. import java.net.MalformedURLException;
  23. import java.util.Date;
  24. import java.util.List;
  25. import java.util.Map;
  26. import javax.xml.transform.Source;
  27. import javax.xml.transform.TransformerException;
  28. import javax.xml.transform.URIResolver;
  29. // avalon configuration
  30. import org.apache.avalon.framework.configuration.Configuration;
  31. import org.apache.avalon.framework.configuration.ConfigurationException;
  32. // commons logging
  33. import org.apache.commons.logging.Log;
  34. import org.apache.commons.logging.LogFactory;
  35. // FOP
  36. import org.apache.fop.fo.ElementMapping;
  37. import org.apache.fop.fo.FOEventHandler;
  38. import org.apache.fop.layoutmgr.LayoutManagerMaker;
  39. import org.apache.fop.pdf.PDFEncryptionParams;
  40. import org.apache.fop.render.Renderer;
  41. import org.apache.fop.render.XMLHandlerRegistry;
  42. /**
  43. * The User Agent for fo.
  44. * This user agent is used by the processing to obtain user configurable
  45. * options.
  46. * <p>
  47. * Renderer specific extensions (that do not produce normal areas on
  48. * the output) will be done like so:
  49. * <br>
  50. * The extension will create an area, custom if necessary
  51. * <br>
  52. * this area will be added to the user agent with a key
  53. * <br>
  54. * the renderer will know keys for particular extensions
  55. * <br>
  56. * eg. bookmarks will be held in a special hierarchical area representing
  57. * the title and bookmark structure
  58. * <br>
  59. * These areas may contain resolvable areas that will be processed
  60. * with other resolvable areas
  61. */
  62. public class FOUserAgent {
  63. /** Defines the default resolution (72dpi) for FOP */
  64. public static final float DEFAULT_RESOLUTION = 72.0f; //dpi
  65. /** Defines the default resolution (72dpi) for FOP */
  66. public static final float DEFAULT_PX2MM = (25.4f / DEFAULT_RESOLUTION); //dpi (=25.4/dpi)
  67. /** Defines the default page-height */
  68. public static final String DEFAULT_PAGE_HEIGHT = "11in";
  69. /** Defines the default page-width */
  70. public static final String DEFAULT_PAGE_WIDTH = "8.26in";
  71. /** Registry for XML handlers */
  72. private XMLHandlerRegistry xmlHandlers = new XMLHandlerRegistry();
  73. private String baseURL;
  74. /** A user settable URI Resolver */
  75. private URIResolver uriResolver = null;
  76. /** Our default resolver if none is set */
  77. private URIResolver foURIResolver = new FOURIResolver();
  78. private PDFEncryptionParams pdfEncryptionParams;
  79. private float resolution = DEFAULT_RESOLUTION;
  80. private String pageHeight = DEFAULT_PAGE_HEIGHT;
  81. private String pageWidth = DEFAULT_PAGE_WIDTH;
  82. private Map rendererOptions = new java.util.HashMap();
  83. private File outputFile = null;
  84. private Renderer rendererOverride = null;
  85. private FOEventHandler foEventHandlerOverride = null;
  86. private LayoutManagerMaker lmMakerOverride = null;
  87. /* user configuration */
  88. private Configuration userConfig = null;
  89. private Log log = LogFactory.getLog("FOP");
  90. /* FOP has the ability, for some FO's, to continue processing even if the
  91. * input XSL violates that FO's content model. This is the default
  92. * behavior for FOP. However, this flag, if set, provides the user the
  93. * ability for FOP to halt on all content model violations if desired.
  94. */
  95. private boolean strictValidation = true;
  96. /* Additional fo.ElementMapping subclasses set by user */
  97. private List additionalElementMappings = null;
  98. /** Producer: Metadata element for the system/software that produces
  99. * the document. (Some renderers can store this in the document.)
  100. */
  101. protected String producer = "Apache FOP Version " + Fop.getVersion();
  102. /** Creator: Metadata element for the user that created the
  103. * document. (Some renderers can store this in the document.)
  104. */
  105. protected String creator = null;
  106. /** Creation Date: Override of the date the document was created.
  107. * (Some renderers can store this in the document.)
  108. */
  109. protected Date creationDate = null;
  110. /** Author of the content of the document. */
  111. protected String author = null;
  112. /** Title of the document. */
  113. protected String title = null;
  114. /** Set of keywords applicable to this document. */
  115. protected String keywords = null;
  116. /**
  117. * Add the element mapping with the given class name.
  118. * @param elementMapping the class name representing the element mapping.
  119. */
  120. public void addElementMapping(ElementMapping elementMapping) {
  121. if (additionalElementMappings == null) {
  122. additionalElementMappings = new java.util.ArrayList();
  123. }
  124. additionalElementMappings.add(elementMapping);
  125. }
  126. /**
  127. * Returns the List of user-added ElementMapping class names
  128. * @return List of Strings holding ElementMapping names.
  129. */
  130. public List getAdditionalElementMappings() {
  131. return additionalElementMappings;
  132. }
  133. /**
  134. * Sets an explicit renderer to use which overrides the one defined by the
  135. * render type setting.
  136. * @param renderer the Renderer instance to use
  137. */
  138. public void setRendererOverride(Renderer renderer) {
  139. this.rendererOverride = renderer;
  140. }
  141. /**
  142. * Returns the overriding Renderer instance, if any.
  143. * @return the overriding Renderer or null
  144. */
  145. public Renderer getRendererOverride() {
  146. return rendererOverride;
  147. }
  148. /**
  149. * Sets an explicit FOEventHandler instance which overrides the one
  150. * defined by the render type setting.
  151. * @param handler the FOEventHandler instance
  152. */
  153. public void setFOEventHandlerOverride(FOEventHandler handler) {
  154. this.foEventHandlerOverride = handler;
  155. }
  156. /**
  157. * Returns the overriding FOEventHandler instance, if any.
  158. * @return the overriding FOEventHandler or null
  159. */
  160. public FOEventHandler getFOEventHandlerOverride() {
  161. return this.foEventHandlerOverride;
  162. }
  163. /**
  164. * Activates strict XSL content model validation for FOP
  165. * Default is false (FOP will continue processing where it can)
  166. * @param validateStrictly true to turn on strict validation
  167. */
  168. public void setStrictValidation(boolean validateStrictly) {
  169. this.strictValidation = validateStrictly;
  170. }
  171. /**
  172. * Returns whether FOP is strictly validating input XSL
  173. * @return true of strict validation turned on, false otherwise
  174. */
  175. public boolean validateStrictly() {
  176. return strictValidation;
  177. }
  178. /**
  179. * Sets an explicit LayoutManagerMaker instance which overrides the one
  180. * defined by the AreaTreeHandler.
  181. * @param lmMaker the LayoutManagerMaker instance
  182. */
  183. public void setLayoutManagerMakerOverride(LayoutManagerMaker lmMaker) {
  184. this.lmMakerOverride = lmMaker;
  185. }
  186. /**
  187. * Returns the overriding LayoutManagerMaker instance, if any.
  188. * @return the overriding LayoutManagerMaker or null
  189. */
  190. public LayoutManagerMaker getLayoutManagerMakerOverride() {
  191. return this.lmMakerOverride;
  192. }
  193. /**
  194. * Sets the producer of the document.
  195. * @param producer source of document
  196. */
  197. public void setProducer(String producer) {
  198. this.producer = producer;
  199. }
  200. /**
  201. * Returns the producer of the document
  202. * @return producer name
  203. */
  204. public String getProducer() {
  205. return producer;
  206. }
  207. /**
  208. * Sets the creator of the document.
  209. * @param creator of document
  210. */
  211. public void setCreator(String creator) {
  212. this.creator = creator;
  213. }
  214. /**
  215. * Returns the creator of the document
  216. * @return creator name
  217. */
  218. public String getCreator() {
  219. return creator;
  220. }
  221. /**
  222. * Sets the creation date of the document.
  223. * @param creationDate date of document
  224. */
  225. public void setCreationDate(Date creationDate) {
  226. this.creationDate = creationDate;
  227. }
  228. /**
  229. * Returns the creation date of the document
  230. * @return creation date of document
  231. */
  232. public Date getCreationDate() {
  233. return creationDate;
  234. }
  235. /**
  236. * Sets the author of the document.
  237. * @param author of document
  238. */
  239. public void setAuthor(String author) {
  240. this.author = author;
  241. }
  242. /**
  243. * Returns the author of the document
  244. * @return author name
  245. */
  246. public String getAuthor() {
  247. return author;
  248. }
  249. /**
  250. * Sets the title of the document. This will override any title coming from
  251. * an fo:title element.
  252. * @param title of document
  253. */
  254. public void setTitle(String title) {
  255. this.title = title;
  256. }
  257. /**
  258. * Returns the title of the document
  259. * @return title name
  260. */
  261. public String getTitle() {
  262. return title;
  263. }
  264. /**
  265. * Sets the keywords for the document.
  266. * @param keywords for the document
  267. */
  268. public void setKeywords(String keywords) {
  269. this.keywords = keywords;
  270. }
  271. /**
  272. * Returns the keywords for the document
  273. * @return the keywords
  274. */
  275. public String getKeywords() {
  276. return keywords;
  277. }
  278. /**
  279. * Returns the renderer options
  280. * @return renderer options
  281. */
  282. public Map getRendererOptions() {
  283. return rendererOptions;
  284. }
  285. /**
  286. * Set the user configuration.
  287. * @param userConfig configuration
  288. */
  289. public void setUserConfig(Configuration userConfig) {
  290. this.userConfig = userConfig;
  291. try {
  292. initUserConfig();
  293. } catch (ConfigurationException cfge) {
  294. log.error("Error initializing User Agent configuration: "
  295. + cfge.getMessage());
  296. }
  297. }
  298. /**
  299. * Get the user configuration.
  300. * @return the user configuration
  301. */
  302. public Configuration getUserConfig() {
  303. return userConfig;
  304. }
  305. /**
  306. * Initializes user agent settings from the user configuration
  307. * file, if present: baseURL, resolution, default page size,...
  308. *
  309. * @throws ConfigurationException when there is an entry that
  310. * misses the required attribute
  311. */
  312. public void initUserConfig() throws ConfigurationException {
  313. log.info("Initializing User Agent Configuration");
  314. if (userConfig.getChild("base", false) != null) {
  315. try {
  316. String cfgBaseDir = userConfig.getChild("base").getValue(null);
  317. if (cfgBaseDir != null) {
  318. File dir = new File(cfgBaseDir);
  319. if (dir.isDirectory()) {
  320. cfgBaseDir = "file://" + dir.getCanonicalPath()
  321. + System.getProperty("file.separator");
  322. cfgBaseDir = cfgBaseDir.replace(
  323. System.getProperty("file.separator").charAt(0), '/');
  324. } else {
  325. //The next statement is for validation only
  326. new URL(cfgBaseDir);
  327. }
  328. }
  329. setBaseURL(cfgBaseDir);
  330. } catch (MalformedURLException mue) {
  331. log.error("Base URL in user config is malformed!");
  332. } catch (IOException ioe) {
  333. log.error("Error converting relative base directory to absolute URL.");
  334. }
  335. log.info("Base URL set to: " + baseURL);
  336. }
  337. if (userConfig.getChild("pixelToMillimeter", false) != null) {
  338. this.resolution = 25.4f / userConfig.getChild("pixelToMillimeter")
  339. .getAttributeAsFloat("value", DEFAULT_PX2MM);
  340. log.info("resolution set to: " + resolution
  341. + "dpi (px2mm=" + getPixelUnitToMillimeter() + ")");
  342. } else if (userConfig.getChild("resolution", false) != null) {
  343. this.resolution
  344. = 25.4f / userConfig.getChild("resolution").getValueAsFloat(DEFAULT_RESOLUTION);
  345. log.info("resolution set to: " + resolution
  346. + "dpi (px2mm=" + getPixelUnitToMillimeter() + ")");
  347. }
  348. Configuration pageConfig = userConfig.getChild("default-page-settings");
  349. if (pageConfig.getAttribute("height", null) != null) {
  350. setPageHeight(pageConfig.getAttribute("height"));
  351. log.info("Default page-height set to: " + pageHeight);
  352. }
  353. if (pageConfig.getAttribute("width", null) != null) {
  354. setPageWidth(pageConfig.getAttribute("width"));
  355. log.info("Default page-width set to: " + pageWidth);
  356. }
  357. }
  358. /**
  359. * Returns the configuration subtree for a specific renderer.
  360. * @param mimeType MIME type of the renderer
  361. * @return the requested configuration subtree, null if there's no configuration
  362. */
  363. public Configuration getUserRendererConfig (String mimeType) {
  364. if (userConfig == null || mimeType == null) {
  365. return null;
  366. }
  367. Configuration userRendererConfig = null;
  368. Configuration[] cfgs
  369. = userConfig.getChild("renderers").getChildren("renderer");
  370. for (int i = 0; i < cfgs.length; ++i) {
  371. Configuration cfg = cfgs[i];
  372. try {
  373. if (cfg.getAttribute("mime").equals(mimeType)) {
  374. userRendererConfig = cfg;
  375. break;
  376. }
  377. } catch (ConfigurationException e) {
  378. // silently pass over configurations without mime type
  379. }
  380. }
  381. log.debug((userRendererConfig == null ? "No u" : "U")
  382. + "ser configuration found for MIME type " + mimeType);
  383. return userRendererConfig;
  384. }
  385. /**
  386. * Sets the base URL.
  387. * @param baseURL base URL
  388. */
  389. public void setBaseURL(String baseURL) {
  390. this.baseURL = baseURL;
  391. }
  392. /**
  393. * Returns the base URL.
  394. * @return the base URL
  395. */
  396. public String getBaseURL() {
  397. return this.baseURL;
  398. }
  399. /**
  400. * Sets the URI Resolver.
  401. * @param uriResolver the new URI resolver
  402. */
  403. public void setURIResolver(URIResolver uriResolver) {
  404. this.uriResolver = uriResolver;
  405. }
  406. /**
  407. * Returns the URI Resolver.
  408. * @return the URI Resolver
  409. */
  410. public URIResolver getURIResolver() {
  411. return this.uriResolver;
  412. }
  413. /**
  414. * Returns the parameters for PDF encryption.
  415. * @return the PDF encryption parameters, null if not applicable
  416. */
  417. public PDFEncryptionParams getPDFEncryptionParams() {
  418. return pdfEncryptionParams;
  419. }
  420. /**
  421. * Sets the parameters for PDF encryption.
  422. * @param pdfEncryptionParams the PDF encryption parameters, null to
  423. * disable PDF encryption
  424. */
  425. public void setPDFEncryptionParams(PDFEncryptionParams pdfEncryptionParams) {
  426. this.pdfEncryptionParams = pdfEncryptionParams;
  427. }
  428. /**
  429. * Attempts to resolve the given URI.
  430. * Will use the configured resolver and if not successful fall back
  431. * to the default resolver.
  432. * @param uri URI to access
  433. * @return A {@link javax.xml.transform.Source} object, or null if the URI
  434. * cannot be resolved.
  435. * @see org.apache.fop.apps.FOURIResolver
  436. */
  437. public Source resolveURI(String uri) {
  438. Source source = null;
  439. if (uriResolver != null) {
  440. try {
  441. source = uriResolver.resolve(uri, getBaseURL());
  442. } catch (TransformerException te) {
  443. log.error("Attempt to resolve URI '" + uri + "' failed: ", te);
  444. }
  445. }
  446. if (source == null) {
  447. // URI Resolver not configured or returned null, use default resolver
  448. try {
  449. source = foURIResolver.resolve(uri, getBaseURL());
  450. } catch (TransformerException te) {
  451. log.error("Attempt to resolve URI '" + uri + "' failed: ", te);
  452. }
  453. }
  454. return source;
  455. }
  456. /**
  457. * Sets the output File.
  458. * @param f the output File
  459. */
  460. public void setOutputFile(File f) {
  461. this.outputFile = f;
  462. }
  463. /**
  464. * Gets the output File.
  465. * @return the output File
  466. */
  467. public File getOutputFile() {
  468. return outputFile;
  469. }
  470. /**
  471. * Returns the conversion factor from pixel units to millimeters. This
  472. * depends on the desired reolution.
  473. * @return float conversion factor
  474. */
  475. public float getPixelUnitToMillimeter() {
  476. return 25.4f / this.resolution;
  477. }
  478. /** @return the resolution for resolution-dependant output */
  479. public float getResolution() {
  480. return this.resolution;
  481. }
  482. /**
  483. * Sets the resolution in dpi.
  484. * @param dpi resolution in dpi
  485. */
  486. public void setResolution(int dpi) {
  487. this.resolution = dpi;
  488. }
  489. /**
  490. * Gets the default page-height to use as fallback,
  491. * in case page-height="auto"
  492. *
  493. * @return the page-height, as a String
  494. */
  495. public String getPageHeight() {
  496. return this.pageHeight;
  497. }
  498. /**
  499. * Sets the page-height to use as fallback, in case
  500. * page-height="auto"
  501. *
  502. * @param pageHeight page-height as a String
  503. */
  504. public void setPageHeight(String pageHeight) {
  505. this.pageHeight = pageHeight;
  506. }
  507. /**
  508. * Gets the default page-width to use as fallback,
  509. * in case page-width="auto"
  510. *
  511. * @return the page-width, as a String
  512. */
  513. public String getPageWidth() {
  514. return this.pageWidth;
  515. }
  516. /**
  517. * Sets the page-width to use as fallback, in case
  518. * page-width="auto"
  519. *
  520. * @param pageWidth page-width as a String
  521. */
  522. public void setPageWidth(String pageWidth) {
  523. this.pageWidth = pageWidth;
  524. }
  525. /**
  526. * If to create hot links to footnotes and before floats.
  527. * @return True if hot links should be created
  528. */
  529. public boolean linkToFootnotes() {
  530. return true;
  531. }
  532. /**
  533. * @return the XML handler registry
  534. */
  535. public XMLHandlerRegistry getXMLHandlerRegistry() {
  536. return this.xmlHandlers;
  537. }
  538. }