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.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787
  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 Session which outputs PDF:
  91. *
  92. * <PRE>
  93. * Session session = new Session(new InputSource (args[0]),
  94. * new FileOutputStream(args[1]));
  95. * session.enableLogging(myLogger); //optional
  96. * session.setRenderer(RENDER_PDF);
  97. * session.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 Session may be supplied either with the
  106. * object itself, or the name of the class, in which case Session 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 Session 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 Session which outputs to AWT:
  122. *
  123. * <PRE>
  124. * Session session = new Session();
  125. * session.enableLogging(myLogger); //optional
  126. * session.setRenderer(new org.apache.fop.render.awt.AWTRenderer(translator));
  127. * session.render(parser, fileInputSource(args[0]));
  128. * </PRE>
  129. */
  130. public class Session 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 Session class.
  221. */
  222. public Session() {
  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 Session(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 Session object.
  240. */
  241. public void initialize() {
  242. if (isInitialized()) {
  243. throw new IllegalStateException("Session 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 Session
  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 Session 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 Session 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 Session 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. 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. /* Following code was stolen from org.apache.batik.util and modified slightly.
  635. It does what sun.misc.Service probably does, but it cannot be relied on.
  636. Hopefully, it will be part of standard jdk sometime.
  637. This code was formerly part of a "Service" class, the contents of which have
  638. been extracted here so that they can be used by both Session and the now-
  639. deprecated Driver class.
  640. */
  641. /**
  642. * Map of services in the classpath
  643. */
  644. private static Map providerMap = new java.util.Hashtable();
  645. /**
  646. * Loads services present in the class path.
  647. */
  648. public static synchronized Iterator providers(Class cls) {
  649. ClassLoader cl = cls.getClassLoader();
  650. // null if loaded by bootstrap class loader
  651. if (cl == null) {
  652. cl = ClassLoader.getSystemClassLoader();
  653. }
  654. String serviceFile = "META-INF/services/" + cls.getName();
  655. // getLogger().debug("File: " + serviceFile);
  656. List lst = (List)providerMap.get(serviceFile);
  657. if (lst != null) {
  658. return lst.iterator();
  659. }
  660. lst = new java.util.Vector();
  661. providerMap.put(serviceFile, lst);
  662. Enumeration e;
  663. try {
  664. e = cl.getResources(serviceFile);
  665. } catch (IOException ioe) {
  666. return lst.iterator();
  667. }
  668. while (e.hasMoreElements()) {
  669. try {
  670. java.net.URL u = (java.net.URL)e.nextElement();
  671. //getLogger().debug("URL: " + u);
  672. InputStream is = u.openStream();
  673. Reader r = new InputStreamReader(is, "UTF-8");
  674. BufferedReader br = new BufferedReader(r);
  675. String line = br.readLine();
  676. while (line != null) {
  677. try {
  678. // First strip any comment...
  679. int idx = line.indexOf('#');
  680. if (idx != -1) {
  681. line = line.substring(0, idx);
  682. }
  683. // Trim whitespace.
  684. line = line.trim();
  685. // If nothing left then loop around...
  686. if (line.length() == 0) {
  687. line = br.readLine();
  688. continue;
  689. }
  690. // getLogger().debug("Line: " + line);
  691. // Try and load the class
  692. // Object obj = cl.loadClass(line).newInstance();
  693. // stick it into our vector...
  694. lst.add(line);
  695. } catch (Exception ex) {
  696. // Just try the next line
  697. }
  698. line = br.readLine();
  699. }
  700. } catch (Exception ex) {
  701. // Just try the next file...
  702. }
  703. }
  704. return lst.iterator();
  705. }
  706. }