Index: build.xml
===================================================================
--- build.xml	(revision 502182)
+++ build.xml	(working copy)
@@ -776,6 +776,7 @@
       <formatter type="xml" usefile="true"/>
       <classpath>
         <pathelement location="${build.dir}/test-classes"/>
+        <path refid="libs-build-classpath"/>
         <fileset dir="build">
           <include name="fop-transcoder-allinone.jar"/>
         </fileset>
@@ -789,6 +790,24 @@
     </junit>
   </target>
 
+  <target name="junit-userconfig" depends="junit-compile" if="junit.present" description="Runs FOP's user config JUnit tests">
+    <echo message="Running user config tests"/>
+    <junit dir="${basedir}" haltonfailure="${junit.haltonfailure}" fork="${junit.fork}" errorproperty="fop.junit.error" failureproperty="fop.junit.failure">
+      <sysproperty key="basedir" value="${basedir}"/>
+      <sysproperty key="jawa.awt.headless" value="true"/>
+      <sysproperty key="fop.layoutengine.disabled" value="${layoutengine.disabled}"/>
+      <sysproperty key="fop.layoutengine.testset" value="standard"/>
+      <formatter type="brief" usefile="false"/>
+      <formatter type="plain" usefile="true"/>
+      <formatter type="xml" usefile="true"/>
+      <classpath>
+        <pathelement location="${build.dir}/test-classes"/>
+        <path refid="libs-run-classpath"/>
+      </classpath>
+      <test name="org.apache.fop.config.UserConfigTestSuite" todir="${junit.reports.dir}" outfile="TEST-userconfig"/>
+    </junit>
+  </target>
+
   <target name="junit-basic" depends="junit-compile" description="Runs FOP's JUnit basic tests" if="junit.present">
     <echo message="Running basic functionality tests for fop.jar"/>
     <junit dir="${basedir}" haltonfailure="${junit.haltonfailure}" fork="${junit.fork}" errorproperty="fop.junit.error" failureproperty="fop.junit.failure">
@@ -924,7 +943,7 @@
     </junit>
   </target>
 
-  <target name="junit" depends="junit-basic, junit-transcoder, junit-text-linebreak, junit-layout, junit-fotree, junit-intermediate-format" description="Runs all of FOP's JUnit tests" if="junit.present">
+  <target name="junit" depends="junit-userconfig, junit-basic, junit-transcoder, junit-text-linebreak, junit-layout, junit-fotree, junit-intermediate-format" description="Runs all of FOP's JUnit tests" if="junit.present">
     <fail>
       <condition>
         <or>
Index: src/documentation/content/xdocs/0.93/configuration.xml
===================================================================
--- src/documentation/content/xdocs/0.93/configuration.xml	(revision 502182)
+++ src/documentation/content/xdocs/0.93/configuration.xml	(working copy)
@@ -64,19 +64,21 @@
       <tr>
         <th>Element</th>
         <th>Data Type (for the value)</th>
+        <th>Description</th>
         <th>Default Value</th>
       </tr>
       <tr>
         <td>base</td>
         <td>URL or directory</td>
         <td>Specifies the base URL based on which relative URL will be resolved.</td>
+        <td>current directory</td>
       </tr>
       <tr>
         <td>font-base</td>
         <td>URL or directory</td>
         <td>Specifies the base URL based on which relative font URLs will be resolved.
-        If not specified defaults to the base URL above.
         </td>
+	<td>base URL/directory (above)</td>
       </tr>
       <tr>
         <td>hyphenation-base</td>
@@ -85,6 +87,7 @@
         files will be resolved. If not specified, support for user-supplied hyphenation 
         patterns remains disabled.
         </td>
+        <td>disabled</td>
       </tr>
       <tr>
         <td>source-resolution</td>
@@ -93,6 +96,7 @@
           Resolution in dpi (dots per inch) which is used internally to determine the pixel 
           size for SVG images and bitmap images without resolution information.
         </td>
+        <td>72 dpi</td>
       </tr>
       <tr>
         <td>target-resolution</td>
@@ -102,15 +106,27 @@
           images generated by bitmap renderers (such as the TIFF renderer) and by bitmaps
           generated by Apache Batik for filter effects and such.
         </td>
+        <td>72 dpi</td>
       </tr>
       <tr>
+        <td>strict-configuration</td>
+        <td>Boolean (true, false)</td>
+        <td>
+	  Setting this option to 'true' will cause FOP to strictly verify the contents of the
+	  FOP configuration file to ensure that defined resources (such as fonts and base
+	  URLs/directories) are valid and available to FOP.  Any errors found will cause FOP to
+	  immediately raise an exception.</td>
+        <td>false</td>
+      </tr>
+      <tr>
         <td>strict-validation</td>
         <td>Boolean (true, false)</td>
         <td>
           Setting this option to 'false' causes FOP to be more forgiving about XSL-FO validity, 
           for example, you're allowed to specify a border on a region-body which is supported 
           by some FO implementations but is non-standard. Note that such a border would 
-          currently have no effect in Apache FOP.</td>
+	  currently have no effect in Apache FOP.</td>
+        <td>true</td>
       </tr>
       <tr>
         <td>break-indent-inheritance</td>
@@ -124,6 +140,7 @@
           the desired behaviour and because the behaviour among the commercial implementations
           varies. The default for this option (i.e. false) is to behave exactly like the 
           specification describes.</td>
+        <td>false</td>
       </tr>
       <tr>
         <td>default-page-settings</td>
