aboutsummaryrefslogtreecommitdiffstats
path: root/src/documentation/content/xdocs/1.1rc1/embedding.xml
diff options
context:
space:
mode:
Diffstat (limited to 'src/documentation/content/xdocs/1.1rc1/embedding.xml')
-rw-r--r--src/documentation/content/xdocs/1.1rc1/embedding.xml752
1 files changed, 752 insertions, 0 deletions
diff --git a/src/documentation/content/xdocs/1.1rc1/embedding.xml b/src/documentation/content/xdocs/1.1rc1/embedding.xml
new file mode 100644
index 000000000..24c74f970
--- /dev/null
+++ b/src/documentation/content/xdocs/1.1rc1/embedding.xml
@@ -0,0 +1,752 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<!-- $Id$ -->
+<!DOCTYPE document PUBLIC "-//APACHE//DTD Documentation V2.0//EN" "http://forrest.apache.org/dtd/document-v20.dtd">
+<!-- Embedding FOP -->
+<document>
+ <header>
+ <title>Apache™ FOP: Embedding</title>
+ <subtitle>How to Embed FOP in a Java application</subtitle>
+ <version>$Revision$</version>
+ </header>
+
+ <body>
+ <section id="overview">
+ <title>Overview</title>
+ <p>
+ Review <a href="running.html">Running Apache™ FOP</a> for important information that applies
+ to embedded applications as well as command-line use, such as options and performance.
+ </p>
+ <p>
+ To embed Apache™ FOP in your application, first create a new
+ org.apache.fop.apps.FopFactory instance. This object can be used to launch multiple
+ rendering runs. For each run, create a new org.apache.fop.apps.Fop instance through
+ one of the factory methods of FopFactory. In the method call you specify which output
+ format (i.e. MIME type) to use and, if the selected output format requires an
+ OutputStream, which OutputStream to use for the results of the rendering. You can
+ customize FOP's behaviour in a rendering run by supplying your own FOUserAgent
+ instance. The FOUserAgent can, for example, be used to set your own document handler
+ instance (details below). Finally, you retrieve a SAX DefaultHandler instance from
+ the Fop object and use that as the SAXResult of your transformation.
+ </p>
+ </section>
+ <section id="API">
+ <title>The API</title>
+ <p>
+ FOP has many classes which express the "public" access modifier, however, this is not
+ indicative of their inclusion into the public API. Every attempt will be made to keep the
+ public API static, to minimize regressions for existing users, however, since the API is not
+ clearly defined, the list of classes below are the generally agreed public API:
+ <source><![CDATA[
+org.apache.fop.apps.*
+org.apache.fop.fo.FOEventHandler
+org.apache.fop.fo.ElementMappingRegistry
+org.apache.fop.fonts.FontManager
+org.apache.fop.events.EventListener
+org.apache.fop.events.Event
+org.apache.fop.events.model.EventSeverity
+org.apache.fop.render.ImageHandlerRegistry
+org.apache.fop.render.RendererFactory
+org.apache.fop.render.intermediate.IFContext
+org.apache.fop.render.intermediate.IFDocumentHandler
+org.apache.fop.render.intermediate.IFException
+org.apache.fop.render.intermediate.IFParser
+org.apache.fop.render.intermediate.IFSerializer
+org.apache.fop.render.intermediate.IFUtil
+org.apache.fop.render.intermediate.util.IFConcatenator]]></source>
+ </p>
+ </section>
+ <section id="basics">
+ <title>Basic Usage Pattern</title>
+ <p>
+ Apache FOP relies heavily on JAXP. It uses SAX events exclusively to receive the XSL-FO
+ input document. It is therefore a good idea that you know a few things about JAXP (which
+ is a good skill anyway). Let's look at the basic usage pattern for FOP...
+ </p>
+ <p>Here is the basic pattern to render an XSL-FO file to PDF:
+ </p>
+ <source><![CDATA[
+import org.apache.fop.apps.FopFactory;
+import org.apache.fop.apps.Fop;
+import org.apache.fop.apps.MimeConstants;
+
+/*..*/
+
+// Step 1: Construct a FopFactory
+// (reuse if you plan to render multiple documents!)
+FopFactory fopFactory = FopFactory.newInstance();
+
+// Step 2: Set up output stream.
+// Note: Using BufferedOutputStream for performance reasons (helpful with FileOutputStreams).
+OutputStream out = new BufferedOutputStream(new FileOutputStream(new File("C:/Temp/myfile.pdf")));
+
+try {
+ // Step 3: Construct fop with desired output format
+ Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, out);
+
+ // Step 4: Setup JAXP using identity transformer
+ TransformerFactory factory = TransformerFactory.newInstance();
+ Transformer transformer = factory.newTransformer(); // identity transformer
+
+ // Step 5: Setup input and output for XSLT transformation
+ // Setup input stream
+ Source src = new StreamSource(new File("C:/Temp/myfile.fo"));
+
+ // Resulting SAX events (the generated FO) must be piped through to FOP
+ Result res = new SAXResult(fop.getDefaultHandler());
+
+ // Step 6: Start XSLT transformation and FOP processing
+ transformer.transform(src, res);
+
+} finally {
+ //Clean-up
+ out.close();
+}]]></source>
+ <p>
+ Let's discuss these 5 steps in detail:
+ </p>
+ <ul>
+ <li>
+ <strong>Step 1:</strong> You create a new FopFactory instance. The FopFactory instance holds
+ references to configuration information and cached data. It's important to reuse this
+ instance if you plan to render multiple documents during a JVM's lifetime.
+ </li>
+ <li>
+ <strong>Step 2:</strong> You set up an OutputStream that the generated document
+ will be written to. It's a good idea to buffer the OutputStream as demonstrated
+ to improve performance.
+ </li>
+ <li>
+ <strong>Step 3:</strong> You create a new Fop instance through one of the factory
+ methods on the FopFactory. You tell the FopFactory what your desired output format
+ is. This is done by using the MIME type of the desired output format (ex. "application/pdf").
+ You can use one of the MimeConstants.* constants. The second parameter is the
+ OutputStream you've setup up in step 2.
+ </li>
+ <li>
+ <strong>Step 4</strong> We recommend that you use JAXP Transformers even
+ if you don't do XSLT transformations to generate the XSL-FO file. This way
+ you can always use the same basic pattern. The example here sets up an
+ "identity transformer" which just passes the input (Source) unchanged to the
+ output (Result). You don't have to work with a SAXParser if you don't do any
+ XSLT transformations.
+ </li>
+ <li>
+ <strong>Step 5:</strong> Here you set up the input and output for the XSLT
+ transformation. The Source object is set up to load the "myfile.fo" file.
+ The Result is set up so the output of the XSLT transformation is sent to FOP.
+ The FO file is sent to FOP in the form of SAX events which is the most efficient
+ way. Please always avoid saving intermediate results to a file or a memory buffer
+ because that affects performance negatively.
+ </li>
+ <li>
+ <strong>Step 6:</strong> Finally, we start the XSLT transformation by starting
+ the JAXP Transformer. As soon as the JAXP Transformer starts to send its output
+ to FOP, FOP itself starts its processing in the background. When the
+ <code>transform()</code> method returns FOP will also have finished converting
+ the FO file to a PDF file and you can close the OutputStream.
+ <note label="Tip!">
+ It's a good idea to enclose the whole conversion in a try..finally statement. If
+ you close the OutputStream in the finally section, this will make sure that the
+ OutputStream is properly closed even if an exception occurs during the conversion.
+ </note>
+ </li>
+ </ul>
+ <p>
+ If you're not totally familiar with JAXP Transformers, please have a look at the
+ <a href="#examples">Embedding examples</a> below. The section contains examples
+ for all sorts of use cases. If you look at all of them in turn you should be able
+ to see the patterns in use and the flexibility this approach offers without adding
+ too much complexity.
+ </p>
+ <p>
+ This may look complicated at first, but it's really just the combination of an
+ XSL transformation and a FOP run. It's also easy to comment out the FOP part
+ for debugging purposes, for example when you're tracking down a bug in your
+ stylesheet. You can easily write the XSL-FO output from the XSL transformation
+ to a file to check if that part generates the expected output. An example for that
+ can be found in the <a href="#examples">Embedding examples</a> (See "ExampleXML2FO").
+ </p>
+ <section id="basic-logging">
+ <title>Logging</title>
+ <p>
+ Logging is now a little different than it was in FOP 0.20.5. We've switched from
+ Avalon Logging to <a href="ext:commons-logging">Jakarta Commons Logging</a>.
+ While with Avalon Logging the loggers were directly given to FOP, FOP now retrieves
+ its logger(s) through a statically available LogFactory. This is similar to the
+ general pattern that you use when you work with Apache Log4J directly, for example.
+ We call this "static logging" (Commons Logging, Log4J) as opposed to "instance logging"
+ (Avalon Logging). This has a consequence: You can't give FOP a logger for each
+ processing run anymore. The log output of multiple, simultaneously running FOP instances
+ is sent to the same logger.
+ </p>
+ <p>
+ By default, <a href="ext:commons-logging">Jakarta Commons Logging</a> uses
+ JDK logging (available in JDKs 1.4 or higher) as its backend. You can configure Commons
+ Logging to use an alternative backend, for example Log4J. Please consult the
+ <a href="ext:commons-logging">documentation for Jakarta Commons Logging</a> on
+ how to configure alternative backends.
+ </p>
+ <p>
+ As a result of the above we differentiate between two kinds of "logging":
+ </p>
+ <ul>
+ <li>(FOP-)Developer-oriented logging</li>
+ <li><a href="events.html">User/Integrator-oriented feedback</a> (NEW!)</li>
+ </ul>
+ <p>
+ The use of "feedback" instead of "logging" is intentional. Most people were using
+ log output as a means to get feedback from events within FOP. Therefore, FOP now
+ includes an <code>event</code> package which can be used to receive feedback from
+ the layout engine and other components within FOP <strong>per rendering run</strong>.
+ This feedback is not just some
+ text but event objects with parameters so these events can be interpreted by code.
+ Of course, there is a facility to turn these events into normal human-readable
+ messages. For details, please read on on the <a href="events.html">Events page</a>.
+ This leaves normal logging to be mostly a thing used by the FOP developers
+ although anyone can surely activate certain logging categories but the feedback
+ from the loggers won't be separated by processing runs. If this is required,
+ the <a href="events.html">Events subsystem</a> is the right approach.
+ </p>
+ </section>
+
+ <section id="render">
+ <title>Processing XSL-FO</title>
+ <p>
+ Once the Fop instance is set up, call <code>getDefaultHandler()</code> to obtain a SAX
+ DefaultHandler instance to which you can send the SAX events making up the XSL-FO
+ document you'd like to render. FOP processing starts as soon as the DefaultHandler's
+ <code>startDocument()</code> method is called. Processing stops again when the
+ DefaultHandler's <code>endDocument()</code> method is called. Please refer to the basic
+ usage pattern shown above to render a simple XSL-FO document.
+ </p>
+ </section>
+
+ <section id="render-with-xslt">
+ <title>Processing XSL-FO generated from XML+XSLT</title>
+ <p>
+ If you want to process XSL-FO generated from XML using XSLT we recommend
+ again using standard JAXP to do the XSLT part and piping the generated SAX
+ events directly through to FOP. The only thing you'd change to do that
+ on the basic usage pattern above is to set up the Transformer differently:
+ </p>
+ <source><![CDATA[
+ //without XSLT:
+ //Transformer transformer = factory.newTransformer(); // identity transformer
+
+ //with XSLT:
+ Source xslt = new StreamSource(new File("mystylesheet.xsl"));
+ Transformer transformer = factory.newTransformer(xslt);]]></source>
+ </section>
+ </section>
+ <section id="input">
+ <title>Input Sources</title>
+ <p>
+ The input XSL-FO document is always received by FOP as a SAX stream (see the
+ <a href="../dev/design/parsing.html">Parsing Design Document</a> for the rationale).
+ </p>
+ <p>
+ However, you may not always have your input document available as a SAX stream.
+ But with JAXP it's easy to convert different input sources to a SAX stream so you
+ can pipe it into FOP. That sounds more difficult than it is. You simply have
+ to set up the right Source instance as input for the JAXP transformation.
+ A few examples:
+ </p>
+ <ul>
+ <li>
+ <strong>URL:</strong> <code>Source src = new StreamSource("http://localhost:8080/testfile.xml");</code>
+ </li>
+ <li>
+ <strong>File:</strong> <code>Source src = new StreamSource(new File("C:/Temp/myinputfile.xml"));</code>
+ </li>
+ <li>
+ <strong>String:</strong> <code>Source src = new StreamSource(new StringReader(myString)); // myString is a String</code>
+ </li>
+ <li>
+ <strong>InputStream:</strong> <code>Source src = new StreamSource(new MyInputStream(something));</code>
+ </li>
+ <li>
+ <strong>Byte Array:</strong> <code>Source src = new StreamSource(new ByteArrayInputStream(myBuffer)); // myBuffer is a byte[] here</code>
+ </li>
+ <li>
+ <strong>DOM:</strong> <code>Source src = new DOMSource(myDocument); // myDocument is a Document or a Node</code>
+ </li>
+ <li>
+ <strong>Java Objects:</strong> Please have a look at the <a href="#examples">Embedding examples</a> which contain an example for this.
+ </li>
+ </ul>
+ <p>
+ There are a variety of upstream data manipulations possible.
+ For example, you may have a DOM and an XSL stylesheet; or you may want to
+ set variables in the stylesheet. Interface documentation and some cookbook
+ solutions to these situations are provided in
+ <a href="http://xml.apache.org/xalan-j/usagepatterns.html">Xalan Basic Usage Patterns</a>.
+ </p>
+ </section>
+ <section id="config-internal">
+ <title>Configuring Apache FOP Programmatically</title>
+ <p>
+ Apache FOP provides two levels on which you can customize FOP's
+ behaviour: the FopFactory and the user agent.
+ </p>
+ <section id="fop-factory">
+ <title>Customizing the FopFactory</title>
+ <p>
+ The FopFactory holds configuration data and references to objects which are reusable over
+ multiple rendering runs. It's important to instantiate it only once (except in special
+ environments) and reuse it every time to create new FOUserAgent and Fop instances.
+ </p>
+ <p>
+ You can set all sorts of things on the FopFactory:
+ </p>
+ <ul>
+ <li>
+ <p>
+ The <strong>font base URL</strong> to use when resolving relative URLs for fonts. Example:
+ </p>
+ <source>fopFactory.getFontManager().setFontBaseURL("file:///C:/Temp/fonts");</source>
+ </li>
+ <li>
+ <p>
+ The <strong>hyphenation base URL</strong> to use when resolving relative URLs for
+ hyphenation patterns. Example:
+ </p>
+ <source>fopFactory.setHyphenBaseURL("file:///C:/Temp/hyph");</source>
+ </li>
+ <li>
+ <p>
+ Disable <strong>strict validation</strong>. When disabled FOP is less strict about the rules
+ established by the XSL-FO specification. Example:
+ </p>
+ <source>fopFactory.setStrictValidation(false);</source>
+ </li>
+ <li>
+ <p>
+ Enable an <strong>alternative set of rules for text indents</strong> that tries to mimic the behaviour of many commercial
+ FO implementations, that chose to break the specification in this respect. The default of this option is
+ 'false', which causes Apache FOP to behave exactly as described in the specification. To enable the
+ alternative behaviour, call:
+ </p>
+ <source>fopFactory.setBreakIndentInheritanceOnReferenceAreaBoundary(true);</source>
+ </li>
+ <li>
+ <p>
+ Set the <strong>source resolution</strong> for the document. This is used internally to determine the pixel
+ size for SVG images and bitmap images without resolution information. Default: 72 dpi. Example:
+ </p>
+ <source>fopFactory.setSourceResolution(96); // =96dpi (dots/pixels per Inch)</source>
+ </li>
+ <li>
+ <p>
+ Manually add an <strong>ElementMapping instance</strong>. If you want to supply a special FOP extension
+ you can give the instance to the FOUserAgent. Normally, the FOP extensions can be automatically detected
+ (see the documentation on extension for more info). Example:
+ </p>
+ <source>fopFactory.addElementMapping(myElementMapping); // myElementMapping is a org.apache.fop.fo.ElementMapping</source>
+ </li>
+ <li>
+ <p>
+ Set a <strong>URIResolver</strong> for custom URI resolution. By supplying a JAXP URIResolver you can add
+ custom URI resolution functionality to FOP. For example, you can use
+ <a href="ext:xml.apache.org/commons/resolver">Apache XML Commons Resolver</a> to make use of XCatalogs. Example:
+ </p>
+ <source>fopFactory.setURIResolver(myResolver); // myResolver is a javax.xml.transform.URIResolver</source>
+ <note>
+ Both the FopFactory and the FOUserAgent have a method to set a URIResolver. The URIResolver on the FopFactory
+ is primarily used to resolve URIs on factory-level (hyphenation patterns, for example) and it is always used
+ if no other URIResolver (for example on the FOUserAgent) resolved the URI first.
+ </note>
+ </li>
+ </ul>
+ </section>
+ <section id="user-agent">
+ <title>Customizing the User Agent</title>
+ <p>
+ The user agent is the entity that allows you to interact with a single rendering run, i.e. the processing of a single
+ document. If you wish to customize the user agent's behaviour, the first step is to create your own instance
+ of FOUserAgent using the appropriate factory method on FopFactory and pass that
+ to the factory method that will create a new Fop instance:
+ </p>
+ <source><![CDATA[
+ FopFactory fopFactory = FopFactory.newInstance(); // Reuse the FopFactory if possible!
+ // do the following for each new rendering run
+ FOUserAgent userAgent = fopFactory.newFOUserAgent();
+ // customize userAgent
+ Fop fop = fopFactory.newFop(MimeConstants.MIME_POSTSCRIPT, userAgent, out);]]></source>
+ <p>
+ You can do all sorts of things on the user agent:
+ </p>
+ <ul>
+ <li>
+ <p>
+ The <strong>base URL</strong> to use when resolving relative URLs. Example:
+ </p>
+ <source>userAgent.setBaseURL("file:///C:/Temp/");</source>
+ </li>
+ <li>
+ <p>
+ Set the <strong>producer</strong> of the document. This is metadata information that can be used for certain output formats such as PDF. The default producer is "Apache FOP". Example:
+ </p>
+ <source>userAgent.setProducer("MyKillerApplication");</source>
+ </li>
+ <li>
+ <p>
+ Set the <strong>creating user</strong> of the document. This is metadata information that can be used for certain output formats such as PDF. Example:
+ </p>
+ <source>userAgent.setCreator("John Doe");</source>
+ </li>
+ <li>
+ <p>
+ Set the <strong>author</strong> of the document. This is metadata information that can be used for certain output formats such as PDF. Example:
+ </p>
+ <source>userAgent.setAuthor("John Doe");</source>
+ </li>
+ <li>
+ <p>
+ Override the <strong>creation date and time</strong> of the document. This is metadata information that can be used for certain output formats such as PDF. Example:
+ </p>
+ <source>userAgent.setCreationDate(new Date());</source>
+ </li>
+ <li>
+ <p>
+ Set the <strong>title</strong> of the document. This is metadata information that can be used for certain output formats such as PDF. Example:
+ </p>
+ <source>userAgent.setTitle("Invoice No 138716847");</source>
+ </li>
+ <li>
+ <p>
+ Set the <strong>keywords</strong> of the document. This is metadata information that can be used for certain output formats such as PDF. Example:
+ </p>
+ <source>userAgent.setKeywords("XML XSL-FO");</source>
+ </li>
+ <li>
+ <p>
+ Set the <strong>target resolution</strong> for the document. This is used to
+ specify the output resolution for bitmap images generated by bitmap renderers
+ (such as the TIFF renderer) and by bitmaps generated by Apache Batik for filter
+ effects and such. Default: 72 dpi. Example:
+ </p>
+ <source>userAgent.setTargetResolution(300); // =300dpi (dots/pixels per Inch)</source>
+ </li>
+ <li>
+ <p>
+ Set <strong>your own Document Handler</strong>. This feature can be used for several purposes, the most likey usage of which would probably be
+ binding a MIME type when the output is Intermediate Format (see <a href="#documenthandlers">Document Handlers</a>). This also allows advanced
+ users to create their own implementation of the document handler.
+ </p>
+ <source>userAgent.setDocumentHandlerOverride(documentHandler) // documentHandler is an instance of org.apache.fop.render.intermediate.IFDocumentHandler</source>
+ </li>
+ <li>
+ <p>
+ Set <strong>your own FOEventHandler instance</strong>. If you want to supply your own FOEventHandler or
+ configure an FOEventHandler subclass in a special way you can give the instance to the FOUserAgent. Normally,
+ the FOEventHandler instance is created by FOP. Example:
+ </p>
+ <source>userAgent.setFOEventHandlerOverride(myFOEventHandler); // myFOEventHandler is an org.apache.fop.fo.FOEventHandler</source>
+ </li>
+ <li>
+ <p>
+ Set a <strong>URIResolver</strong> for custom URI resolution. By supplying a JAXP URIResolver you can add
+ custom URI resolution functionality to FOP. For example, you can use
+ <a href="ext:xml.apache.org/commons/resolver">Apache XML Commons Resolver</a> to make use of XCatalogs. Example:
+ </p>
+ <source>userAgent.setURIResolver(myResolver); // myResolver is a javax.xml.transform.URIResolver</source>
+ <note>
+ Both the FopFactory and the FOUserAgent have a method to set a URIResolver. The URIResolver on the FOUserAgent is
+ used for resolving URIs which are document-related. If it's not set or cannot resolve a URI, the URIResolver
+ from the FopFactory is used.
+ </note>
+ </li>
+ </ul>
+ <note>
+ You should not reuse an FOUserAgent instance between FOP rendering runs although you can. Especially
+ in multi-threaded environment, this is a bad idea.
+ </note>
+ </section>
+ </section>
+ <section id="config-external">
+ <title>Using a Configuration File</title>
+ <p>
+ Instead of setting the parameters manually in code as shown above you can also set
+ many values from an XML configuration file:
+ </p>
+ <source><![CDATA[
+import org.apache.avalon.framework.configuration.Configuration;
+import org.apache.avalon.framework.configuration.DefaultConfigurationBuilder;
+
+/*..*/
+
+DefaultConfigurationBuilder cfgBuilder = new DefaultConfigurationBuilder();
+Configuration cfg = cfgBuilder.buildFromFile(new File("C:/Temp/mycfg.xml"));
+fopFactory.setUserConfig(cfg);
+
+/* ..or.. */
+
+fopFactory.setUserConfig(new File("C:/Temp/mycfg.xml"));]]></source>
+ <p>
+ The layout of the configuration file is described on the <a href="configuration.html">Configuration page</a>.
+ </p>
+ </section>
+ <section id="documenthandlers">
+ <title>Document Handlers</title>
+ <p>
+ The document handlers are classes that inherit from <code>org.apache.fop.render.intermediate.IFDocumentHandler</code>. This
+ is an interface for which a MIME type specific implementation can be created. This same handler is used either when XSL-FO
+ is used as the input or when Intermediate Format is used. Since IF is output format agnostic, if custom fonts or other
+ configuration information that affect layout (specific to a particular MIME type) are given then FOP needs that contextual
+ information. The document handler provides that context so that when the IF is rendered, it is more visually consistent with
+ FO rendering. The code below shows an example of how a document handler can be used to provide PDF configuration data to the
+ IFSerializer.
+ <source><![CDATA[
+IFDocumentHandler targetHandler = userAgent.getRendererFactory().createDocumentHandler(userAgent, MimeConstants.MIME_PDF);
+
+IFSerializer ifSerializer = new IFSerializer(); //Create the IFSerializer to write the intermediate format
+ifSerializer.setContext(new IFContext(userAgent));
+ifSerializer.mimicDocumentHandler(targetHandler); //Tell the IFSerializer to mimic the target format
+
+userAgent.setDocumentHandlerOverride(ifSerializer); //Make sure the prepared document handler is used
+ ]]></source>
+ The rest of the code is the same as in <a href="#basics">Basic Usage Patterns</a>.
+ </p>
+ </section>
+ <section id="hints">
+ <title>Hints</title>
+ <section id="object-reuse">
+ <title>Object reuse</title>
+ <p>
+ Fop instances shouldn't (and can't) be reused. Please recreate
+ Fop and FOUserAgent instances for each rendering run using the FopFactory.
+ This is a cheap operation as all reusable information is held in the
+ FopFactory. That's why it's so important to reuse the FopFactory instance.
+ </p>
+ </section>
+ <section id="awt">
+ <title>AWT issues</title>
+ <p>
+ If your XSL-FO files contain SVG then Apache Batik will be used. When Batik is
+ initialised it uses certain classes in <code>java.awt</code> that
+ intialise the Java AWT classes. This means that a daemon thread
+ is created by the JVM and on Unix it will need to connect to a
+ DISPLAY.
+ </p>
+ <p>
+ The thread means that the Java application may not automatically quit
+ when finished, you will need to call <code>System.exit()</code>. These
+ issues should be fixed in the JDK 1.4.
+ </p>
+ <p>
+ If you run into trouble running FOP on a head-less server, please see the
+ <a href="graphics.html#batik">notes on Batik</a>.
+ </p>
+ </section>
+ <section id="render-info">
+ <title>Getting information on the rendering process</title>
+ <p>
+ To get the number of pages that were rendered by FOP you can call
+ <code>Fop.getResults()</code>. This returns a <code>FormattingResults</code> object
+ where you can look up the number of pages produced. It also gives you the
+ page-sequences that were produced along with their id attribute and their
+ numbers of pages. This is particularly useful if you render multiple
+ documents (each enclosed by a page-sequence) and have to know the number of
+ pages of each document.
+ </p>
+ </section>
+ </section>
+ <section id="performance">
+ <title>Improving performance</title>
+ <p>
+ There are several options to consider:
+ </p>
+ <ul>
+ <li>
+ Whenever possible, try to use SAX to couple the individual components involved
+ (parser, XSL transformer, SQL datasource etc.).
+ </li>
+ <li>
+ Depending on the target OutputStream (in case of a FileOutputStream, but not
+ for a ByteArrayOutputStream, for example) it may improve performance considerably
+ if you buffer the OutputStream using a BufferedOutputStream:
+ <code>out = new java.io.BufferedOutputStream(out);</code>
+ <br/>
+ Make sure you properly close the OutputStream when FOP is finished.
+ </li>
+ <li>
+ Cache the stylesheet. If you use the same stylesheet multiple times
+ you can set up a JAXP <code>Templates</code> object and reuse it each time you do
+ the XSL transformation. (More information can be found
+ <a class="fork" href="http://www.javaworld.com/javaworld/jw-05-2003/jw-0502-xsl.html">here</a>.)
+ </li>
+ <li>
+ Use an XSLT compiler like <a class="fork" href="http://xml.apache.org/xalan-j/xsltc_usage.html">XSLTC</a>
+ that comes with Xalan-J.
+ </li>
+ <li>
+ Fine-tune your stylesheet to make the XSLT process more efficient and to create XSL-FO that can
+ be processed by FOP more efficiently. Less is more: Try to make use of property inheritance where possible.
+ </li>
+ <li>
+ You may also wish to consider trying to reduce <a href="http://xmlgraphics.apache.org/fop/trunk/running.html#memory">memory usage</a>.
+ </li>
+ </ul>
+ </section>
+ <section id="multithreading">
+ <title>Multithreading FOP</title>
+ <p>
+ Apache FOP may currently not be completely thread safe.
+ The code has not been fully tested for multi-threading issues, yet.
+ If you encounter any suspicious behaviour, please notify us.
+ </p>
+ <p>
+ There is also a known issue with fonts being jumbled between threads when using
+ the Java2D/AWT renderer (which is used by the -awt and -print output options).
+ In general, you cannot safely run multiple threads through the AWT renderer.
+ </p>
+ </section>
+<section id="examples">
+ <title>Examples</title>
+ <p>
+ The directory "{fop-dir}/examples/embedding" contains several working examples.
+ </p>
+ <section id="ExampleFO2PDF">
+ <title>ExampleFO2PDF.java</title>
+ <p>This
+ <a href="http://svn.apache.org/viewcvs.cgi/xmlgraphics/fop/trunk/examples/embedding/java/embedding/ExampleFO2PDF.java?view=markup">
+ example</a>
+demonstrates the basic usage pattern to transform an XSL-FO
+file to PDF using FOP.
+ </p>
+ <figure src="images/EmbeddingExampleFO2PDF.png" alt="Example XSL-FO to PDF"/>
+ </section>
+ <section id="ExampleXML2FO">
+ <title>ExampleXML2FO.java</title>
+ <p>This
+ <a href="http://svn.apache.org/viewcvs.cgi/xmlgraphics/fop/trunk/examples/embedding/java/embedding/ExampleXML2FO.java?view=markup">
+ example</a>
+has nothing to do with FOP. It is there to show you how an XML
+file can be converted to XSL-FO using XSLT. The JAXP API is used to do the
+transformation. Make sure you've got a JAXP-compliant XSLT processor in your
+classpath (ex. <a href="http://xml.apache.org/xalan-j">Xalan</a>).
+ </p>
+ <figure src="images/EmbeddingExampleXML2FO.png" alt="Example XML to XSL-FO"/>
+ </section>
+ <section id="ExampleXML2PDF">
+ <title>ExampleXML2PDF.java</title>
+ <p>This
+ <a href="http://svn.apache.org/viewcvs.cgi/xmlgraphics/fop/trunk/examples/embedding/java/embedding/ExampleXML2PDF.java?view=markup">
+ example</a>
+demonstrates how you can convert an arbitrary XML file to PDF
+using XSLT and XSL-FO/FOP. It is a combination of the first two examples
+above. The example uses JAXP to transform the XML file to XSL-FO and FOP to
+transform the XSL-FO to PDF.
+ </p>
+ <figure src="images/EmbeddingExampleXML2PDF.png" alt="Example XML to PDF (via XSL-FO)"/>
+ <p>
+The output (XSL-FO) from the XSL transformation is piped through to FOP using
+SAX events. This is the most efficient way to do this because the
+intermediate result doesn't have to be saved somewhere. Often, novice users
+save the intermediate result in a file, a byte array or a DOM tree. We
+strongly discourage you to do this if it isn't absolutely necessary. The
+performance is significantly higher with SAX.
+ </p>
+ </section>
+ <section id="ExampleObj2XML">
+ <title>ExampleObj2XML.java</title>
+ <p>This
+ <a href="http://svn.apache.org/viewcvs.cgi/xmlgraphics/fop/trunk/examples/embedding/java/embedding/ExampleObj2XML.java?view=markup">
+ example</a>
+is a preparatory example for the next one. It's an example that
+shows how an arbitrary Java object can be converted to XML. It's an often
+needed task to do this. Often people create a DOM tree from a Java object and
+use that. This is pretty straightforward. The example here, however, shows how
+to do this using SAX, which will probably be faster and not even more
+complicated once you know how this works.
+ </p>
+ <figure src="images/EmbeddingExampleObj2XML.png" alt="Example Java object to XML"/>
+ <p>
+For this example we've created two classes: ProjectTeam and ProjectMember
+(found in xml-fop/examples/embedding/java/embedding/model). They represent
+the same data structure found in
+xml-fop/examples/embedding/xml/xml/projectteam.xml. We want to serialize to XML a
+project team with several members which exist as Java objects.
+Therefore we created the two classes: ProjectTeamInputSource and
+ProjectTeamXMLReader (in the same place as ProjectTeam above).
+ </p>
+ <p>
+The XMLReader implementation (regard it as a special kind of XML parser) is
+responsible for creating SAX events from the Java object. The InputSource
+class is only used to hold the ProjectTeam object to be used.
+ </p>
+ <p>
+Have a look at the source of ExampleObj2XML.java to find out how this is
+used. For more detailed information see other resources on JAXP (ex.
+<a class="fork" href="http://java.sun.com/xml/jaxp/dist/1.1/docs/tutorial/xslt/3_generate.html">An older JAXP tutorial</a>).
+ </p>
+ </section>
+ <section id="ExampleObj2PDF">
+ <title>ExampleObj2PDF.java</title>
+ <p>This
+ <a href="http://svn.apache.org/viewcvs.cgi/xmlgraphics/fop/trunk/examples/embedding/java/embedding/ExampleObj2PDF.java?view=markup">
+ example</a>
+combines the previous and the third to demonstrate
+how you can transform a Java object to a PDF directly in one smooth run
+by generating SAX events from the Java object that get fed to an XSL
+transformation. The result of the transformation is then converted to PDF
+using FOP as before.
+ </p>
+ <figure src="images/EmbeddingExampleObj2PDF.png" alt="Example Java object to PDF (via XML and XSL-FO)"/>
+ </section>
+ <section id="ExampleDOM2PDF">
+ <title>ExampleDOM2PDF.java</title>
+ <p>This
+ <a href="http://svn.apache.org/viewcvs.cgi/xmlgraphics/fop/trunk/examples/embedding/java/embedding/ExampleDOM2PDF.java?view=markup">
+ example</a>
+has FOP use a DOMSource instead of a StreamSource in order to
+use a DOM tree as input for an XSL transformation.
+ </p>
+ </section>
+ <section id="ExampleSVG2PDF">
+ <title>ExampleSVG2PDF.java (PDF Transcoder example)</title>
+ <p>This
+ <a href="http://svn.apache.org/viewcvs.cgi/xmlgraphics/fop/trunk/examples/embedding/java/embedding/ExampleSVG2PDF.java?view=markup">
+ example</a>
+shows the usage of the PDF Transcoder, a sub-application within FOP.
+It is used to generate a PDF document from an SVG file.
+ </p>
+ </section>
+ <section id="ExampleConcat">
+ <title>ExampleConcat.java (IF Concatenation example)</title>
+ <p>
+This can be found in the <code>embedding.intermediate</code> package within the
+examples and describes how IF can be concatenated to produce a document. Because
+IF has been through FOPs layout engine, it should be visually consistent with FO
+rendered documents while allowing the user to merge numerous documents together.
+ </p>
+ </section>
+ <section id="example-notes">
+ <title>Final notes</title>
+ <p>
+These examples should give you an idea of what's possible. It should be easy
+to adjust these examples to your needs. Also, if you have other examples that you
+think should be added here, please let us know via either the fop-users or fop-dev
+mailing lists. Finally, for more help please send your questions to the fop-users
+mailing list.
+ </p>
+ </section>
+</section>
+ </body>
+</document> \ No newline at end of file