From 506dc799d08fece47bd72f1d0ede606a80013c52 Mon Sep 17 00:00:00 2001 From: Kelly Campbell Date: Sat, 3 Mar 2001 07:06:04 +0000 Subject: [PATCH] Refactored Driver to simplify usage required for other apps to integrate Fop. PR: Obtained from: Submitted by: Reviewed by: git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@194114 13f79535-47bb-0310-9956-ffa450edef68 --- docs/examples/embedding/FopServlet.java | 14 +- src/org/apache/fop/apps/AWTStarter.java | 10 +- .../apache/fop/apps/CommandLineOptions.java | 10 +- .../apache/fop/apps/CommandLineStarter.java | 13 +- src/org/apache/fop/apps/Driver.java | 571 ++++++++++-------- src/org/apache/fop/apps/FOPException.java | 11 + src/org/apache/fop/apps/PrintStarter.java | 4 - .../apache/fop/tools/DocumentInputSource.java | 48 ++ src/org/apache/fop/tools/DocumentReader.java | 520 ++++++++++++++++ src/org/apache/fop/tools/anttasks/Fop.java | 48 +- 10 files changed, 934 insertions(+), 315 deletions(-) create mode 100644 src/org/apache/fop/tools/DocumentInputSource.java create mode 100644 src/org/apache/fop/tools/DocumentReader.java diff --git a/docs/examples/embedding/FopServlet.java b/docs/examples/embedding/FopServlet.java index 56dbf9852..53a54ec27 100644 --- a/docs/examples/embedding/FopServlet.java +++ b/docs/examples/embedding/FopServlet.java @@ -114,17 +114,9 @@ public class FopServlet extends HttpServlet response.setContentType("application/pdf"); - Driver driver = new Driver(); - driver.setRenderer("org.apache.fop.render.pdf.PDFRenderer", - Version.getVersion()); - driver.addElementMapping("org.apache.fop.fo.StandardElementMapping"); - driver.addElementMapping("org.apache.fop.svg.SVGElementMapping"); - driver.addPropertyList("org.apache.fop.fo.StandardPropertyListMapping"); - driver.addPropertyList("org.apache.fop.svg.SVGPropertyListMapping"); - driver.setOutputStream(out); - driver.buildFOTree(createParser(), foFile); - driver.format(); - driver.render(); + Driver driver = new Driver(foFile, out); + driver.run(); + byte[] content = out.toByteArray(); response.setContentLength(content.length); response.getOutputStream().write(content); diff --git a/src/org/apache/fop/apps/AWTStarter.java b/src/org/apache/fop/apps/AWTStarter.java index 061c391ba..1aa7de739 100644 --- a/src/org/apache/fop/apps/AWTStarter.java +++ b/src/org/apache/fop/apps/AWTStarter.java @@ -90,7 +90,7 @@ public class AWTStarter extends CommandLineStarter { public void run () { - Driver driver = new Driver(); + Driver driver = new Driver(); if (errorDump) { driver.setErrorDump(true); } @@ -109,14 +109,6 @@ public class AWTStarter extends CommandLineStarter { try { driver.setRenderer(renderer); - // init mappings: time - frame.progress(resource.getString("Init mappings") + " ..."); - - driver.addElementMapping("org.apache.fop.fo.StandardElementMapping"); - driver.addElementMapping("org.apache.fop.svg.SVGElementMapping"); - driver.addPropertyList("org.apache.fop.fo.StandardPropertyListMapping"); - driver.addPropertyList("org.apache.fop.svg.SVGPropertyListMapping"); - // build FO tree: time frame.progress(resource.getString("Build FO tree") + " ..."); driver.buildFOTree(parser, inputHandler.getInputSource()); diff --git a/src/org/apache/fop/apps/CommandLineOptions.java b/src/org/apache/fop/apps/CommandLineOptions.java index 939fc2c64..ccac4966d 100644 --- a/src/org/apache/fop/apps/CommandLineOptions.java +++ b/src/org/apache/fop/apps/CommandLineOptions.java @@ -260,18 +260,18 @@ public class CommandLineOptions { /** * returns the chosen renderer, throws FOPException */ - public String getRenderer () throws FOPException { + public int getRenderer () throws FOPException { switch (outputmode) { case NOT_SET: throw new FOPException("Renderer has not been set!"); case PDF_OUTPUT: - return "org.apache.fop.render.pdf.PDFRenderer"; + return Driver.RENDER_PDF; case AWT_OUTPUT: - return "org.apache.fop.render.awt.AWTRenderer"; + return Driver.RENDER_AWT; case MIF_OUTPUT: - return "org.apache.fop.render.mif.MIFRenderer"; + return Driver.RENDER_MIF; case PRINT_OUTPUT: - return "org.apache.fop.render.awt.PrintRenderer"; + return Driver.RENDER_PRINT; default: throw new FOPException("Invalid Renderer setting!"); } diff --git a/src/org/apache/fop/apps/CommandLineStarter.java b/src/org/apache/fop/apps/CommandLineStarter.java index fe8cddec6..7d6aae9fc 100644 --- a/src/org/apache/fop/apps/CommandLineStarter.java +++ b/src/org/apache/fop/apps/CommandLineStarter.java @@ -38,20 +38,15 @@ public class CommandLineStarter extends Starter { XMLReader parser = inputHandler.getParser(); setParserFeatures(parser,errorDump); - Driver driver = new Driver(); + Driver driver = new Driver(); if (errorDump) { driver.setErrorDump(true); } try { - driver.setRenderer(commandLineOptions.getRenderer(), ""); - driver.addElementMapping("org.apache.fop.fo.StandardElementMapping"); - driver.addElementMapping("org.apache.fop.svg.SVGElementMapping"); - driver.addElementMapping("org.apache.fop.extensions.ExtensionElementMapping"); - driver.addPropertyList("org.apache.fop.fo.StandardPropertyListMapping"); - driver.addPropertyList("org.apache.fop.svg.SVGPropertyListMapping"); - driver.addPropertyList("org.apache.fop.extensions.ExtensionPropertyListMapping"); - driver.buildFOTree(parser,inputHandler.getInputSource()); + driver.setRenderer(commandLineOptions.getRenderer()); + + driver.buildFOTree(parser, inputHandler.getInputSource()); driver.format(); driver.setOutputStream(new FileOutputStream(commandLineOptions.getOutputFile())); driver.render(); diff --git a/src/org/apache/fop/apps/Driver.java b/src/org/apache/fop/apps/Driver.java index 0490b62df..9bb0099c4 100644 --- a/src/org/apache/fop/apps/Driver.java +++ b/src/org/apache/fop/apps/Driver.java @@ -17,6 +17,8 @@ import org.apache.fop.render.Renderer; import org.apache.fop.messaging.MessageHandler; import org.apache.fop.configuration.ConfigurationReader; import org.apache.fop.configuration.Configuration; +import org.apache.fop.tools.DocumentInputSource; +import org.apache.fop.tools.DocumentReader; // DOM @@ -37,370 +39,443 @@ import java.io.*; /** - *

Primary class that drives overall FOP process. + * Primary class that drives overall FOP process. + *

+ * The simplest way to use this is to instantiate it with the + * InputSource and OutputStream, then set the renderer desired, and + * calling run(); + *

+ * Here is an example use of Driver which outputs PDF: * - *

Once this class is instantiated, methods are called to set the + *

+ *   Driver driver = new Driver(new InputSource (args[0]), 
+ *                              new FileOutputStream(args[1]));
+ *   driver.setRenderer(RENDER_PDF);
+ *   driver.run();
+ * 
+ + * If neccessary, calling classes can call into the lower level + * methods to setup and + * render. Methods can be called to set the * Renderer to use, the (possibly multiple) ElementMapping(s) to - * use and the PrintWriter to use to output the results of the + * use and the OutputStream to use to output the results of the * rendering (where applicable). In the case of the Renderer and * ElementMapping(s), the Driver may be supplied either with the * object itself, or the name of the class, in which case Driver will * instantiate the class itself. The advantage of the latter is it * enables runtime determination of Renderer and ElementMapping(s). - * - *

Once the Driver is set up, the buildFOTree method + *

+ * Once the Driver is set up, the buildFOTree method * is called. Depending on whether DOM or SAX is being used, the * invocation of the method is either buildFOTree(Document) or * buildFOTree(Parser, InputSource) respectively. - * - *

A third possibility may be used to build the FO Tree, namely + *

+ * A third possibility may be used to build the FO Tree, namely * calling getContentHandler() and firing the SAX events yourself. - * - *

Once the FO Tree is built, the format() and render() methods may be + *

+ * Once the FO Tree is built, the format() and render() methods may be * called in that order. - * - *

Here is an example use of Driver from CommandLine.java: + *

+ * Here is an example use of Driver which outputs to AWT: * *

  *   Driver driver = new Driver();
- *   driver.setRenderer("org.apache.fop.render.pdf.PDFRenderer", version);
- *   driver.addElementMapping("org.apache.fop.fo.StandardElementMapping");
- *   driver.addElementMapping("org.apache.fop.svg.SVGElementMapping");
- *   driver.addPropertyList("org.apache.fop.fo.StandardPropertyListMapping");
- *   driver.addPropertyList("org.apache.fop.svg.SVGPropertyListMapping");
- *   driver.setOutputStream(new FileOutputStream(args[1]));
+ *   driver.setRenderer(new org.apache.fop.render.awt.AWTRenderer(translator));
  *   driver.buildFOTree(parser, fileInputSource(args[0]));
  *   driver.format();
  *   driver.render();
  * 
*/ public class Driver { + + /** Render to PDF. OutputStream must be set */ + public static final int RENDER_PDF = 1; + + /** Render to a GUI window. No OutputStream neccessary */ + public static final int RENDER_AWT = 2; + + /** Render to MIF. OutputStream must be set */ + public static final int RENDER_MIF = 3; + + /** Render to XML. OutputStream must be set */ + public static final int RENDER_XML = 4; + + /** Render to PRINT. No OutputStream neccessary */ + public static final int RENDER_PRINT = 5; /** the FO tree builder */ - protected FOTreeBuilder treeBuilder; + private FOTreeBuilder _treeBuilder; /** the area tree that is the result of formatting the FO tree */ - protected AreaTree areaTree; + private AreaTree _areaTree; /** the renderer to use to output the area tree */ - protected Renderer renderer; + private Renderer _renderer; + /** the source of the FO file */ + private InputSource _source; + /** the stream to use to output the results of the renderer */ - protected OutputStream stream; + private OutputStream _stream; + /** The XML parser to use when building the FO tree */ + private XMLReader _reader; + /** If true, full error stacks are reported */ - protected boolean errorDump = false; + private boolean _errorDump = false; /** create a new Driver */ public Driver() { - this.treeBuilder = new FOTreeBuilder(); + reset(); + } + + public Driver(InputSource source, OutputStream stream) { + this(); + _source = source; + _stream = stream; } - /** Set the error dump option - * @param dump if true, full stacks will be reported to the error log - */ + /** + * Resets the Driver so it can be reused. Property and element mappings are reset to defaults. + * The output stream is cleared. The renderer is cleared. + */ + public synchronized void reset() + { + _stream = null; + _treeBuilder = new FOTreeBuilder(); + setupDefaultMappings(); + } + + /** + * Set the error dump option + * @param dump if true, full stacks will be reported to the error log + */ public void setErrorDump(boolean dump) { - errorDump = dump; + _errorDump = dump; } - /** set the Renderer to use */ - public void setRenderer(Renderer renderer) { - this.renderer = renderer; + /** + * Set the OutputStream to use to output the result of the Renderer + * (if applicable) + * @param stream the stream to output the result of rendering to + * + */ + public void setOutputStream(OutputStream stream) { + _stream = stream; } /** - * set the class name of the Renderer to use as well as the - * producer string for those renderers that can make use of it - */ - public void setRenderer(String rendererClassName, String producer) { - this.renderer = createRenderer(rendererClassName); - this.renderer.setProducer(producer); + * Set the source for the FO document. This can be a normal SAX + * InputSource, or an DocumentInputSource containing a DOM document. + * @see DocumentInputSource + */ + public void setInputSource(InputSource source) + { + _source = source; } + + /** + * Sets the reader used when reading in the source. If not set, + * this defaults to a basic SAX parser. + */ + public void setXMLReader(XMLReader reader) + { + _reader = reader; + } + /** - * protected method used by setRenderer(String, String) to - * instantiate the Renderer class - */ - protected Renderer createRenderer(String rendererClassName) { - MessageHandler.logln("using renderer " + rendererClassName); + * Sets all the element and property list mappings to their default values. + * + */ + public void setupDefaultMappings() + { + addElementMapping("org.apache.fop.fo.StandardElementMapping"); + addPropertyList ("org.apache.fop.fo.StandardPropertyListMapping"); + + addElementMapping("org.apache.fop.svg.SVGElementMapping"); + addPropertyList ("org.apache.fop.svg.SVGPropertyListMapping"); + + addElementMapping("org.apache.fop.extensions.ExtensionElementMapping"); + addPropertyList ("org.apache.fop.extensions.ExtensionPropertyListMapping"); + } - try { - return (Renderer) Class.forName( - rendererClassName).newInstance(); - } catch (ClassNotFoundException e) { - MessageHandler.errorln("Could not find " + rendererClassName); + /** + * Set the rendering type to use. Must be one of + * + * @param renderer the type of renderer to use + */ + public void setRenderer(int renderer) + throws IllegalArgumentException + { + switch (renderer) { + case RENDER_PDF: + setRenderer(new org.apache.fop.render.pdf.PDFRenderer()); + break; + case RENDER_AWT: + throw new IllegalArgumentException("Use renderer form of setRenderer() for AWT"); + case RENDER_PRINT: + throw new IllegalArgumentException("Use renderer form of setRenderer() for PRINT"); + case RENDER_MIF: + setRenderer(new org.apache.fop.render.mif.MIFRenderer()); + break; + case RENDER_XML: + setRenderer(new org.apache.fop.render.xml.XMLRenderer()); + break; + default: + throw new IllegalArgumentException("Unknown renderer type"); + } + + } + + + /** + * Set the Renderer to use + * @param renderer the renderer instance to use + */ + public void setRenderer(Renderer renderer) { + _renderer = renderer; + } + + /** + * @deprecated use renderer.setProducer(version) + setRenderer(renderer) or just setRenderer(renderer_type) which will use the default producer string. + * @see #setRenderer(int) + * @see #setRenderer(Renderer) + */ + public void setRenderer(String rendererClassName, String version) + { + setRenderer(rendererClassName); + } + + /** + * Set the class name of the Renderer to use as well as the + * producer string for those renderers that can make use of it. + * @param rendererClassName classname of the renderer to use such as + * "org.apache.fop.render.pdf.PDFRenderer" + * @exception IllegalArgumentException if the classname was invalid. + * @see #setRenderer(int) + */ + public void setRenderer(String rendererClassName) + throws IllegalArgumentException + { + try { + _renderer = (Renderer) Class.forName(rendererClassName).newInstance(); + _renderer.setProducer(Version.getVersion()); + } + catch (ClassNotFoundException e) { + throw new IllegalArgumentException("Could not find " + + rendererClassName); } catch (InstantiationException e) { - MessageHandler.errorln("Could not instantiate " + + throw new IllegalArgumentException("Could not instantiate " + rendererClassName); } catch (IllegalAccessException e) { - MessageHandler.errorln("Could not access " + rendererClassName); + throw new IllegalArgumentException("Could not access " + rendererClassName); } catch (ClassCastException e) { - MessageHandler.errorln(rendererClassName + " is not a renderer"); + throw new IllegalArgumentException(rendererClassName + " is not a renderer"); } - return null; } /** - * add the given element mapping. - * - * an element mapping maps element names to Java classes - */ + * Add the given element mapping. + * An element mapping maps element names to Java classes. + * + * @param mapping the element mappingto add + */ public void addElementMapping(ElementMapping mapping) { - mapping.addToBuilder(this.treeBuilder); + mapping.addToBuilder(_treeBuilder); } /** - * add the element mapping with the given class name - */ - public void addElementMapping(String mappingClassName) { - createElementMapping(mappingClassName).addToBuilder( - this.treeBuilder); - } - - /** - * protected method used by addElementMapping(String) to - * instantiate element mapping class - */ - protected ElementMapping createElementMapping( - String mappingClassName) { - MessageHandler.logln("using element mapping " + mappingClassName); - - try { - return (ElementMapping) Class.forName( + * add the element mapping with the given class name + */ + public void addElementMapping(String mappingClassName) + throws IllegalArgumentException + { + try { + ElementMapping mapping = (ElementMapping) Class.forName( mappingClassName).newInstance(); - } catch (ClassNotFoundException e) { - MessageHandler.errorln("Could not find " + mappingClassName); - dumpError(e); - } + addElementMapping(mapping); + } catch (ClassNotFoundException e) { + throw new IllegalArgumentException("Could not find " + mappingClassName); + } catch (InstantiationException e) { - MessageHandler.errorln("Could not instantiate " + + throw new IllegalArgumentException("Could not instantiate " + mappingClassName); - dumpError(e); - } + } catch (IllegalAccessException e) { - MessageHandler.errorln("Could not access " + mappingClassName); - dumpError(e); - } + throw new IllegalArgumentException("Could not access " + mappingClassName); + } catch (ClassCastException e) { - MessageHandler.errorln(mappingClassName + " is not an element mapping"); - dumpError(e); - } - return null; + throw new IllegalArgumentException(mappingClassName + " is not an ElementMapping"); + } } /** - * add the element mapping with the given class name - */ - public void addPropertyList(String listClassName) { - createPropertyList(listClassName).addToBuilder(this.treeBuilder); + * Add the PropertyListMapping. + */ + public void addPropertyList(PropertyListMapping mapping) + { + mapping.addToBuilder(_treeBuilder); } + /** - * protected method used by addPropertyList(String) to - * instantiate list mapping class - */ - protected PropertyListMapping createPropertyList( - String listClassName) { - MessageHandler.logln("using property list mapping " + - listClassName); - - try { - return (PropertyListMapping) Class.forName( + * Add the PropertyListMapping with the given class name. + */ + public void addPropertyList(String listClassName) + throws IllegalArgumentException + { + try { + PropertyListMapping mapping = (PropertyListMapping) Class.forName( listClassName).newInstance(); - } catch (ClassNotFoundException e) { - MessageHandler.errorln("Could not find " + listClassName); - dumpError(e); - } + addPropertyList(mapping); + + } catch (ClassNotFoundException e) { + throw new IllegalArgumentException("Could not find " + listClassName); + } catch (InstantiationException e) { - MessageHandler.errorln("Could not instantiate " + - listClassName); - dumpError(e); - } + throw new IllegalArgumentException("Could not instantiate " + + listClassName); + } catch (IllegalAccessException e) { - MessageHandler.errorln("Could not access " + listClassName); - dumpError(e); - } + throw new IllegalArgumentException("Could not access " + listClassName); + } catch (ClassCastException e) { - MessageHandler.errorln(listClassName + " is not an property list"); - dumpError(e); - } - return null; + throw new IllegalArgumentException(listClassName + " is not an ElementMapping"); + } } /** - * return the tree builder (a SAX ContentHandler). - * - * used in situations where SAX is used but not via a FOP-invoked - * SAX parser. A good example is an XSLT engine that fires SAX - * events but isn't a SAX Parser itself. - */ + * Returns the tree builder (a SAX ContentHandler). + * + * Used in situations where SAX is used but not via a FOP-invoked + * SAX parser. A good example is an XSLT engine that fires SAX + * events but isn't a SAX Parser itself. + */ public ContentHandler getContentHandler() { - return this.treeBuilder; + return _treeBuilder; } /** - * build the formatting object tree using the given SAX Parser and - * SAX InputSource - */ - public void buildFOTree(XMLReader parser, - InputSource source) throws FOPException { - - parser.setContentHandler(this.treeBuilder); + * Build the formatting object tree using the given SAX Parser and + * SAX InputSource + */ + public synchronized void buildFOTree(XMLReader parser, + InputSource source) + throws FOPException + { + + parser.setContentHandler(_treeBuilder); try { parser.parse(source); } catch (SAXException e) { if (e.getException() instanceof FOPException) { - dumpError(e.getException()); throw (FOPException) e.getException(); } else { - dumpError(e); - throw new FOPException(e.getMessage()); + throw new FOPException(e); } } catch (IOException e) { - dumpError(e); - throw new FOPException(e.getMessage()); + throw new FOPException(e); } } /** - * build the formatting object tree using the given DOM Document - */ - public void buildFOTree(Document document) throws FOPException { - - /* most of this code is modified from John Cowan's */ - - Node currentNode; - AttributesImpl currentAtts; - - /* temporary array for making Strings into character arrays */ - char[] array = null; - - currentAtts = new AttributesImpl(); - - /* start at the document element */ - currentNode = document; - - try { - while (currentNode != null) { - switch (currentNode.getNodeType()) { - case Node.DOCUMENT_NODE: - this.treeBuilder.startDocument(); - break; - case Node.CDATA_SECTION_NODE: - case Node.TEXT_NODE: - String data = currentNode.getNodeValue(); - int datalen = data.length(); - if (array == null || array.length < datalen) { - /* if the array isn't big enough, make a new - one */ - array = new char[datalen]; - } - data.getChars(0, datalen, array, 0); - this.treeBuilder.characters(array, 0, datalen); - break; - case Node.PROCESSING_INSTRUCTION_NODE: - this.treeBuilder.processingInstruction( - currentNode.getNodeName(), - currentNode.getNodeValue()); - break; - case Node.ELEMENT_NODE: - NamedNodeMap map = currentNode.getAttributes(); - currentAtts.clear(); - for (int i = map.getLength() - 1; i >= 0; i--) { - Attr att = (Attr) map.item(i); - currentAtts.addAttribute( att.getNamespaceURI(), - att.getLocalName(), att.getName(), - "CDATA", att.getValue()); - } - this.treeBuilder.startElement( - currentNode.getNamespaceURI(), - currentNode.getLocalName(), - currentNode.getNodeName(), currentAtts); - break; - } - - Node nextNode = currentNode.getFirstChild(); - if (nextNode != null) { - currentNode = nextNode; - continue; - } - - while (currentNode != null) { - switch (currentNode.getNodeType()) { - case Node.DOCUMENT_NODE: - this.treeBuilder.endDocument(); - break; - case Node.ELEMENT_NODE: - this.treeBuilder.endElement( - currentNode.getNamespaceURI(), - currentNode.getLocalName(), - currentNode.getNodeName()); - break; - } - - nextNode = currentNode.getNextSibling(); - if (nextNode != null) { - currentNode = nextNode; - break; - } - - currentNode = currentNode.getParentNode(); - } - } - } catch (SAXException e) { - dumpError(e); - throw new FOPException(e.getMessage()); - } - } + * Build the formatting object tree using the given DOM Document + */ + public synchronized void buildFOTree(Document document) + throws FOPException + { + try { + DocumentInputSource source = new DocumentInputSource(document); + DocumentReader reader = new DocumentReader(); + reader.setContentHandler(_treeBuilder); + reader.parse(source); + } catch (SAXException e) { + throw new FOPException(e); + } catch (IOException e) { + throw new FOPException(e); + } + + } /** - * Dumps an error - */ + * Dumps an error + */ public void dumpError(Exception e) { - if (errorDump) { + if (_errorDump) { if (e instanceof SAXException) { e.printStackTrace(); if (((SAXException) e).getException() != null) { ((SAXException) e).getException().printStackTrace(); } - } else { + } + else if (e instanceof FOPException) { + e.printStackTrace(); + if (((FOPException) e).getException() != null) { + ((FOPException) e).getException().printStackTrace(); + } + } + else { e.printStackTrace(); } } - } /** - * set the OutputStream to use to output the result of the Renderer - * (if applicable) - */ - public void setOutputStream(OutputStream stream) { - this.stream = stream; - } - - /** - * format the formatting object tree into an area tree - */ - public void format() throws FOPException { + * format the formatting object tree into an area tree + */ + public synchronized void format() throws FOPException { FontInfo fontInfo = new FontInfo(); - this.renderer.setupFontInfo(fontInfo); + _renderer.setupFontInfo(fontInfo); - this.areaTree = new AreaTree(); - this.areaTree.setFontInfo(fontInfo); + _areaTree = new AreaTree(); + _areaTree.setFontInfo(fontInfo); - this.treeBuilder.format(areaTree); + _treeBuilder.format(_areaTree); } /** - * render the area tree to the output form - */ - public void render() throws IOException, FOPException { - this.renderer.render(areaTree, this.stream); + * render the area tree to the output form + */ + public synchronized void render() throws IOException, FOPException { + _renderer.render(_areaTree, _stream); } - + /** + * Runs the formatting and renderering process using the previously set + * inputsource and outputstream + */ + public synchronized void run() + throws IOException, FOPException + { + if (_renderer == null) { + setRenderer(RENDER_PDF); + } + if (_source == null) { + throw new FOPException("InputSource is not set."); + } + if (_reader == null) { + if (!(_source instanceof DocumentInputSource)) { + _reader = ConfigurationReader.createParser(); + } + } + if (_source instanceof DocumentInputSource) { + buildFOTree(((DocumentInputSource)_source).getDocument()); + } + else { + buildFOTree(_reader, _source); + } + format(); + render(); + } + } diff --git a/src/org/apache/fop/apps/FOPException.java b/src/org/apache/fop/apps/FOPException.java index d28d36052..94ca52bdf 100644 --- a/src/org/apache/fop/apps/FOPException.java +++ b/src/org/apache/fop/apps/FOPException.java @@ -11,6 +11,8 @@ package org.apache.fop.apps; */ public class FOPException extends Exception { + private Throwable _exception; + /** * create a new FOP Exception * @@ -19,4 +21,13 @@ public class FOPException extends Exception { public FOPException(String message) { super(message); } + public FOPException(Throwable e) { + super(e.getMessage()); + _exception = e; + } + + public Throwable getException() + { + return _exception; + } } diff --git a/src/org/apache/fop/apps/PrintStarter.java b/src/org/apache/fop/apps/PrintStarter.java index e246335cc..91c24f9ba 100644 --- a/src/org/apache/fop/apps/PrintStarter.java +++ b/src/org/apache/fop/apps/PrintStarter.java @@ -65,10 +65,6 @@ public class PrintStarter extends CommandLineStarter { try { driver.setRenderer(renderer); - driver.addElementMapping("org.apache.fop.fo.StandardElementMapping"); - driver.addElementMapping("org.apache.fop.svg.SVGElementMapping"); - driver.addPropertyList("org.apache.fop.fo.StandardPropertyListMapping"); - driver.addPropertyList("org.apache.fop.svg.SVGPropertyListMapping"); driver.buildFOTree(parser, inputHandler.getInputSource()); driver.format(); driver.render(); diff --git a/src/org/apache/fop/tools/DocumentInputSource.java b/src/org/apache/fop/tools/DocumentInputSource.java new file mode 100644 index 000000000..1228ce05a --- /dev/null +++ b/src/org/apache/fop/tools/DocumentInputSource.java @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2001 The Apache Software Foundation. All rights reserved. + * For details on use and redistribution please refer to the + * LICENSE file included with these sources." + */ + + +package org.apache.fop.tools; + +import java.util.*; +import org.w3c.dom.*; +import org.xml.sax.*; + +/** + * This is an InputSource to be used with DocumentReader. + * + * @author Kelly A Campbell + * + */ + +public class DocumentInputSource extends InputSource +{ + private Document _document; + + public DocumentInputSource() + { + super(); + } + + public DocumentInputSource(Document document) + { + this(); + _document = document; + } + + public Document getDocument() + { + return _document; + } + + public void setDocument(Document document) + { + _document = document; + } + +} + + diff --git a/src/org/apache/fop/tools/DocumentReader.java b/src/org/apache/fop/tools/DocumentReader.java new file mode 100644 index 000000000..2abdd537c --- /dev/null +++ b/src/org/apache/fop/tools/DocumentReader.java @@ -0,0 +1,520 @@ +/* + * Copyright (C) 2001 The Apache Software Foundation. All rights reserved. + * For details on use and redistribution please refer to the + * LICENSE file included with these sources." + */ + + +package org.apache.fop.tools; + +import java.io.IOException; +//import java.util.*; + +// DOM +import org.w3c.dom.*; + +// SAX +import org.xml.sax.*; +import org.xml.sax.helpers.AttributesImpl; + +/** + * This presents a DOM as an XMLReader to make it easy to use a Document + * with a SAX-based implementation. + * + * @author Kelly A Campbell + * + */ + +public class DocumentReader implements XMLReader +{ + + //////////////////////////////////////////////////////////////////// + // Configuration. + //////////////////////////////////////////////////////////////////// + private boolean _namespaces = true; + private boolean _namespace_prefixes = true; + + + /** + * Look up the value of a feature. + * + *

The feature name is any fully-qualified URI. It is + * possible for an XMLReader to recognize a feature name but + * to be unable to return its value; this is especially true + * in the case of an adapter for a SAX1 Parser, which has + * no way of knowing whether the underlying parser is + * performing validation or expanding external entities.

+ * + *

All XMLReaders are required to recognize the + * http://xml.org/sax/features/namespaces and the + * http://xml.org/sax/features/namespace-prefixes feature names.

+ * + *

Some feature values may be available only in specific + * contexts, such as before, during, or after a parse.

+ * + *

Typical usage is something like this:

+ * + *
+     * XMLReader r = new MySAXDriver();
+     *
+     *                         // try to activate validation
+     * try {
+     *   r.setFeature("http://xml.org/sax/features/validation", true);
+     * } catch (SAXException e) {
+     *   System.err.println("Cannot activate validation."); 
+     * }
+     *
+     *                         // register event handlers
+     * r.setContentHandler(new MyContentHandler());
+     * r.setErrorHandler(new MyErrorHandler());
+     *
+     *                         // parse the first document
+     * try {
+     *   r.parse("http://www.foo.com/mydoc.xml");
+     * } catch (IOException e) {
+     *   System.err.println("I/O exception reading XML document");
+     * } catch (SAXException e) {
+     *   System.err.println("XML exception reading document.");
+     * }
+     * 
+ * + *

Implementors are free (and encouraged) to invent their own features, + * using names built on their own URIs.

+ * + * @param name The feature name, which is a fully-qualified URI. + * @return The current state of the feature (true or false). + * @exception org.xml.sax.SAXNotRecognizedException When the + * XMLReader does not recognize the feature name. + * @exception org.xml.sax.SAXNotSupportedException When the + * XMLReader recognizes the feature name but + * cannot determine its value at this time. + * @see #setFeature + */ + public boolean getFeature (String name) + throws SAXNotRecognizedException, SAXNotSupportedException + { + if ("http://xml.org/sax/features/namespaces".equals(name)) { + return _namespaces; + } + else if ("http://xml.org/sax/features/namespace-prefixes".equals(name)) { + return _namespace_prefixes; + } + else { + throw new SAXNotRecognizedException("Feature '"+name+"' not recognized or supported by Document2SAXAdapter"); + } + + } + + + + /** + * Set the state of a feature. + * + *

The feature name is any fully-qualified URI. It is + * possible for an XMLReader to recognize a feature name but + * to be unable to set its value; this is especially true + * in the case of an adapter for a SAX1 {@link org.xml.sax.Parser Parser}, + * which has no way of affecting whether the underlying parser is + * validating, for example.

+ * + *

All XMLReaders are required to support setting + * http://xml.org/sax/features/namespaces to true and + * http://xml.org/sax/features/namespace-prefixes to false.

+ * + *

Some feature values may be immutable or mutable only + * in specific contexts, such as before, during, or after + * a parse.

+ * + * @param name The feature name, which is a fully-qualified URI. + * @param state The requested state of the feature (true or false). + * @exception org.xml.sax.SAXNotRecognizedException When the + * XMLReader does not recognize the feature name. + * @exception org.xml.sax.SAXNotSupportedException When the + * XMLReader recognizes the feature name but + * cannot set the requested value. + * @see #getFeature + */ + public void setFeature (String name, boolean value) + throws SAXNotRecognizedException, SAXNotSupportedException + { + if ("http://xml.org/sax/features/namespaces".equals(name)) { + _namespaces = value; + } + else if ("http://xml.org/sax/features/namespace-prefixes".equals(name)) { + _namespace_prefixes = value; + } + else { + throw new SAXNotRecognizedException("Feature '"+name+"' not recognized or supported by Document2SAXAdapter"); + } + + } + + + + /** + * Look up the value of a property. + * + *

The property name is any fully-qualified URI. It is + * possible for an XMLReader to recognize a property name but + * to be unable to return its state; this is especially true + * in the case of an adapter for a SAX1 {@link org.xml.sax.Parser + * Parser}.

+ * + *

XMLReaders are not required to recognize any specific + * property names, though an initial core set is documented for + * SAX2.

+ * + *

Some property values may be available only in specific + * contexts, such as before, during, or after a parse.

+ * + *

Implementors are free (and encouraged) to invent their own properties, + * using names built on their own URIs.

+ * + * @param name The property name, which is a fully-qualified URI. + * @return The current value of the property. + * @exception org.xml.sax.SAXNotRecognizedException When the + * XMLReader does not recognize the property name. + * @exception org.xml.sax.SAXNotSupportedException When the + * XMLReader recognizes the property name but + * cannot determine its value at this time. + * @see #setProperty + */ + public Object getProperty (String name) + throws SAXNotRecognizedException, SAXNotSupportedException + { + throw new SAXNotRecognizedException("Property '"+name+"' not recognized or supported by Document2SAXAdapter"); + } + + + + /** + * Set the value of a property. + * + *

The property name is any fully-qualified URI. It is + * possible for an XMLReader to recognize a property name but + * to be unable to set its value; this is especially true + * in the case of an adapter for a SAX1 {@link org.xml.sax.Parser + * Parser}.

+ * + *

XMLReaders are not required to recognize setting + * any specific property names, though a core set is provided with + * SAX2.

+ * + *

Some property values may be immutable or mutable only + * in specific contexts, such as before, during, or after + * a parse.

+ * + *

This method is also the standard mechanism for setting + * extended handlers.

+ * + * @param name The property name, which is a fully-qualified URI. + * @param state The requested value for the property. + * @exception org.xml.sax.SAXNotRecognizedException When the + * XMLReader does not recognize the property name. + * @exception org.xml.sax.SAXNotSupportedException When the + * XMLReader recognizes the property name but + * cannot set the requested value. + */ + public void setProperty (String name, Object value) + throws SAXNotRecognizedException, SAXNotSupportedException + { + throw new SAXNotRecognizedException("Property '"+name+"' not recognized or supported by Document2SAXAdapter"); + } + + + + //////////////////////////////////////////////////////////////////// + // Event handlers. + //////////////////////////////////////////////////////////////////// + private EntityResolver _entityResolver = null; + private DTDHandler _dtdHandler = null; + private ContentHandler _contentHandler = null; + private ErrorHandler _errorHandler = null; + + + /** + * Allow an application to register an entity resolver. + * + *

If the application does not register an entity resolver, + * the XMLReader will perform its own default resolution.

+ * + *

Applications may register a new or different resolver in the + * middle of a parse, and the SAX parser must begin using the new + * resolver immediately.

+ * + * @param resolver The entity resolver. + * @exception java.lang.NullPointerException If the resolver + * argument is null. + * @see #getEntityResolver + */ + public void setEntityResolver (EntityResolver resolver) + { + _entityResolver = resolver; + } + + + + /** + * Return the current entity resolver. + * + * @return The current entity resolver, or null if none + * has been registered. + * @see #setEntityResolver + */ + public EntityResolver getEntityResolver () + { + return _entityResolver; + } + + + + /** + * Allow an application to register a DTD event handler. + * + *

If the application does not register a DTD handler, all DTD + * events reported by the SAX parser will be silently ignored.

+ * + *

Applications may register a new or different handler in the + * middle of a parse, and the SAX parser must begin using the new + * handler immediately.

+ * + * @param handler The DTD handler. + * @exception java.lang.NullPointerException If the handler + * argument is null. + * @see #getDTDHandler + */ + public void setDTDHandler (DTDHandler handler) + { + _dtdHandler = handler; + } + + + + /** + * Return the current DTD handler. + * + * @return The current DTD handler, or null if none + * has been registered. + * @see #setDTDHandler + */ + public DTDHandler getDTDHandler () + { + return _dtdHandler; + } + + + + /** + * Allow an application to register a content event handler. + * + *

If the application does not register a content handler, all + * content events reported by the SAX parser will be silently + * ignored.

+ * + *

Applications may register a new or different handler in the + * middle of a parse, and the SAX parser must begin using the new + * handler immediately.

+ * + * @param handler The content handler. + * @exception java.lang.NullPointerException If the handler + * argument is null. + * @see #getContentHandler + */ + public void setContentHandler (ContentHandler handler) + { + _contentHandler = handler; + } + + + + /** + * Return the current content handler. + * + * @return The current content handler, or null if none + * has been registered. + * @see #setContentHandler + */ + public ContentHandler getContentHandler () + { + return _contentHandler; + } + + + + /** + * Allow an application to register an error event handler. + * + *

If the application does not register an error handler, all + * error events reported by the SAX parser will be silently + * ignored; however, normal processing may not continue. It is + * highly recommended that all SAX applications implement an + * error handler to avoid unexpected bugs.

+ * + *

Applications may register a new or different handler in the + * middle of a parse, and the SAX parser must begin using the new + * handler immediately.

+ * + * @param handler The error handler. + * @exception java.lang.NullPointerException If the handler + * argument is null. + * @see #getErrorHandler + */ + public void setErrorHandler (ErrorHandler handler) + { + _errorHandler = handler; + } + + /** + * Return the current error handler. + * + * @return The current error handler, or null if none + * has been registered. + * @see #setErrorHandler + */ + public ErrorHandler getErrorHandler () + { + return _errorHandler; + } + + + + //////////////////////////////////////////////////////////////////// + // Parsing. + //////////////////////////////////////////////////////////////////// + + /** + * Parse an XML DOM document. + * + * + * + * @param source The input source for the top-level of the + * XML document. + * @exception org.xml.sax.SAXException Any SAX exception, possibly + * wrapping another exception. + * @exception java.io.IOException An IO exception from the parser, + * possibly from a byte stream or character stream + * supplied by the application. + * @see org.xml.sax.InputSource + * @see #parse(java.lang.String) + * @see #setEntityResolver + * @see #setDTDHandler + * @see #setContentHandler + * @see #setErrorHandler + */ + public void parse (InputSource input) + throws IOException, SAXException + { + if (input instanceof DocumentInputSource) { + Document document = ((DocumentInputSource)input).getDocument(); + if (_contentHandler == null) { + throw new SAXException("ContentHandler is null. Please use setContentHandler()"); + } + + // refactored from org.apache.fop.apps.Driver + /* most of this code is modified from John Cowan's */ + + Node currentNode; + AttributesImpl currentAtts; + + /* temporary array for making Strings into character arrays */ + char[] array = null; + + currentAtts = new AttributesImpl(); + + /* start at the document element */ + currentNode = document; + while (currentNode != null) { + switch (currentNode.getNodeType()) { + case Node.DOCUMENT_NODE: + _contentHandler.startDocument(); + break; + case Node.CDATA_SECTION_NODE: + case Node.TEXT_NODE: + String data = currentNode.getNodeValue(); + int datalen = data.length(); + if (array == null || array.length < datalen) { + /* if the array isn't big enough, make a new + one */ + array = new char[datalen]; + } + data.getChars(0, datalen, array, 0); + _contentHandler.characters(array, 0, datalen); + break; + case Node.PROCESSING_INSTRUCTION_NODE: + _contentHandler.processingInstruction(currentNode.getNodeName(), + currentNode.getNodeValue()); + break; + case Node.ELEMENT_NODE: + NamedNodeMap map = currentNode.getAttributes(); + currentAtts.clear(); + for (int i = map.getLength() - 1; i >= 0; i--) { + Attr att = (Attr) map.item(i); + currentAtts.addAttribute( att.getNamespaceURI(), + att.getLocalName(), att.getName(), + "CDATA", att.getValue()); + } + _contentHandler.startElement(currentNode.getNamespaceURI(), + currentNode.getLocalName(), + currentNode.getNodeName(), + currentAtts); + break; + } + + Node nextNode = currentNode.getFirstChild(); + if (nextNode != null) { + currentNode = nextNode; + continue; + } + + while (currentNode != null) { + switch (currentNode.getNodeType()) { + case Node.DOCUMENT_NODE: + _contentHandler.endDocument(); + break; + case Node.ELEMENT_NODE: + _contentHandler.endElement(currentNode.getNamespaceURI(), + currentNode.getLocalName(), + currentNode.getNodeName()); + break; + } + + nextNode = currentNode.getNextSibling(); + if (nextNode != null) { + currentNode = nextNode; + break; + } + + currentNode = currentNode.getParentNode(); + } + } + + } + else { + throw new SAXException("DocumentReader only supports parsing of a DocumentInputSource"); + } + + } + + + + /** + * DocumentReader requires a DocumentInputSource, so this is not + * implements and simply throws a SAXException. Use parse(DocumentInputSource) + * instead + * + * @param systemId The system identifier (URI). + * @exception org.xml.sax.SAXException Any SAX exception, possibly + * wrapping another exception. + * @exception java.io.IOException An IO exception from the parser, + * possibly from a byte stream or character stream + * supplied by the application. + * @see #parse(org.xml.sax.InputSource) + */ + public void parse (String systemId) + throws IOException, SAXException + { + throw new SAXException("DocumentReader only supports parsing of a DocumentInputSource"); + } +} + + diff --git a/src/org/apache/fop/tools/anttasks/Fop.java b/src/org/apache/fop/tools/anttasks/Fop.java index ccdbfa8db..cf72a2400 100644 --- a/src/org/apache/fop/tools/anttasks/Fop.java +++ b/src/org/apache/fop/tools/anttasks/Fop.java @@ -99,42 +99,32 @@ public class Fop extends Starter { } - public void run () { - Driver driver = new Driver(); - Options options = new Options(); - boolean errors = false; + public void run () { + Options options = new Options(); + boolean errors = false; String version = Version.getVersion(); - - File fofileF = new File (fofile); - Configuration.put("baseDir",new File(fofileF.getAbsolutePath()).getParent()); - if (!fofileF.exists()) { + + File fofileF = new File (fofile); + Configuration.put("baseDir",new File(fofileF.getAbsolutePath()).getParent()); + if (!fofileF.exists()) { errors = true; - MessageHandler.errorln( - "Task Fop - ERROR: Formatting objects file " + - fofile + " missing."); + MessageHandler.errorln("Task Fop - ERROR: Formatting objects file " + + fofile + " missing."); } - - InputHandler inputHandler = new FOInputHandler(fofileF); + + InputHandler inputHandler = new FOInputHandler(fofileF); XMLReader parser = inputHandler.getParser(); - super.setParserFeatures(parser); - + super.setParserFeatures(parser); + MessageHandler.logln("=======================\nTask " + version + "\nconverting file " + fofile + " to " + pdffile); - + if (!errors) { try { - driver.setRenderer("org.apache.fop.render.pdf.PDFRenderer", - version); - driver.addElementMapping("org.apache.fop.fo.StandardElementMapping"); - driver.addElementMapping("org.apache.fop.svg.SVGElementMapping"); - driver.addElementMapping("org.apache.fop.extensions.ExtensionElementMapping"); - driver.addPropertyList("org.apache.fop.fo.StandardPropertyListMapping"); - driver.addPropertyList("org.apache.fop.svg.SVGPropertyListMapping"); - driver.addPropertyList("org.apache.fop.extensions.ExtensionPropertyListMapping"); - driver.setOutputStream(new FileOutputStream(pdffile)); - driver.buildFOTree(parser, inputHandler.fileInputSource(fofileF)); - driver.format(); - driver.render(); + Driver driver = new Driver(inputHandler.fileInputSource(fofileF), new FileOutputStream(pdffile)); + driver.setRenderer(Driver.RENDER_PDF); + driver.setXMLReader(parser); + driver.run(); } catch (Exception e) { MessageHandler.errorln("Task Fop - FATAL ERROR: " + e.getMessage()); @@ -142,7 +132,7 @@ public class Fop extends Starter { } } MessageHandler.logln("=======================\n"); - } + } /** * main method, starts execution of this task -- 2.39.5