]> source.dussan.org Git - xmlgraphics-fop.git/commitdiff
Most of the API finalization proposal is implemented now. No deprecations, yet, and...
authorJeremias Maerki <jeremias@apache.org>
Mon, 13 Feb 2006 16:08:26 +0000 (16:08 +0000)
committerJeremias Maerki <jeremias@apache.org>
Mon, 13 Feb 2006 16:08:26 +0000 (16:08 +0000)
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_API_Finalization@377403 13f79535-47bb-0310-9956-ffa450edef68

src/java/org/apache/fop/apps/FOUserAgent.java
src/java/org/apache/fop/apps/Fop.java
src/java/org/apache/fop/apps/FopFactory.java [new file with mode: 0644]
src/java/org/apache/fop/area/AreaTreeHandler.java
src/java/org/apache/fop/area/AreaTreeParser.java
src/java/org/apache/fop/cli/CommandLineOptions.java
src/java/org/apache/fop/fo/ElementMappingRegistry.java
src/java/org/apache/fop/fo/FOTreeBuilder.java
test/java/org/apache/fop/fotreetest/FOTreeTester.java

index 203f7f951e680745b1088eee63a01309d34dedac..273d952f0890ba47d8691c46c940d2dbaa61d000 100644 (file)
@@ -20,11 +20,7 @@ package org.apache.fop.apps;
 
 // Java
 import java.io.File;
-import java.io.IOException;
-import java.net.URL;
-import java.net.MalformedURLException;
 import java.util.Date;
-import java.util.List;
 import java.util.Map;
 import javax.xml.transform.Source;
 import javax.xml.transform.TransformerException;
@@ -40,18 +36,16 @@ import org.apache.commons.logging.LogFactory;
 
 // FOP
 import org.apache.fop.Version;
-import org.apache.fop.fo.ElementMapping;
 import org.apache.fop.fo.FOEventHandler;