@@ -132,11 +149,13 @@
           Specifies the default width and height of a page if "auto" is specified 
           for either or both values. Use "height" and "width" attributes on the 
           default-page-settings element to specify the two values.</td>
+        <td>"height" 11 inches, "width" 8.26 inches</td>
       </tr>
       <tr>
         <td>renderers</td>
         <td>(see text below)</td>
         <td>Contains the configuration for each renderer. See below.</td>
+	<td>N/A</td>
       </tr>
     </table>
     <p>
@@ -145,6 +164,12 @@
     <source><![CDATA[
 <fop version="1.0">
 
+  <!-- Strict user configuration -->
+  <strict-configuration>true</strict-configuration>
+
+  <!-- Strict FO validation -->
+  <strict-validation>true</strict-validation>
+
   <!-- Base URL for resolving relative URLs -->
   <base>./</base>
Index: src/java/org/apache/fop/apps/FopFactory.java
===================================================================
--- src/java/org/apache/fop/apps/FopFactory.java	(revision 502182)
+++ src/java/org/apache/fop/apps/FopFactory.java	(working copy)
@@ -63,11 +63,25 @@
 
     /** Defines the default source resolution (72dpi) for FOP */
     private 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 */
     private static final String DEFAULT_PAGE_HEIGHT = "11in";
+    
     /** Defines the default page-width */
     private static final String DEFAULT_PAGE_WIDTH = "8.26in";
+    
+    /** Defines if FOP should use strict validation for FO and user config */
+    public static final boolean DEFAULT_STRICT_FO_VALIDATION = true;
 
+    /** Defines if FOP should validate the user config strictly */
+    public static final boolean DEFAULT_STRICT_USERCONFIG_VALIDATION = true;
+    
+    /** Defines if FOP should use an alternative rule to determine text indents */
+    public static final boolean DEFAULT_BREAK_INDENT_INHERITANCE = false;
+
     /** logger instance */
     private static Log log = LogFactory.getLog(FopFactory.class);
     
@@ -97,27 +111,46 @@
     /** user configuration */
     private Configuration userConfig = null;
 
+    /** 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;
-    
+
+    /** The base URL for all hyphen URL resolutions */
+    private String hyphenBaseURL;
+
     /**
      * 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.   
+     * ability for FOP to halt on all content model violations if desired.
      */ 
-    private boolean strictValidation = true;
+    private boolean strictValidation = DEFAULT_STRICT_FO_VALIDATION;
 
+    /**
+     * FOP will validate the contents of the user configuration strictly
+     * (e.g. base-urls and font urls/paths).
+     */
+    private boolean strictUserConfigValidation = DEFAULT_STRICT_USERCONFIG_VALIDATION;
+    
     /** Allows enabling kerning on the base 14 fonts, default is false */
     private boolean enableBase14Kerning = false;
     
     /** Source resolution in dpi */
     private float sourceResolution = DEFAULT_SOURCE_RESOLUTION;
+
+    /** Target resolution in dpi */
+    private float targetResolution = DEFAULT_TARGET_RESOLUTION;
+
+    /** Page height */
     private String pageHeight = DEFAULT_PAGE_HEIGHT;
+    
+    /** Page width */
     private String pageWidth = DEFAULT_PAGE_WIDTH;
 
     /** @see #setBreakIndentInheritanceOnReferenceAreaBoundary(boolean) */
-    private boolean breakIndentInheritanceOnReferenceAreaBoundary = false;
+    private boolean breakIndentInheritanceOnReferenceAreaBoundary = DEFAULT_BREAK_INDENT_INHERITANCE;
 
     /** Optional overriding LayoutManagerMaker */
     private LayoutManagerMaker lmMakerOverride = null;
@@ -149,6 +182,7 @@
      * 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
+     * @throws FOPException 
      */
     public FOUserAgent newFOUserAgent() {
         FOUserAgent userAgent = new FOUserAgent(this);
@@ -296,6 +330,22 @@
     }
 
     /**
+     * Sets the base URL.
+     * @param baseURL base URL
+     */
+    void setBaseURL(String baseURL) {
+        this.baseURL = baseURL;
+    }
+
+    /**
+     * Returns the base URL.
+     * @return the base URL
+     */
+    public String getBaseURL() {
+        return this.baseURL;
+    }
+
+    /**
      * Sets the font base URL.
      * @param fontBaseURL font base URL
      */
@@ -308,7 +358,20 @@
         return this.fontBaseURL;
     }
 
+    /** @return the hyphen base URL */
+    public String getHyphenBaseURL() {
+        return hyphenBaseURL;
+    }
+
     /**
+     * Sets the hyphen base URL.
+     * @param fontBaseURL font base URL
+     */
+    public void setHyphenBaseURL(String hyphenBaseURL) {
+        this.hyphenBaseURL = hyphenBaseURL;
+    }
+
+    /**
      * Sets the URI Resolver. It is used for resolving factory-level URIs like hyphenation
      * patterns and as backup for URI resolution performed during a rendering run. 
      * @param resolver the new URI resolver
@@ -399,15 +462,50 @@
     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) {
+    public void setSourceResolution(float dpi) {
         this.sourceResolution = dpi;
+        log.info("source-resolution set to: " + sourceResolution 
+                + "dpi (px2mm=" + getSourcePixelUnitToMillimeter() + ")");
     }
+
+    /** @return the resolution for resolution-dependant output */
+    public float getTargetResolution() {
+        return this.targetResolution;
+    }
+
+    /**
+     * Returns the conversion factor from pixel units to millimeters. This
+     * depends on the desired target resolution.
+     * @return float conversion factor
+     * @see #getTargetResolution()
+     */
+    public float getTargetPixelUnitToMillimeter() {
+        return 25.4f / 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 setTargetResolution(float dpi) {
+        this.targetResolution = dpi;
+    }
+
+    /**
+     * 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) {
+        setSourceResolution((float)dpi);
+    }
     
     /**
      * Gets the default page-height to use as fallback,
@@ -427,6 +525,7 @@
      */
     public void setPageHeight(String pageHeight) {
         this.pageHeight = pageHeight;
+        log.info("Default page-height set to: " + pageHeight);
     }
     
     /**
@@ -447,6 +546,7 @@
      */
     public void setPageWidth(String pageWidth) {
         this.pageWidth = pageWidth;
+        log.info("Default page-width set to: " + pageWidth);
     }
     
     /**
@@ -491,14 +591,12 @@
      * @throws IOException if an I/O error occurs
      * @throws SAXException if a parsing error occurs
      */
-    public void setUserConfig(File userConfigFile)
-                throws SAXException, IOException {
+    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());
+        } catch (ConfigurationException e) {
+            throw new FOPException(e);
         }
     }
     
