aboutsummaryrefslogtreecommitdiffstats
path: root/src/java/org/apache/fop/image/ImageFactory.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/java/org/apache/fop/image/ImageFactory.java')
-rw-r--r--src/java/org/apache/fop/image/ImageFactory.java708
1 files changed, 0 insertions, 708 deletions
diff --git a/src/java/org/apache/fop/image/ImageFactory.java b/src/java/org/apache/fop/image/ImageFactory.java
deleted file mode 100644
index 5c9f198e8..000000000
--- a/src/java/org/apache/fop/image/ImageFactory.java
+++ /dev/null
@@ -1,708 +0,0 @@
-/*
- * 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.image;
-
-// Java
-import java.io.InputStream;
-import java.lang.ref.Reference;
-import java.lang.ref.ReferenceQueue;
-import java.lang.ref.SoftReference;
-import java.lang.reflect.Constructor;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.Map.Entry;
-
-import javax.xml.transform.Source;
-import javax.xml.transform.stream.StreamSource;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.fop.apps.FOUserAgent;
-import org.apache.fop.datatypes.URISpecification;
-import org.apache.fop.image.analyser.ImageReaderFactory;
-import org.apache.xmlgraphics.util.Service;
-
-/**
- * Create FopImage objects (with a configuration file - not yet implemented).
- * @author Eric SCHAEFFER
- */
-public final class ImageFactory {
-
- /**
- * logging instance
- */
- protected static Log log = LogFactory.getLog(FopImage.class);
-
- private HashMap imageMimeTypes = new HashMap();
-
- private ImageCache cache = new ContextImageCache(true);
-
- /**
- * Main constructor for the ImageFactory.
- */
- public ImageFactory() {
- /* @todo The mappings set up below of image mime types to implementing
- * classes should be made externally configurable
- */
- ImageProvider jaiImage = new ImageProvider("JAIImage", "org.apache.fop.image.JAIImage");
- ImageProvider jimiImage = new ImageProvider("JIMIImage", "org.apache.fop.image.JimiImage");
- ImageProvider imageIoImage = new ImageProvider(
- "ImageIOImage", "org.apache.fop.image.ImageIOImage");
- ImageProvider gifImage = new ImageProvider("GIFImage", "org.apache.fop.image.GifImage");
- ImageProvider jpegImage = new ImageProvider("JPEGImage", "org.apache.fop.image.JpegImage");
- ImageProvider jpegImageIOImage = new ImageProvider(
- "JPEGImage", "org.apache.fop.image.JpegImageIOImage");
- ImageProvider bmpImage = new ImageProvider("BMPImage", "org.apache.fop.image.BmpImage");
- ImageProvider epsImage = new ImageProvider("EPSImage", "org.apache.fop.image.EPSImage");
- ImageProvider pngImage = new ImageProvider("PNGImage", "org.apache.fop.image.PNGImage");
- ImageProvider tiffImage = new ImageProvider("TIFFImage", "org.apache.fop.image.TIFFImage");
- ImageProvider xmlImage = new ImageProvider("XMLImage", "org.apache.fop.image.XMLImage");
- ImageProvider emfImage = new ImageProvider("EMFImage", "org.apache.fop.image.EmfImage");
-
- ImageMimeType imt = new ImageMimeType("image/gif");
- imageMimeTypes.put(imt.getMimeType(), imt);
- imt.addProvider(imageIoImage);
- imt.addProvider(jaiImage);
- imt.addProvider(jimiImage);
- imt.addProvider(gifImage);
-
- imt = new ImageMimeType("image/jpeg");
- imageMimeTypes.put(imt.getMimeType(), imt);
- imt.addProvider(jpegImageIOImage);
- imt.addProvider(jpegImage);
-
- imt = new ImageMimeType("image/bmp");
- imageMimeTypes.put(imt.getMimeType(), imt);
- imt.addProvider(bmpImage);
-
- imt = new ImageMimeType("image/eps");
- imageMimeTypes.put(imt.getMimeType(), imt);
- imt.addProvider(epsImage);
-
- imt = new ImageMimeType("image/png");
- imageMimeTypes.put(imt.getMimeType(), imt);
- //Image I/O is faster and more memory-efficient than own codec for PNG
- imt.addProvider(imageIoImage);
- imt.addProvider(pngImage);
-
- imt = new ImageMimeType("image/tga");
- imageMimeTypes.put(imt.getMimeType(), imt);
- imt.addProvider(jaiImage);
- imt.addProvider(imageIoImage);
- imt.addProvider(jimiImage);
-
- imt = new ImageMimeType("image/tiff");
- imageMimeTypes.put(imt.getMimeType(), imt);
- imt.addProvider(tiffImage); //Slower but supports CCITT embedding
- imt.addProvider(imageIoImage); //Fast but doesn't support CCITT embedding
- imt.addProvider(jaiImage); //Fast but doesn't support CCITT embedding
-
- imt = new ImageMimeType("image/svg+xml");
- imageMimeTypes.put(imt.getMimeType(), imt);
- imt.addProvider(xmlImage);
-
- imt = new ImageMimeType("text/xml");
- imageMimeTypes.put(imt.getMimeType(), imt);
- imt.addProvider(xmlImage);
-
- imt = new ImageMimeType("image/emf");
- imageMimeTypes.put(imt.getMimeType(), imt);
- imt.addProvider(emfImage);
-
- Iterator iter = Service.providers(RegisterableImageProvider.class, true);
- while (iter.hasNext()) {
- RegisterableImageProvider impl = (RegisterableImageProvider)iter.next();
- imt = new ImageMimeType(impl.getSupportedMimeType());
- imageMimeTypes.put(imt.getMimeType(), imt);
- imt.addProvider(new ImageProvider(impl.getName(), impl.getClassName()));
- }
- }
-
- /**
- * Get the url string from a wrapped url.
- *
- * @param href the input wrapped url
- * @return the raw url
- */
- public static String getURL(String href) {
- return URISpecification.getURL(href);
- }
-
- /**
- * Get the image from the cache or load.
- * If this returns null then the image could not be loaded
- * due to an error. Messages should be logged.
- * Before calling this the getURL(url) must be used.
- *
- * @param url the url for the image
- * @param context the user agent context
- * @return the fop image instance
- */
- public FopImage getImage(String url, FOUserAgent context) {
- return cache.getImage(url, context);
- }
-
- /**
- * Release an image from the cache.
- * This can be used if the renderer has its own cache of
- * the image.
- * The image should then be put into the weak cache.
- *
- * @param url the url for the image
- * @param context the user agent context
- */
- public void releaseImage(String url, FOUserAgent context) {
- cache.releaseImage(url, context);
- }
-
- /**
- * Release the context and all images in the context.
- *
- * @param context the context to remove
- */
- public void removeContext(FOUserAgent context) {
- cache.removeContext(context);
- }
-
- /**
- * Create an FopImage objects.
- * @param href the url for the image
- * @param ua the user agent context
- * @return the fop image instance
- */
- public FopImage loadImage(String href, FOUserAgent ua) {
-
- Source source = ua.resolveURI(href);
- if (source == null) {
- return null;
- }
-
- // Got a valid source, obtain an InputStream from it
- InputStream in = null;
- if (source instanceof StreamSource) {
- in = ((StreamSource)source).getInputStream();
- }
- if (in == null) {
- try {
- in = new java.net.URL(source.getSystemId()).openStream();
- } catch (Exception ex) {
- log.error("Unable to obtain stream from id '"
- + source.getSystemId() + "'");
- }
- }
- if (in == null) {
- return null;
- }
-
- //Make sure the InputStream is decorated with a BufferedInputStream
- if (!(in instanceof java.io.BufferedInputStream)) {
- in = new java.io.BufferedInputStream(in);
- }
-
- // Check image type
- FopImage.ImageInfo imgInfo = null;
- try {
- imgInfo = ImageReaderFactory.make(source.getSystemId(), in, ua);
- } catch (Exception e) {
- log.error("Error while recovering image information ("
- + href + ") : " + e.getMessage(), e);
- return null;
- }
- if (imgInfo == null) {
- try {
- in.close();
- in = null;
- } catch (Exception e) {
- log.debug("Error closing the InputStream for the image", e);
- }
- log.error("No ImageReader for this type of image (" + href + ")");
- return null;
- }
- // Associate mime-type to FopImage class
- String imgMimeType = imgInfo.mimeType;
- Class imageClass = getImageClass(imgMimeType);
- if (imageClass == null) {
- log.error("Unsupported image type (" + href + "): " + imgMimeType);
- return null;
- } else {
- if (log.isDebugEnabled()) {
- log.debug("Loading " + imgMimeType + " with " + imageClass.getName()
- + ": " + href);
- }
- }
-
- // load the right image class
- // return new <FopImage implementing class>
- Object imageInstance = null;
- try {
- Class[] imageConstructorParameters = new Class[1];
- imageConstructorParameters[0] = org.apache.fop.image.FopImage.ImageInfo.class;
- Constructor imageConstructor = imageClass.getDeclaredConstructor(
- imageConstructorParameters);
- Object[] initArgs = new Object[1];
- initArgs[0] = imgInfo;
- imageInstance = imageConstructor.newInstance(initArgs);
- } catch (java.lang.reflect.InvocationTargetException ex) {
- Throwable t = ex.getTargetException();
- String msg;
- if (t != null) {
- msg = t.getMessage();
- } else {
- msg = ex.getMessage();
- }
- log.error("Error creating FopImage object ("
- + href + "): " + msg, (t == null) ? ex : t);
- return null;
- } catch (InstantiationException ie) {
- log.error("Error creating FopImage object ("
- + href + "): Could not instantiate " + imageClass.getName() + " instance");
- return null;
- } catch (Exception ex) {
- log.error("Error creating FopImage object ("
- + href + "): " + ex.getMessage(), ex);
- return null;
- }
- if (!(imageInstance instanceof org.apache.fop.image.FopImage)) {
- log.error("Error creating FopImage object (" + href + "): " + "class "
- + imageClass.getName()
- + " doesn't implement org.apache.fop.image.FopImage interface");
- return null;
- }
- return (FopImage) imageInstance;
- }
-
- private Class getImageClass(String imgMimeType) {
- ImageMimeType imt = (ImageMimeType)imageMimeTypes.get(imgMimeType);
- if (imt == null) {
- return null;
- }
- return imt.getFirstImplementingClass();
- }
-
- /**
- * Forces all the image caches to be cleared. This should normally only be used in
- * testing environments. If you happen to think that you need to call this yourself
- * in a production environment, please notify the development team so we can look
- * into the issue. A call like this shouldn't be necessary anymore like it may have
- * been with FOP 0.20.5.
- */
- public void clearCaches() {
- cache.clearAll();
- }
-}
-
-/**
- * Basic image cache.
- * This keeps track of invalid images.
- */
-class BasicImageCache implements ImageCache {
-
- private Set invalid = Collections.synchronizedSet(new java.util.HashSet());
- //private Map contextStore = Collections.synchronizedMap(new java.util.HashMap());
-
- public FopImage getImage(String url, FOUserAgent context) {
- if (invalid.contains(url)) {
- return null;
- }
- //TODO Doesn't seem to be fully implemented. Do we need it at all? Not referenced.
- return null;
- }
-
- public void releaseImage(String url, FOUserAgent context) {
- // do nothing
- }
-
- public void invalidateImage(String url, FOUserAgent context) {
- // cap size of invalid list
- if (invalid.size() > 100) {
- invalid.clear();
- }
- invalid.add(url);
- }
-
- public void removeContext(FOUserAgent context) {
- // do nothing
- }
-
- /** {@inheritDoc} */
- public void clearAll() {
- invalid.clear();
- }
-
-}
-
-/**
- * This is the context image cache.
- * This caches images on the basis of the given context.
- * Common images in different contexts are currently not handled.
- * There are two possiblities, each context handles its own images
- * and renderers can cache information or images are shared and
- * all information is retained.
- * Once a context is removed then all images are placed into a
- * weak hashmap so they may be garbage collected.
- */
-class ContextImageCache implements ImageCache {
-
- // if this cache is collective then images can be shared
- // among contexts, this implies that the base directory
- // is either the same or does not effect the images being
- // loaded
- private boolean collective;
- private Map contextStore = Collections.synchronizedMap(new java.util.HashMap());
- private Set invalid = null;
- private Map refStore = null;
- private ReferenceQueue refQueue = new ReferenceQueue();
-
- public ContextImageCache(boolean col) {
- collective = col;
- if (collective) {
- refStore = Collections.synchronizedMap(new java.util.HashMap());
- invalid = Collections.synchronizedSet(new java.util.HashSet());
- }
- }
-
- // sync around lookups and puts
- // another sync around load for a particular image
- public FopImage getImage(String url, FOUserAgent context) {
- ImageLoader im = null;
- // this protects the finding or creating of a new
- // ImageLoader for multi threads
- synchronized (this) {
- if (collective && invalid.contains(url)) {
- return null;
- }
- Context con = (Context) contextStore.get(context);
- if (con == null) {
- con = new Context(context, collective);
- contextStore.put(context, con);
- } else {
- if (con.invalid(url)) {
- return null;
- }
- im = con.getImage(url);
- }
- if (im == null && collective) {
- Iterator i = contextStore.values().iterator();
- while (i.hasNext()) {
- Context c = (Context)i.next();
- if (c != con) {
- im = c.getImage(url);
- if (im != null) {
- break;
- }
- }
- }
- if (im == null) {
- Reference ref = (Reference)refStore.get(url);
- if (ref != null) {
- im = (ImageLoader) ref.get();
- if (im == null) {
- //Remove key if its value has been garbage collected
- refStore.remove(url);
- }
- }
- }
- }
-
- if (im != null) {
- con.putImage(url, im);
- } else {
- im = con.getImage(url, this);
- }
- }
-
- // the ImageLoader is synchronized so images with the
- // same url will not be loaded at the same time
- if (im != null) {
- return im.loadImage();
- }
- return null;
- }
-
- public void releaseImage(String url, FOUserAgent context) {
- Context con = (Context) contextStore.get(context);
- if (con != null) {
- if (collective) {
- ImageLoader im = con.getImage(url);
- refStore.put(url, wrapInReference(im, url));
- }
- con.releaseImage(url);
- }
- }
-
- public void invalidateImage(String url, FOUserAgent context) {
- if (collective) {
- // cap size of invalid list
- if (invalid.size() > 100) {
- invalid.clear();
- }
- invalid.add(url);
- }
- Context con = (Context) contextStore.get(context);
- if (con != null) {
- con.invalidateImage(url);
- }
- }
-
- private Reference wrapInReference(Object obj, Object key) {
- return new SoftReferenceWithKey(obj, key, refQueue);
- }
-
- private static class SoftReferenceWithKey extends SoftReference {
-
- private Object key;
-
- public SoftReferenceWithKey(Object referent, Object key, ReferenceQueue q) {
- super(referent, q);
- this.key = key;
- }
- }
-
- public void removeContext(FOUserAgent context) {
- Context con = (Context) contextStore.get(context);
- if (con != null) {
- if (collective) {
- Map images = con.getImages();
- Iterator iter = images.entrySet().iterator();
- while (iter.hasNext()) {
- Entry entry = (Entry)iter.next();
- refStore.put(entry.getKey(),
- wrapInReference(entry.getValue(), entry.getKey()));
- }
- }
- contextStore.remove(context);
- }
- //House-keeping (remove cleared references)
- checkReferenceQueue();
- }
-
- /**
- * Checks the reference queue if any references have been cleared and removes them from the
- * cache.
- */
- private void checkReferenceQueue() {
- SoftReferenceWithKey ref;
- while ((ref = (SoftReferenceWithKey)refQueue.poll()) != null) {
- refStore.remove(ref.key);
- }
- }
-
- class Context {
- private Map images = Collections.synchronizedMap(new java.util.HashMap());
- private Set invalid = null;
- private FOUserAgent userAgent;
-
- public Context(FOUserAgent ua, boolean inv) {
- userAgent = ua;
- if (inv) {
- invalid = Collections.synchronizedSet(new java.util.HashSet());
- }
- }
-
- public ImageLoader getImage(String url, ImageCache c) {
- if (images.containsKey(url)) {
- return (ImageLoader) images.get(url);
- }
- ImageLoader loader = new ImageLoader(url, c, userAgent);
- images.put(url, loader);
- return loader;
- }
-
- public void putImage(String url, ImageLoader image) {
- images.put(url, image);
- }
-
- public ImageLoader getImage(String url) {
- return (ImageLoader) images.get(url);
- }
-
- public void releaseImage(String url) {
- images.remove(url);
- }
-
- public Map getImages() {
- return images;
- }
-
- public void invalidateImage(String url) {
- invalid.add(url);
- }
-
- public boolean invalid(String url) {
- return invalid.contains(url);
- }
-
- }
-
- /** {@inheritDoc} */
- public void clearAll() {
- this.refStore.clear();
- this.invalid.clear();
- //The context-sensitive caches are not cleared so there are no negative side-effects
- //in a multi-threaded environment. Not that it's a good idea to use this method at
- //all except in testing environments. If such a calls is necessary in normal environments
- //we need to check on memory leaks!
- }
-
-}
-
-/**
- * Encapsulates a class of type FopImage by holding its class name.
- * This allows dynamic loading of the class at runtime.
- */
-class ImageProvider {
-
- private String name = null;
-
- private String className = null;
-
- private boolean checked = false;
-
- private Class clazz = null;
-
- /**
- * Creates an ImageProvider with a given name and implementing class.
- * The class name should refer to a class of type {@link FopImage}.
- * However, this is not checked on construction.
- * @param name The name of the provider
- * @param className The full class name of the class implementing this provider
- */
- public ImageProvider(String name, String className) {
- setName(name);
- setClassName(className);
- }
-
- /**
- * Returns the provider name.
- * @return The provider name
- */
- public String getName() {
- return name;
- }
-
- private void setName(String name) {
- this.name = name;
- }
-
- /**
- * Returns the implementing class name.
- * @return The implementing class name
- */
- public String getClassName() {
- return className;
- }
-
- private void setClassName(String className) {
- this.className = className;
- }
-
- /**
- * Returns the implementing class as a {@link Class} object.
- * @return The implementing class or null if it couldn't be loaded.
- */
- public Class getImplementingClass() {
- if (!checked) {
- try {
- clazz = Class.forName(getClassName());
- } catch (ClassNotFoundException cnfe) {
- //nop
- } catch (LinkageError le) {
- // This can happen if fop was build with support for a
- // particular provider (e.g. a binary fop distribution)
- // but the required support files (e.g. jai, jimi) are not
- // available in the current runtime environment.
- ImageFactory.log.debug("Image support provider " + getName()
- + " could not be loaded. If " + getName() + " should be"
- + " available please make sure all required external libraries"
- + " are on the classpath.");
- }
- checked = true;
- }
- return clazz;
- }
-}
-
-/**
- * Holds a mime type for a particular image format plus a list of
- * {@link ImageProvider} objects which support the particular image format.
- */
-class ImageMimeType {
-
- private String mimeType = null;
-
- private List providers = null;
-
- /**
- * Constructor for a particular mime type.
- * @param mimeType The mime type
- */
- public ImageMimeType(String mimeType) {
- setMimeType(mimeType);
- }
-
- /**
- * Returns the mime type.
- * @return The mime type
- */
- public String getMimeType() {
- return mimeType;
- }
-
- private void setMimeType(String mimeType) {
- this.mimeType = mimeType;
- }
-
- /**
- * Returns the class from the first available provider.
- * @return The first available class or null if none can be found
- */
- public Class getFirstImplementingClass() {
- if (providers == null) {
- return null;
- }
- for (Iterator it = providers.iterator(); it.hasNext();) {
- ImageProvider ip = (ImageProvider)it.next();
- Class clazz = ip.getImplementingClass();
- if (clazz != null) {
- return clazz;
- }
- }
- return null;
- }
-
- /**
- * Adds a new provider.
- * The provider is added to the end of the current provider list.
- * @param The new provider to add
- */
- public void addProvider(ImageProvider provider) {
- if (providers == null) {
- providers = new ArrayList(4); // Assume we only have a few providers
- }
- if (!providers.contains(provider)) {
- providers.add(provider);
- }
- }
-} \ No newline at end of file