| /* |
| * 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; |
| |
| // Java |
| import java.io.File; |
| import java.net.MalformedURLException; |
| import java.util.Date; |
| import java.util.Map; |
| |
| import javax.xml.transform.Source; |
| import javax.xml.transform.TransformerException; |
| import javax.xml.transform.URIResolver; |
| |
| 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.ImageSessionContext; |
| import org.apache.xmlgraphics.image.loader.impl.AbstractImageSessionContext; |
| |
| import org.apache.fop.Version; |
| import org.apache.fop.events.DefaultEventBroadcaster; |
| import org.apache.fop.events.Event; |
| import org.apache.fop.events.EventBroadcaster; |
| import org.apache.fop.events.EventListener; |
| import org.apache.fop.events.FOPEventListenerProxy; |
| import org.apache.fop.events.LoggingEventListener; |
| import org.apache.fop.fo.FOEventHandler; |
| import org.apache.fop.fonts.FontManager; |
| import org.apache.fop.render.Renderer; |
| import org.apache.fop.render.RendererFactory; |
| import org.apache.fop.render.XMLHandlerRegistry; |
| import org.apache.fop.render.intermediate.IFDocumentHandler; |
| |
| /** |
| * This is the user agent for FOP. |
| * It is the entity through which you can interact with the XSL-FO processing and is |
| * used by the processing to obtain user configurable options. |
| * <p> |
| * Renderer specific extensions (that do not produce normal areas on |
| * the output) will be done like so: |
| * <br> |
| * The extension will create an area, custom if necessary |
| * <br> |
| * this area will be added to the user agent with a key |
| * <br> |
| * the renderer will know keys for particular extensions |
| * <br> |
| * eg. bookmarks will be held in a special hierarchical area representing |
| * the title and bookmark structure |
| * <br> |
| * These areas may contain resolvable areas that will be processed |
| * with other resolvable areas |
| */ |
| public class FOUserAgent { |
| |
| /** Defines the default target resolution (72dpi) for FOP */ |
| public static final float DEFAULT_TARGET_RESOLUTION |
| = FopFactoryConfigurator.DEFAULT_TARGET_RESOLUTION; |
| |
| private static Log log = LogFactory.getLog("FOP"); |
| |
| private FopFactory factory; |
| |
| /** |
| * The base URL for all URL resolutions, especially for |
| * external-graphics. |
| */ |
| private String base = null; |
| |
| /** A user settable URI Resolver */ |
| private URIResolver uriResolver = null; |
| |
| private float targetResolution = FopFactoryConfigurator.DEFAULT_TARGET_RESOLUTION; |
| private Map rendererOptions = new java.util.HashMap(); |
| private File outputFile = null; |
| private IFDocumentHandler documentHandlerOverride = null; |
| private Renderer rendererOverride = null; |
| private FOEventHandler foEventHandlerOverride = null; |
| private boolean locatorEnabled = true; // true by default (for error messages). |
| private boolean conserveMemoryPolicy = false; |
| private EventBroadcaster eventBroadcaster = new FOPEventBroadcaster(); |
| |
| /** Producer: Metadata element for the system/software that produces |
| * the document. (Some renderers can store this in the document.) |
| */ |
| protected String producer = "Apache FOP Version " + Version.getVersion(); |
| |
| /** Creator: Metadata element for the user that created the |
| * document. (Some renderers can store this in the document.) |
| */ |
| protected String creator = null; |
| |
| /** Creation Date: Override of the date the document was created. |
| * (Some renderers can store this in the document.) |
| */ |
| protected Date creationDate = null; |
| |
| /** Author of the content of the document. */ |
| protected String author = null; |
| /** Title of the document. */ |
| protected String title = null; |
| /** Subject of the document. */ |
| protected String subject = null; |
| /** Set of keywords applicable to this document. */ |
| protected String keywords = null; |
| |
| private ImageSessionContext imageSessionContext = new AbstractImageSessionContext() { |
| |
| public ImageContext getParentContext() { |
| return getFactory(); |
| } |
| |
| public float getTargetResolution() { |
| return FOUserAgent.this.getTargetResolution(); |
| } |
| |
| public Source resolveURI(String uri) { |
| return FOUserAgent.this.resolveURI(uri); |
| } |
| |
| }; |
| |
| /** |
| * Main constructor. <b>This constructor should not be called directly. Please use the |
| * methods from FopFactory to construct FOUserAgent instances!</b> |
| * @param factory the factory that provides environment-level information |
| * @see org.apache.fop.apps.FopFactory |
| */ |
| public FOUserAgent(FopFactory factory) { |
| if (factory == null) { |
| throw new NullPointerException("The factory parameter must not be null"); |
| } |
| this.factory = factory; |
| setBaseURL(factory.getBaseURL()); |
| setTargetResolution(factory.getTargetResolution()); |
| } |
| |
| /** @return the associated FopFactory instance */ |
| public FopFactory getFactory() { |
| return this.factory; |
| } |
| |
| // ---------------------------------------------- rendering-run dependent stuff |
| |
| /** |
| * Sets an explicit document handler to use which overrides the one that would be |
| * selected by default. |
| * @param documentHandler the document handler instance to use |
| */ |
| public void setDocumentHandlerOverride(IFDocumentHandler documentHandler) { |
| this.documentHandlerOverride = documentHandler; |
| |
| } |
| |
| /** |
| * Returns the overriding {@link IFDocumentHandler} instance, if any. |
| * @return the overriding document handler or null |
| */ |
| public IFDocumentHandler getDocumentHandlerOverride() { |
| return this.documentHandlerOverride; |
| } |
| |
| /** |
| * Sets an explicit renderer to use which overrides the one defined by the |
| * render type setting. |
| * @param renderer the Renderer instance to use |
| */ |
| public void setRendererOverride(Renderer renderer) { |
| this.rendererOverride = renderer; |
| } |
| |
| /** |
| * Returns the overriding Renderer instance, if any. |
| * @return the overriding Renderer or null |
| */ |
| public Renderer getRendererOverride() { |
| return rendererOverride; |
| } |
| |
| /** |
| * Sets an explicit FOEventHandler instance which overrides the one |
| * defined by the render type setting. |
| * @param handler the FOEventHandler instance |
| */ |
| public void setFOEventHandlerOverride(FOEventHandler handler) { |
| this.foEventHandlerOverride = handler; |
| } |
| |
| /** |
| * Returns the overriding FOEventHandler instance, if any. |
| * @return the overriding FOEventHandler or null |
| */ |
| public FOEventHandler getFOEventHandlerOverride() { |
| return this.foEventHandlerOverride; |
| } |
| |
| /** |
| * Sets the producer of the document. |
| * @param producer source of document |
| */ |
| public void setProducer(String producer) { |
| this.producer = producer; |
| } |
| |
| /** |
| * Returns the producer of the document |
| * @return producer name |
| */ |
| public String getProducer() { |
| return producer; |
| } |
| |
| /** |
| * Sets the creator of the document. |
| * @param creator of document |
| */ |
| public void setCreator(String creator) { |
| this.creator = creator; |
| } |
| |
| /** |
| * Returns the creator of the document |
| * @return creator name |
| */ |
| public String getCreator() { |
| return creator; |
| } |
| |
| /** |
| * Sets the creation date of the document. |
| * @param creationDate date of document |
| */ |
| public void setCreationDate(Date creationDate) { |
| this.creationDate = creationDate; |
| } |
| |
| /** |
| * Returns the creation date of the document |
| * @return creation date of document |
| */ |
| public Date getCreationDate() { |
| return creationDate; |
| } |
| |
| /** |
| * Sets the author of the document. |
| * @param author of document |
| */ |
| public void setAuthor(String author) { |
| this.author = author; |
| } |
| |
| /** |
| * Returns the author of the document |
| * @return author name |
| */ |
| public String getAuthor() { |
| return author; |
| } |
| |
| /** |
| * Sets the title of the document. This will override any title coming from |
| * an fo:title element. |
| * @param title of document |
| */ |
| public void setTitle(String title) { |
| this.title = title; |
| } |
| |
| /** |
| * Returns the title of the document |
| * @return title name |
| */ |
| public String getTitle() { |
| return title; |
| } |
| |
| /** |
| * Sets the subject of the document. |
| * @param subject of document |
| */ |
| public void setSubject(String subject) { |
| this.subject = subject; |
| } |
| |
| /** |
| * Returns the subject of the document |
| * @return the subject |
| */ |
| public String getSubject() { |
| return subject; |
| } |
| |
| /** |
| * Sets the keywords for the document. |
| * @param keywords for the document |
| */ |
| public void setKeywords(String keywords) { |
| this.keywords = keywords; |
| } |
| |
| /** |
| * Returns the keywords for the document |
| * @return the keywords |
| */ |
| public String getKeywords() { |
| return keywords; |
| } |
| |
| /** |
| * Returns the renderer options |
| * @return renderer options |
| */ |
| public Map getRendererOptions() { |
| return rendererOptions; |
| } |
| |
| /** |
| * Sets the base URL. |
| * @param baseUrl base URL |
| */ |
| public void setBaseURL(String baseUrl) { |
| this.base = baseUrl; |
| } |
| |
| /** |
| * Sets font base URL. |
| * @param fontBaseUrl font base URL |
| * @deprecated Use {@link FontManager#setFontBaseURL(String)} instead. |
| */ |
| public void setFontBaseURL(String fontBaseUrl) { |
| try { |
| getFactory().getFontManager().setFontBaseURL(fontBaseUrl); |
| } catch (MalformedURLException e) { |
| throw new IllegalArgumentException(e.getMessage()); |
| } |
| } |
| |
| /** |
| * Returns the base URL. |
| * @return the base URL |
| */ |
| public String getBaseURL() { |
| return this.base; |
| } |
| |
| /** |
| * Sets the URI Resolver. |
| * @param resolver the new URI resolver |
| */ |
| public void setURIResolver(URIResolver resolver) { |
| this.uriResolver = resolver; |
| } |
| |
| /** |
| * Returns the URI Resolver. |
| * @return the URI Resolver |
| */ |
| public URIResolver getURIResolver() { |
| return this.uriResolver; |
| } |
| |
| /** |
| * Attempts to resolve the given URI. |
| * Will use the configured resolver and if not successful fall back |
| * to the default resolver. |
| * @param uri URI to access |
| * @return A {@link javax.xml.transform.Source} object, or null if the URI |
| * cannot be resolved. |
| * @see org.apache.fop.apps.FOURIResolver |
| */ |
| public Source resolveURI(String uri) { |
| return resolveURI(uri, getBaseURL()); |
| } |
| |
| /** |
| * Attempts to resolve the given URI. |
| * Will use the configured resolver and if not successful fall back |
| * to the default resolver. |
| * @param href URI to access |
| * @param base the base URI to resolve against |
| * @return A {@link javax.xml.transform.Source} object, or null if the URI |
| * cannot be resolved. |
| * @see org.apache.fop.apps.FOURIResolver |
| */ |
| public Source resolveURI(String href, String base) { |
| Source source = null; |
| //RFC 2397 data URLs don't need to be resolved, just decode them through FOP's default |
| //URIResolver. |
| boolean bypassURIResolution = href.startsWith("data:"); |
| if (!bypassURIResolution && uriResolver != null) { |
| try { |
| source = uriResolver.resolve(href, base); |
| } catch (TransformerException te) { |
| log.error("Attempt to resolve URI '" + href + "' failed: ", te); |
| } |
| } |
| if (source == null) { |
| // URI Resolver not configured or returned null, use default resolver from the factory |
| source = getFactory().resolveURI(href, base); |
| } |
| return source; |
| } |
| |
| /** |
| * Sets the output File. |
| * @param f the output File |
| */ |
| public void setOutputFile(File f) { |
| this.outputFile = f; |
| } |
| |
| /** |
| * Gets the output File. |
| * @return the output File |
| */ |
| public File getOutputFile() { |
| return outputFile; |
| } |
| |
| /** |
| * 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; |
| } |
| |
| /** @return the resolution for resolution-dependant output */ |
| public float getTargetResolution() { |
| return this.targetResolution; |
| } |
| |
| /** |
| * 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(float dpi) { |
| this.targetResolution = dpi; |
| if (log.isDebugEnabled()) { |
| log.debug("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); |
| } |
| |
| /** |
| * Returns the image session context for the image package. |
| * @return the ImageSessionContext instance for this rendering run |
| */ |
| public ImageSessionContext getImageSessionContext() { |
| return this.imageSessionContext; |
| } |
| |
| // ---------------------------------------------- environment-level stuff |
| // (convenience access to FopFactory methods) |
| |
| /** |
| * Returns the font base URL. |
| * @return the font base URL |
| * @deprecated Use {@link FontManager#getFontBaseURL()} instead. This method is not used by FOP. |
| */ |
| public String getFontBaseURL() { |
| String fontBase = getFactory().getFontManager().getFontBaseURL(); |
| return fontBase != null ? fontBase : getBaseURL(); |
| } |
| |
| /** |
| * 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 getFactory().getSourcePixelUnitToMillimeter(); |
| } |
| |
| /** @return the resolution for resolution-dependant input */ |
| public float getSourceResolution() { |
| return getFactory().getSourceResolution(); |
| } |
| |
| /** |
| * Gets the default page-height to use as fallback, |
| * in case page-height="auto" |
| * |
| * @return the page-height, as a String |
| * @see FopFactory#getPageHeight() |
| */ |
| public String getPageHeight() { |
| return getFactory().getPageHeight(); |
| } |
| |
| /** |
| * Gets the default page-width to use as fallback, |
| * in case page-width="auto" |
| * |
| * @return the page-width, as a String |
| * @see FopFactory#getPageWidth() |
| */ |
| public String getPageWidth() { |
| return getFactory().getPageWidth(); |
| } |
| |
| /** |
| * Returns whether FOP is strictly validating input XSL |
| * @return true of strict validation turned on, false otherwise |
| * @see FopFactory#validateStrictly() |
| */ |
| public boolean validateStrictly() { |
| return getFactory().validateStrictly(); |
| } |
| |
| /** |
| * @return true if the indent inheritance should be broken when crossing reference area |
| * boundaries (for more info, see the javadoc for the relative member variable) |
| * @see FopFactory#isBreakIndentInheritanceOnReferenceAreaBoundary() |
| */ |
| public boolean isBreakIndentInheritanceOnReferenceAreaBoundary() { |
| return getFactory().isBreakIndentInheritanceOnReferenceAreaBoundary(); |
| } |
| |
| /** |
| * @return the RendererFactory |
| */ |
| public RendererFactory getRendererFactory() { |
| return getFactory().getRendererFactory(); |
| } |
| |
| /** |
| * @return the XML handler registry |
| */ |
| public XMLHandlerRegistry getXMLHandlerRegistry() { |
| return getFactory().getXMLHandlerRegistry(); |
| } |
| |
| /** |
| * Controls the use of SAXLocators to provide location information in error |
| * messages. |
| * |
| * @param enableLocator <code>false</code> if SAX Locators should be disabled |
| */ |
| public void setLocatorEnabled(boolean enableLocator) { |
| locatorEnabled = enableLocator; |
| } |
| |
| /** |
| * Checks if the use of Locators is enabled |
| * @return true if context information should be stored on each node in the FO tree. |
| */ |
| public boolean isLocatorEnabled() { |
| return locatorEnabled; |
| } |
| |
| /** |
| * Returns the event broadcaster that control events sent inside a processing run. Clients |
| * can register event listeners with the event broadcaster to listen for events that occur |
| * while a document is being processed. |
| * @return the event broadcaster. |
| */ |
| public EventBroadcaster getEventBroadcaster() { |
| return this.eventBroadcaster; |
| } |
| |
| private class FOPEventBroadcaster extends DefaultEventBroadcaster { |
| |
| private EventListener rootListener; |
| |
| public FOPEventBroadcaster() { |
| //Install a temporary event listener that catches the first event to |
| //do some initialization. |
| this.rootListener = new EventListener() { |
| public void processEvent(Event event) { |
| if (!listeners.hasEventListeners()) { |
| //Backwards-compatibility: Make sure at least the LoggingEventListener is |
| //plugged in so no events are just silently swallowed. |
| addEventListener( |
| new LoggingEventListener(LogFactory.getLog(FOUserAgent.class))); |
| } |
| //Replace with final event listener |
| rootListener = new FOPEventListenerProxy( |
| listeners, FOUserAgent.this); |
| rootListener.processEvent(event); |
| } |
| }; |
| } |
| |
| /** {@inheritDoc} */ |
| public void broadcastEvent(Event event) { |
| rootListener.processEvent(event); |
| } |
| |
| } |
| |
| /** |
| * Check whether memory-conservation is enabled. |
| * |
| * @return true if FOP is to conserve as much as possible |
| */ |
| public boolean isConserveMemoryPolicyEnabled() { |
| return this.conserveMemoryPolicy; |
| } |
| |
| /** |
| * Control whether memory-conservation should be enabled |
| * |
| * @param conserveMemoryPolicy the cachingEnabled to set |
| */ |
| public void setConserveMemoryPolicy(boolean conserveMemoryPolicy) { |
| this.conserveMemoryPolicy = conserveMemoryPolicy; |
| } |
| |
| } |
| |