@@ -508,28 +606,27 @@
      * @throws IOException if an I/O error occurs
      * @throws SAXException if a parsing error occurs
      */
-    public void setUserConfig(String uri)
-                throws SAXException, IOException {
+    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());
+        } catch (ConfigurationException e) {
+            throw new FOPException(e);
         }
     }
     
     /**
      * Set the user configuration.
      * @param userConfig configuration
+     * @throws FOPException if a configuration problem occurs 
      */
-    public void setUserConfig(Configuration userConfig) {
+    public void setUserConfig(Configuration userConfig) throws FOPException {
         this.userConfig = userConfig;
         try {
-            initUserConfig();
-        } catch (ConfigurationException cfge) {
-            log.error("Error initializing factory configuration: "
-                    + cfge.getMessage());
+            configure(userConfig);
+        } catch (ConfigurationException e) {            
+            throw new FOPException(e);
         }
     }
 
@@ -540,75 +637,127 @@
     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
+     * Configures the FopFactory.
+     * @param cfg Avalon Configuration Object
+     * @see org.apache.avalon.framework.configuration.Configurable
      */
-    public void initUserConfig() throws ConfigurationException {
-        log.debug("Initializing User Agent Configuration");
-        setFontBaseURL(getBaseURLfromConfig(userConfig, "font-base"));
-        final String hyphBase = getBaseURLfromConfig(userConfig, "hyphenation-base");
-        if (hyphBase != null) {
-            this.hyphResolver = new HyphenationTreeResolver() {
-                public Source resolve(String href) {
-                    return resolveURI(href, hyphBase);
-                }
-            };
+    public void configure(Configuration cfg) throws ConfigurationException {        
+        log.info("Initializing FopFactory Configuration");        
+        
+        boolean strictConfig = DEFAULT_STRICT_USERCONFIG_VALIDATION;
+        if (cfg.getChild("strict-configuration", false) != null) {
+            strictConfig = cfg.getChild("strict-configuration").getValueAsBoolean();
+            setStrictUserConfigValidation(strictConfig);
         }
-        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() + ")");
+        boolean strictFO = DEFAULT_STRICT_FO_VALIDATION;
+        if (cfg.getChild("strict-validation", false) != null) {
+            strictFO = cfg.getChild("strict-validation").getValueAsBoolean();
+            setStrictValidation(strictFO);
         }
-        if (userConfig.getChild("strict-validation", false) != null) {
-            this.strictValidation = userConfig.getChild("strict-validation").getValueAsBoolean();
+        try {
+            if( cfg.getChild("base", false) != null ) {
+                setBaseURL(getBaseURLfromConfig(cfg, "base"));
+            }
+        } catch( ConfigurationException e ) {
+            if( strictFO ) throw e;
+            log.error( e.getMessage() );
         }
-        if (userConfig.getChild("break-indent-inheritance", false) != null) {
-            this.breakIndentInheritanceOnReferenceAreaBoundary 
-                = userConfig.getChild("break-indent-inheritance").getValueAsBoolean();
+        if( cfg.getChild("font-base", false) != null ) {
+            try {
+                setFontBaseURL(getBaseURLfromConfig(cfg, "font-base"));
+            } catch( ConfigurationException e ) {
+                if( strictFO ) throw e;
+                log.error( e.getMessage() );
+            }
         }
-        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(cfg.getChild("hyphenation-base", false) != null) {
+            try {
+                setHyphenBaseURL(getBaseURLfromConfig(cfg, "hyphenation-base"));
+            } catch( ConfigurationException e ) {
+                if( strictFO ) throw e;
+                log.error( e.getMessage() );
+            }
         }
-        if (pageConfig.getAttribute("width", null) != null) {
-            setPageWidth(pageConfig.getAttribute("width"));
-            log.info("Default page-width set to: " + pageWidth);
+        if(cfg.getChild("source-resolution", false) != null) {
+            setSourceResolution(cfg.getChild("source-resolution").getValueAsFloat(DEFAULT_SOURCE_RESOLUTION));
         }
+        if (cfg.getChild("target-resolution", false) != null) {
+            setTargetResolution(cfg.getChild("target-resolution").getValueAsFloat(FOUserAgent.DEFAULT_TARGET_RESOLUTION));
+        }
+        if (cfg.getChild("break-indent-inheritance", false) != null) {
+            setBreakIndentInheritanceOnReferenceAreaBoundary(
+                    cfg.getChild("break-indent-inheritance").getValueAsBoolean());
+        }        
+        Configuration pageConfig = cfg.getChild("default-page-settings");
+        if( pageConfig != null ) {
+            if (pageConfig.getAttribute("height", null) != null) {
+                setPageHeight(pageConfig.getAttribute("height",DEFAULT_PAGE_HEIGHT));
+            }
+            if (pageConfig.getAttribute("width", null) != null) {
+                setPageWidth(pageConfig.getAttribute("width",DEFAULT_PAGE_WIDTH));
+            }
+        } else {
+            setPageHeight(DEFAULT_PAGE_HEIGHT);
+            setPageWidth(DEFAULT_PAGE_WIDTH);            
+        }
     }
 
+
     /**
      * 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) {
+     * @throws ConfigurationException 
+     */    
+    public static String getBaseURLfromConfig(Configuration cfg, String name)
+    throws ConfigurationException {
         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()) {
+                    if (!dir.exists()) {
+                        throw new ConfigurationException("Base URL '" + name +
+                                "' references non-existent resource '" +
+                                cfgBaseDir + "'");
+                    } else if (dir.isDirectory()) {
                         cfgBaseDir = dir.toURL().toExternalForm(); 
                     }
                 }
                 log.info(name + " set to: " + cfgBaseDir);
                 return cfgBaseDir;
             } catch (MalformedURLException mue) {
-                log.error("Base URL in user config is malformed!");
+                throw new ConfigurationException("Base URL '" + name + "' in user config is malformed!");
             }
         }
         return null;
     }
 
+    /**
+     * Is the user configuration to be validated?
+     * @param strictUserConfigValidation strict user config validation
+     * @return if the user configuration should be validated
+     */
+    public void setStrictUserConfigValidation(boolean strictUserConfigValidation) {
+        this.strictUserConfigValidation = strictUserConfigValidation;
+    }
+
+    /**
+     * Is the user configuration to be validated?
+     * @return if the user configuration should be validated
+     */
+    public boolean validateUserConfigStrictly() {
+        return this.strictUserConfigValidation;
+    }
+
     //------------------------------------------- URI resolution
 
     /**
@@ -700,5 +849,4 @@
         }
         return colorSpace;
     }
-    
-}
+}
\ No newline at end of file
Index: src/java/org/apache/fop/apps/FOURIResolver.java
===================================================================
--- src/java/org/apache/fop/apps/FOURIResolver.java	(revision 502182)
+++ src/java/org/apache/fop/apps/FOURIResolver.java	(working copy)
@@ -84,7 +84,7 @@
             try {
                 absoluteURL = f.toURL();
             } catch (MalformedURLException mfue) {
-                log.error("Could not convert filename to URL: " + mfue.getMessage(), mfue); 
+                log.error("Could not convert filename to URL: " + mfue.getMessage()); 
             }
         } else {
             URL baseURL = toBaseURL(base);
@@ -98,7 +98,7 @@
                         // the href contains only a path then file: is assumed
                         absoluteURL = new URL("file:" + href);
                     } catch (MalformedURLException mfue) {
-                        log.error("Error with URL '" + href + "': " + mue.getMessage(), mue);
+                        log.error("Error with URL '" + href + "': " + mue.getMessage());
                         return null;
                     }
                 }
@@ -137,7 +137,7 @@
                     }
                     absoluteURL = new URL(baseURL, href);
                 } catch (MalformedURLException mfue) {
-                    log.error("Error with URL '" + href + "': " + mfue.getMessage(), mfue);
+                    log.error("Error with URL '" + href + "': " + mfue.getMessage());
                     return null;
                 }
             }
@@ -155,7 +155,7 @@
             //Note: This is on "debug" level since the caller is supposed to handle this
             log.debug("File not found: " + effURL);
         } catch (java.io.IOException ioe) {
-            log.error("Error with opening URL '" + href + "': " + ioe.getMessage(), ioe);
+            log.error("Error with opening URL '" + href + "': " + ioe.getMessage());
         }
         return null;
     }
Index: src/java/org/apache/fop/apps/FOUserAgent.java
===================================================================
--- src/java/org/apache/fop/apps/FOUserAgent.java	(revision 502182)
+++ src/java/org/apache/fop/apps/FOUserAgent.java	(working copy)
@@ -67,7 +67,7 @@
 public class FOUserAgent {
 
     /** Defines the default target resolution (72dpi) for FOP */
-    public static final float DEFAULT_TARGET_RESOLUTION = 72.0f; //dpi
+    public static final float DEFAULT_TARGET_RESOLUTION = FopFactory.DEFAULT_TARGET_RESOLUTION;
 
     private static Log log = LogFactory.getLog("FOP");
 
@@ -109,11 +109,12 @@
     
     /**
      * Default constructor
+     * @throws FOPException 
      * @see org.apache.fop.apps.FopFactory
      * @deprecated Provided for compatibility only. Please use the methods from 
      *             FopFactory to construct FOUserAgent instances!
      */
-    public FOUserAgent() {
+    public FOUserAgent() throws FOPException {
         this(FopFactory.newInstance());
     }
     
@@ -285,14 +286,8 @@
      * @see org.apache.avalon.framework.configuration.Configurable
      */
     protected void configure(Configuration cfg) {
-        setBaseURL(FopFactory.getBaseURLfromConfig(cfg, "base"));
-        if (cfg.getChild("target-resolution", false) != null) {
-            this.targetResolution 
-                = cfg.getChild("target-resolution").getValueAsFloat(
-                        DEFAULT_TARGET_RESOLUTION);
-            log.info("Target resolution set to: " + targetResolution 
-                    + "dpi (px2mm=" + getTargetPixelUnitToMillimeter() + ")");
-        }
+        setBaseURL(factory.getBaseURL());
+        setTargetResolution(factory.getTargetResolution());
     }
     
     /**
@@ -301,12 +296,11 @@
      * @return the requested configuration subtree, null if there's no configuration
      */
     public Configuration getUserRendererConfig(String mimeType) {
-
         Configuration cfg = getFactory().getUserConfig();
         if (cfg == null || mimeType == null) {
             return null;
         }
-
+        
         Configuration userRendererConfig = null;
 
         Configuration[] cfgs
@@ -460,9 +454,21 @@
      * bitmap images generated by filter effects in Apache Batik.
      * @param dpi resolution in dpi
      */
-    public void setTargetResolution(int dpi) {
+    public void setTargetResolution(float dpi) {
         this.targetResolution = dpi;
+        log.info("target-resolution set to: " + targetResolution 
+                + "dpi (px2mm=" + getTargetPixelUnitToMillimeter() + ")");
     }
+
+    /**
+     * 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
+     * bitmap images generated by filter effects in Apache Batik.
+     * @param dpi resolution in dpi
+     */
+    public void setTargetResolution(int dpi) {
+        setTargetResolution((float)dpi);
+    }
     
     // ---------------------------------------------- environment-level stuff
     //                                                (convenience access to FopFactory methods)
@@ -470,7 +476,7 @@
     /** @return the font base URL */
     public String getFontBaseURL() {
         String fontBaseURL = getFactory().getFontBaseURL(); 
-        return fontBaseURL != null ? fontBaseURL : this.baseURL;
+        return fontBaseURL != null ? fontBaseURL : getBaseURL();
     }
 
     /**
@@ -541,6 +547,5 @@
     public XMLHandlerRegistry getXMLHandlerRegistry() {
         return getFactory().getXMLHandlerRegistry();
     }
-
 }
 
Index: src/java/org/apache/fop/fonts/FontSetup.java
===================================================================
--- src/java/org/apache/fop/fonts/FontSetup.java	(revision 502182)
+++ src/java/org/apache/fop/fonts/FontSetup.java	(working copy)
@@ -34,6 +34,7 @@
 import org.apache.fop.fonts.base14.CourierBoldOblique;
 import org.apache.fop.fonts.base14.Symbol;
 import org.apache.fop.fonts.base14.ZapfDingbats;
+import org.apache.fop.render.PrintRenderer;
 
 // commons logging
 import org.apache.commons.logging.Log;
@@ -44,6 +45,8 @@
 import org.apache.avalon.framework.configuration.ConfigurationException;
 
 // Java
+import java.io.File;
+import java.io.FilenameFilter;
 import java.util.List;
 
 import javax.xml.transform.Source;
@@ -247,46 +250,127 @@
             
         };
     }
+   
     /**
      * Builds a list of EmbedFontInfo objects for use with the setup() method.
+     * 
      * @param cfg Configuration object
+     * @param renderer calling Renderer object
      * @return List the newly created list of fonts
      * @throws ConfigurationException if something's wrong with the config data
      */
-    public static List buildFontListFromConfiguration(Configuration cfg)
+    public static List buildFontListFromConfiguration(Configuration cfg, PrintRenderer renderer)
             throws ConfigurationException {
         List fontList = new java.util.ArrayList();
-        Configuration[] font = cfg.getChild("fonts").getChildren("font");
-        for (int i = 0; i < font.length; i++) {
-            Configuration[] triple = font[i].getChildren("font-triplet");
-            List tripleList = new java.util.ArrayList();
-            for (int j = 0; j < triple.length; j++) {
-                int weight = FontUtil.parseCSS2FontWeight(triple[j].getAttribute("weight"));
-                tripleList.add(FontInfo.createFontKey(triple[j].getAttribute("name"),
-                                               triple[j].getAttribute("style"),
-                                               weight));
-            }
-
-            EmbedFontInfo efi;
-            efi = new EmbedFontInfo(font[i].getAttribute("metrics-url", null),
-                                    font[i].getAttributeAsBoolean("kerning", false),
-                                    tripleList, font[i].getAttribute("embed-url", null));
-
-            if (log.isDebugEnabled()) {
-                log.debug("Adding font " + efi.getEmbedFile()
-                          + ", metric file " + efi.getMetricsFile());
-                for (int j = 0; j < tripleList.size(); ++j) {
-                    FontTriplet triplet = (FontTriplet) tripleList.get(j);
-                    log.debug("Font triplet "
-                              + triplet.getName() + ", "
-                              + triplet.getStyle() + ", "
-                              + triplet.getWeight());
+               
+        FontResolver fontResolver = renderer.getFontResolver();
+        if (fontResolver == null) {
+            //Ensure that we have minimal font resolution capabilities
+            fontResolver = FontSetup.createMinimalFontResolver();
+        }
+       
+        boolean strictUserConfigValidation = renderer.getUserAgent().getFactory().validateUserConfigStrictly();
+        
+        Configuration[] fonts = cfg.getChildren("fonts");
+        for( int f = 0; f < fonts.length; f++ ) {
+                
+            Configuration[] font = fonts[f].getChildren("font");
+            for (int i = 0; i < font.length; i++) {
+    
+                String metricsUrl = font[i].getAttribute("metrics-url", null);
+                String embedUrl = font[i].getAttribute("embed-url", null);
+    
+                if( metricsUrl == null && embedUrl == null ) {
+                    if( strictUserConfigValidation ) {
+                        throw new ConfigurationException( "Font configuration without metric-url or embed-url" );
+                    }
+                    log.error("Font configuration without metric-url or embed-url");
+                    continue;
                 }
+                
+                if( metricsUrl != null && fontResolver.resolve(metricsUrl) == null ) {
+                    if( strictUserConfigValidation ) {
+                        throw new ConfigurationException( "Failed to resolve font metric-url '"
+                            + metricsUrl + "'" );                    
+                    }
+                    log.error("Failed to resolve font metric-url '" + metricsUrl + "'");
+                    continue;
+                }
+                
+                if( embedUrl != null && fontResolver.resolve(embedUrl) == null ) {
+                    if( strictUserConfigValidation ) {
+                        throw new ConfigurationException( "Failed to resolve font with embed-url '"
+                                + embedUrl + "'" );
+                    }
+                    log.error("Failed to resolve font with embed-url '" + embedUrl + "'" );
+                    continue;
+                }
+            
+                boolean useKerning = font[i].getAttributeAsBoolean("kerning", false);
+    
+                Configuration[] triple = font[i].getChildren("font-triplet");
+                List tripleList = new java.util.ArrayList();
+                for (int j = 0; j < triple.length; j++) {
+                    String name = triple[j].getAttribute("name");
+                    if( name == null ) {
+                        if( strictUserConfigValidation ) {
+                            throw new ConfigurationException( "font-triplet without name" );
+                        }
+                        log.error("font-triplet without name" );
+                        continue;
+                    }
+                    
+                    String weightStr = triple[j].getAttribute("weight");
+                    if( weightStr == null ) {
+                        if( strictUserConfigValidation ) {
+                            throw new ConfigurationException( "font-triplet without weight" );
+                        }
+                        log.error("font-triplet without weight" );
+                        continue;
+                    }
+                    int weight = FontUtil.parseCSS2FontWeight(weightStr);
+    
+                    String style = triple[j].getAttribute("style");
+                    if( style == null ) {
+                        if( strictUserConfigValidation ) {
+                            throw new ConfigurationException( "font-triplet without style" );
+                        }
+                        log.error("font-triplet without style" );
+                        continue;
+                    }
+                    
+                    tripleList.add(FontInfo.createFontKey(name,
+                            style, weight));
+                }
+    
+                EmbedFontInfo configFontInfo = new EmbedFontInfo(metricsUrl, 
+                        useKerning, tripleList, embedUrl);
+                
+                if (log.isDebugEnabled()) {
+                    log.debug("Adding font " + configFontInfo.getEmbedFile()
+                            + ", metric file " + configFontInfo.getMetricsFile());
+                    for (int j = 0; j < tripleList.size(); ++j) {
+                        FontTriplet triplet = (FontTriplet) tripleList.get(j);
+                        log.debug("Font triplet "
+                                    + triplet.getName() + ", "
+                                    + triplet.getStyle() + ", "
+                                    + triplet.getWeight());
+                    }
+                }
+                fontList.add(configFontInfo);
             }
-
-            fontList.add(efi);
         }
         return fontList;
+    }    
+
+    /**
+     * Builds a list of EmbedFontInfo objects for use with the setup() method.
+     * 
+     * @param cfg Configuration object
+     * @return List the newly created list of fonts
+     * @throws ConfigurationException if something's wrong with the config data
+     */
+    public static List buildFontListFromConfiguration(Configuration cfg) throws ConfigurationException {
+        return buildFontListFromConfiguration(cfg, null);
     }
-}
-
+}
\ No newline at end of file
Index: src/java/org/apache/fop/render/AbstractRenderer.java
===================================================================
--- src/java/org/apache/fop/render/AbstractRenderer.java	(revision 502182)
+++ src/java/org/apache/fop/render/AbstractRenderer.java	(working copy)
@@ -88,7 +88,7 @@
     /**
      * user agent
      */
-    protected FOUserAgent userAgent;
+    protected FOUserAgent userAgent = null;
 
     /**
      * block progression position
@@ -135,6 +135,13 @@
         userAgent = agent;
     }
 
+    /**
+     *  @see org.apache.fop.render.Renderer#getUserAgent()
+     */
+    public FOUserAgent getUserAgent() {
+        return userAgent;
+    }
+
     /** @see org.apache.fop.render.Renderer#startRenderer(OutputStream) */
     public void startRenderer(OutputStream outputStream)
         throws IOException { }
Index: src/java/org/apache/fop/render/pdf/PDFRenderer.java
===================================================================
--- src/java/org/apache/fop/render/pdf/PDFRenderer.java	(revision 502182)
+++ src/java/org/apache/fop/render/pdf/PDFRenderer.java	(working copy)
@@ -243,7 +243,7 @@
         this.filterMap = PDFFilterList.buildFilterMapFromConfiguration(cfg);
 
         //Font configuration
-        List cfgFonts = FontSetup.buildFontListFromConfiguration(cfg);
+        List cfgFonts = FontSetup.buildFontListFromConfiguration(cfg, this);
         if (this.fontList == null) {
             this.fontList = cfgFonts;
         } else {
Index: src/java/org/apache/fop/render/PrintRenderer.java
===================================================================
--- src/java/org/apache/fop/render/PrintRenderer.java	(revision 502182)
+++ src/java/org/apache/fop/render/PrintRenderer.java	(working copy)
@@ -41,9 +41,12 @@
     /** Font configuration */
     protected FontInfo fontInfo;
 
+    /** Font resolver */
+    protected FontResolver fontResolver = null;
+
     /** list of fonts */
     protected List fontList = null;
-
+    
     /**
      * Set up the font info
      *
@@ -51,8 +54,7 @@
      */
     public void setupFontInfo(FontInfo inFontInfo) {
         this.fontInfo = inFontInfo;
-        FontResolver resolver = new DefaultFontResolver(userAgent);
-        FontSetup.setup(fontInfo, fontList, resolver, 
+        FontSetup.setup(fontInfo, fontList, fontResolver, 
                 userAgent.getFactory().isBase14KerningEnabled());
     }
 
@@ -147,5 +149,16 @@
         
         renderXML(context, doc, ns);
     }
-    
+
+    /**
+     * Get FontResolver
+     *
+     * @return FontResolver
+     */
+    public FontResolver getFontResolver() {
+        if( this.fontResolver == null ) {
+            this.fontResolver = new DefaultFontResolver(super.userAgent);
+        }
+        return this.fontResolver;
+    }
 }
Index: src/java/org/apache/fop/render/ps/PSRenderer.java
===================================================================
--- src/java/org/apache/fop/render/ps/PSRenderer.java	(revision 502182)
+++ src/java/org/apache/fop/render/ps/PSRenderer.java	(working copy)
@@ -129,7 +129,7 @@
         this.autoRotateLandscape = cfg.getChild("auto-rotate-landscape").getValueAsBoolean(false);
 
         //Font configuration
-        List cfgFonts = FontSetup.buildFontListFromConfiguration(cfg);
+        List cfgFonts = FontSetup.buildFontListFromConfiguration(cfg, this);
         if (this.fontList == null) {
             this.fontList = cfgFonts;
         } else {
Index: src/java/org/apache/fop/render/xml/XMLRenderer.java
===================================================================
--- src/java/org/apache/fop/render/xml/XMLRenderer.java	(revision 502182)
+++ src/java/org/apache/fop/render/xml/XMLRenderer.java	(working copy)
@@ -145,7 +145,7 @@
     public void configure(Configuration cfg) throws ConfigurationException {
         super.configure(cfg);
         //Font configuration
-        List cfgFonts = FontSetup.buildFontListFromConfiguration(cfg);
+        List cfgFonts = FontSetup.buildFontListFromConfiguration(cfg, this);
         if (this.fontList == null) {
             this.fontList = cfgFonts;
         } else {
Index: test/java/org/apache/fop/render/pdf/BasePDFTestCase.java
===================================================================
--- test/java/org/apache/fop/render/pdf/BasePDFTestCase.java	(revision 502182)
+++ test/java/org/apache/fop/render/pdf/BasePDFTestCase.java	(working copy)
@@ -29,17 +29,16 @@
 
 import org.apache.commons.io.FileUtils;
 import org.apache.commons.io.output.ByteArrayOutputStream;
+import org.apache.fop.AbstractFOPTestCase;
 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 junit.framework.TestCase;
-
 /**
  * Base class for automated tests that create PDF files
  */
-public class BasePDFTestCase extends TestCase {
+public class BasePDFTestCase extends AbstractFOPTestCase {
 
     /** the FopFactory */
     protected final FopFactory fopFactory = FopFactory.newInstance();
@@ -53,7 +52,10 @@
      */
     protected BasePDFTestCase(String name) {
         super(name);
+        init();
+    }
 
+    protected void init() {
         final File uc = getUserConfigFile();
 
         try {
@@ -63,7 +65,7 @@
                     + uc.getAbsolutePath() + ") failed: " + e.getMessage());
         }
     }
-
+    
     /**
      * Convert a test FO file to PDF
      * @param foFile the FO file
Index: test/test_embedurl_bad.xconf
===================================================================
--- test/test_embedurl_bad.xconf	(revision 0)
+++ test/test_embedurl_bad.xconf	(revision 0)
@@ -0,0 +1,22 @@
+<?xml version="1.0"?>
+<fop version="1.0">
+  <!-- Strict configuration On -->
+  <strict-configuration>true</strict-configuration>
+
+  <!-- Base URL for resolving relative URLs -->
+  <base>./</base>
+
+  <!-- Font Base URL for resolving relative font URLs -->
+  <font-base>./</font-base>
+  
+  <renderers>
+    <renderer mime="application/pdf">
+      <fonts>
+		<!-- this font has an embed-url that does not exist on filesystem -->
+		<font metrics-url="test/resources/fonts/glb12.ttf.xml" embed-url="test/resources/fonts/doesnotexist.ttf">
+          <font-triplet name="Gladiator-Ansi" style="normal" weight="normal"/>
+        </font>
+      </fonts>
+    </renderer>
+  </renderers>
+</fop>
Index: test/test_embedurl_malformed.xconf
===================================================================
--- test/test_embedurl_malformed.xconf	(revision 0)
+++ test/test_embedurl_malformed.xconf	(revision 0)
@@ -0,0 +1,22 @@
+<?xml version="1.0"?>
+<fop version="1.0">
+  <!-- Strict configuration On -->
+  <strict-configuration>true</strict-configuration>
+
+  <!-- Base URL for resolving relative URLs -->
+  <base>./</base>
+
+  <!-- Font Base URL for resolving relative font URLs -->
+  <font-base>./</font-base>
+  
+  <renderers>
+    <renderer mime="application/pdf">
+      <fonts>
+		<!-- this font has a malformed embed-url -->
+		<font metrics-url="test/resources/fonts/glb12.ttf.xml" embed-url="badprotocol:test/resources/fonts/glb12.ttf">
+          <font-triplet name="Gladiator-Ansi" style="normal" weight="normal"/>
+        </font>
+      </fonts>
+    </renderer>
+  </renderers>
+</fop>
Index: test/test_fontattributes_missing.xconf
===================================================================
--- test/test_fontattributes_missing.xconf	(revision 0)
+++ test/test_fontattributes_missing.xconf	(revision 0)
@@ -0,0 +1,22 @@
+<?xml version="1.0"?>
+<fop version="1.0">
+  <!-- Strict configuration On -->
+  <strict-configuration>true</strict-configuration>
+
+  <!-- Base URL for resolving relative URLs -->
+  <base>./</base>
+
+  <!-- Font Base URL for resolving relative font URLs -->
+  <font-base>./</font-base>
+  
+  <renderers>
+    <renderer mime="application/pdf">
+      <fonts>
+		<!-- this font is without a metrics-url -->
+		<font>
+          <font-triplet name="Gladiator" style="normal" weight="normal"/>
+        </font>
+      </fonts>
+    </renderer>
+  </renderers>
+</fop>
Index: test/test_fontbase_bad.xconf
===================================================================
--- test/test_fontbase_bad.xconf	(revision 0)
+++ test/test_fontbase_bad.xconf	(revision 0)
@@ -0,0 +1,23 @@
+<?xml version="1.0"?>
+<fop version="1.0">
+  <!-- Strict configuration On -->
+  <strict-configuration>true</strict-configuration>
+
+  <!-- Base URL for resolving relative URLs -->
+  <base>./</base>
+
+  <!-- Font Base URL for resolving relative font URLs -->
+  <font-base>./doesnotexist/</font-base>
+  
+  <renderers>
+    <renderer mime="application/pdf">
+      <fonts>
+		<!-- this font is with a relative metrics-url
+		     so should call upon the bad font-base -->
+        <font metrics-url="test/resources/fonts/glb12.ttf.xml" embed-url="test/resources/fonts/glb12.ttf">
+          <font-triplet name="Gladiator" style="normal" weight="normal"/>
+        </font>
+      </fonts>
+    </renderer>
+  </renderers>
+</fop>
Index: test/test_fonttripletattribute_missing.xconf
===================================================================
--- test/test_fonttripletattribute_missing.xconf	(revision 0)
+++ test/test_fonttripletattribute_missing.xconf	(revision 0)
@@ -0,0 +1,22 @@
+<?xml version="1.0"?>
+<fop version="1.0">
+  <!-- Strict configuration On -->
+  <strict-configuration>true</strict-configuration>
+
+  <!-- Base URL for resolving relative URLs -->
+  <base>./</base>
+
+  <!-- Font Base URL for resolving relative font URLs -->
+  <font-base>./</font-base>
+  
+  <renderers>
+    <renderer mime="application/pdf">
+      <fonts>
+        <font metrics-url="test/resources/fonts/glb12.ttf.xml">
+		  <!-- this font-triplet has a missing style attribute -->           
+          <font-triplet name="Gladiator" weight="normal"/>
+        </font>
+      </fonts>
+    </renderer>
+  </renderers>
+</fop>
Index: test/test_metricsurl_bad.xconf
===================================================================
--- test/test_metricsurl_bad.xconf	(revision 0)
+++ test/test_metricsurl_bad.xconf	(revision 0)
@@ -0,0 +1,22 @@
+<?xml version="1.0"?>
+<fop version="1.0">
+  <!-- Strict configuration On -->
+  <strict-configuration>true</strict-configuration>
+
+  <!-- Base URL for resolving relative URLs -->
+  <base>./</base>
+
+  <!-- Font Base URL for resolving relative font URLs -->
+  <font-base>./</font-base>
+  
+  <renderers>
+    <renderer mime="application/pdf">
+      <fonts>
+		<!-- this font has a metrics-url that does not exist on filesystem -->
+        <font metrics-url="test/resources/fonts/doesnotexist.ttf.ansi.xml">
+          <font-triplet name="Gladiator-Ansi" style="normal" weight="normal"/>
+        </font>
+      </fonts>
+    </renderer>
+  </renderers>
+</fop>
Index: test/test_metricsurl_malformed.xconf
===================================================================
--- test/test_metricsurl_malformed.xconf	(revision 0)
+++ test/test_metricsurl_malformed.xconf	(revision 0)
@@ -0,0 +1,22 @@
+<?xml version="1.0"?>
+<fop version="1.0">
+  <!-- Strict configuration On -->
+  <strict-configuration>true</strict-configuration>
+
+  <!-- Base URL for resolving relative URLs -->
+  <base>./</base>
+
+  <!-- Font Base URL for resolving relative font URLs -->
+  <font-base>./</font-base>
+  
+  <renderers>
+    <renderer mime="application/pdf">
+      <fonts>
+		<!-- this font has a malformed metrics-url -->
+        <font metrics-url="badprotocol:test/resources/fonts/glb12.ttf.xml">
+          <font-triplet name="Gladiator" style="normal" weight="normal"/>
+        </font>
+      </fonts>
+    </renderer>
+  </renderers>
+</fop>
Index: status.xml
===================================================================
--- status.xml	(revision 504579)
+++ status.xml	(working copy)
@@ -28,6 +28,9 @@
 
   <changes>
     <release version="FOP Trunk">
+      <action context="Code" dev="AD" type="fix" fixes-bug="40120,40288" due-to="Adrian Cumiskey">
+        Strict FOP user configuration checking.
+      </action>
       <action context="Code" dev="JM" type="add">
         Support for GIF images in RTF output (RTF handler, only. Does not affect the RTF library.)
       </action>
