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.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785
  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. // FOP
  53. import org.apache.fop.fo.ElementMapping;
  54. import org.apache.fop.fo.FOTreeBuilder;
  55. import org.apache.fop.fo.FOUserAgent;
  56. import org.apache.fop.render.Renderer;
  57. import org.apache.fop.tools.DocumentInputSource;
  58. import org.apache.fop.tools.DocumentReader;
  59. // Avalon
  60. import org.apache.avalon.framework.logger.ConsoleLogger;
  61. import org.apache.avalon.framework.logger.LogEnabled;
  62. import org.apache.avalon.framework.logger.Logger;
  63. // DOM
  64. import org.w3c.dom.Document;
  65. // SAX
  66. import org.xml.sax.ContentHandler;
  67. import org.xml.sax.InputSource;
  68. import org.xml.sax.SAXException;
  69. import org.xml.sax.XMLReader;
  70. import javax.xml.parsers.ParserConfigurationException;
  71. import javax.xml.parsers.SAXParserFactory;
  72. // Java
  73. import java.io.BufferedReader;
  74. import java.io.IOException;
  75. import java.io.InputStream;
  76. import java.io.InputStreamReader;
  77. import java.io.OutputStream;
  78. import java.io.Reader;
  79. import java.util.Enumeration;
  80. import java.util.Iterator;
  81. import java.util.List;
  82. import java.util.Map;
  83. /**
  84. * Primary class that drives overall FOP process.
  85. * <P>
  86. * The simplest way to use this is to instantiate it with the
  87. * InputSource and OutputStream, then set the renderer desired, and
  88. * calling run();
  89. * <P>
  90. * Here is an example use of Driver which outputs PDF:
  91. *
  92. * <PRE>
  93. * Driver driver = new Driver(new InputSource (args[0]),
  94. * new FileOutputStream(args[1]));
  95. * driver.enableLogging(myLogger); //optional
  96. * driver.setRenderer(RENDER_PDF);
  97. * driver.run();
  98. * </PRE>
  99. * If neccessary, calling classes can call into the lower level
  100. * methods to setup and
  101. * render. Methods can be called to set the
  102. * Renderer to use, the (possibly multiple) ElementMapping(s) to
  103. * use and the OutputStream to use to output the results of the
  104. * rendering (where applicable). In the case of the Renderer and
  105. * ElementMapping(s), the Driver may be supplied either with the
  106. * object itself, or the name of the class, in which case Driver will
  107. * instantiate the class itself. The advantage of the latter is it
  108. * enables runtime determination of Renderer and ElementMapping(s).
  109. * <P>
  110. * Once the Driver is set up, the render method
  111. * is called. Depending on whether DOM or SAX is being used, the
  112. * invocation of the method is either render(Document) or
  113. * buildFOTree(Parser, InputSource) respectively.
  114. * <P>
  115. * A third possibility may be used to build the FO Tree, namely
  116. * calling getContentHandler() and firing the SAX events yourself.
  117. * <P>
  118. * Once the FO Tree is built, the format() and render() methods may be
  119. * called in that order.
  120. * <P>
  121. * Here is an example use of Driver which outputs to AWT:
  122. *
  123. * <PRE>
  124. * Driver driver = new Driver();
  125. * driver.enableLogging(myLogger); //optional
  126. * driver.setRenderer(new org.apache.fop.render.awt.AWTRenderer(translator));
  127. * driver.render(parser, fileInputSource(args[0]));
  128. * </PRE>
  129. */
  130. public class Driver implements LogEnabled {
  131. /**
  132. * Render to PDF. OutputStream must be set
  133. */
  134. public static final int RENDER_PDF = 1;
  135. /**
  136. * Render to a GUI window. No OutputStream neccessary
  137. */
  138. public static final int RENDER_AWT = 2;
  139. /**
  140. * Render to MIF. OutputStream must be set
  141. */
  142. public static final int RENDER_MIF = 3;
  143. /**
  144. * Render to XML. OutputStream must be set
  145. */
  146. public static final int RENDER_XML = 4;
  147. /**
  148. * Render to PRINT. No OutputStream neccessary
  149. */
  150. public static final int RENDER_PRINT = 5;
  151. /**
  152. * Render to PCL. OutputStream must be set
  153. */
  154. public static final int RENDER_PCL = 6;
  155. /**
  156. * Render to Postscript. OutputStream must be set
  157. */
  158. public static final int RENDER_PS = 7;
  159. /**
  160. * Render to Text. OutputStream must be set
  161. */
  162. public static final int RENDER_TXT = 8;
  163. /**
  164. * Render to SVG. OutputStream must be set
  165. */
  166. public static final int RENDER_SVG = 9;
  167. /**
  168. * Render to RTF. OutputStream must be set
  169. */
  170. public static final int RENDER_RTF = 10;
  171. /**
  172. * the FO tree builder
  173. */
  174. private FOTreeBuilder treeBuilder;
  175. /**
  176. * the renderer type code given by setRenderer
  177. */
  178. private int rendererType;
  179. /**
  180. * the renderer to use to output the area tree
  181. */
  182. private Renderer renderer;
  183. /**
  184. * the structure handler
  185. */
  186. private StructureHandler structHandler;
  187. /**
  188. * the source of the FO file
  189. */
  190. private InputSource source;
  191. /**
  192. * the stream to use to output the results of the renderer
  193. */
  194. private OutputStream stream;
  195. /**
  196. * The XML parser to use when building the FO tree
  197. */
  198. private XMLReader reader;
  199. /**
  200. * the system resources that FOP will use
  201. */
  202. private Logger log = null;
  203. private FOUserAgent userAgent = null;
  204. /**
  205. * Returns the fully qualified classname of the standard XML parser for FOP
  206. * to use.
  207. * @return the XML parser classname
  208. */
  209. public static final String getParserClassName() {
  210. try {
  211. return javax.xml.parsers.SAXParserFactory.newInstance()
  212. .newSAXParser().getXMLReader().getClass().getName();
  213. } catch (javax.xml.parsers.ParserConfigurationException e) {
  214. return null;
  215. } catch (org.xml.sax.SAXException e) {
  216. return null;
  217. }
  218. }
  219. /**
  220. * Main constructor for the Driver class.
  221. */
  222. public Driver() {
  223. stream = null;
  224. }
  225. /**
  226. * Convenience constructor for directly setting input and output.
  227. * @param source InputSource to take the XSL-FO input from
  228. * @param stream Target output stream
  229. */
  230. public Driver(InputSource source, OutputStream stream) {
  231. this();
  232. this.source = source;
  233. this.stream = stream;
  234. }
  235. private boolean isInitialized() {
  236. return (treeBuilder != null);
  237. }
  238. /**
  239. * Initializes the Driver object.
  240. */
  241. public void initialize() {
  242. if (isInitialized()) {
  243. throw new IllegalStateException("Driver already initialized");
  244. }
  245. treeBuilder = new FOTreeBuilder();
  246. treeBuilder.setUserAgent(getUserAgent());
  247. setupDefaultMappings();
  248. }
  249. /**
  250. * Optionally sets the FOUserAgent instance for FOP to use. The Driver
  251. * class sets up its own FOUserAgent if none is set through this method.
  252. * @param agent FOUserAgent to use
  253. */
  254. public void setUserAgent(FOUserAgent agent) {
  255. userAgent = agent;
  256. }
  257. private FOUserAgent getUserAgent() {
  258. if (userAgent == null) {
  259. userAgent = new FOUserAgent();
  260. userAgent.enableLogging(getLogger());
  261. userAgent.setBaseURL("");
  262. }
  263. return userAgent;
  264. }
  265. /**
  266. * Provide the Driver instance with a logger. More information on Avalon
  267. * logging can be found at the
  268. * <a href="http://avalon.apache.org">Avalon site</a>.
  269. *
  270. * @param log the logger. Must not be <code>null</code>.
  271. * @see org.apache.avalon.framework.logger.LogEnabled#enableLogging(Logger)
  272. */
  273. public void enableLogging(Logger log) {
  274. if (this.log == null) {
  275. this.log = log;
  276. } else {
  277. getLogger().warn("Logger is already set! Won't use the new logger.");
  278. }
  279. }
  280. /**
  281. * Provide the Driver instance with a logger.
  282. * @param log the logger. Must not be <code>null</code>.
  283. * @deprecated Use #enableLogging(Logger) instead.
  284. */
  285. public void setLogger(Logger log) {
  286. enableLogging(log);
  287. }
  288. /**
  289. * Returns the logger for use by FOP.
  290. * @return the logger
  291. * @see #enableLogging(Logger)
  292. */
  293. protected Logger getLogger() {
  294. if (this.log == null) {
  295. this.log = new ConsoleLogger(ConsoleLogger.LEVEL_INFO);
  296. this.log.error("Logger not set. Using ConsoleLogger as default.");
  297. }
  298. return this.log;
  299. }
  300. /**
  301. * Resets the Driver so it can be reused. Property and element
  302. * mappings are reset to defaults.
  303. * The output stream is cleared. The renderer is cleared.
  304. */
  305. public synchronized void reset() {
  306. source = null;
  307. stream = null;
  308. reader = null;
  309. treeBuilder.reset();
  310. }
  311. /**
  312. * Indicates whether FOP has already received input data.
  313. * @return true, if input data was received
  314. */
  315. public boolean hasData() {
  316. return (treeBuilder.hasData());
  317. }
  318. /**
  319. * Set the OutputStream to use to output the result of the Renderer
  320. * (if applicable)
  321. * @param stream the stream to output the result of rendering to
  322. */
  323. public void setOutputStream(OutputStream stream) {
  324. this.stream = stream;
  325. }
  326. private void validateOutputStream() {
  327. if (this.stream == null) {
  328. throw new IllegalStateException("OutputStream has not been set");
  329. }
  330. }
  331. /**
  332. * Set the source for the FO document. This can be a normal SAX
  333. * InputSource, or an DocumentInputSource containing a DOM document.
  334. * @see DocumentInputSource
  335. */
  336. public void setInputSource(InputSource source) {
  337. this.source = source;
  338. }
  339. /**
  340. * Sets the reader used when reading in the source. If not set,
  341. * this defaults to a basic SAX parser.
  342. * @param reader the reader to use.
  343. */
  344. public void setXMLReader(XMLReader reader) {
  345. this.reader = reader;
  346. }
  347. /**
  348. * Sets all the element and property list mappings to their default values.
  349. *
  350. */
  351. public void setupDefaultMappings() {
  352. addElementMapping("org.apache.fop.fo.FOElementMapping");
  353. addElementMapping("org.apache.fop.svg.SVGElementMapping");
  354. addElementMapping("org.apache.fop.extensions.ExtensionElementMapping");
  355. // add mappings from available services
  356. Iterator providers =
  357. Service.providers(org.apache.fop.fo.ElementMapping.class);
  358. if (providers != null) {
  359. while (providers.hasNext()) {
  360. String str = (String)providers.next();
  361. try {
  362. addElementMapping(str);
  363. } catch (IllegalArgumentException e) {
  364. getLogger().warn("Error while adding element mapping", e);
  365. }
  366. }
  367. }
  368. }
  369. /**
  370. * Shortcut to set the rendering type to use. Must be one of
  371. * <ul>
  372. * <li>RENDER_PDF</li>
  373. * <li>RENDER_AWT</li>
  374. * <li>RENDER_MIF</li>
  375. * <li>RENDER_XML</li>
  376. * <li>RENDER_PCL</li>
  377. * <li>RENDER_PS</li>
  378. * <li>RENDER_TXT</li>
  379. * <li>RENDER_SVG</li>
  380. * <li>RENDER_RTF</li>
  381. * </ul>
  382. * @param renderer the type of renderer to use
  383. * @throws IllegalArgumentException if an unsupported renderer type was required.
  384. */
  385. public void setRenderer(int renderer) throws IllegalArgumentException {
  386. rendererType = renderer;
  387. switch (renderer) {
  388. case RENDER_PDF:
  389. setRenderer("org.apache.fop.render.pdf.PDFRenderer");
  390. break;
  391. case RENDER_AWT:
  392. throw new IllegalArgumentException("Use renderer form of setRenderer() for AWT");
  393. case RENDER_PRINT:
  394. throw new IllegalArgumentException("Use renderer form of setRenderer() for PRINT");
  395. case RENDER_PCL:
  396. setRenderer("org.apache.fop.render.pcl.PCLRenderer");
  397. break;
  398. case RENDER_PS:
  399. setRenderer("org.apache.fop.render.ps.PSRenderer");
  400. break;
  401. case RENDER_TXT:
  402. setRenderer("org.apache.fop.render.txt.TXTRenderer()");
  403. break;
  404. case RENDER_MIF:
  405. //structHandler will be set later
  406. break;
  407. case RENDER_XML:
  408. setRenderer("org.apache.fop.render.xml.XMLRenderer");
  409. break;
  410. case RENDER_SVG:
  411. setRenderer("org.apache.fop.render.svg.SVGRenderer");
  412. break;
  413. case RENDER_RTF:
  414. //structHandler will be set later
  415. break;
  416. default:
  417. throw new IllegalArgumentException("Unknown renderer type");
  418. }
  419. }
  420. /**
  421. * Set the Renderer to use.
  422. * @param renderer the renderer instance to use (Note: Logger must be set at this point)
  423. */
  424. public void setRenderer(Renderer renderer) {
  425. renderer.setUserAgent(getUserAgent());
  426. this.renderer = renderer;
  427. }
  428. /**
  429. * Returns the currently active renderer.
  430. * @return the renderer
  431. */
  432. public Renderer getRenderer() {
  433. return renderer;
  434. }
  435. /**
  436. * Sets the renderer.
  437. * @param rendererClassName the fully qualified classname of the renderer
  438. * class to use.
  439. * @param version version number
  440. * @deprecated use renderer.setProducer(version) + setRenderer(renderer) or
  441. * just setRenderer(rendererType) which will use the default producer string.
  442. * @see #setRenderer(int)
  443. * @see #setRenderer(Renderer)
  444. */
  445. public void setRenderer(String rendererClassName, String version) {
  446. setRenderer(rendererClassName);
  447. }
  448. /**
  449. * Set the class name of the Renderer to use as well as the
  450. * producer string for those renderers that can make use of it.
  451. * @param rendererClassName classname of the renderer to use such as
  452. * "org.apache.fop.render.pdf.PDFRenderer"
  453. * @exception IllegalArgumentException if the classname was invalid.
  454. * @see #setRenderer(int)
  455. */
  456. public void setRenderer(String rendererClassName)
  457. throws IllegalArgumentException {
  458. try {
  459. renderer =
  460. (Renderer)Class.forName(rendererClassName).newInstance();
  461. if (renderer instanceof LogEnabled) {
  462. ((LogEnabled)renderer).enableLogging(getLogger());
  463. }
  464. renderer.setProducer(Version.getVersion());
  465. renderer.setUserAgent(getUserAgent());
  466. } catch (ClassNotFoundException e) {
  467. throw new IllegalArgumentException("Could not find "
  468. + rendererClassName);
  469. } catch (InstantiationException e) {
  470. throw new IllegalArgumentException("Could not instantiate "
  471. + rendererClassName);
  472. } catch (IllegalAccessException e) {
  473. throw new IllegalArgumentException("Could not access "
  474. + rendererClassName);
  475. } catch (ClassCastException e) {
  476. throw new IllegalArgumentException(rendererClassName
  477. + " is not a renderer");
  478. }
  479. }
  480. /**
  481. * Add the given element mapping.
  482. * An element mapping maps element names to Java classes.
  483. *
  484. * @param mapping the element mappingto add
  485. */
  486. public void addElementMapping(ElementMapping mapping) {
  487. mapping.addToBuilder(treeBuilder);
  488. }
  489. /**
  490. * Add the element mapping with the given class name.
  491. * @param mappingClassName the class name representing the element mapping.
  492. * @throws IllegalArgumentException if there was not such element mapping.
  493. */
  494. public void addElementMapping(String mappingClassName)
  495. throws IllegalArgumentException {
  496. try {
  497. ElementMapping mapping =
  498. (ElementMapping)Class.forName(mappingClassName).newInstance();
  499. addElementMapping(mapping);
  500. } catch (ClassNotFoundException e) {
  501. throw new IllegalArgumentException("Could not find "
  502. + mappingClassName);
  503. } catch (InstantiationException e) {
  504. throw new IllegalArgumentException("Could not instantiate "
  505. + mappingClassName);
  506. } catch (IllegalAccessException e) {
  507. throw new IllegalArgumentException("Could not access "
  508. + mappingClassName);
  509. } catch (ClassCastException e) {
  510. throw new IllegalArgumentException(mappingClassName
  511. + " is not an ElementMapping");
  512. }
  513. }
  514. /**
  515. * Returns the tree builder (a SAX ContentHandler).
  516. *
  517. * Used in situations where SAX is used but not via a FOP-invoked
  518. * SAX parser. A good example is an XSLT engine that fires SAX
  519. * events but isn't a SAX Parser itself.
  520. * @return a content handler for handling the SAX events.
  521. */
  522. public ContentHandler getContentHandler() {
  523. if (!isInitialized()) {
  524. initialize();
  525. }
  526. validateOutputStream();
  527. // TODO: - do this stuff in a better way
  528. // PIJ: I guess the structure handler should be created by the renderer.
  529. if (rendererType == RENDER_MIF) {
  530. structHandler = new org.apache.fop.mif.MIFHandler(stream);
  531. } else if (rendererType == RENDER_RTF) {
  532. structHandler = new org.apache.fop.rtf.renderer.RTFHandler(stream);
  533. } else {
  534. if (renderer == null) {
  535. throw new IllegalStateException(
  536. "Renderer not set when using standard structHandler");
  537. }
  538. structHandler = new LayoutHandler(stream, renderer, true);
  539. }
  540. structHandler.enableLogging(getLogger());
  541. treeBuilder.setUserAgent(getUserAgent());
  542. treeBuilder.setStructHandler(structHandler);
  543. return treeBuilder;
  544. }
  545. /**
  546. * Render the FO document read by a SAX Parser from an InputSource.
  547. * @param parser the SAX parser.
  548. * @param source the input source the parser reads from.
  549. * @throws FOPException if anything goes wrong.
  550. */
  551. public synchronized void render(XMLReader parser, InputSource source)
  552. throws FOPException {
  553. if (!isInitialized()) {
  554. initialize();
  555. }
  556. parser.setContentHandler(getContentHandler());
  557. try {
  558. parser.parse(source);
  559. } catch (SAXException e) {
  560. if (e.getException() instanceof FOPException) {
  561. // Undo exception tunneling.
  562. throw (FOPException)e.getException();
  563. } else {
  564. throw new FOPException(e);
  565. }
  566. } catch (IOException e) {
  567. throw new FOPException(e);
  568. }
  569. }
  570. /**
  571. * Render the FO ducument represented by a DOM Document.
  572. * @param document the DOM document to read from
  573. * @throws FOPException if anything goes wrong.
  574. */
  575. public synchronized void render(Document document)
  576. throws FOPException {
  577. if (!isInitialized()) {
  578. initialize();
  579. }
  580. try {
  581. DocumentInputSource source = new DocumentInputSource(document);
  582. DocumentReader reader = new DocumentReader();
  583. reader.setContentHandler(getContentHandler());
  584. reader.parse(source);
  585. } catch (SAXException e) {
  586. if (e.getException() instanceof FOPException) {
  587. // Undo exception tunneling.
  588. throw (FOPException)e.getException();
  589. } else {
  590. throw new FOPException(e);
  591. }
  592. } catch (IOException e) {
  593. throw new FOPException(e);
  594. }
  595. }
  596. /**
  597. * Runs the formatting and renderering process using the previously set
  598. * parser, input source, renderer and output stream.
  599. * If the renderer was not set, default to PDF.
  600. * If no parser was set, and the input source is not a dom document,
  601. * get a default SAX parser.
  602. * @throws IOException in case of IO errors.
  603. * @throws FOPException if anything else goes wrong.
  604. */
  605. public synchronized void run() throws IOException, FOPException {
  606. if (!isInitialized()) {
  607. initialize();
  608. }
  609. if (renderer == null) {
  610. setRenderer(RENDER_PDF);
  611. }
  612. if (source == null) {
  613. throw new FOPException("InputSource is not set.");
  614. }
  615. if (reader == null) {
  616. if (!(source instanceof DocumentInputSource)) {
  617. try {
  618. SAXParserFactory spf = javax.xml.parsers.SAXParserFactory.newInstance();
  619. spf.setNamespaceAware(true);
  620. reader = spf.newSAXParser().getXMLReader();
  621. } catch (SAXException e) {
  622. throw new FOPException(e);
  623. } catch (ParserConfigurationException e) {
  624. throw new FOPException(e);
  625. }
  626. }
  627. }
  628. if (source instanceof DocumentInputSource) {
  629. render(((DocumentInputSource)source).getDocument());
  630. } else {
  631. render(reader, source);
  632. }
  633. }
  634. }
  635. // code stolen from org.apache.batik.util and modified slightly
  636. // does what sun.misc.Service probably does, but it cannot be relied on.
  637. // hopefully will be part of standard jdk sometime.
  638. /**
  639. * This class loads services present in the class path.
  640. */
  641. class Service {
  642. private static Map providerMap = new java.util.Hashtable();
  643. public static synchronized Iterator providers(Class cls) {
  644. ClassLoader cl = cls.getClassLoader();
  645. // null if loaded by bootstrap class loader
  646. if (cl == null) {
  647. cl = ClassLoader.getSystemClassLoader();
  648. }
  649. String serviceFile = "META-INF/services/" + cls.getName();
  650. // getLogger().debug("File: " + serviceFile);
  651. List lst = (List)providerMap.get(serviceFile);
  652. if (lst != null) {
  653. return lst.iterator();
  654. }
  655. lst = new java.util.Vector();
  656. providerMap.put(serviceFile, lst);
  657. Enumeration e;
  658. try {
  659. e = cl.getResources(serviceFile);
  660. } catch (IOException ioe) {
  661. return lst.iterator();
  662. }
  663. while (e.hasMoreElements()) {
  664. try {
  665. java.net.URL u = (java.net.URL)e.nextElement();
  666. //getLogger().debug("URL: " + u);
  667. InputStream is = u.openStream();
  668. Reader r = new InputStreamReader(is, "UTF-8");
  669. BufferedReader br = new BufferedReader(r);
  670. String line = br.readLine();
  671. while (line != null) {
  672. try {
  673. // First strip any comment...
  674. int idx = line.indexOf('#');
  675. if (idx != -1) {
  676. line = line.substring(0, idx);
  677. }
  678. // Trim whitespace.
  679. line = line.trim();
  680. // If nothing left then loop around...
  681. if (line.length() == 0) {
  682. line = br.readLine();
  683. continue;
  684. }
  685. // getLogger().debug("Line: " + line);
  686. // Try and load the class
  687. // Object obj = cl.loadClass(line).newInstance();
  688. // stick it into our vector...
  689. lst.add(line);
  690. } catch (Exception ex) {
  691. // Just try the next line
  692. }
  693. line = br.readLine();
  694. }
  695. } catch (Exception ex) {
  696. // Just try the next file...
  697. }
  698. }
  699. return lst.iterator();
  700. }
  701. }