blob: 2685fe02182e4c803cd24dfa96b0f8809268cb60 [file] [log] [blame]
/*
* 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.apps;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import org.xml.sax.SAXException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.xmlgraphics.image.loader.ImageContext;
import org.apache.xmlgraphics.image.loader.ImageManager;
import org.apache.xmlgraphics.image.loader.impl.AbstractImageSessionContext.FallbackResolver;
import org.apache.xmlgraphics.util.UnitConv;
import org.apache.fop.apps.io.InternalResourceResolver;
import org.apache.fop.apps.io.ResourceResolverFactory;
import org.apache.fop.configuration.Configuration;
import org.apache.fop.fo.ElementMapping;
import org.apache.fop.fo.ElementMappingRegistry;
import org.apache.fop.fonts.FontManager;
import org.apache.fop.hyphenation.HyphenationTreeCache;
import org.apache.fop.layoutmgr.LayoutManagerMaker;
import org.apache.fop.render.ImageHandlerRegistry;
import org.apache.fop.render.RendererConfig;
import org.apache.fop.render.RendererConfig.RendererConfigParser;
import org.apache.fop.render.RendererFactory;
import org.apache.fop.render.XMLHandlerRegistry;
import org.apache.fop.util.ColorSpaceCache;
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 renderingq run can be
* found and managed in the FOUserAgent.
*/
public final class FopFactory implements ImageContext {
/** logger instance */
private static Log log = LogFactory.getLog(FopFactory.class);
/** Factory for Renderers and FOEventHandlers */
private final RendererFactory rendererFactory;
/** Registry for XML handlers */
private final XMLHandlerRegistry xmlHandlers;
/** Registry for image handlers */
private final ImageHandlerRegistry imageHandlers;
/** The registry for ElementMapping instances */
private final ElementMappingRegistry elementMappingRegistry;
/** The registry for ContentHandlerFactory instance */
private final ContentHandlerFactoryRegistry contentHandlerFactoryRegistry
= new ContentHandlerFactoryRegistry();
private final ColorSpaceCache colorSpaceCache;
private final FopFactoryConfig config;
private final InternalResourceResolver resolver;
private final Map<String, RendererConfig> rendererConfig;
private HyphenationTreeCache hyphenationTreeCache;
private FopFactory(FopFactoryConfig config) {
this.config = config;
this.resolver = ResourceResolverFactory.createInternalResourceResolver(config.getBaseURI(),
config.getResourceResolver());
this.elementMappingRegistry = new ElementMappingRegistry(this);
this.colorSpaceCache = new ColorSpaceCache(resolver);
this.rendererFactory = new RendererFactory(config.preferRenderer());
this.xmlHandlers = new XMLHandlerRegistry();
this.imageHandlers = new ImageHandlerRegistry();
rendererConfig = new HashMap<String, RendererConfig>();
}
/**
* Map of configured names of hyphenation pattern file names: ll_CC => name
*/
private Map<String, String> hyphPatNames;
/**
* 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.
* Returns a new FopFactory instance that is configured using the {@link FopFactoryConfig} object.
*
* @param config the fop configuration
* @return the requested FopFactory instance.
*/
public static FopFactory newInstance(FopFactoryConfig config) {
return new FopFactory(config);
}
/**
* Returns a new FopFactory instance that is configured using the {@link FopFactoryConfig} object that
* is created when the fopConf is parsed.
*
* @param fopConf the fop conf configuration file to parse
* @return the requested FopFactory instance.
* @throws IOException
* @throws SAXException
*/
public static FopFactory newInstance(File fopConf) throws SAXException, IOException {
return new FopConfParser(fopConf).getFopFactoryBuilder().build();
}
/**
* Returns a new FopFactory instance that is configured only by the default configuration
* parameters.
*
* @param baseURI the base URI to resolve resource URIs against
* @return the requested FopFactory instance.
*/
public static FopFactory newInstance(final URI baseURI) {
return AccessController.doPrivileged(
new PrivilegedAction<FopFactory>() {
public FopFactory run() {
return new FopFactoryBuilder(baseURI).build();
}
}
);
}
/**
* Returns a new FopFactory instance that is configured using the {@link FopFactoryConfig} object that
* is created when the fopConf is parsed.
*
* @param baseURI the base URI to resolve resource URIs against
* @param confStream the fop conf configuration stream to parse
* @return the requested FopFactory instance.
* @throws SAXException
* @throws IOException
*/
public static FopFactory newInstance(URI baseURI, InputStream confStream) throws SAXException,
IOException {
return new FopConfParser(confStream, baseURI).getFopFactoryBuilder().build();
}
/**
* Returns a new FOUserAgent instance. Use the FOUserAgent to configure special values that
* are particular to a rendering run. Don't reuse instances over multiple rendering runs but
* instead create a new one each time and reuse the FopFactory.
* @return the newly created FOUserAgent instance initialized with default values
*/
public FOUserAgent newFOUserAgent() {
FOUserAgent userAgent = new FOUserAgent(this, resolver);
return userAgent;
}
boolean isComplexScriptFeaturesEnabled() {
return config.isComplexScriptFeaturesEnabled();
}
/**
* Returns a new {@link Fop} instance. FOP will be configured with a default user agent
* instance.
* <p>
* MIME types are used to select the output format (ex. "application/pdf" for PDF). You can
* use the constants defined in {@link MimeConstants}.
* @param outputFormat the MIME type of the output format to use (ex. "application/pdf").
* @return the new Fop instance
* @throws FOPException when the constructor fails
*/
public Fop newFop(String outputFormat) throws FOPException {
return newFOUserAgent().newFop(outputFormat);
}
/**
* Returns a new {@link Fop} instance. Use this factory method if you want to configure this
* very rendering run, i.e. if you want to set some metadata like the title and author of the
* document you want to render. In that case, create a new {@link FOUserAgent}
* instance using {@link #newFOUserAgent()}.
* <p>
* MIME types are used to select the output format (ex. "application/pdf" for PDF). You can
* use the constants defined in {@link MimeConstants}.
* @param outputFormat the MIME type of the output format to use (ex. "application/pdf").
* @param userAgent the user agent that will be used to control the rendering run
* @return the new Fop instance
* @throws FOPException when the constructor fails
*/
public Fop newFop(String outputFormat, FOUserAgent userAgent) throws FOPException {
return userAgent.newFop(outputFormat, null);
}
boolean isTableBorderOverpaint() {
return config.isTableBorderOverpaint();
}
/**
* Returns a new {@link Fop} instance. FOP will be configured with a default user agent
* instance. Use this factory method if your output type requires an output stream.
* <p>
* MIME types are used to select the output format (ex. "application/pdf" for PDF). You can
* use the constants defined in {@link MimeConstants}.
* @param outputFormat the MIME type of the output format to use (ex. "application/pdf").
* @param stream the output stream
* @return the new Fop instance
* @throws FOPException when the constructor fails
*/
public Fop newFop(String outputFormat, OutputStream stream) throws FOPException {
return newFOUserAgent().newFop(outputFormat, stream);
}
/**
* Returns a new {@link Fop} instance. Use this factory method if your output type
* requires an output stream and you want to configure this very rendering run,
* i.e. if you want to set some metadata like the title and author of the document
* you want to render. In that case, create a new {@link FOUserAgent} instance
* using {@link #newFOUserAgent()}.
* <p>
* MIME types are used to select the output format (ex. "application/pdf" for PDF). You can
* use the constants defined in {@link MimeConstants}.
* @param outputFormat the MIME type of the output format to use (ex. "application/pdf").
* @param userAgent the user agent that will be used to control the rendering run
* @param stream the output stream
* @return the new Fop instance
* @throws FOPException when the constructor fails
*/
public Fop newFop(String outputFormat, FOUserAgent userAgent, OutputStream stream)
throws FOPException {
return userAgent.newFop(outputFormat, stream);
}
/**
* Returns a new {@link Fop} instance. Use this factory method if you want to supply your
* own {@link org.apache.fop.render.Renderer Renderer} or
* {@link org.apache.fop.fo.FOEventHandler FOEventHandler}
* instance instead of the default ones created internally by FOP.
* @param userAgent the user agent that will be used to control the rendering run
* @return the new Fop instance
* @throws FOPException when the constructor fails
*/
public Fop newFop(FOUserAgent userAgent) throws FOPException {
if (userAgent.getRendererOverride() == null
&& userAgent.getFOEventHandlerOverride() == null
&& userAgent.getDocumentHandlerOverride() == null) {
throw new IllegalStateException("An overriding renderer,"
+ " FOEventHandler or IFDocumentHandler must be set on the user agent"
+ " when this factory method is used!");
}
return newFop(null, userAgent);
}
/** @return the RendererFactory */
public RendererFactory getRendererFactory() {
return this.rendererFactory;
}
/** @return the XML handler registry */
public XMLHandlerRegistry getXMLHandlerRegistry() {
return this.xmlHandlers;
}
/** @return the image handler registry */
public ImageHandlerRegistry getImageHandlerRegistry() {
return this.imageHandlers;
}
/** @return the element mapping registry */
public ElementMappingRegistry getElementMappingRegistry() {
return this.elementMappingRegistry;
}
/** @return the content handler factory registry */
public ContentHandlerFactoryRegistry getContentHandlerFactoryRegistry() {
return this.contentHandlerFactoryRegistry;
}
/**
* Returns the renderer configuration object for a specific renderer given the parser and
* configuration to read. The renderer config is cached such that the {@link Configuration} is
* only parsed once per renderer, per FopFactory instance.
*
* @param userAgent the user agent
* @param cfg the configuration to be parsed
* @param configCreator the parser that creates the config object
* @return the config object
* @throws FOPException when an error occurs while creating the configuration object
*/
synchronized RendererConfig getRendererConfig(FOUserAgent userAgent, Configuration cfg,
RendererConfigParser configCreator) throws FOPException {
RendererConfig config = rendererConfig.get(configCreator.getMimeType());
if (config == null) {
try {
config = configCreator.build(userAgent, cfg);
rendererConfig.put(configCreator.getMimeType(), config);
} catch (Exception e) {
throw new FOPException(e);
}
}
return config;
}
/**
* Add the element mapping with the given class name.
* @param elementMapping the class name representing the element mapping.
*/
public void addElementMapping(ElementMapping elementMapping) {
this.elementMappingRegistry.addElementMapping(elementMapping);
}
/**
* Returns whether accessibility is enabled.
* @return true if accessibility is enabled
*/
boolean isAccessibilityEnabled() {
return config.isAccessibilityEnabled();
}
boolean isKeepEmptyTags() {
return config.isKeepEmptyTags();
}
/** @see FopFactoryConfig#getImageManager() */
public ImageManager getImageManager() {
return config.getImageManager();
}
/** @see FopFactoryConfig#getLayoutManagerMakerOverride() */
public LayoutManagerMaker getLayoutManagerMakerOverride() {
return config.getLayoutManagerMakerOverride();
}
/** @see FopFactoryConfig#getHyphenationPatternNames() */
public Map<String, String> getHyphenationPatternNames() {
return config.getHyphenationPatternNames();
}
/** @see FopFactoryConfig#validateStrictly() */
public boolean validateStrictly() {
return config.validateStrictly();
}
/** @see FopFactoryConfig#isBreakIndentInheritanceOnReferenceAreaBoundary() */
public boolean isBreakIndentInheritanceOnReferenceAreaBoundary() {
return config.isBreakIndentInheritanceOnReferenceAreaBoundary();
}
/** @see FopFactoryConfig#getSourceResolution() */
public float getSourceResolution() {
return config.getSourceResolution();
}
/** @see FopFactoryConfig#getTargetResolution() */
public float getTargetResolution() {
return config.getTargetResolution();
}
public InternalResourceResolver getHyphenationResourceResolver() {
return config.getHyphenationResourceResolver();
}
/**
* Returns the conversion factor from pixel units to millimeters. This
* depends on the desired source resolution.
* @return float conversion factor
* @see #getSourceResolution()
*/
public float getSourcePixelUnitToMillimeter() {
return UnitConv.IN2MM / getSourceResolution();
}
/**
* 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 / getTargetResolution();
}
/** @see FopFactoryConfig#getPageHeight() */
public String getPageHeight() {
return config.getPageHeight();
}
/** @see FopFactoryConfig#getPageWidth() */
public String getPageWidth() {
return config.getPageWidth();
}
/** @see FopFactoryConfig#isNamespaceIgnored(String) */
public boolean isNamespaceIgnored(String namespaceURI) {
return config.isNamespaceIgnored(namespaceURI);
}
/** @see FopFactoryConfig#getIgnoredNamespaces() */
public Set<String> getIgnoredNamespace() {
return config.getIgnoredNamespaces();
}
/**
* Get the user configuration.
* @return the user configuration
*/
public Configuration getUserConfig() {
return config.getUserConfig();
}
/** @see FopFactoryConfig#validateUserConfigStrictly() */
public boolean validateUserConfigStrictly() {
return config.validateUserConfigStrictly();
}
/** @see FopFactoryConfig#getFontManager() */
public FontManager getFontManager() {
return config.getFontManager();
}
/** @see FopFactoryConfig#getFallbackResolver() */
FallbackResolver getFallbackResolver() {
return config.getFallbackResolver();
}
/**
* Returns the color space cache for this instance.
* <p>
* Note: this method should not be considered as part of FOP's external API.
* @return the color space cache
*/
public ColorSpaceCache getColorSpaceCache() {
return this.colorSpaceCache;
}
public HyphenationTreeCache getHyphenationTreeCache() {
if (hyphenationTreeCache == null) {
hyphenationTreeCache = new HyphenationTreeCache();
}
return hyphenationTreeCache;
}
}