-import org.apache.fop.layoutmgr.LayoutManagerMaker;
 import org.apache.fop.pdf.PDFEncryptionParams;
 import org.apache.fop.render.Renderer;
 import org.apache.fop.render.RendererFactory;
 import org.apache.fop.render.XMLHandlerRegistry;
 
 /**
- * The User Agent for fo.
- * This user agent is used by the processing to obtain user configurable
- * options.
+ * This is the user agent for FOP.
+ * It is the entity through which you can interact with the XSL-FO processing and is
+ * used by the processing to obtain user configurable options.
  * <p>
  * Renderer specific extensions (that do not produce normal areas on
  * the output) will be done like so:
@@ -70,59 +64,28 @@ import org.apache.fop.render.XMLHandlerRegistry;
  */
 public class FOUserAgent {
 
-    /** Defines the default source resolution (72dpi) for FOP */
-    public static final float DEFAULT_SOURCE_RESOLUTION = 72.0f; //dpi
     /** Defines the default target resolution (72dpi) for FOP */
     public static final float DEFAULT_TARGET_RESOLUTION = 72.0f; //dpi
-    /** Defines the default page-height */
-    public static final String DEFAULT_PAGE_HEIGHT = "11in";
-    /** Defines the default page-width */
-    public static final String DEFAULT_PAGE_WIDTH = "8.26in";
-    
-    /** Factory for Renderers and FOEventHandlers */
-    private RendererFactory rendererFactory = new RendererFactory();
-    
-    /** Registry for XML handlers */
-    private XMLHandlerRegistry xmlHandlers = new XMLHandlerRegistry();
+
+    private static Log log = LogFactory.getLog("FOP");
+
+    private FopFactory factory;
     
     /** The base URL for all URL resolutions, especially for external-graphics */
     private String baseURL;
     
-    /** The base URL for all font URL resolutions */
-    private String fontBaseURL;
-    
     /** A user settable URI Resolver */
     private URIResolver uriResolver = null;
     /** Our default resolver if none is set */
     private URIResolver foURIResolver = new FOURIResolver();
     
     private PDFEncryptionParams pdfEncryptionParams;
-    private float sourceResolution = DEFAULT_SOURCE_RESOLUTION;
     private float targetResolution = DEFAULT_TARGET_RESOLUTION;
-    private String pageHeight = DEFAULT_PAGE_HEIGHT;
-    private String pageWidth = DEFAULT_PAGE_WIDTH;
     private Map rendererOptions = new java.util.HashMap();
     private File outputFile = null;
     private Renderer rendererOverride = null;
     private FOEventHandler foEventHandlerOverride = null;
-    private LayoutManagerMaker lmMakerOverride = null;
-    /* user configuration */
-    private Configuration userConfig = null;
-    private Log log = LogFactory.getLog("FOP");
     
-    /* FOP has the ability, for some FO's, to continue processing even if the
-     * input XSL violates that FO's content model.  This is the default  
-     * behavior for FOP.  However, this flag, if set, provides the user the
-     * ability for FOP to halt on all content model violations if desired.   
-     */ 
-    private boolean strictValidation = true;
-    
-    /** @see #setBreakIndentInheritanceOnReferenceAreaBoundary(boolean) */
-    private boolean breakIndentInheritanceOnReferenceAreaBoundary = false;
-
-    /* Additional fo.ElementMapping subclasses set by user */
-    private List additionalElementMappings = null;
-
     /** Producer:  Metadata element for the system/software that produces
      * the document. (Some renderers can store this in the document.)
      */
@@ -146,24 +109,42 @@ public class FOUserAgent {
     protected String keywords = null;
     
     /**
-     * Add the element mapping with the given class name.
-     * @param elementMapping the class name representing the element mapping.
+     * Default constructor. <b>Provided for compatibility only. Please use the methods from 
+     * FopFactory to construct FOUserAgent instances!</b>
+     * @see org.apache.fop.apps.FopFactory
      */
-    public void addElementMapping(ElementMapping elementMapping) {
-        if (additionalElementMappings == null) {
-            additionalElementMappings = new java.util.ArrayList();
-        }
-        additionalElementMappings.add(elementMapping);
+    public FOUserAgent() {
+        this(FopFactory.newInstance());
     }
-
+    
     /**
-     * Returns the List of user-added ElementMapping class names
-     * @return List of Strings holding ElementMapping names.
+     * Main constructor. <b>This constructor should not be called directly. Please use the 
+     * methods from FopFactory to construct FOUserAgent instances!</b>
+     * @param factory the factory that provides environment-level information
+     * @see org.apache.fop.apps.FopFactory
      */
-    public List getAdditionalElementMappings() {
-        return additionalElementMappings;
+    public FOUserAgent(FopFactory factory) {
+        if (factory == null) {
+            throw new NullPointerException("The factory parameter must not be null");
+        }
+        this.factory = factory;
+        try {
+            if (factory.getUserConfig() != null) {
+                configure(factory.getUserConfig());
+            }
+        } catch (ConfigurationException cfge) {
+            log.error("Error while initializing the user asgent: "
+                    + cfge.getMessage());
+        }
     }
-
+    
+    /** @return the associated FopFactory instance */
+    public FopFactory getFactory() {
+        return this.factory;
+    }
+    
+    // ---------------------------------------------- rendering-run dependent stuff
+    
     /**
      * Sets an explicit renderer to use which overrides the one defined by the 
      * render type setting.  
@@ -198,65 +179,6 @@ public class FOUserAgent {
         return this.foEventHandlerOverride;
     }
 
-    /**
-     * Activates strict XSL content model validation for FOP
-     * Default is false (FOP will continue processing where it can)
-     * @param validateStrictly true to turn on strict validation
-     */
-    public void setStrictValidation(boolean validateStrictly) {
-        this.strictValidation = validateStrictly;
-    }
-
-    /**
-     * Returns whether FOP is strictly validating input XSL
-     * @return true of strict validation turned on, false otherwise
-     */
-    public boolean validateStrictly() {
-        return strictValidation;
-    }
-
-    /**
-     * @return true if the indent inheritance should be broken when crossing reference area 
-     *         boundaries (for more info, see the javadoc for the relative member variable)
-     */
-    public boolean isBreakIndentInheritanceOnReferenceAreaBoundary() {
-        return breakIndentInheritanceOnReferenceAreaBoundary;
-    }
-
-    /**
-     * Controls whether to enable a feature that breaks indent inheritance when crossing
-     * reference area boundaries.
-     * <p>
-     * This flag controls whether FOP will enable special code that breaks property
-     * inheritance for start-indent and end-indent when the evaluation of the inherited
-     * value would cross a reference area. This is described under
-     * http://wiki.apache.org/xmlgraphics-fop/IndentInheritance as is intended to
-     * improve interoperability with commercial FO implementations and to produce
-     * results that are more in line with the expectation of unexperienced FO users.
-     * Note: Enabling this features violates the XSL specification!
-     * @param value true to enable the feature
-     */
-    public void setBreakIndentInheritanceOnReferenceAreaBoundary(boolean value) {
-        this.breakIndentInheritanceOnReferenceAreaBoundary = value;
-    }
-    
-    /**
-     * Sets an explicit LayoutManagerMaker instance which overrides the one
-     * defined by the AreaTreeHandler.
-     * @param lmMaker the LayoutManagerMaker instance
-     */
-    public void setLayoutManagerMakerOverride(LayoutManagerMaker lmMaker) {
-        this.lmMakerOverride = lmMaker;
-    }
-
-    /**
-     * Returns the overriding LayoutManagerMaker instance, if any.
-     * @return the overriding LayoutManagerMaker or null
-     */
-    public LayoutManagerMaker getLayoutManagerMakerOverride() {
-        return this.lmMakerOverride;
-    }
-
     /**
      * Sets the producer of the document.  
      * @param producer source of document
@@ -363,95 +285,18 @@ public class FOUserAgent {
     }
 
     /**
-     * Set the user configuration.
-     * @param userConfig configuration
-     */
-    public void setUserConfig(Configuration userConfig) {
-        this.userConfig = userConfig;
-        try {
-            initUserConfig();
-        } catch (ConfigurationException cfge) {
-            log.error("Error initializing User Agent configuration: "
-                    + cfge.getMessage());
-        }
-    }
-
-    /**
-     * Get the user configuration.
-     * @return the user configuration
+     * Configures the FOUserAgent through the factory's configuration. 
+     * @see org.apache.avalon.framework.configuration.Configurable
      */
-    public Configuration getUserConfig() {
-        return userConfig;
-    }
-    
-    /**
-     * Initializes user agent settings from the user configuration
-     * file, if present: baseURL, resolution, default page size,...
-     * 
-     * @throws ConfigurationException when there is an entry that 
-     *          misses the required attribute
-     */
-    public void initUserConfig() throws ConfigurationException {
-        log.debug("Initializing User Agent Configuration");
-        setBaseURL(getBaseURLfromConfig("base"));
-        setFontBaseURL(getBaseURLfromConfig("font-base"));
-        if (userConfig.getChild("source-resolution", false) != null) {
-            this.sourceResolution 
-                = userConfig.getChild("source-resolution").getValueAsFloat(
-                        DEFAULT_SOURCE_RESOLUTION);
-            log.info("Source resolution set to: " + sourceResolution 
-                    + "dpi (px2mm=" + getSourcePixelUnitToMillimeter() + ")");
-        }
-        if (userConfig.getChild("target-resolution", false) != null) {
+    protected void configure(Configuration cfg) throws ConfigurationException {
+        setBaseURL(FopFactory.getBaseURLfromConfig(cfg, "base"));
+        if (cfg.getChild("target-resolution", false) != null) {
             this.targetResolution 
-                = userConfig.getChild("target-resolution").getValueAsFloat(
+                = cfg.getChild("target-resolution").getValueAsFloat(
                         DEFAULT_TARGET_RESOLUTION);
             log.info("Target resolution set to: " + targetResolution 
                     + "dpi (px2mm=" + getTargetPixelUnitToMillimeter() + ")");
         }
-        if (userConfig.getChild("strict-validation", false) != null) {
-            this.strictValidation = userConfig.getChild("strict-validation").getValueAsBoolean();
-        }
-        if (userConfig.getChild("break-indent-inheritance", false) != null) {
-            this.breakIndentInheritanceOnReferenceAreaBoundary 
-                = userConfig.getChild("break-indent-inheritance").getValueAsBoolean();
-        }
-        Configuration pageConfig = userConfig.getChild("default-page-settings");
-        if (pageConfig.getAttribute("height", null) != null) {
-            setPageHeight(pageConfig.getAttribute("height"));
-            log.info("Default page-height set to: " + pageHeight);
-        }
-        if (pageConfig.getAttribute("width", null) != null) {
-            setPageWidth(pageConfig.getAttribute("width"));
-            log.info("Default page-width set to: " + pageWidth);
-        }
-    }
-
-    private String getBaseURLfromConfig(String name) {
-        if (userConfig.getChild(name, false) != null) {
-            try {
-                String cfgBaseDir = userConfig.getChild(name).getValue(null);
-                if (cfgBaseDir != null) {
-                    File dir = new File(cfgBaseDir);
-                    if (dir.isDirectory()) {
-                        cfgBaseDir = "file://" + dir.getCanonicalPath() 
-                            + System.getProperty("file.separator");
-                        cfgBaseDir = cfgBaseDir.replace(
-                                System.getProperty("file.separator").charAt(0), '/');
-                    } else {
-                        //The next statement is for validation only
-                        new URL(cfgBaseDir);
-                    }
-                }
-                log.info(name + " set to: " + cfgBaseDir);
-                return cfgBaseDir;
-            } catch (MalformedURLException mue) {
-                log.error("Base URL in user config is malformed!");
-            } catch (IOException ioe) {
-                log.error("Error converting relative base directory to absolute URL.");
-            }
-        }
-        return null;
     }
     
     /**
@@ -459,21 +304,22 @@ public class FOUserAgent {
      * @param mimeType MIME type of the renderer
      * @return the requested configuration subtree, null if there's no configuration
      */
-    public Configuration getUserRendererConfig (String mimeType) {
+    public Configuration getUserRendererConfig(String mimeType) {
 
-        if (userConfig == null || mimeType == null) {
+        Configuration cfg = getFactory().getUserConfig();
+        if (cfg == null || mimeType == null) {
             return null;
         }
 
         Configuration userRendererConfig = null;
 
         Configuration[] cfgs
-            = userConfig.getChild("renderers").getChildren("renderer");
+            = cfg.getChild("renderers").getChildren("renderer");
         for (int i = 0; i < cfgs.length; ++i) {
-            Configuration cfg = cfgs[i];
+            Configuration child = cfgs[i];
             try {
-                if (cfg.getAttribute("mime").equals(mimeType)) {
-                    userRendererConfig = cfg;
+                if (child.getAttribute("mime").equals(mimeType)) {
+                    userRendererConfig = child;
                     break;
                 }
             } catch (ConfigurationException e) {
@@ -501,22 +347,6 @@ public class FOUserAgent {
         return this.baseURL;
     }
 
-    /**
-     * Sets the font base URL.
-     * @param fontBaseURL font base URL
-     */
-    public void setFontBaseURL(String fontBaseURL) {
-        this.fontBaseURL = fontBaseURL;
-    }
-
-    /**
-     * Returns the font base URL.
-     * @return the font base URL
-     */
-    public String getFontBaseURL() {
-        return this.fontBaseURL != null ? this.fontBaseURL : this.baseURL ;
-    }
-
     /**
      * Sets the URI Resolver.
      * @param uriResolver the new URI resolver
@@ -610,45 +440,21 @@ public class FOUserAgent {
         return outputFile;
     }
 
-    /**
-     * Returns the conversion factor from pixel units to millimeters. This
-     * depends on the desired source resolution.
-     * @return float conversion factor
-     * @see getSourceResolution()
-     */
-    public float getSourcePixelUnitToMillimeter() {
-        return 25.4f / this.sourceResolution; 
-    }
-    
     /**
      * Returns the conversion factor from pixel units to millimeters. This
      * depends on the desired target resolution.
      * @return float conversion factor
-     * @see getTargetResolution()
+     * @see #getTargetResolution()
      */
     public float getTargetPixelUnitToMillimeter() {
         return 25.4f / this.targetResolution; 
     }
     
-    /** @return the resolution for resolution-dependant input */
-    public float getSourceResolution() {
-        return this.sourceResolution;
-    }
-
     /** @return the resolution for resolution-dependant output */
     public float getTargetResolution() {
         return this.targetResolution;
     }
 
-    /**
-     * Sets the source resolution in dpi. This value is used to interpret the pixel size
-     * of source documents like SVG images and bitmap images without resolution information.
-     * @param dpi resolution in dpi
-     */
-    public void setSourceResolution(int dpi) {
-        this.sourceResolution = dpi;
-    }
-    
     /**
      * Sets the target resolution in dpi. This value defines the target resolution of
      * bitmap images generated by the bitmap renderers (such as the TIFF renderer) and of
@@ -659,24 +465,39 @@ public class FOUserAgent {
         this.targetResolution = dpi;
     }
     
+    // ---------------------------------------------- environment-level stuff
+    //                                                (convenience access to FopFactory methods)
+
+    /** @return the font base URL */
+    public String getFontBaseURL() {
+        String fontBaseURL = getFactory().getFontBaseURL(); 
+        return fontBaseURL != null ? fontBaseURL : this.baseURL;
+    }
+
     /**
-     * Gets the default page-height to use as fallback,
-     * in case page-height="auto"
-     * 
-     * @return the page-height, as a String
+     * Returns the conversion factor from pixel units to millimeters. This
+     * depends on the desired source resolution.
+     * @return float conversion factor
+     * @see #getSourceResolution()
      */
-    public String getPageHeight() {
-        return this.pageHeight;
+    public float getSourcePixelUnitToMillimeter() {
+        return getFactory().getSourcePixelUnitToMillimeter(); 
     }
     
+    /** @return the resolution for resolution-dependant input */
+    public float getSourceResolution() {
+        return getFactory().getSourceResolution();
+    }
+
     /**
-     * Sets the page-height to use as fallback, in case
-     * page-height="auto"
+     * Gets the default page-height to use as fallback,
+     * in case page-height="auto"
      * 
-     * @param pageHeight    page-height as a String
+     * @return the page-height, as a String
+     * @see FopFactory#getPageHeight()
      */
-    public void setPageHeight(String pageHeight) {
-        this.pageHeight = pageHeight;
+    public String getPageHeight() {
+        return getFactory().getPageWidth();
     }
     
     /**
@@ -684,43 +505,43 @@ public class FOUserAgent {
      * in case page-width="auto"
      * 
      * @return the page-width, as a String
+     * @see FopFactory#getPageWidth()
      */
     public String getPageWidth() {
-        return this.pageWidth;
+        return getFactory().getPageWidth();
     }
     
     /**
-     * Sets the page-width to use as fallback, in case
-     * page-width="auto"
-     * 
-     * @param pageWidth    page-width as a String
+     * Returns whether FOP is strictly validating input XSL
+     * @return true of strict validation turned on, false otherwise
+     * @see FopFactory#validateStrictly()
      */
-    public void setPageWidth(String pageWidth) {
-        this.pageWidth = pageWidth;
+    public boolean validateStrictly() {
+        return getFactory().validateStrictly();
     }
-    
+
     /**
-     * If to create hot links to footnotes and before floats.
-     * @return True if hot links should be created
+     * @return true if the indent inheritance should be broken when crossing reference area 
+     *         boundaries (for more info, see the javadoc for the relative member variable)
+     * @see FopFactory#isBreakIndentInheritanceOnReferenceAreaBoundary()
      */
-    /* TODO This method is never referenced!
-    public boolean linkToFootnotes() {
-        return true;
-    }*/
+    public boolean isBreakIndentInheritanceOnReferenceAreaBoundary() {
+        return getFactory().isBreakIndentInheritanceOnReferenceAreaBoundary();
+    }
 
     /**
      * @return the RendererFactory
      */
     public RendererFactory getRendererFactory() {
-        return this.rendererFactory;
+        return getFactory().getRendererFactory();
     }
 
     /**
      * @return the XML handler registry
      */
     public XMLHandlerRegistry getXMLHandlerRegistry() {
-        return this.xmlHandlers;
+        return getFactory().getXMLHandlerRegistry();
     }
-    
+
 }
 
index 720d78644687cf8eaa9eea08feccccb157c56f73..cf02028523aabf6b3b85718b19a6de987b93de83 100644 (file)
@@ -45,7 +45,7 @@ import org.apache.fop.fo.FOTreeBuilder;
  * At the moment, it is recommended not to reuse an instance of this
  * class for more than one rendering run.
  */
-public class Fop implements Constants {
+public class Fop {
 
     // desired output format: MIME type such as "application/pdf", "application/postscript" etc.
     private String outputFormat = null;
diff --git a/src/java/org/apache/fop/apps/FopFactory.java b/src/java/org/apache/fop/apps/FopFactory.java
new file mode 100644 (file)
index 0000000..0196f4e
--- /dev/null
@@ -0,0 +1,466 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed 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$ */
+
+package org.apache.fop.apps;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.List;
+
+import org.apache.avalon.framework.configuration.Configuration;
+import org.apache.avalon.framework.configuration.ConfigurationException;
+import org.apache.avalon.framework.configuration.DefaultConfigurationBuilder;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.fop.fo.ElementMapping;
+import org.apache.fop.fo.ElementMappingRegistry;
+import org.apache.fop.layoutmgr.LayoutManagerMaker;
+import org.apache.fop.render.RendererFactory;
+import org.apache.fop.render.XMLHandlerRegistry;
+import org.xml.sax.SAXException;
+
+/**
+ * Factory class which instantiates new Fop and FOUserAgent instances. This class also holds
+ * environmental information and configuration used by FOP. Information that may potentially be
+ * different for each rendering run can be found and managed in the FOUserAgent.
+ */
+public class FopFactory {
+
+    /** Defines the default source resolution (72dpi) for FOP */
+    private static final float DEFAULT_SOURCE_RESOLUTION = 72.0f; //dpi
+    /** Defines the default page-height */
+    private static final String DEFAULT_PAGE_HEIGHT = "11in";
+    /** Defines the default page-width */
+    private static final String DEFAULT_PAGE_WIDTH = "8.26in";
+
+    /** logger instance */
+    private static Log log = LogFactory.getLog(FopFactory.class);
+    
+    /** Factory for Renderers and FOEventHandlers */
+    private RendererFactory rendererFactory = new RendererFactory();
+    
+    /** Registry for XML handlers */
+    private XMLHandlerRegistry xmlHandlers = new XMLHandlerRegistry();
+    
+    /** The registry for ElementMapping instances */
+    private ElementMappingRegistry elementMappingRegistry;
+    
+    /** user configuration */
+    private Configuration userConfig = null;
+
+    /** The base URL for all font URL resolutions */
+    private String fontBaseURL;
+    
+    /**
+     * FOP has the ability, for some FO's, to continue processing even if the
+     * input XSL violates that FO's content model.  This is the default  
+     * behavior for FOP.  However, this flag, if set, provides the user the
+     * ability for FOP to halt on all content model violations if desired.   
+     */ 
+    private boolean strictValidation = true;
+
+    /** Source resolution in dpi */
+    private float sourceResolution = DEFAULT_SOURCE_RESOLUTION;
+    private String pageHeight = DEFAULT_PAGE_HEIGHT;
+    private String pageWidth = DEFAULT_PAGE_WIDTH;
+
+    /** @see #setBreakIndentInheritanceOnReferenceAreaBoundary(boolean) */
+    private boolean breakIndentInheritanceOnReferenceAreaBoundary = false;
+
+    /** Additional fo.ElementMapping subclasses set by user */
+    private List additionalElementMappings = null;
+
+    /** Optional overriding LayoutManagerMaker */
+    private LayoutManagerMaker lmMakerOverride = null;
+    
+    /**
+     * Main constructor.
+     */
+    protected FopFactory() {
+        this.elementMappingRegistry = new ElementMappingRegistry(this);
+    }
+    
+    /**
+     * Returns a new FopFactory instance.
+     * @return the requested FopFactory instance.
+     */
+    public static FopFactory newInstance() {
+        return new FopFactory();
+    }
+    
+    /**
+     * Returns a new FOUserAgent instance. Use the FOUserAgent to configure special values that
+     * are particular to a rendering run. Don't reuse instances over multiple rendering runs but
+     * instead create a new one each time and reuse the FopFactory.
+     * @return the newly created FOUserAgent instance initialized with default values
+     */
+    public FOUserAgent newFOUserAgent() {
+        FOUserAgent userAgent = new FOUserAgent(this);
+        return userAgent;
+    }
+
+    /**
+     * Returns a new {@link Fop} instance. FOP will be configured with a default user agent 
+     * instance.
+     * <p>
+     * MIME types are used to select the output format (ex. "application/pdf" for PDF). You can
+     * use the constants defined in {@link MimeConstants}.
+     * @param outputFormat the MIME type of the output format to use (ex. "application/pdf").     
+     * @return the new Fop instance
+     */
+    public Fop newFop(String outputFormat) {
+        return new Fop(outputFormat, newFOUserAgent());
+    }
+
+    /**
+     * Returns a new {@link Fop} instance. Use this factory method if you want to configure this 
+     * very rendering run, i.e. if you want to set some metadata like the title and author of the
+     * document you want to render. In that case, create a new {@link FOUserAgent} 
+     * instance using {@link #newFOUserAgent()}.
+     * <p>
+     * MIME types are used to select the output format (ex. "application/pdf" for PDF). You can
+     * use the constants defined in {@link MimeConstants}.
+     * @param outputFormat the MIME type of the output format to use (ex. "application/pdf").
+     * @param userAgent the user agent that will be used to control the rendering run     
+     * @return the new Fop instance
+     */
+    public Fop newFop(String outputFormat, FOUserAgent userAgent) {
+        if (userAgent == null) {
+            throw new NullPointerException("The userAgent parameter must not be null!");
+        }
+        return new Fop(outputFormat, userAgent);
+    }
+    
+    /**
+     * Returns a new {@link Fop} instance. Use this factory method if you want to supply your
+     * own {@link org.apache.fop.render.Renderer Renderer} or 
+     * {@link org.apache.fop.fo.FOEventHandler FOEventHandler} 
+     * instance instead of the default ones created internally by FOP.
+     * @param userAgent the user agent that will be used to control the rendering run     
+     * @return the new Fop instance
+     */
+    public Fop newFop(FOUserAgent userAgent) {
+        if (userAgent.getRendererOverride() == null 
+                && userAgent.getFOEventHandlerOverride() == null) {
+            throw new IllegalStateException("Either the overriding renderer or the overriding"
+                    + " FOEventHandler must be set when this factory method is used!");
+        }
+        return newFop(null, userAgent);
+    }
+
+    /** @return the RendererFactory */
+    public RendererFactory getRendererFactory() {
+        return this.rendererFactory;
+    }
+
+    /** @return the XML handler registry */
+    public XMLHandlerRegistry getXMLHandlerRegistry() {
+        return this.xmlHandlers;
+    }
+    
+    /** @return the element mapping registry */
+    public ElementMappingRegistry getElementMappingRegistry() {
+        return this.elementMappingRegistry;
+    }
+
+    /**
+     * Add the element mapping with the given class name.
+     * @param elementMapping the class name representing the element mapping.
+     */
+    public void addElementMapping(ElementMapping elementMapping) {
+        if (additionalElementMappings == null) {
+            additionalElementMappings = new java.util.ArrayList();
+        }
+        additionalElementMappings.add(elementMapping);
+    }
+
+    /**
+     * Returns the List of user-added ElementMapping class names
+     * @return List of Strings holding ElementMapping names.
+     */
+    public List getAdditionalElementMappings() {
+        return additionalElementMappings;
+    }
+
+    /**
+     * Sets an explicit LayoutManagerMaker instance which overrides the one
+     * defined by the AreaTreeHandler.
+     * @param lmMaker the LayoutManagerMaker instance
+     */
+    public void setLayoutManagerMakerOverride(LayoutManagerMaker lmMaker) {
+        this.lmMakerOverride = lmMaker;
+    }
+
+    /**
+     * Returns the overriding LayoutManagerMaker instance, if any.
+     * @return the overriding LayoutManagerMaker or null
+     */
+    public LayoutManagerMaker getLayoutManagerMakerOverride() {
+        return this.lmMakerOverride;
+    }
+
+    /**
+     * Sets the font base URL.
+     * @param fontBaseURL font base URL
+     */
+    public void setFontBaseURL(String fontBaseURL) {
+        this.fontBaseURL = fontBaseURL;
+    }
+
+    /** @return the font base URL */
+    public String getFontBaseURL() {
+        return this.fontBaseURL;
+    }
+
+    /**
+     * Activates strict XSL content model validation for FOP
+     * Default is false (FOP will continue processing where it can)
+     * @param validateStrictly true to turn on strict validation
+     */
+    public void setStrictValidation(boolean validateStrictly) {
+        this.strictValidation = validateStrictly;
+    }
+
+    /**
+     * Returns whether FOP is strictly validating input XSL
+     * @return true of strict validation turned on, false otherwise
+     */
+    public boolean validateStrictly() {
+        return strictValidation;
+    }
+
+    /**
+     * @return true if the indent inheritance should be broken when crossing reference area 
+     *         boundaries (for more info, see the javadoc for the relative member variable)
+     */
+    public boolean isBreakIndentInheritanceOnReferenceAreaBoundary() {
+        return breakIndentInheritanceOnReferenceAreaBoundary;
+    }
+
+    /**
+     * Controls whether to enable a feature that breaks indent inheritance when crossing
+     * reference area boundaries.
+     * <p>
+     * This flag controls whether FOP will enable special code that breaks property
+     * inheritance for start-indent and end-indent when the evaluation of the inherited
+     * value would cross a reference area. This is described under
+     * http://wiki.apache.org/xmlgraphics-fop/IndentInheritance as is intended to
+     * improve interoperability with commercial FO implementations and to produce
+     * results that are more in line with the expectation of unexperienced FO users.
+     * Note: Enabling this features violates the XSL specification!
+     * @param value true to enable the feature
+     */
+    public void setBreakIndentInheritanceOnReferenceAreaBoundary(boolean value) {
+        this.breakIndentInheritanceOnReferenceAreaBoundary = value;
+    }
+    
+    /** @return the resolution for resolution-dependant input */
+    public float getSourceResolution() {
+        return this.sourceResolution;
+    }
+
+    /**
+     * Returns the conversion factor from pixel units to millimeters. This
+     * depends on the desired source resolution.
+     * @return float conversion factor
+     * @see #getSourceResolution()
+     */
+    public float getSourcePixelUnitToMillimeter() {
+        return 25.4f / getSourceResolution(); 
+    }
+    
+    /**
+     * Sets the source resolution in dpi. This value is used to interpret the pixel size
+     * of source documents like SVG images and bitmap images without resolution information.
+     * @param dpi resolution in dpi
+     */
+    public void setSourceResolution(int dpi) {
+        this.sourceResolution = dpi;
+    }
+    
+    /**
+     * Gets the default page-height to use as fallback,
+     * in case page-height="auto"
+     * 
+     * @return the page-height, as a String
+     */
+    public String getPageHeight() {
+        return this.pageHeight;
+    }
+    
+    /**
+     * Sets the page-height to use as fallback, in case
+     * page-height="auto"
+     * 
+     * @param pageHeight    page-height as a String
+     */
+    public void setPageHeight(String pageHeight) {
+        this.pageHeight = pageHeight;
+    }
+    
+    /**
+     * Gets the default page-width to use as fallback,
+     * in case page-width="auto"
+     * 
+     * @return the page-width, as a String
+     */
+    public String getPageWidth() {
+        return this.pageWidth;
+    }
+    
+    /**
+     * Sets the page-width to use as fallback, in case
+     * page-width="auto"
+     * 
+     * @param pageWidth    page-width as a String
+     */
+    public void setPageWidth(String pageWidth) {
+        this.pageWidth = pageWidth;
+    }
+    
+    //------------------------------------------- Configuration stuff
+    
+    /**
+     * Set the user configuration.
+     * @param userConfigFile the configuration file
+     * @throws IOException if an I/O error occurs
+     * @throws SAXException if a parsing error occurs
+     */
+    public void setUserConfig(File userConfigFile)
+                throws SAXException, IOException {
+        try {
+            DefaultConfigurationBuilder cfgBuilder = new DefaultConfigurationBuilder();
+            setUserConfig(cfgBuilder.buildFromFile(userConfigFile));
+        } catch (ConfigurationException cfge) {
+            log.error("Error loading configuration: "
+                    + cfge.getMessage());
+        }
+    }
+    
+    /**
+     * Set the user configuration from an URI.
+     * @param uri the URI to the configuration file
+     * @throws IOException if an I/O error occurs
+     * @throws SAXException if a parsing error occurs
+     */
+    public void setUserConfig(String uri)
+                throws SAXException, IOException {
+        try {
+            DefaultConfigurationBuilder cfgBuilder = new DefaultConfigurationBuilder();
+            setUserConfig(cfgBuilder.build(uri));
+        } catch (ConfigurationException cfge) {
+            log.error("Error loading configuration: "
+                    + cfge.getMessage());
+        }
+    }
+    
+    /**
+     * Set the user configuration.
+     * @param userConfig configuration
+     */
+    public void setUserConfig(Configuration userConfig) {
+        this.userConfig = userConfig;
+        try {
+            initUserConfig();
+        } catch (ConfigurationException cfge) {
+            log.error("Error initializing factory configuration: "
+                    + cfge.getMessage());
+        }
+    }
+
+    /**
+     * Get the user configuration.
+     * @return the user configuration
+     */
+    public Configuration getUserConfig() {
+        return userConfig;
+    }
+    
+    /**
+     * Initializes user agent settings from the user configuration
+     * file, if present: baseURL, resolution, default page size,...
+     * 
+     * @throws ConfigurationException when there is an entry that 
+     *          misses the required attribute
+     */
+    public void initUserConfig() throws ConfigurationException {
+        log.debug("Initializing User Agent Configuration");
+        setFontBaseURL(getBaseURLfromConfig(userConfig, "font-base"));
+        if (userConfig.getChild("source-resolution", false) != null) {
+            this.sourceResolution 
+                = userConfig.getChild("source-resolution").getValueAsFloat(
+                        DEFAULT_SOURCE_RESOLUTION);
+            log.info("Source resolution set to: " + sourceResolution 
+                    + "dpi (px2mm=" + getSourcePixelUnitToMillimeter() + ")");
+        }
+        if (userConfig.getChild("strict-validation", false) != null) {
+            this.strictValidation = userConfig.getChild("strict-validation").getValueAsBoolean();
+        }
+        if (userConfig.getChild("break-indent-inheritance", false) != null) {
+            this.breakIndentInheritanceOnReferenceAreaBoundary 
+                = userConfig.getChild("break-indent-inheritance").getValueAsBoolean();
+        }
+        Configuration pageConfig = userConfig.getChild("default-page-settings");
+        if (pageConfig.getAttribute("height", null) != null) {
+            setPageHeight(pageConfig.getAttribute("height"));
+            log.info("Default page-height set to: " + pageHeight);
+        }
+        if (pageConfig.getAttribute("width", null) != null) {
+            setPageWidth(pageConfig.getAttribute("width"));
+            log.info("Default page-width set to: " + pageWidth);
+        }
+    }
+
+    /**
+     * Retrieves and verifies a base URL.
+     * @param cfg The Configuration object to retrieve the base URL from
+     * @param name the element name for the base URL
+     * @return the requested base URL or null if not available
+     */
+    public static String getBaseURLfromConfig(Configuration cfg, String name) {
+        if (cfg.getChild(name, false) != null) {
+            try {
+                String cfgBaseDir = cfg.getChild(name).getValue(null);
+                if (cfgBaseDir != null) {
+                    File dir = new File(cfgBaseDir);
+                    if (dir.isDirectory()) {
+                        cfgBaseDir = "file://" + dir.getCanonicalPath() 
+                            + System.getProperty("file.separator");
+                        cfgBaseDir = cfgBaseDir.replace(
+                                System.getProperty("file.separator").charAt(0), '/');
+                    } else {
+                        //The next statement is for validation only
+                        new URL(cfgBaseDir);
+                    }
+                }
+                log.info(name + " set to: " + cfgBaseDir);
+                return cfgBaseDir;
+            } catch (MalformedURLException mue) {
+                log.error("Base URL in user config is malformed!");
+            } catch (IOException ioe) {
+                log.error("Error converting relative base directory to absolute URL.");
+            }
+        }
+        return null;
+    }
+
+    
+    
+}
index dfe2e7fa38025e354c28cf6058c684c71517b87f..82a4ba234210c3429efba0749bdb17b4ef1c3f2d 100644 (file)
@@ -116,7 +116,7 @@ public class AreaTreeHandler extends FOEventHandler {
 
         setupModel(userAgent, outputFormat, stream);
             
-        lmMaker = userAgent.getLayoutManagerMakerOverride();
+        lmMaker = userAgent.getFactory().getLayoutManagerMakerOverride();
         if (lmMaker == null) {
             lmMaker = new LayoutManagerMapping();
         }
index 13643f5efd024201ab63441c5fdc44194628ea32..0f2cd0a4314b3187ba3099bddcf623eaee7f5a2b 100644 (file)
@@ -108,8 +108,8 @@ public class AreaTreeParser {
      * @return the ContentHandler instance to receive the SAX stream from the area tree XML
      */
     public ContentHandler getContentHandler(AreaTreeModel treeModel, FOUserAgent userAgent) {
-        //TODO Retrieve this instance from the environment class once it has been created.
-        ElementMappingRegistry elementMappingRegistry = new ElementMappingRegistry(userAgent);
+        ElementMappingRegistry elementMappingRegistry 
+            = userAgent.getFactory().getElementMappingRegistry();
         return new Handler(treeModel, userAgent, elementMappingRegistry);
     }
     
index e955f7e8ce3527c6d7f60c1ec4984d4f1583f617..86155239d9bc8085604dd4b58b26d36970042d5c 100644 (file)
@@ -28,6 +28,7 @@ import java.util.Vector;
 import org.apache.fop.Version;
 import org.apache.fop.apps.FOPException;
 import org.apache.fop.apps.FOUserAgent;
+import org.apache.fop.apps.FopFactory;
 import org.apache.fop.apps.MimeConstants;
 import org.apache.fop.pdf.PDFEncryptionManager;
 import org.apache.fop.pdf.PDFEncryptionParams;
@@ -41,14 +42,7 @@ import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
 // SAX
-import org.xml.sax.XMLReader;
 import org.xml.sax.SAXException;
-import javax.xml.parsers.SAXParserFactory;
-
-// avalon configuration
-import org.apache.avalon.framework.configuration.DefaultConfigurationBuilder;
-import org.apache.avalon.framework.configuration.Configuration;
-import org.apache.avalon.framework.configuration.ConfigurationException;
 
 /**
  * Options parses the commandline arguments
@@ -92,6 +86,7 @@ public class CommandLineOptions {
     /* output mode */
     private String outputmode = null;
 
+    private FopFactory factory = FopFactory.newInstance();
     private FOUserAgent foUserAgent;
 
     private InputHandler inputHandler;
@@ -130,7 +125,7 @@ public class CommandLineOptions {
             throws FOPException, IOException {
         boolean optionsParsed = true;
 
-        foUserAgent = new FOUserAgent();
+        foUserAgent = factory.newFOUserAgent();
 
         try {
             optionsParsed = parseOptions(args);
@@ -217,7 +212,7 @@ public class CommandLineOptions {
             } else if (args[i].equals("-d")) {
                 setLogOption("debug", "debug");
             } else if (args[i].equals("-r")) {
-                foUserAgent.setStrictValidation(false);
+                factory.setStrictValidation(false);
             } else if (args[i].equals("-dpi")) {
                 i = i + parseResolution(args, i);
             } else if (args[i].equals("-q") || args[i].equals("--quiet")) {
@@ -721,18 +716,11 @@ public class CommandLineOptions {
         if (userConfigFile == null) {
             return;
         }
-        XMLReader parser = createParser();
-        DefaultConfigurationBuilder configBuilder
-            = new DefaultConfigurationBuilder(parser);
-        Configuration userConfig = null;
         try {
-            userConfig = configBuilder.buildFromFile(userConfigFile);
+            factory.setUserConfig(userConfigFile);
         } catch (SAXException e) {
             throw new FOPException(e);
-        } catch (ConfigurationException e) {
-            throw new FOPException(e);
         }
-        foUserAgent.setUserConfig(userConfig);
      }
 
     /**
@@ -970,20 +958,5 @@ public class CommandLineOptions {
         }
     }
 
-    /**
-     * Creates <code>XMLReader</code> object using default
-     * <code>SAXParserFactory</code>
-     * @return the created <code>XMLReader</code>
-     * @throws FOPException if the parser couldn't be created or configured for proper operation.
-     */
-    private XMLReader createParser() throws FOPException {
-        try {
-            SAXParserFactory factory = SAXParserFactory.newInstance();
-            factory.setNamespaceAware(true);
-            return factory.newSAXParser().getXMLReader();
-        } catch (Exception e) {
-            throw new FOPException("Couldn't create XMLReader", e);
-        }
-    }
 }
 
index 35224e7ae525c7bf5c50f16879143b35f03c25f9..3a38a518df33e851387f4f489ad5c9f604d0ad21 100644 (file)
@@ -25,7 +25,7 @@ import java.util.Map;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.fop.apps.FOPException;
-import org.apache.fop.apps.FOUserAgent;
+import org.apache.fop.apps.FopFactory;
 import org.apache.fop.fo.ElementMapping.Maker;
 import org.apache.fop.util.Service;
 import org.w3c.dom.DOMImplementation;
@@ -54,14 +54,14 @@ public class ElementMappingRegistry {
     /**
      * Main constructor. Adds all default element mapping as well as detects ElementMapping
      * through the Service discovery.
-     * @param userAgent the user agent
+     * @param factory the Fop Factory
      */
-    public ElementMappingRegistry(FOUserAgent userAgent) {
+    public ElementMappingRegistry(FopFactory factory) {
         // Add standard element mappings
         setupDefaultMappings();
 
         // add additional ElementMappings defined within FOUserAgent
-        List addlEMs = userAgent.getAdditionalElementMappings();
+        List addlEMs = factory.getAdditionalElementMappings();
 
         if (addlEMs != null) {
             for (int i = 0; i < addlEMs.size(); i++) {
index f674d58c842be360a5197a7e922cb8305938bde7..34ad4337519d5b1cd453cdd6fb28a54834529d47 100644 (file)
@@ -48,9 +48,7 @@ public class FOTreeBuilder extends DefaultHandler {
 
     /** The registry for ElementMapping instances */
     protected ElementMappingRegistry elementMappingRegistry;
-    //TODO Remove the ElementMappingRegistry from here and move it to a new environmental class
-    //FOTreeBuilder should be a "one-use" component.
-    
+
     /**
      * The root of the formatting object tree
      */
@@ -91,7 +89,7 @@ public class FOTreeBuilder extends DefaultHandler {
         OutputStream stream) throws FOPException {
 
         this.userAgent = foUserAgent;
-        
+        this.elementMappingRegistry = userAgent.getFactory().getElementMappingRegistry();        
         //This creates either an AreaTreeHandler and ultimately a Renderer, or
         //one of the RTF-, MIF- etc. Handlers.
         foEventHandler = foUserAgent.getRendererFactory().createFOEventHandler(
@@ -101,8 +99,6 @@ public class FOTreeBuilder extends DefaultHandler {
                 return new StaticPropertyList(fobj, parentPropertyList);
             }
         });
-
-        this.elementMappingRegistry = new ElementMappingRegistry(foUserAgent);
     }
 
     /**
index 773593f09303d8c7acf09a66d006604a9c9605e5..27081ecbe299acf8134259ec39774cbf640ce5d3 100644 (file)
@@ -31,6 +31,7 @@ import javax.xml.transform.stream.StreamSource;
 
 import org.apache.fop.apps.FOUserAgent;
 import org.apache.fop.apps.Fop;
+import org.apache.fop.apps.FopFactory;
 import org.apache.fop.apps.MimeConstants;
 
 import org.apache.fop.fotreetest.ext.TestElementMapping;
@@ -63,10 +64,12 @@ public class FOTreeTester {
         XMLReader reader = parser.getXMLReader();
         
         //Setup FOP for area tree rendering
-        FOUserAgent ua = new FOUserAgent();
+        FopFactory factory = FopFactory.newInstance();
+        factory.addElementMapping(new TestElementMapping());
+        
+        FOUserAgent ua = factory.newFOUserAgent();
         ua.setBaseURL(testFile.getParentFile().toURL().toString());
         ua.setFOEventHandlerOverride(new DummyFOEventHandler(ua));
-        ua.addElementMapping(new TestElementMapping());
 
         //Used to set values in the user agent through processing instructions
         reader = new PIListener(reader, ua);
@@ -100,7 +103,7 @@ public class FOTreeTester {
         /** @see org.xml.sax.helpers.XMLFilterImpl */
         public void processingInstruction(String target, String data) throws SAXException {
             if ("fop-useragent-break-indent-inheritance".equals(target)) {
-                userAgent.setBreakIndentInheritanceOnReferenceAreaBoundary(
+                userAgent.getFactory().setBreakIndentInheritanceOnReferenceAreaBoundary(
                         Boolean.valueOf(data).booleanValue());
             }
             super.processingInstruction(target, data);