選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

Driver.java 22KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683
  1. /*
  2. * $Id$
  3. * ============================================================================
  4. * The Apache Software License, Version 1.1
  5. * ============================================================================
  6. *
  7. * Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved.
  8. *
  9. * Redistribution and use in source and binary forms, with or without modifica-
  10. * tion, are permitted provided that the following conditions are met:
  11. *
  12. * 1. Redistributions of source code must retain the above copyright notice,
  13. * this list of conditions and the following disclaimer.
  14. *
  15. * 2. Redistributions in binary form must reproduce the above copyright notice,
  16. * this list of conditions and the following disclaimer in the documentation
  17. * and/or other materials provided with the distribution.
  18. *
  19. * 3. The end-user documentation included with the redistribution, if any, must
  20. * include the following acknowledgment: "This product includes software
  21. * developed by the Apache Software Foundation (http://www.apache.org/)."
  22. * Alternately, this acknowledgment may appear in the software itself, if
  23. * and wherever such third-party acknowledgments normally appear.
  24. *
  25. * 4. The names "FOP" and "Apache Software Foundation" must not be used to
  26. * endorse or promote products derived from this software without prior
  27. * written permission. For written permission, please contact
  28. * apache@apache.org.
  29. *
  30. * 5. Products derived from this software may not be called "Apache", nor may
  31. * "Apache" appear in their name, without prior written permission of the
  32. * Apache Software Foundation.
  33. *
  34. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
  35. * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  36. * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  37. * APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
  38. * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
  39. * DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  40. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
  41. * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  42. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  43. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  44. * ============================================================================
  45. *
  46. * This software consists of voluntary contributions made by many individuals
  47. * on behalf of the Apache Software Foundation and was originally created by
  48. * James Tauber <jtauber@jtauber.com>. For more information on the Apache
  49. * Software Foundation, please see <http://www.apache.org/>.
  50. */
  51. package org.apache.fop.apps;
  52. // Java
  53. import java.awt.print.PrinterJob;
  54. // FOP
  55. import org.apache.fop.fo.ElementMapping;
  56. import org.apache.fop.fo.FOTreeBuilder;
  57. import org.apache.fop.fo.FOUserAgent;
  58. import org.apache.fop.fo.StructureHandler;
  59. import org.apache.fop.layoutmgr.LayoutHandler;
  60. import org.apache.fop.mif.MIFHandler;
  61. import org.apache.fop.render.Renderer;
  62. import org.apache.fop.render.awt.AWTPrintRenderer;
  63. import org.apache.fop.rtf.renderer.RTFHandler;
  64. import org.apache.fop.tools.DocumentInputSource;
  65. import org.apache.fop.tools.DocumentReader;
  66. // Avalon
  67. import org.apache.avalon.framework.logger.ConsoleLogger;
  68. import org.apache.avalon.framework.logger.LogEnabled;
  69. import org.apache.avalon.framework.logger.Logger;
  70. // DOM
  71. import org.w3c.dom.Document;
  72. // SAX
  73. import org.xml.sax.ContentHandler;
  74. import org.xml.sax.InputSource;
  75. import org.xml.sax.SAXException;
  76. import org.xml.sax.XMLReader;
  77. import javax.xml.parsers.ParserConfigurationException;
  78. import javax.xml.parsers.SAXParserFactory;
  79. // Java
  80. import java.io.IOException;
  81. import java.io.OutputStream;
  82. /**
  83. * Primary class that drives overall FOP process.
  84. * <P>
  85. * The simplest way to use this is to instantiate it with the
  86. * InputSource and OutputStream, then set the renderer desired, and
  87. * calling run();
  88. * <P>
  89. * Here is an example use of Driver which outputs PDF:
  90. *
  91. * <PRE>
  92. * Driver driver = new Driver(new InputSource (args[0]),
  93. * new FileOutputStream(args[1]));
  94. * driver.enableLogging(myLogger); //optional
  95. * driver.setRenderer(RENDER_PDF);
  96. * driver.run();
  97. * </PRE>
  98. * If neccessary, calling classes can call into the lower level
  99. * methods to setup and
  100. * render. Methods can be called to set the
  101. * Renderer to use, the (possibly multiple) ElementMapping(s) to
  102. * use and the OutputStream to use to output the results of the
  103. * rendering (where applicable). In the case of the Renderer and
  104. * ElementMapping(s), the Driver may be supplied either with the
  105. * object itself, or the name of the class, in which case Driver will
  106. * instantiate the class itself. The advantage of the latter is it
  107. * enables runtime determination of Renderer and ElementMapping(s).
  108. * <P>
  109. * Once the Driver is set up, the render method
  110. * is called. Depending on whether DOM or SAX is being used, the
  111. * invocation of the method is either render(Document) or
  112. * buildFOTree(Parser, InputSource) respectively.
  113. * <P>
  114. * A third possibility may be used to build the FO Tree, namely
  115. * calling getContentHandler() and firing the SAX events yourself.
  116. * <P>
  117. * Once the FO Tree is built, the format() and render() methods may be
  118. * called in that order.
  119. * <P>
  120. * Here is an example use of Driver which outputs to AWT:
  121. *
  122. * <PRE>
  123. * Driver driver = new Driver();
  124. * driver.enableLogging(myLogger); //optional
  125. * driver.setRenderer(new org.apache.fop.render.awt.AWTRenderer(translator));
  126. * driver.render(parser, fileInputSource(args[0]));
  127. * </PRE>
  128. */
  129. public class Driver implements LogEnabled {
  130. /**
  131. * Render to PDF. OutputStream must be set
  132. */
  133. public static final int RENDER_PDF = 1;
  134. /**
  135. * Render to a GUI window. No OutputStream neccessary
  136. */
  137. public static final int RENDER_AWT = 2;
  138. /**
  139. * Render to MIF. OutputStream must be set
  140. */
  141. public static final int RENDER_MIF = 3;
  142. /**
  143. * Render to XML. OutputStream must be set
  144. */
  145. public static final int RENDER_XML = 4;
  146. /**
  147. * Render to PRINT. No OutputStream neccessary
  148. */
  149. public static final int RENDER_PRINT = 5;
  150. /**
  151. * Render to PCL. OutputStream must be set
  152. */
  153. public static final int RENDER_PCL = 6;
  154. /**
  155. * Render to Postscript. OutputStream must be set
  156. */
  157. public static final int RENDER_PS = 7;
  158. /**
  159. * Render to Text. OutputStream must be set
  160. */
  161. public static final int RENDER_TXT = 8;
  162. /**
  163. * Render to SVG. OutputStream must be set
  164. */
  165. public static final int RENDER_SVG = 9;
  166. /**
  167. * Render to RTF. OutputStream must be set
  168. */
  169. public static final int RENDER_RTF = 10;
  170. /**
  171. * the FO tree builder
  172. */
  173. private FOTreeBuilder treeBuilder;
  174. /**
  175. * the renderer type code given by setRenderer
  176. */
  177. private int rendererType;
  178. /**
  179. * the renderer to use to output the area tree
  180. */
  181. private Renderer renderer;
  182. /**
  183. * the structure handler
  184. */
  185. private StructureHandler structHandler;
  186. /**
  187. * the source of the FO file
  188. */
  189. private InputSource source;
  190. /**
  191. * the stream to use to output the results of the renderer
  192. */
  193. private OutputStream stream;
  194. /**
  195. * The XML parser to use when building the FO tree
  196. */
  197. private XMLReader reader;
  198. /**
  199. * the system resources that FOP will use
  200. */
  201. private Logger log = null;
  202. private FOUserAgent userAgent = null;
  203. /**
  204. * Returns the fully qualified classname of the standard XML parser for FOP
  205. * to use.
  206. * @return the XML parser classname
  207. */
  208. public static final String getParserClassName() {
  209. try {
  210. return javax.xml.parsers.SAXParserFactory.newInstance()
  211. .newSAXParser().getXMLReader().getClass().getName();
  212. } catch (javax.xml.parsers.ParserConfigurationException e) {
  213. return null;
  214. } catch (org.xml.sax.SAXException e) {
  215. return null;
  216. }
  217. }
  218. /**
  219. * Main constructor for the Driver class.
  220. */
  221. public Driver() {
  222. stream = null;
  223. }
  224. /**
  225. * Convenience constructor for directly setting input and output.
  226. * @param source InputSource to take the XSL-FO input from
  227. * @param stream Target output stream
  228. */
  229. public Driver(InputSource source, OutputStream stream) {
  230. this();
  231. this.source = source;
  232. this.stream = stream;
  233. }
  234. private boolean isInitialized() {
  235. return (treeBuilder != null);
  236. }
  237. /**
  238. * Initializes the Driver object.
  239. */
  240. public void initialize() {
  241. if (isInitialized()) {
  242. throw new IllegalStateException("Driver already initialized");
  243. }
  244. treeBuilder = new FOTreeBuilder();
  245. treeBuilder.setUserAgent(getUserAgent());
  246. }
  247. /**
  248. * Optionally sets the FOUserAgent instance for FOP to use. The Driver
  249. * class sets up its own FOUserAgent if none is set through this method.
  250. * @param agent FOUserAgent to use
  251. */
  252. public void setUserAgent(FOUserAgent agent) {
  253. userAgent = agent;
  254. }
  255. private FOUserAgent getUserAgent() {
  256. if (userAgent == null) {
  257. userAgent = new FOUserAgent();
  258. userAgent.enableLogging(getLogger());
  259. userAgent.setBaseURL("");
  260. }
  261. return userAgent;
  262. }
  263. /**
  264. * Provide the Driver instance with a logger. More information on Avalon
  265. * logging can be found at the
  266. * <a href="http://avalon.apache.org">Avalon site</a>.
  267. *
  268. * @param log the logger. Must not be <code>null</code>.
  269. * @see org.apache.avalon.framework.logger.LogEnabled#enableLogging(Logger)
  270. */
  271. public void enableLogging(Logger log) {
  272. if (this.log == null) {
  273. this.log = log;
  274. } else {
  275. getLogger().warn("Logger is already set! Won't use the new logger.");
  276. }
  277. }
  278. /**
  279. * Provide the Driver instance with a logger.
  280. * @param log the logger. Must not be <code>null</code>.
  281. * @deprecated Use #enableLogging(Logger) instead.
  282. */
  283. public void setLogger(Logger log) {
  284. enableLogging(log);
  285. }
  286. /**
  287. * Returns the logger for use by FOP.
  288. * @return the logger
  289. * @see #enableLogging(Logger)
  290. */
  291. protected Logger getLogger() {
  292. if (this.log == null) {
  293. this.log = new ConsoleLogger(ConsoleLogger.LEVEL_INFO);
  294. this.log.error("Logger not set. Using ConsoleLogger as default.");
  295. }
  296. return this.log;
  297. }
  298. /**
  299. * Resets the Driver so it can be reused. Property and element
  300. * mappings are reset to defaults.
  301. * The output stream is cleared. The renderer is cleared.
  302. */
  303. public synchronized void reset() {
  304. source = null;
  305. stream = null;
  306. reader = null;
  307. treeBuilder.reset();
  308. }
  309. /**
  310. * Indicates whether FOP has already received input data.
  311. * @return true, if input data was received
  312. */
  313. public boolean hasData() {
  314. return (treeBuilder.hasData());
  315. }
  316. /**
  317. * Set the OutputStream to use to output the result of the Renderer
  318. * (if applicable)
  319. * @param stream the stream to output the result of rendering to
  320. */
  321. public void setOutputStream(OutputStream stream) {
  322. this.stream = stream;
  323. }
  324. private void validateOutputStream() {
  325. if (this.stream == null) {
  326. throw new IllegalStateException("OutputStream has not been set");
  327. }
  328. }
  329. /**
  330. * Set the source for the FO document. This can be a normal SAX
  331. * InputSource, or an DocumentInputSource containing a DOM document.
  332. * @see DocumentInputSource
  333. */
  334. public void setInputSource(InputSource source) {
  335. this.source = source;
  336. }
  337. /**
  338. * Sets the reader used when reading in the source. If not set,
  339. * this defaults to a basic SAX parser.
  340. * @param reader the reader to use.
  341. */
  342. public void setXMLReader(XMLReader reader) {
  343. this.reader = reader;
  344. }
  345. /**
  346. * Shortcut to set the rendering type to use. Must be one of
  347. * <ul>
  348. * <li>RENDER_PDF</li>
  349. * <li>RENDER_AWT</li>
  350. * <li>RENDER_MIF</li>
  351. * <li>RENDER_XML</li>
  352. * <li>RENDER_PCL</li>
  353. * <li>RENDER_PS</li>
  354. * <li>RENDER_TXT</li>
  355. * <li>RENDER_SVG</li>
  356. * <li>RENDER_RTF</li>
  357. * </ul>
  358. * @param renderer the type of renderer to use
  359. * @throws IllegalArgumentException if an unsupported renderer type was required.
  360. */
  361. public void setRenderer(int renderer) throws IllegalArgumentException {
  362. rendererType = renderer;
  363. switch (renderer) {
  364. case RENDER_PDF:
  365. setRenderer("org.apache.fop.render.pdf.PDFRenderer");
  366. break;
  367. case RENDER_AWT:
  368. throw new IllegalArgumentException("Use renderer form of setRenderer() for AWT");
  369. case RENDER_PRINT:
  370. // a PrinterJob object is needed to create this renderer
  371. PrinterJob pj = PrinterJob.getPrinterJob();
  372. int copies = AWTPrintRenderer.getIntProperty("copies", 1);
  373. pj.setCopies(copies);
  374. if (System.getProperty("dialog") != null) {
  375. if (!pj.printDialog()) {
  376. throw new IllegalArgumentException("Printing cancelled by operator");
  377. }
  378. }
  379. setRenderer(new AWTPrintRenderer(pj));
  380. break;
  381. case RENDER_PCL:
  382. setRenderer("org.apache.fop.render.pcl.PCLRenderer");
  383. break;
  384. case RENDER_PS:
  385. setRenderer("org.apache.fop.render.ps.PSRenderer");
  386. break;
  387. case RENDER_TXT:
  388. setRenderer("org.apache.fop.render.txt.TXTRenderer()");
  389. break;
  390. case RENDER_MIF:
  391. //structHandler will be set later
  392. break;
  393. case RENDER_XML:
  394. setRenderer("org.apache.fop.render.xml.XMLRenderer");
  395. break;
  396. case RENDER_SVG:
  397. setRenderer("org.apache.fop.render.svg.SVGRenderer");
  398. break;
  399. case RENDER_RTF:
  400. //structHandler will be set later
  401. break;
  402. default:
  403. throw new IllegalArgumentException("Unknown renderer type");
  404. }
  405. }
  406. /**
  407. * Set the Renderer to use.
  408. * @param renderer the renderer instance to use (Note: Logger must be set at this point)
  409. */
  410. public void setRenderer(Renderer renderer) {
  411. renderer.setProducer(Version.getVersion());
  412. renderer.setUserAgent(getUserAgent());
  413. this.renderer = renderer;
  414. }
  415. /**
  416. * Returns the currently active renderer.
  417. * @return the renderer
  418. */
  419. public Renderer getRenderer() {
  420. return renderer;
  421. }
  422. /**
  423. * Sets the renderer.
  424. * @param rendererClassName the fully qualified classname of the renderer
  425. * class to use.
  426. * @param version version number
  427. * @deprecated use renderer.setProducer(version) + setRenderer(renderer) or
  428. * just setRenderer(rendererType) which will use the default producer string.
  429. * @see #setRenderer(int)
  430. * @see #setRenderer(Renderer)
  431. */
  432. public void setRenderer(String rendererClassName, String version) {
  433. setRenderer(rendererClassName);
  434. }
  435. /**
  436. * Set the class name of the Renderer to use as well as the
  437. * producer string for those renderers that can make use of it.
  438. * @param rendererClassName classname of the renderer to use such as
  439. * "org.apache.fop.render.pdf.PDFRenderer"
  440. * @exception IllegalArgumentException if the classname was invalid.
  441. * @see #setRenderer(int)
  442. */
  443. public void setRenderer(String rendererClassName)
  444. throws IllegalArgumentException {
  445. try {
  446. renderer =
  447. (Renderer)Class.forName(rendererClassName).newInstance();
  448. if (renderer instanceof LogEnabled) {
  449. ((LogEnabled)renderer).enableLogging(getLogger());
  450. }
  451. renderer.setProducer(Version.getVersion());
  452. renderer.setUserAgent(getUserAgent());
  453. } catch (ClassNotFoundException e) {
  454. throw new IllegalArgumentException("Could not find "
  455. + rendererClassName);
  456. } catch (InstantiationException e) {
  457. throw new IllegalArgumentException("Could not instantiate "
  458. + rendererClassName);
  459. } catch (IllegalAccessException e) {
  460. throw new IllegalArgumentException("Could not access "
  461. + rendererClassName);
  462. } catch (ClassCastException e) {
  463. throw new IllegalArgumentException(rendererClassName
  464. + " is not a renderer");
  465. }
  466. }
  467. /**
  468. * Add the given element mapping.
  469. * An element mapping maps element names to Java classes.
  470. *
  471. * @param mapping the element mappingto add
  472. */
  473. public void addElementMapping(ElementMapping mapping) {
  474. treeBuilder.addElementMapping(mapping);
  475. }
  476. /**
  477. * Add the element mapping with the given class name.
  478. * @param mappingClassName the class name representing the element mapping.
  479. */
  480. public void addElementMapping(String mappingClassName) {
  481. treeBuilder.addElementMapping(mappingClassName);
  482. }
  483. /**
  484. * Returns the tree builder (a SAX ContentHandler).
  485. *
  486. * Used in situations where SAX is used but not via a FOP-invoked
  487. * SAX parser. A good example is an XSLT engine that fires SAX
  488. * events but isn't a SAX Parser itself.
  489. * @return a content handler for handling the SAX events.
  490. */
  491. public ContentHandler getContentHandler() {
  492. if (!isInitialized()) {
  493. initialize();
  494. }
  495. if (rendererType != RENDER_PRINT && rendererType != RENDER_AWT) {
  496. validateOutputStream();
  497. }
  498. // TODO: - do this stuff in a better way
  499. // PIJ: I guess the structure handler should be created by the renderer.
  500. if (rendererType == RENDER_MIF) {
  501. structHandler = new MIFHandler(stream);
  502. } else if (rendererType == RENDER_RTF) {
  503. structHandler = new RTFHandler(stream);
  504. } else {
  505. if (renderer == null) {
  506. throw new IllegalStateException(
  507. "Renderer not set when using standard structHandler");
  508. }
  509. structHandler = new LayoutHandler(stream, renderer, true);
  510. }
  511. structHandler.enableLogging(getLogger());
  512. treeBuilder.setUserAgent(getUserAgent());
  513. treeBuilder.setStructHandler(structHandler);
  514. return treeBuilder;
  515. }
  516. /**
  517. * Render the FO document read by a SAX Parser from an InputHandler
  518. * @param InputHandler the input handler containing the source and
  519. * parser information.
  520. * @throws FOPException if anything goes wrong.
  521. */
  522. public synchronized void render(InputHandler inputHandler)
  523. throws FOPException {
  524. XMLReader parser = inputHandler.getParser();
  525. inputHandler.setParserFeatures(parser);
  526. render(parser, inputHandler.getInputSource());
  527. }
  528. /**
  529. * Render the FO document read by a SAX Parser from an InputSource.
  530. * @param parser the SAX parser.
  531. * @param source the input source the parser reads from.
  532. * @throws FOPException if anything goes wrong.
  533. */
  534. public synchronized void render(XMLReader parser, InputSource source)
  535. throws FOPException {
  536. if (!isInitialized()) {
  537. initialize();
  538. }
  539. parser.setContentHandler(getContentHandler());
  540. try {
  541. parser.parse(source);
  542. } catch (SAXException e) {
  543. if (e.getException() instanceof FOPException) {
  544. // Undo exception tunneling.
  545. throw (FOPException)e.getException();
  546. } else {
  547. throw new FOPException(e);
  548. }
  549. } catch (IOException e) {
  550. throw new FOPException(e);
  551. }
  552. }
  553. /**
  554. * Render the FO ducument represented by a DOM Document.
  555. * @param document the DOM document to read from
  556. * @throws FOPException if anything goes wrong.
  557. */
  558. public synchronized void render(Document document)
  559. throws FOPException {
  560. if (!isInitialized()) {
  561. initialize();
  562. }
  563. try {
  564. DocumentInputSource source = new DocumentInputSource(document);
  565. DocumentReader reader = new DocumentReader();
  566. reader.setContentHandler(getContentHandler());
  567. reader.parse(source);
  568. } catch (SAXException e) {
  569. if (e.getException() instanceof FOPException) {
  570. // Undo exception tunneling.
  571. throw (FOPException)e.getException();
  572. } else {
  573. throw new FOPException(e);
  574. }
  575. } catch (IOException e) {
  576. throw new FOPException(e);
  577. }
  578. }
  579. /**
  580. * Runs the formatting and renderering process using the previously set
  581. * parser, input source, renderer and output stream.
  582. * If the renderer was not set, default to PDF.
  583. * If no parser was set, and the input source is not a dom document,
  584. * get a default SAX parser.
  585. * @throws IOException in case of IO errors.
  586. * @throws FOPException if anything else goes wrong.
  587. */
  588. public synchronized void run() throws IOException, FOPException {
  589. if (!isInitialized()) {
  590. initialize();
  591. }
  592. if (renderer == null) {
  593. setRenderer(RENDER_PDF);
  594. }
  595. if (source == null) {
  596. throw new FOPException("InputSource is not set.");
  597. }
  598. if (reader == null) {
  599. if (!(source instanceof DocumentInputSource)) {
  600. try {
  601. SAXParserFactory spf = javax.xml.parsers.SAXParserFactory.newInstance();
  602. spf.setNamespaceAware(true);
  603. reader = spf.newSAXParser().getXMLReader();
  604. } catch (SAXException e) {
  605. throw new FOPException(e);
  606. } catch (ParserConfigurationException e) {
  607. throw new FOPException(e);
  608. }
  609. }
  610. }
  611. if (source instanceof DocumentInputSource) {
  612. render(((DocumentInputSource)source).getDocument());
  613. } else {
  614. render(reader, source);
  615. }
  616. }
  617. }