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/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,10 +63,14 @@
 
     /** 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_VALIDATION = true;
 
     /** logger instance */
     private static Log log = LogFactory.getLog(FopFactory.class);
@@ -97,23 +101,37 @@
     /** 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.
+     * This flag also applies to the parsing of user config.   
      */ 
-    private boolean strictValidation = true;
+    private boolean strictValidation = DEFAULT_STRICT_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) */
@@ -149,6 +167,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 +315,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 +343,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
@@ -340,7 +388,7 @@
     }
 
     /**
-     * Returns whether FOP is strictly validating input XSL
+     * Returns whether FOP is strictly validating input XSL and user configuration
      * @return true of strict validation turned on, false otherwise
      */
     public boolean validateStrictly() {
@@ -399,15 +447,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 +510,7 @@
      */
     public void setPageHeight(String pageHeight) {
         this.pageHeight = pageHeight;
+        log.info("Default page-height set to: " + pageHeight);
     }
     
     /**
@@ -447,6 +531,7 @@
      */
     public void setPageWidth(String pageWidth) {
         this.pageWidth = pageWidth;
+        log.info("Default page-width set to: " + pageWidth);
     }
     
     /**
@@ -496,9 +581,11 @@
         try {
             DefaultConfigurationBuilder cfgBuilder = new DefaultConfigurationBuilder();
             setUserConfig(cfgBuilder.buildFromFile(userConfigFile));
-        } catch (ConfigurationException cfge) {
-            log.error("Error loading configuration: "
-                    + cfge.getMessage());
+        } catch (ConfigurationException e) {
+            log.error("Error loading configuration: " + e.getMessage());
+            if( validateStrictly() ) {
+                throw new FOPException(e);
+            }
         }
     }
     
@@ -513,23 +600,25 @@
         try {
             DefaultConfigurationBuilder cfgBuilder = new DefaultConfigurationBuilder();
             setUserConfig(cfgBuilder.build(uri));
-        } catch (ConfigurationException cfge) {
-            log.error("Error loading configuration: "
-                    + cfge.getMessage());
+        } catch (ConfigurationException e) {
+            log.error("Error loading configuration: " + e.getMessage());
+            if( validateStrictly() ) throw new FOPException(e);;
         }
     }
     
     /**
      * Set the user configuration.
      * @param userConfig configuration
+     * @throws IOException if an I/O error occurs
+     * @throws SAXException if a parsing error occurs
      */
-    public void setUserConfig(Configuration userConfig) {
+    public void setUserConfig(Configuration userConfig) throws SAXException, IOException {
         this.userConfig = userConfig;
         try {
-            initUserConfig();
-        } catch (ConfigurationException cfge) {
-            log.error("Error initializing factory configuration: "
-                    + cfge.getMessage());
+            configure(userConfig);
+        } catch (ConfigurationException e) {            
+            log.error("Error initializing factory configuration: " + e.getMessage());
+            if( validateStrictly() ) throw new FOPException(e);;
         }
     }
 
@@ -540,70 +629,106 @@
     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 strictValidation = DEFAULT_STRICT_VALIDATION;
+        if (cfg.getChild("strict-validation", false) != null) {
+            strictValidation = cfg.getChild("strict-validation").getValueAsBoolean();
+            setStrictValidation(strictValidation);
+        }
+        try {
+            if( cfg.getChild("base", false) != null ) {
+                setBaseURL(getBaseURLfromConfig(cfg, "base"));
+            }
+        } catch( ConfigurationException e ) {
+            if( strictValidation ) {
+                throw e;
+            }
+            log.error( e.getMessage() );
+        }
+        if( cfg.getChild("font-base", false) != null ) {
+            try {
+                setFontBaseURL(getBaseURLfromConfig(cfg, "font-base"));
+            } catch( ConfigurationException e ) {
+                if( strictValidation ) {
+                    throw e;
                 }
-            };
+                log.error( e.getMessage() );
+            }
         }
-        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(cfg.getChild("hyphenation-base", false) != null) {
+            try {
+                setHyphenBaseURL(getBaseURLfromConfig(cfg, "hyphenation-base"));
+            } catch( ConfigurationException e ) {
+                if( strictValidation ) {
+                    throw e;
+                }
+                log.error( e.getMessage() );
+            }
         }
-        if (userConfig.getChild("strict-validation", false) != null) {
-            this.strictValidation = userConfig.getChild("strict-validation").getValueAsBoolean();
+        if(cfg.getChild("source-resolution", false) != null) {
+            setSourceResolution(cfg.getChild("source-resolution").getValueAsFloat(DEFAULT_SOURCE_RESOLUTION));
         }
-        if (userConfig.getChild("break-indent-inheritance", false) != null) {
-            this.breakIndentInheritanceOnReferenceAreaBoundary 
-                = userConfig.getChild("break-indent-inheritance").getValueAsBoolean();
+        if (cfg.getChild("target-resolution", false) != null) {
+            setTargetResolution(cfg.getChild("target-resolution").getValueAsFloat(FOUserAgent.DEFAULT_TARGET_RESOLUTION));
         }
-        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("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);            
         }
-        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) {
+     * @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;
@@ -700,5 +825,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;
@@ -247,46 +248,124 @@
             
         };
     }
+   
     /**
      * 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();
+               
+        FontResolver fontResolver = renderer.getFontResolver();
+        if (fontResolver == null) {
+            //Ensure that we have minimal font resolution capabilities
+            fontResolver = FontSetup.createMinimalFontResolver();
+        }
+       
+        boolean validateStrictly = renderer.getUserAgent().getFactory().validateStrictly();        
+
         Configuration[] font = cfg.getChild("fonts").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( validateStrictly ) {
+                    log.error("Font configuration without metric-url or embed-url");
+                    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( validateStrictly ) {
+                    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( validateStrictly ) {
+                    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++) {
-                int weight = FontUtil.parseCSS2FontWeight(triple[j].getAttribute("weight"));
-                tripleList.add(FontInfo.createFontKey(triple[j].getAttribute("name"),
-                                               triple[j].getAttribute("style"),
-                                               weight));
+                String name = triple[j].getAttribute("name");
+                if( name == null ) {
+                    if( validateStrictly ) {
+                        throw new ConfigurationException( "font-triplet without name" );
+                    }
+                    log.error("font-triplet without name" );
+                    continue;
+                }
+                
+                String weightStr = triple[j].getAttribute("weight");
+                if( weightStr == null ) {
+                    if( validateStrictly ) {
+                        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( validateStrictly ) {
+                        throw new ConfigurationException( "font-triplet without style" );
+                    }
+                    log.error("font-triplet without style" );
+                    continue;
+                }
+                
+                tripleList.add(FontInfo.createFontKey(name,
+                        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));
-
+            EmbedFontInfo configFontInfo = new EmbedFontInfo(metricsUrl, 
+                    useKerning, tripleList, embedUrl);
+            
             if (log.isDebugEnabled()) {
-                log.debug("Adding font " + efi.getEmbedFile()
-                          + ", metric file " + efi.getMetricsFile());
+                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());
+                                + triplet.getName() + ", "
+                                + triplet.getStyle() + ", "
+                                + triplet.getWeight());
                 }
             }
-
-            fontList.add(efi);
+            fontList.add(configFontInfo);
         }
         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/config/EmbedUrlBadTestCase.java
===================================================================
--- test/java/org/apache/fop/config/EmbedUrlBadTestCase.java	(revision 0)
+++ test/java/org/apache/fop/config/EmbedUrlBadTestCase.java	(revision 0)
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id: $ */
+package org.apache.fop.config;
+
+import java.io.File;
+
+// this font has an embed-url that does not exist on filesystem
+public class EmbedUrlBadTestCase extends BaseUserConfigTestCase {
+
+    public EmbedUrlBadTestCase(String name) {
+        super(name);
+    }
+
+    protected File getUserConfigFile() {
+        return new File("test/test_embedurl_bad.xconf");
+    }
+    
+    public String getName() {
+        return "test_embedurl_bad.xconf";
+    }
+}
Index: test/java/org/apache/fop/config/EmbedUrlMalformedTestCase.java
===================================================================
--- test/java/org/apache/fop/config/EmbedUrlMalformedTestCase.java	(revision 0)
+++ test/java/org/apache/fop/config/EmbedUrlMalformedTestCase.java	(revision 0)
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id: $ */
+package org.apache.fop.config;
+
+import java.io.File;
+
+// this font has a malformed embed-url
+public class EmbedUrlMalformedTestCase extends BaseUserConfigTestCase {
+
+    public EmbedUrlMalformedTestCase(String name) {
+        super(name);
+    }
+
+    protected File getUserConfigFile() {
+        return new File("test/test_embedurl_malformed.xconf");
+    }
+    
+    public String getName() {
+        return "test_embedurl_malformed.xconf";
+    }
+}
Index: test/java/org/apache/fop/config/FontAttributesMissingTestCase.java
===================================================================
--- test/java/org/apache/fop/config/FontAttributesMissingTestCase.java	(revision 0)
+++ test/java/org/apache/fop/config/FontAttributesMissingTestCase.java	(revision 0)
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id: $ */
+package org.apache.fop.config;
+
+import java.io.File;
+
+// this font is without a metrics-url or an embed-url
+public class FontAttributesMissingTestCase extends BaseUserConfigTestCase {
+
+    public FontAttributesMissingTestCase(String name) {
+        super(name);
+    }
+
+    protected File getUserConfigFile() {
+        return new File("test/test_fontattributes_missing.xconf");
+    }
+    
+    public String getName() {
+        return "test_fontattributes_missing.xconf";
+    }
+}
Index: test/java/org/apache/fop/config/FontBaseBadTestCase.java
===================================================================
--- test/java/org/apache/fop/config/FontBaseBadTestCase.java	(revision 0)
+++ test/java/org/apache/fop/config/FontBaseBadTestCase.java	(revision 0)
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id: $ */
+package org.apache.fop.config;
+
+import java.io.File;
+
+// this font base does not exist and a relative font path is used
+public class FontBaseBadTestCase extends BaseUserConfigTestCase {
+
+    public FontBaseBadTestCase(String name) {
+        super(name);
+    }
+
+    protected File getUserConfigFile() {
+        return new File("test/test_fontbase_bad.xconf");
+    }
+    
+    public String getName() {
+        return "test_fontbase_bad.xconf";
+    }
+}
Index: test/java/org/apache/fop/config/FontTripletAttributeMissingTestCase.java
===================================================================
--- test/java/org/apache/fop/config/FontTripletAttributeMissingTestCase.java	(revision 0)
+++ test/java/org/apache/fop/config/FontTripletAttributeMissingTestCase.java	(revision 0)
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id: $ */
+package org.apache.fop.config;
+
+import java.io.File;
+
+// this font has an embed-url that does not exist on filesystem
+public class FontTripletAttributeMissingTestCase extends BaseUserConfigTestCase {
+
+    public FontTripletAttributeMissingTestCase(String name) {
+        super(name);
+    }
+
+    protected File getUserConfigFile() {
+        return new File("test/test_fonttripletattribute_missing.xconf");
+    }
+    
+    public String getName() {
+        return "test_fonttripletattribute_missing.xconf";
+    }
+}
Index: test/java/org/apache/fop/config/BaseUserConfigTestCase.java
===================================================================
--- test/java/org/apache/fop/config/BaseUserConfigTestCase.java	(revision 0)
+++ test/java/org/apache/fop/config/BaseUserConfigTestCase.java	(revision 0)
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id: $ */
+
+package org.apache.fop.config;
+
+import java.io.File;
+
+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.render.pdf.BasePDFTestCase;
+
+/**
+ * Basic runtime test for FOP's font configuration. It is used to verify that 
+ * nothing obvious is broken after compiling.
+ */
+public abstract class BaseUserConfigTestCase extends BasePDFTestCase {
+    
+    /** logging instance */
+    protected Log log = LogFactory.getLog(BaseUserConfigTestCase.class);
+
+    /**
+     * @see junit.framework.TestCase#TestCase(String)
+     */
+    public BaseUserConfigTestCase(String name) {
+        super(name);
+    }
+
+    protected void init() {
+        // do nothing
+    }
+
+    /**
+     * Test using a standard FOP font
+     * @throws Exception checkstyle wants a comment here, even a silly one
+     */
+    public void testUserConfig() throws Exception {
+        try {
+            final File uc = getUserConfigFile();
+            fopFactory.setUserConfig(uc);        
+            final File baseDir = getBaseDir();
+            final String fontFOFilePath = getFontFOFilePath();
+            File foFile = new File(baseDir, fontFOFilePath);
+            final boolean dumpOutput = false;
+            FOUserAgent foUserAgent = fopFactory.newFOUserAgent();
+            convertFO(foFile, foUserAgent, dumpOutput);
+            fail( getName() + ": Expected Configuration Exception" );
+        } catch (FOPException e) {
+            // this *should* happen!
+        } catch (Exception e) {
+            fail( getName() + ": Expected FOPException but got: " + e.getMessage() );
+        }
+    }
+
+    /** get test FOP config File */
+    private String getFontFOFilePath() {
+        return "test/xml/bugtests/font.fo";
+    }
+
+    /** get test FOP config File */
+    abstract protected File getUserConfigFile();
+}
\ No newline at end of file
Index: test/java/org/apache/fop/config/MetricsUrlBadTestCase.java
===================================================================
--- test/java/org/apache/fop/config/MetricsUrlBadTestCase.java	(revision 0)
+++ test/java/org/apache/fop/config/MetricsUrlBadTestCase.java	(revision 0)
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id: $ */
+package org.apache.fop.config;
+
+import java.io.File;
+
+// this font has a metrics-url that does not exist on filesystem
+public class MetricsUrlBadTestCase extends BaseUserConfigTestCase {
+
+    public MetricsUrlBadTestCase(String name) {
+        super(name);
+    }
+
+    protected File getUserConfigFile() {
+        return new File("test/test_metricsurl_bad.xconf");
+    }
+    
+    public String getName() {
+        return "test_metricsurl_bad.xconf";
+    }
+}
Index: test/java/org/apache/fop/config/MetricsUrlMalformedTestCase.java
===================================================================
--- test/java/org/apache/fop/config/MetricsUrlMalformedTestCase.java	(revision 0)
+++ test/java/org/apache/fop/config/MetricsUrlMalformedTestCase.java	(revision 0)
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id: $ */
+package org.apache.fop.config;
+
+import java.io.File;
+
+// this font has a malformed metrics-url
+public class MetricsUrlMalformedTestCase extends BaseUserConfigTestCase {
+
+    public MetricsUrlMalformedTestCase(String name) {
+        super(name);
+    }
+
+    protected File getUserConfigFile() {
+        return new File("test/test_metricsurl_malformed.xconf");
+    }
+    
+    public String getName() {
+        return "test_metricsurl_malformed.xconf";
+    }
+}
Index: test/java/org/apache/fop/config/UserConfigTestSuite.java
===================================================================
--- test/java/org/apache/fop/config/UserConfigTestSuite.java	(revision 0)
+++ test/java/org/apache/fop/config/UserConfigTestSuite.java	(revision 0)
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id: $ */
+package org.apache.fop.config;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+/**
+ * Test suite for font configuration.
+ */
+public class UserConfigTestSuite {
+
+    /**
+     * Builds the test suite
+     * @return the test suite
+     */
+    public static Test suite() {
+        TestSuite suite = new TestSuite(
+            "Basic functionality test suite for user configuration");
+        //$JUnit-BEGIN$
+        suite.addTest(new TestSuite(FontBaseBadTestCase.class));
+        suite.addTest(new TestSuite(FontAttributesMissingTestCase.class));
+        suite.addTest(new TestSuite(FontTripletAttributeMissingTestCase.class));
+        suite.addTest(new TestSuite(MetricsUrlBadTestCase.class));
+        suite.addTest(new TestSuite(EmbedUrlBadTestCase.class));
+        suite.addTest(new TestSuite(MetricsUrlMalformedTestCase.class));
+        suite.addTest(new TestSuite(EmbedUrlMalformedTestCase.class));
+        //$JUnit-END$
+        return suite;
+    }
+
+}
Index: test/java/org/apache/fop/config/BaseUserConfigTestCase.java
===================================================================
--- test/java/org/apache/fop/config/BaseUserConfigTestCase.java	(revision 0)
+++ test/java/org/apache/fop/config/BaseUserConfigTestCase.java	(revision 0)
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id: $ */
+
+package org.apache.fop.config;
+
+import java.io.File;
+
+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.render.pdf.BasePDFTestCase;
+
+/**
+ * Basic runtime test for FOP's font configuration. It is used to verify that 
+ * nothing obvious is broken after compiling.
+ */
+public abstract class BaseUserConfigTestCase extends BasePDFTestCase {
+    
+    /** logging instance */
+    protected Log log = LogFactory.getLog(BaseUserConfigTestCase.class);
+
+    /**
+     * @see junit.framework.TestCase#TestCase(String)
+     */
+    public BaseUserConfigTestCase(String name) {
+        super(name);
+    }
+
+    protected void init() {
+        // do nothing
+    }
+
+    /**
+     * Test using a standard FOP font
+     * @throws Exception checkstyle wants a comment here, even a silly one
+     */
+    public void testUserConfig() throws Exception {
+        try {
+            final File uc = getUserConfigFile();
+            fopFactory.setUserConfig(uc);        
+            final File baseDir = getBaseDir();
+            final String fontFOFilePath = getFontFOFilePath();
+            File foFile = new File(baseDir, fontFOFilePath);
+            final boolean dumpOutput = false;
+            FOUserAgent foUserAgent = fopFactory.newFOUserAgent();
+            convertFO(foFile, foUserAgent, dumpOutput);
+            fail( getName() + ": Expected Configuration Exception" );
+        } catch (FOPException e) {
+            // this *should* happen!
+        } catch (Exception e) {
+            fail( getName() + ": Expected FOPException but got: " + e.getMessage() );
+        }
+    }
+
+    /** get test FOP config File */
+    private String getFontFOFilePath() {
+        return "test/xml/bugtests/font.fo";
+    }
+
+    /** get test FOP config File */
+    abstract protected File getUserConfigFile();
+}
\ No newline at end of file
Index: test/java/org/apache/fop/config/EmbedUrlBadTestCase.java
===================================================================
--- test/java/org/apache/fop/config/EmbedUrlBadTestCase.java	(revision 0)
+++ test/java/org/apache/fop/config/EmbedUrlBadTestCase.java	(revision 0)
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id: $ */
+package org.apache.fop.config;
+
+import java.io.File;
+
+// this font has an embed-url that does not exist on filesystem
+public class EmbedUrlBadTestCase extends BaseUserConfigTestCase {
+
+    public EmbedUrlBadTestCase(String name) {
+        super(name);
+    }
+
+    protected File getUserConfigFile() {
+        return new File("test/test_embedurl_bad.xconf");
+    }
+    
+    public String getName() {
+        return "test_embedurl_bad.xconf";
+    }
+}
Index: test/java/org/apache/fop/config/EmbedUrlMalformedTestCase.java
===================================================================
--- test/java/org/apache/fop/config/EmbedUrlMalformedTestCase.java	(revision 0)
+++ test/java/org/apache/fop/config/EmbedUrlMalformedTestCase.java	(revision 0)
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id: $ */
+package org.apache.fop.config;
+
+import java.io.File;
+
+// this font has a malformed embed-url
+public class EmbedUrlMalformedTestCase extends BaseUserConfigTestCase {
+
+    public EmbedUrlMalformedTestCase(String name) {
+        super(name);
+    }
+
+    protected File getUserConfigFile() {
+        return new File("test/test_embedurl_malformed.xconf");
+    }
+    
+    public String getName() {
+        return "test_embedurl_malformed.xconf";
+    }
+}
Index: test/java/org/apache/fop/config/FontAttributesMissingTestCase.java
===================================================================
--- test/java/org/apache/fop/config/FontAttributesMissingTestCase.java	(revision 0)
+++ test/java/org/apache/fop/config/FontAttributesMissingTestCase.java	(revision 0)
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id: $ */
+package org.apache.fop.config;
+
+import java.io.File;
+
+// this font is without a metrics-url or an embed-url
+public class FontAttributesMissingTestCase extends BaseUserConfigTestCase {
+
+    public FontAttributesMissingTestCase(String name) {
+        super(name);
+    }
+
+    protected File getUserConfigFile() {
+        return new File("test/test_fontattributes_missing.xconf");
+    }
+    
+    public String getName() {
+        return "test_fontattributes_missing.xconf";
+    }
+}
Index: test/java/org/apache/fop/config/FontBaseBadTestCase.java
===================================================================
--- test/java/org/apache/fop/config/FontBaseBadTestCase.java	(revision 0)
+++ test/java/org/apache/fop/config/FontBaseBadTestCase.java	(revision 0)
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id: $ */
+package org.apache.fop.config;
+
+import java.io.File;
+
+// this font base does not exist and a relative font path is used
+public class FontBaseBadTestCase extends BaseUserConfigTestCase {
+
+    public FontBaseBadTestCase(String name) {
+        super(name);
+    }
+
+    protected File getUserConfigFile() {
+        return new File("test/test_fontbase_bad.xconf");
+    }
+    
+    public String getName() {
+        return "test_fontbase_bad.xconf";
+    }
+}
Index: test/java/org/apache/fop/config/FontTripletAttributeMissingTestCase.java
===================================================================
--- test/java/org/apache/fop/config/FontTripletAttributeMissingTestCase.java	(revision 0)
+++ test/java/org/apache/fop/config/FontTripletAttributeMissingTestCase.java	(revision 0)
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id: $ */
+package org.apache.fop.config;
+
+import java.io.File;
+
+// this font has an embed-url that does not exist on filesystem
+public class FontTripletAttributeMissingTestCase extends BaseUserConfigTestCase {
+
+    public FontTripletAttributeMissingTestCase(String name) {
+        super(name);
+    }
+
+    protected File getUserConfigFile() {
+        return new File("test/test_fonttripletattribute_missing.xconf");
+    }
+    
+    public String getName() {
+        return "test_fonttripletattribute_missing.xconf";
+    }
+}
Index: test/java/org/apache/fop/config/MetricsUrlBadTestCase.java
===================================================================
--- test/java/org/apache/fop/config/MetricsUrlBadTestCase.java	(revision 0)
+++ test/java/org/apache/fop/config/MetricsUrlBadTestCase.java	(revision 0)
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id: $ */
+package org.apache.fop.config;
+
+import java.io.File;
+
+// this font has a metrics-url that does not exist on filesystem
+public class MetricsUrlBadTestCase extends BaseUserConfigTestCase {
+
+    public MetricsUrlBadTestCase(String name) {
+        super(name);
+    }
+
+    protected File getUserConfigFile() {
+        return new File("test/test_metricsurl_bad.xconf");
+    }
+    
+    public String getName() {
+        return "test_metricsurl_bad.xconf";
+    }
+}
Index: test/java/org/apache/fop/config/MetricsUrlMalformedTestCase.java
===================================================================
--- test/java/org/apache/fop/config/MetricsUrlMalformedTestCase.java	(revision 0)
+++ test/java/org/apache/fop/config/MetricsUrlMalformedTestCase.java	(revision 0)
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id: $ */
+package org.apache.fop.config;
+
+import java.io.File;
+
+// this font has a malformed metrics-url
+public class MetricsUrlMalformedTestCase extends BaseUserConfigTestCase {
+
+    public MetricsUrlMalformedTestCase(String name) {
+        super(name);
+    }
+
+    protected File getUserConfigFile() {
+        return new File("test/test_metricsurl_malformed.xconf");
+    }
+    
+    public String getName() {
+        return "test_metricsurl_malformed.xconf";
+    }
+}
Index: test/java/org/apache/fop/config/UserConfigTestSuite.java
===================================================================
--- test/java/org/apache/fop/config/UserConfigTestSuite.java	(revision 0)
+++ test/java/org/apache/fop/config/UserConfigTestSuite.java	(revision 0)
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id: $ */
+package org.apache.fop.config;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+/**
+ * Test suite for font configuration.
+ */
+public class UserConfigTestSuite {
+
+    /**
+     * Builds the test suite
+     * @return the test suite
+     */
+    public static Test suite() {
+        TestSuite suite = new TestSuite(
+            "Basic functionality test suite for user configuration");
+        //$JUnit-BEGIN$
+        suite.addTest(new TestSuite(FontBaseBadTestCase.class));
+        suite.addTest(new TestSuite(FontAttributesMissingTestCase.class));
+        suite.addTest(new TestSuite(FontTripletAttributeMissingTestCase.class));
+        suite.addTest(new TestSuite(MetricsUrlBadTestCase.class));
+        suite.addTest(new TestSuite(EmbedUrlBadTestCase.class));
+        suite.addTest(new TestSuite(MetricsUrlMalformedTestCase.class));
+        suite.addTest(new TestSuite(EmbedUrlMalformedTestCase.class));
+        //$JUnit-END$
+        return suite;
+    }
+
+}
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 Validation On -->
+  <strict-validation>true</strict-validation>
+
+  <!-- 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 Validation On -->
+  <strict-validation>true</strict-validation>
+
+  <!-- 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 Validation On -->
+  <strict-validation>true</strict-validation>
+
+  <!-- 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 Validation On -->
+  <strict-validation>true</strict-validation>
+
+  <!-- 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 Validation On -->
+  <strict-validation>true</strict-validation>
+
+  <!-- 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 Validation On -->
+  <strict-validation>true</strict-validation>
+
+  <!-- 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 Validation On -->
+  <strict-validation>true</strict-validation>
+
+  <!-- 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>

