aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorVincent Hennebert <vhennebert@apache.org>2007-02-14 14:24:36 +0000
committerVincent Hennebert <vhennebert@apache.org>2007-02-14 14:24:36 +0000
commit404013f30e23b12ab477650846eb0e65b58a1394 (patch)
tree68d16c7870a4a6beb3ea5c07f02a4bf46c5f8610 /src
parentdfb9bf9c3a9d1300d1575a9151580208f1ed994f (diff)
downloadxmlgraphics-fop-404013f30e23b12ab477650846eb0e65b58a1394.tar.gz
xmlgraphics-fop-404013f30e23b12ab477650846eb0e65b58a1394.zip
Stricter user config file validation.
Add a configuration parameter (strict-configuration), enabled by default, which makes FOP throw an exception instead of logging an error when a problem occurs. Invalid resource paths should be catched now. Fixes bug #40120. Submitted by: Adrian Cumiskey (fop-dev AT cumiskey DOT com) git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@507539 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src')
-rw-r--r--src/documentation/content/xdocs/trunk/configuration.xml29
-rw-r--r--src/foschema/fop-configuration.xsd1
-rw-r--r--src/java/org/apache/fop/apps/FOURIResolver.java8
-rw-r--r--src/java/org/apache/fop/apps/FOUserAgent.java79
-rw-r--r--src/java/org/apache/fop/apps/FopFactory.java319
-rw-r--r--src/java/org/apache/fop/fonts/FontSetup.java143
-rw-r--r--src/java/org/apache/fop/render/AbstractRenderer.java11
-rw-r--r--src/java/org/apache/fop/render/PrintRenderer.java21
-rw-r--r--src/java/org/apache/fop/render/RendererFactory.java2
-rw-r--r--src/java/org/apache/fop/render/pdf/PDFRenderer.java2
-rw-r--r--src/java/org/apache/fop/render/ps/PSRenderer.java2
-rw-r--r--src/java/org/apache/fop/render/xml/XMLRenderer.java2
12 files changed, 451 insertions, 168 deletions
diff --git a/src/documentation/content/xdocs/trunk/configuration.xml b/src/documentation/content/xdocs/trunk/configuration.xml
index c40a64de5..7032379ca 100644
--- a/src/documentation/content/xdocs/trunk/configuration.xml
+++ b/src/documentation/content/xdocs/trunk/configuration.xml
@@ -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,6 +106,17 @@
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>
@@ -110,7 +125,8 @@
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>
diff --git a/src/foschema/fop-configuration.xsd b/src/foschema/fop-configuration.xsd
index c5a12d27f..ad959f947 100644
--- a/src/foschema/fop-configuration.xsd
+++ b/src/foschema/fop-configuration.xsd
@@ -38,6 +38,7 @@
type="xsd:positiveInteger" minOccurs="0">
</xsd:element>
<xsd:element name="strict-validation" type="xsd:boolean" minOccurs="0"></xsd:element>
+ <xsd:element name="strict-configuration" type="xsd:boolean" minOccurs="0"></xsd:element>
<xsd:element name="break-indent-inheritance"
type="xsd:boolean" minOccurs="0">
</xsd:element>
diff --git a/src/java/org/apache/fop/apps/FOURIResolver.java b/src/java/org/apache/fop/apps/FOURIResolver.java
index 925cd62f8..db0cae75e 100644
--- a/src/java/org/apache/fop/apps/FOURIResolver.java
+++ b/src/java/org/apache/fop/apps/FOURIResolver.java
@@ -84,7 +84,7 @@ public class FOURIResolver
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 @@ public class FOURIResolver
// 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 @@ public class FOURIResolver
}
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 @@ public class FOURIResolver
//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;
}
diff --git a/src/java/org/apache/fop/apps/FOUserAgent.java b/src/java/org/apache/fop/apps/FOUserAgent.java
index 63a3859ac..f15ddcc31 100644
--- a/src/java/org/apache/fop/apps/FOUserAgent.java
+++ b/src/java/org/apache/fop/apps/FOUserAgent.java
@@ -27,10 +27,6 @@ import javax.xml.transform.Source;
import javax.xml.transform.TransformerException;
import javax.xml.transform.URIResolver;
-// avalon configuration
-import org.apache.avalon.framework.configuration.Configuration;
-import org.apache.avalon.framework.configuration.ConfigurationException;
-
// commons logging
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -67,7 +63,7 @@ import org.apache.fop.render.pdf.PDFRenderer;
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 +105,12 @@ public class FOUserAgent {
/**
* 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());
}
@@ -128,9 +125,8 @@ public class FOUserAgent {
throw new NullPointerException("The factory parameter must not be null");
}
this.factory = factory;
- if (factory.getUserConfig() != null) {
- configure(factory.getUserConfig());
- }
+ setBaseURL(factory.getBaseURL());
+ setTargetResolution(factory.getTargetResolution());
}
/** @return the associated FopFactory instance */
@@ -278,56 +274,8 @@ public class FOUserAgent {
public Map getRendererOptions() {
return rendererOptions;
}
-
- /**
- * Configures the FOUserAgent through the factory's configuration.
- * @param cfg Avalon Configuration Object
- * @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() + ")");
- }
- }
/**
- * Returns the configuration subtree for a specific renderer.
- * @param mimeType MIME type of the renderer
- * @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
- = cfg.getChild("renderers").getChildren("renderer");
- for (int i = 0; i < cfgs.length; ++i) {
- Configuration child = cfgs[i];
- try {
- if (child.getAttribute("mime").equals(mimeType)) {
- userRendererConfig = child;
- break;
- }
- } catch (ConfigurationException e) {
- // silently pass over configurations without mime type
- }
- }
- log.debug((userRendererConfig == null ? "No u" : "U")
- + "ser configuration found for MIME type " + mimeType);
- return userRendererConfig;
- }
-
- /**
* Sets the base URL.
* @param baseURL base URL
*/
@@ -460,8 +408,20 @@ public class FOUserAgent {
* 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
@@ -470,7 +430,7 @@ public class FOUserAgent {
/** @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 +501,5 @@ public class FOUserAgent {
public XMLHandlerRegistry getXMLHandlerRegistry() {
return getFactory().getXMLHandlerRegistry();
}
-
}
diff --git a/src/java/org/apache/fop/apps/FopFactory.java b/src/java/org/apache/fop/apps/FopFactory.java
index 363d68059..f7a3bd251 100644
--- a/src/java/org/apache/fop/apps/FopFactory.java
+++ b/src/java/org/apache/fop/apps/FopFactory.java
@@ -55,18 +55,33 @@ import org.apache.fop.render.XMLHandlerRegistry;
import org.apache.fop.util.ContentHandlerFactoryRegistry;
/**
- * Factory class which instantiates new Fop and FOUserAgent instances. This class also holds
- * environmental information and configuration used by FOP. Information that may potentially be
- * different for each rendering run can be found and managed in the FOUserAgent.
+ * Factory class which instantiates new Fop and FOUserAgent instances. This
+ * class also holds environmental information and configuration used by FOP.
+ * Information that may potentially be different for each rendering run can be
+ * found and managed in the FOUserAgent.
*/
public class FopFactory {
+
+ /** Defines the default target resolution (72dpi) for FOP */
+ public static final float DEFAULT_TARGET_RESOLUTION = 72.0f; //dpi
/** Defines the default source resolution (72dpi) for FOP */
private static final float DEFAULT_SOURCE_RESOLUTION = 72.0f; //dpi
+
/** Defines the default page-height */
private static final String DEFAULT_PAGE_HEIGHT = "11in";
+
/** Defines the default page-width */
private static final String DEFAULT_PAGE_WIDTH = "8.26in";
+
+ /** Defines if FOP should use strict validation for FO and user config */
+ private static final boolean DEFAULT_STRICT_FO_VALIDATION = true;
+
+ /** Defines if FOP should validate the user config strictly */
+ private static final boolean DEFAULT_STRICT_USERCONFIG_VALIDATION = true;
+
+ /** Defines if FOP should use an alternative rule to determine text indents */
+ private static final boolean DEFAULT_BREAK_INDENT_INHERITANCE = false;
/** logger instance */
private static Log log = LogFactory.getLog(FopFactory.class);
@@ -86,6 +101,7 @@ public class FopFactory {
/** Our default resolver if none is set */
private URIResolver foURIResolver = new FOURIResolver();
+
/** A user settable URI Resolver */
private URIResolver uriResolver = null;
@@ -97,27 +113,50 @@ public class FopFactory {
/** user configuration */
private Configuration userConfig = null;
- /** The base URL for all font URL resolutions */
+ /**
+ * 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 strictFOValidation = 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 +188,7 @@ public class FopFactory {
* 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 +336,22 @@ public class FopFactory {
}
/**
+ * 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,6 +364,26 @@ public class FopFactory {
return this.fontBaseURL;
}
+ /** @return the hyphen base URL */
+ public String getHyphenBaseURL() {
+ return hyphenBaseURL;
+ }
+
+ /**
+ * Sets the hyphen base URL.
+ * @param hyphenBaseURL hythen base URL
+ */
+ public void setHyphenBaseURL(final String hyphenBaseURL) {
+ if (hyphenBaseURL != null) {
+ this.hyphResolver = new HyphenationTreeResolver() {
+ public Source resolve(String href) {
+ return resolveURI(href, 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.
@@ -336,7 +412,7 @@ public class FopFactory {
* @param validateStrictly true to turn on strict validation
*/
public void setStrictValidation(boolean validateStrictly) {
- this.strictValidation = validateStrictly;
+ this.strictFOValidation = validateStrictly;
}
/**
@@ -344,7 +420,7 @@ public class FopFactory {
* @return true of strict validation turned on, false otherwise
*/
public boolean validateStrictly() {
- return strictValidation;
+ return strictFOValidation;
}
/**
@@ -399,14 +475,49 @@ public class FopFactory {
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);
}
/**
@@ -427,6 +538,7 @@ public class FopFactory {
*/
public void setPageHeight(String pageHeight) {
this.pageHeight = pageHeight;
+ log.info("Default page-height set to: " + pageHeight);
}
/**
@@ -447,6 +559,7 @@ public class FopFactory {
*/
public void setPageWidth(String pageWidth) {
this.pageWidth = pageWidth;
+ log.info("Default page-width set to: " + pageWidth);
}
/**
@@ -491,14 +604,12 @@ public class FopFactory {
* @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 +619,26 @@ public class FopFactory {
* @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,47 +649,105 @@ public class FopFactory {
public Configuration getUserConfig() {
return userConfig;
}
-
+
+ /**
+ * Returns the configuration subtree for a specific renderer.
+ * @param mimeType MIME type of the renderer
+ * @return the requested configuration subtree, null if there's no configuration
+ */
+ public Configuration getUserRendererConfig(String mimeType) {
+ if (userConfig == null || mimeType == null) {
+ return null;
+ }
+
+ Configuration userRendererConfig = null;
+
+ Configuration[] cfgs
+ = userConfig.getChild("renderers").getChildren("renderer");
+ for (int i = 0; i < cfgs.length; ++i) {
+ Configuration child = cfgs[i];
+ try {
+ if (child.getAttribute("mime").equals(mimeType)) {
+ userRendererConfig = child;
+ break;
+ }
+ } catch (ConfigurationException e) {
+ // silently pass over configurations without mime type
+ }
+ }
+ log.debug((userRendererConfig == null ? "No u" : "U")
+ + "ser configuration found for MIME type " + mimeType);
+ return userRendererConfig;
+ }
+
/**
* 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");
+
+ if (cfg.getChild("strict-configuration", false) != null) {
+ this.strictUserConfigValidation
+ = cfg.getChild("strict-configuration").getValueAsBoolean();
+ }
+ if (cfg.getChild("strict-validation", false) != null) {
+ this.strictFOValidation = cfg.getChild("strict-validation").getValueAsBoolean();
+ }
+ if (cfg.getChild("base", false) != null) {
+ try {
+ setBaseURL(getBaseURLfromConfig(cfg, "base"));
+ } catch (ConfigurationException e) {
+ if (strictUserConfigValidation) {
+ 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("font-base", false) != null) {
+ try {
+ setFontBaseURL(getBaseURLfromConfig(cfg, "font-base"));
+ } catch (ConfigurationException e) {
+ if (strictUserConfigValidation) {
+ throw e;
+ }
+ log.error(e.getMessage());
+ }
}
- if (userConfig.getChild("strict-validation", false) != null) {
- this.strictValidation = userConfig.getChild("strict-validation").getValueAsBoolean();
+ if (cfg.getChild("hyphenation-base", false) != null) {
+ try {
+ setHyphenBaseURL(getBaseURLfromConfig(cfg, "hyphenation-base"));
+ } catch (ConfigurationException e) {
+ if (strictUserConfigValidation) {
+ throw e;
+ }
+ log.error(e.getMessage());
+ }
+ }
+ 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(DEFAULT_TARGET_RESOLUTION));
}
- Configuration pageConfig = userConfig.getChild("default-page-settings");
+ if (cfg.getChild("break-indent-inheritance", false) != null) {
+ setBreakIndentInheritanceOnReferenceAreaBoundary(
+ cfg.getChild("break-indent-inheritance").getValueAsBoolean());
+ }
+ Configuration pageConfig = cfg.getChild("default-page-settings");
if (pageConfig.getAttribute("height", null) != null) {
- setPageHeight(pageConfig.getAttribute("height"));
- log.info("Default page-height set to: " + pageHeight);
+ setPageHeight(pageConfig.getAttribute("height", DEFAULT_PAGE_HEIGHT));
}
if (pageConfig.getAttribute("width", null) != null) {
- setPageWidth(pageConfig.getAttribute("width"));
- log.info("Default page-width set to: " + pageWidth);
+ setPageWidth(pageConfig.getAttribute("width", DEFAULT_PAGE_WIDTH));
}
}
@@ -589,26 +756,53 @@ public class FopFactory {
* @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);
+ String cfgBasePath = cfg.getChild(name).getValue(null);
+ if (cfgBasePath != null) {
+ // Is the path a dirname?
+ File dir = new File(cfgBasePath);
+// if (!dir.exists()) {
+// throw new ConfigurationException("Base URL '" + name
+// + "' references non-existent resource '"
+// + cfgBasePath + "'");
+// } else if (dir.isDirectory()) {
if (dir.isDirectory()) {
- cfgBaseDir = dir.toURL().toExternalForm();
+ // Yes, convert it into a URL
+ cfgBasePath = dir.toURL().toExternalForm();
}
+ // Otherwise, this is already a URL
}
- log.info(name + " set to: " + cfgBaseDir);
- return cfgBaseDir;
+ log.info(name + " set to: " + cfgBasePath);
+ return cfgBasePath;
} 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
+ */
+ 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 +894,4 @@ public class FopFactory {
}
return colorSpace;
}
-
}
diff --git a/src/java/org/apache/fop/fonts/FontSetup.java b/src/java/org/apache/fop/fonts/FontSetup.java
index 3362ce334..bd3e81d4f 100644
--- a/src/java/org/apache/fop/fonts/FontSetup.java
+++ b/src/java/org/apache/fop/fonts/FontSetup.java
@@ -34,6 +34,7 @@ import org.apache.fop.fonts.base14.CourierOblique;
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,130 @@ public class FontSetup {
};
}
+
/**
* 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 strict
+ = 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 (strict) {
+ 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 (strict) {
+ 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 (strict) {
+ 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 (strict) {
+ throw new ConfigurationException("font-triplet without name");
+ }
+ log.error("font-triplet without name");
+ continue;
+ }
+
+ String weightStr = triple[j].getAttribute("weight");
+ if (weightStr == null) {
+ if (strict) {
+ 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 (strict) {
+ 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);
}
}
-
diff --git a/src/java/org/apache/fop/render/AbstractRenderer.java b/src/java/org/apache/fop/render/AbstractRenderer.java
index 562666bdc..91cfe7bfa 100644
--- a/src/java/org/apache/fop/render/AbstractRenderer.java
+++ b/src/java/org/apache/fop/render/AbstractRenderer.java
@@ -88,7 +88,7 @@ public abstract class AbstractRenderer
/**
* user agent
*/
- protected FOUserAgent userAgent;
+ protected FOUserAgent userAgent = null;
/**
* block progression position
@@ -135,6 +135,13 @@ public abstract class AbstractRenderer
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 { }
@@ -845,7 +852,7 @@ public abstract class AbstractRenderer
if (handler != null) {
try {
//Optional XML handler configuration
- Configuration cfg = userAgent.getUserRendererConfig(getMimeType());
+ Configuration cfg = userAgent.getFactory().getUserRendererConfig(getMimeType());
if (cfg != null) {
cfg = getHandlerConfig(cfg, namespace);
if (cfg != null) {
diff --git a/src/java/org/apache/fop/render/PrintRenderer.java b/src/java/org/apache/fop/render/PrintRenderer.java
index ddb335564..6a3cdf2c6 100644
--- a/src/java/org/apache/fop/render/PrintRenderer.java
+++ b/src/java/org/apache/fop/render/PrintRenderer.java
@@ -41,9 +41,12 @@ public abstract class PrintRenderer extends AbstractRenderer {
/** 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 abstract class PrintRenderer extends AbstractRenderer {
*/
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 @@ public abstract class PrintRenderer extends AbstractRenderer {
renderXML(context, doc, ns);
}
-
+
+ /**
+ * Get FontResolver
+ *
+ * @return FontResolver
+ */
+ public FontResolver getFontResolver() {
+ if (this.fontResolver == null) {
+ this.fontResolver = new DefaultFontResolver(super.userAgent);
+ }
+ return this.fontResolver;
+ }
}
diff --git a/src/java/org/apache/fop/render/RendererFactory.java b/src/java/org/apache/fop/render/RendererFactory.java
index 8c35ec65a..4d3f3a12c 100644
--- a/src/java/org/apache/fop/render/RendererFactory.java
+++ b/src/java/org/apache/fop/render/RendererFactory.java
@@ -189,7 +189,7 @@ public class RendererFactory {
Configuration userRendererConfig = null;
if (mimeType != null) {
userRendererConfig
- = userAgent.getUserRendererConfig(mimeType);
+ = userAgent.getFactory().getUserRendererConfig(mimeType);
}
if (userRendererConfig != null) {
try {
diff --git a/src/java/org/apache/fop/render/pdf/PDFRenderer.java b/src/java/org/apache/fop/render/pdf/PDFRenderer.java
index 966aef2e5..481ce844c 100644
--- a/src/java/org/apache/fop/render/pdf/PDFRenderer.java
+++ b/src/java/org/apache/fop/render/pdf/PDFRenderer.java
@@ -243,7 +243,7 @@ public class PDFRenderer extends AbstractPathOrientedRenderer {
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 {
diff --git a/src/java/org/apache/fop/render/ps/PSRenderer.java b/src/java/org/apache/fop/render/ps/PSRenderer.java
index 75c3817f1..6553f06b6 100644
--- a/src/java/org/apache/fop/render/ps/PSRenderer.java
+++ b/src/java/org/apache/fop/render/ps/PSRenderer.java
@@ -129,7 +129,7 @@ public class PSRenderer extends AbstractPathOrientedRenderer implements ImageAda
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 {
diff --git a/src/java/org/apache/fop/render/xml/XMLRenderer.java b/src/java/org/apache/fop/render/xml/XMLRenderer.java
index c1f85be87..857847e10 100644
--- a/src/java/org/apache/fop/render/xml/XMLRenderer.java
+++ b/src/java/org/apache/fop/render/xml/XMLRenderer.java
@@ -145,7 +145,7 @@ public class XMLRenderer extends PrintRenderer {
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 {