diff options
Diffstat (limited to 'src/java/org/apache/fop/image/ImageFactory.java')
-rw-r--r-- | src/java/org/apache/fop/image/ImageFactory.java | 708 |
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 |