You are viewing a plain text version of this content. The canonical link for it is here.
Posted to fop-commits@xmlgraphics.apache.org by je...@apache.org on 2007/12/04 11:27:55 UTC

svn commit: r600870 [1/3] - in /xmlgraphics/fop/branches/Temp_ImagePackageRedesign: src/java/org/apache/fop/apps/ src/java/org/apache/fop/area/ src/java/org/apache/fop/fo/flow/ src/java/org/apache/fop/image2/ src/java/org/apache/fop/image2/cache/ src/j...

Author: jeremias
Date: Tue Dec  4 02:27:51 2007
New Revision: 600870

URL: http://svn.apache.org/viewvc?rev=600870&view=rev
Log:
Note: The API of the new image package has changed a bit. (it became necessary when I introduced caching)

The direct dependency on FOUserAgent has been removed to make the image package more universally usable. Instead an ImageContext (provided by FopFactory in FOP) and ImageSessionContext (provided by FOUserAgent in FOP) was introduced.
Introduced image caching with soft references (I didn't reintroduce the FOUserAgent lock, yet, because it doesn't help much)
ImageInfo doesn't carry the Source for the image anymore. The Source is provided by the new ImageSessionContext.java and only shared within the same thread to make things simpler and to avoid complex synchronization and cleanup.
Image instances now indicate whether they are cacheable (not all Image instances are cacheable, for example when they just carry an InputStream).
Moved the converter pipeline functionality into its own subpackage to keep "spi" clean.
Added checks in ImageSize to detect incomplete Preloaders.
ImageSource can now indicate whether its a fast source (loading from local file) or a slow source (loading over the network). (but this isn't used, yet)
Fixed a bug in WMF and SVG preloaders: they didn't close their Sources after fully loading the images.
Bugfix in ImageRawJPEG: it illegally reported being an EPS file
ImageRawStream got an "InputStreamFactory" so it is possible to reuse raw images if they have been loaded into memory (or to a local file which hasn't been implemented, yet).
The pipeline code now converts single-use raw images to reusable raw images when possible. But there's nothing built in to restrict the image size to a maximum, yet.
Improved JPEG preloader so it can stop early an deal with images that have to APP0 segment. Images from digicams are such an example. They carry the resolution info in the EXIF block which is currently not interpreted. Fallback is to the configured source resolution.

Added:
    xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/ImageContext.java   (with props)
    xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/ImageSessionContext.java   (with props)
    xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/cache/
    xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/cache/ImageCache.java   (with props)
    xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/cache/ImageCacheListener.java   (with props)
    xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/cache/ImageCacheStatistics.java   (with props)
    xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/cache/ImageKey.java   (with props)
    xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/impl/AbstractImageSessionContext.java   (with props)
    xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/pipeline/
    xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/pipeline/ImageConversionEdge.java   (with props)
    xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/pipeline/ImageProviderPipeline.java   (with props)
    xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/pipeline/ImageRepresentation.java   (with props)
    xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/pipeline/PipelineFactory.java   (with props)
    xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/util/SoftMapCache.java   (with props)
    xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/util/SoftReferenceWithKey.java   (with props)
    xmlgraphics/fop/branches/Temp_ImagePackageRedesign/test/java/org/apache/fop/image2/cache/
    xmlgraphics/fop/branches/Temp_ImagePackageRedesign/test/java/org/apache/fop/image2/cache/ImageCacheLoggingStatistics.java   (with props)
    xmlgraphics/fop/branches/Temp_ImagePackageRedesign/test/java/org/apache/fop/image2/cache/ImageCacheTestCase.java   (with props)
Removed:
    xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/spi/ImageConversionEdge.java
    xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/spi/ImageConverterPipeline.java
    xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/spi/ImageRepresentation.java
Modified:
    xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/apps/FOUserAgent.java
    xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/apps/FopFactory.java
    xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/area/RenderPagesModel.java
    xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/fo/flow/ExternalGraphic.java
    xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/Image.java
    xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/ImageInfo.java
    xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/ImageManager.java
    xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/ImageSize.java
    xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/ImageSource.java
    xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/impl/AbstractImageLoader.java
    xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/impl/ImageGraphics2D.java
    xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/impl/ImageLoaderEPS.java
    xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/impl/ImageLoaderRaw.java
    xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/impl/ImageLoaderRawJPEG.java
    xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/impl/ImageRawJPEG.java
    xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/impl/ImageRawStream.java
    xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/impl/ImageRendered.java
    xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/impl/ImageXMLDOM.java
    xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/impl/PreloaderBMP.java
    xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/impl/PreloaderEMF.java
    xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/impl/PreloaderEPS.java
    xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/impl/PreloaderGIF.java
    xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/impl/PreloaderJPEG.java
    xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/impl/PreloaderPNG.java
    xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/impl/PreloaderTIFF.java
    xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/impl/batik/ImageLoaderSVG.java
    xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/impl/batik/ImageLoaderWMF.java
    xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/impl/batik/ImageWMF.java
    xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/impl/batik/PreloaderSVG.java
    xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/impl/batik/PreloaderWMF.java
    xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/impl/imageio/ImageLoaderImageIO.java
    xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/spi/ImageImplRegistry.java
    xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/spi/ImageLoader.java
    xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/spi/ImagePreloader.java
    xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/util/ImageUtil.java
    xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/render/java2d/Java2DRenderer.java
    xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/render/ps/PSRenderer.java
    xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/render/rtf/RTFHandler.java
    xmlgraphics/fop/branches/Temp_ImagePackageRedesign/test/java/org/apache/fop/image2/ImageLoaderTestCase.java
    xmlgraphics/fop/branches/Temp_ImagePackageRedesign/test/java/org/apache/fop/image2/ImagePreloaderTestCase.java

Modified: xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/apps/FOUserAgent.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/apps/FOUserAgent.java?rev=600870&r1=600869&r2=600870&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/apps/FOUserAgent.java (original)
+++ xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/apps/FOUserAgent.java Tue Dec  4 02:27:51 2007
@@ -23,17 +23,19 @@
 import java.io.File;
 import java.util.Date;
 import java.util.Map;
+
 import javax.xml.transform.Source;
 import javax.xml.transform.TransformerException;
 import javax.xml.transform.URIResolver;
 
-// commons logging
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
-// FOP
 import org.apache.fop.Version;
 import org.apache.fop.fo.FOEventHandler;
+import org.apache.fop.image2.ImageContext;
+import org.apache.fop.image2.ImageSessionContext;
+import org.apache.fop.image2.impl.AbstractImageSessionContext;
 import org.apache.fop.pdf.PDFEncryptionParams;
 import org.apache.fop.render.Renderer;
 import org.apache.fop.render.RendererFactory;
@@ -110,6 +112,22 @@
     /** 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);
+        }
+        
+    };
+    
     /**
      * Default constructor
      * @see org.apache.fop.apps.FopFactory
@@ -440,6 +458,14 @@
      */
     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

Modified: xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/apps/FopFactory.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/apps/FopFactory.java?rev=600870&r1=600869&r2=600870&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/apps/FopFactory.java (original)
+++ xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/apps/FopFactory.java Tue Dec  4 02:27:51 2007
@@ -45,6 +45,7 @@
 import org.apache.fop.fonts.FontCache;
 import org.apache.fop.hyphenation.HyphenationTreeResolver;
 import org.apache.fop.image.ImageFactory;
+import org.apache.fop.image2.ImageContext;
 import org.apache.fop.image2.ImageManager;
 import org.apache.fop.layoutmgr.LayoutManagerMaker;
 import org.apache.fop.render.RendererFactory;
@@ -58,7 +59,7 @@
  * Information that may potentially be different for each rendering run can be
  * found and managed in the FOUserAgent.
  */
-public class FopFactory {
+public class FopFactory implements ImageContext {
     
     /** logger instance */
     private static Log log = LogFactory.getLog(FopFactory.class);
@@ -155,7 +156,7 @@
         this.foURIResolver = new FOURIResolver(validateUserConfigStrictly());
         this.colorSpaceCache = new ColorSpaceCache(foURIResolver);
         this.imageFactory = new ImageFactory();
-        this.imageManager = new ImageManager();
+        this.imageManager = new ImageManager(this);
         this.rendererFactory = new RendererFactory();
         this.xmlHandlers = new XMLHandlerRegistry();
         this.ignoredNamespaces = new java.util.HashSet();

Modified: xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/area/RenderPagesModel.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/area/RenderPagesModel.java?rev=600870&r1=600869&r2=600870&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/area/RenderPagesModel.java (original)
+++ xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/area/RenderPagesModel.java Tue Dec  4 02:27:51 2007
@@ -22,13 +22,11 @@
 // Java
 import java.io.IOException;
 import java.io.OutputStream;
-import java.util.List;
 import java.util.Iterator;
+import java.util.List;
 
-// XML
 import org.xml.sax.SAXException;
 
-// FOP
 import org.apache.fop.apps.FOPException;
 import org.apache.fop.apps.FOUserAgent;
 import org.apache.fop.fonts.FontInfo;
@@ -119,6 +117,8 @@
             try {
                 renderer.renderPage(page);
             } catch (RuntimeException re) {
+                String err = "Error while rendering page " + page.getPageNumberString(); 
+                log.error(err, re);
                 throw re;
             } catch (Exception e) {
                 //TODO use error handler to handle this FOP or IO Exception or propagate exception

Modified: xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/fo/flow/ExternalGraphic.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/fo/flow/ExternalGraphic.java?rev=600870&r1=600869&r2=600870&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/fo/flow/ExternalGraphic.java (original)
+++ xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/fo/flow/ExternalGraphic.java Tue Dec  4 02:27:51 2007
@@ -69,13 +69,13 @@
         super.bind(pList);
         src = pList.get(PR_SRC).getString();
         
-        //Additional processing: preload image
+        //Additional processing: obtain the image's intrinsic size and baseline information
         url = URISpecification.getURL(src);
         FOUserAgent userAgent = getUserAgent();
         ImageManager manager = userAgent.getFactory().getImageManager();
         ImageInfo info = null;
         try {
-            info = manager.preloadImage(url, userAgent);
+            info = manager.getImageInfo(url, userAgent.getImageSessionContext());
         } catch (ImageException e) {
             log.error("Image not available: " + e.getMessage());
         } catch (IOException ioe) {

Modified: xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/Image.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/Image.java?rev=600870&r1=600869&r2=600870&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/Image.java (original)
+++ xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/Image.java Tue Dec  4 02:27:51 2007
@@ -43,4 +43,10 @@
      */
     ImageFlavor getFlavor();
     
+    /**
+     * Indicates whether the Image instance is cacheable in memory.
+     * @return true if the Image is cacheable
+     */
+    boolean isCacheable();
+    
 }

Added: xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/ImageContext.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/ImageContext.java?rev=600870&view=auto
==============================================================================
--- xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/ImageContext.java (added)
+++ xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/ImageContext.java Tue Dec  4 02:27:51 2007
@@ -0,0 +1,36 @@
+/*
+ * 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.image2;
+
+
+/**
+ * The ImageContext interface provides session-independent information (mainly configuration
+ * values).
+ */
+public interface ImageContext {
+
+    /**
+     * Returns the resolution (in dpi) that is to be used when interpreting pixel sizes where no
+     * resolution information is available.
+     * @return the source resolution (in dpi)
+     */
+    float getSourceResolution();
+    
+}

Propchange: xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/ImageContext.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/ImageContext.java
------------------------------------------------------------------------------
    svn:keywords = Id

Modified: xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/ImageInfo.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/ImageInfo.java?rev=600870&r1=600869&r2=600870&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/ImageInfo.java (original)
+++ xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/ImageInfo.java Tue Dec  4 02:27:51 2007
@@ -21,8 +21,6 @@
 
 import java.util.Map;
 
-import javax.xml.transform.Source;
-
 /**
  * Represents an image that may not have been fully loaded. Usually, the loading only goes as far
  * as necessary to know the intrinsic size of the image. The image will only fully loaded later
@@ -40,8 +38,6 @@
 
     /** Original URI the image was accessed with */
     private String originalURI;
-    /** Source to load the image from (may be null) */
-    private Source src;
     /** MIME type of the image */
     private String mimeType;
 
@@ -57,21 +53,11 @@
     /**
      * Main constructor.
      * @param originalURI the original URI that was specified by the user (not the resolved URI!)
-     * @param src The Source object from which an image is loaded
      * @param mimeType the MIME type of the image
      */
-    public ImageInfo(String originalURI, Source src, String mimeType) {
+    public ImageInfo(String originalURI, String mimeType) {
         this.originalURI = originalURI;
-        this.src = src;
         this.mimeType = mimeType;
-    }
-
-    /**
-     * Returns the Source that the image is originally loaded from.
-     * @return the Source
-     */
-    public Source getSource() {
-        return this.src;
     }
 
     /**

Modified: xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/ImageManager.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/ImageManager.java?rev=600870&r1=600869&r2=600870&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/ImageManager.java (original)
+++ xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/ImageManager.java Tue Dec  4 02:27:51 2007
@@ -19,26 +19,20 @@
  
 package org.apache.fop.image2;
 
-import java.io.File;
 import java.io.IOException;
-import java.io.InputStream;
-import java.net.MalformedURLException;
-import java.net.URL;
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.Map;
 
-import javax.imageio.ImageIO;
 import javax.xml.transform.Source;
-import javax.xml.transform.stream.StreamSource;
 
-import org.apache.commons.io.FileUtils;
-import org.apache.commons.io.IOUtils;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
 import org.apache.fop.apps.FOUserAgent;
-import org.apache.fop.image2.spi.ImageConverterPipeline;
+import org.apache.fop.image2.cache.ImageCache;
+import org.apache.fop.image2.pipeline.ImageProviderPipeline;
+import org.apache.fop.image2.pipeline.PipelineFactory;
 import org.apache.fop.image2.spi.ImageImplRegistry;
 import org.apache.fop.image2.spi.ImagePreloader;
 import org.apache.fop.image2.util.ImageUtil;
@@ -54,6 +48,22 @@
     /** Holds all registered interface implementations for the image package */
     private ImageImplRegistry registry = ImageImplRegistry.getDefaultInstance();
     
+    /** Provides session-independent information */
+    private ImageContext imageContext;
+
+    /** The image cache for this instance */
+    private ImageCache cache = new ImageCache();
+    
+    private PipelineFactory pipelineFactory = new PipelineFactory(this);
+    
+    /**
+     * Main constructor.
+     * @param context the session-independent context information
+     */
+    public ImageManager(ImageContext context) {
+        this.imageContext = context;
+    }
+    
     /**
      * Returns the ImageImplRegistry in use by the ImageManager.
      * @return the ImageImplRegistry
@@ -62,90 +72,65 @@
         return this.registry;
     }
     
-    protected ImageSource newImageSource(String uri, FOUserAgent userAgent) {
-        Source source = userAgent.resolveURI(uri);
-        if (source == null) {
-            if (log.isDebugEnabled()) {
-                log.debug("URI could not be resolved: " + uri);
-            }
-            return null;
-        }
-        
-        ImageSource imageSource = null;
-        
-        String resolvedURI = source.getSystemId();
-        URL url;
-        try {
-            url = new URL(resolvedURI);
-        } catch (MalformedURLException e) {
-            url = null;
-        } 
-        File f = FileUtils.toFile(url);
-        if (f != null) {
-            boolean directFileAccess = true;
-            InputStream in = null;
-            if (source instanceof StreamSource) {
-                StreamSource streamSource = (StreamSource)source; 
-                in = streamSource.getInputStream();
-                in = ImageUtil.decorateMarkSupported(in);
-                try {
-                    if (ImageUtil.isGZIPCompressed(in)) {
-                        //GZIPped stream are not seekable, so buffer/cache like other URLs
-                        directFileAccess = false;
-                    }
-                } catch (IOException ioe) {
-                    log.error("Error while checking the InputStream for GZIP compression."
-                            + " Could not load image from system identifier '"
-                            + source.getSystemId() + "' (" + ioe.getMessage() + ")");
-                    return null;
-                }
-            }
-            
-            if (directFileAccess) {
-                //Close as the file is reopened in a more optimal way
-                IOUtils.closeQuietly(in);
-                try {
-                    imageSource = new ImageSource(ImageIO.createImageInputStream(f), resolvedURI);
-                } catch (IOException ioe) {
-                    log.error("Unable to create ImageInputStream for local file"
-                            + " from system identifier '"
-                            + source.getSystemId() + "' (" + ioe.getMessage() + ")");
-                }
-            }
+    /**
+     * Returns the ImageCache in use by the ImageManager.
+     * @return the ImageCache
+     */
+    public ImageCache getCache() {
+        return this.cache;
+    }
+    
+    /**
+     * Returns the PipelineFactory in use by the ImageManager.
+     * @return the PipelineFactory
+     */
+    public PipelineFactory getPipelineFactory() {
+        return this.pipelineFactory;
+    }
+    
+    /**
+     * Returns an ImageInfo object containing its intrinsic size for a given URI. The ImageInfo
+     * is retrieved from an image cache if it has been requested before.
+     * @param uri the URI of the image 
+     * @param session the session context through which to resolve the URI if the image is not in
+     *                the cache
+     * @return the ImageInfo object created from the image
+     * @throws ImageException If no suitable ImagePreloader can be found to load the image or
+     *          if an error occurred while preloading the image.
+     * @throws IOException If an I/O error occurs while preloading the image
+     */
+    public ImageInfo getImageInfo(String uri, ImageSessionContext session)
+                throws ImageException, IOException {
+        if (getCache() != null) {
+            return getCache().needImageInfo(uri, session, this);
+        } else {
+            return preloadImage(uri, session);
         }
-        
-        if (imageSource == null) {
-            // Got a valid source, obtain an InputStream from it
-            InputStream in = null;
-            if (source instanceof StreamSource) {
-                in = ((StreamSource)source).getInputStream();
-            }
-            if (in == null && url != null) {
-                try {
-                    in = url.openStream();
-                } catch (Exception ex) {
-                    log.error("Unable to obtain stream from system identifier '" 
-                        + source.getSystemId() + "'");
-                }
-            }
-            if (in == null) {
-                log.error("The Source that was returned from URI resolution didn't contain"
-                        + " an InputStream for URI: " + uri);
-                return null;
-            }
+    }
 
-            try {
-                //Buffer and uncompress if necessary
-                in = ImageUtil.autoDecorateInputStream(in);
-                imageSource = new ImageSource(
-                        ImageIO.createImageInputStream(in), source.getSystemId());
-            } catch (IOException ioe) {
-                log.error("Unable to create ImageInputStream for InputStream"
-                        + " from system identifier '"
-                        + source.getSystemId() + "' (" + ioe.getMessage() + ")");
-            }
-        }
-        return imageSource;
+    /**
+     * Preloads an image, i.e. the format of the image is identified and some basic information
+     * (MIME type, intrinsic size and possibly other values) are loaded and returned as an
+     * ImageInfo object. Note that the image is not fully loaded normally. Only with certain formats
+     * the image is already fully loaded and references added to the ImageInfo's custom objects
+     * (see {@link ImageInfo#getOriginalImage()}).
+     * <p>
+     * The reason for the preloading: Apache FOP, for example, only needs the image's intrinsic
+     * size during layout. Only when the document is rendered to the final format does FOP need
+     * to load the full image. Like this a lot of memory can be saved.
+     * @param uri the original URI of the image
+     * @param session the session context through which to resolve the URI
+     * @return the ImageInfo object created from the image
+     * @throws ImageException If no suitable ImagePreloader can be found to load the image or
+     *          if an error occurred while preloading the image.
+     * @throws IOException If an I/O error occurs while preloading the image
+     */
+    public ImageInfo preloadImage(String uri, ImageSessionContext session)
+            throws ImageException, IOException {
+        Source src = session.needSource(uri);
+        ImageInfo info = preloadImage(uri, src);
+        session.returnSource(uri, src);
+        return info;
     }
     
     /**
@@ -158,30 +143,23 @@
      * The reason for the preloading: Apache FOP, for example, only needs the image's intrinsic
      * size during layout. Only when the document is rendered to the final format does FOP need
      * to load the full image. Like this a lot of memory can be saved.
-     * @param uri the URI to load the image from
-     * @param userAgent the user agent used during the loading process
+     * @param uri the original URI of the image
+     * @param src the Source object to load the image from
      * @return the ImageInfo object created from the image
      * @throws ImageException If no suitable ImagePreloader can be found to load the image or
      *          if an error occurred while preloading the image.
      * @throws IOException If an I/O error occurs while preloading the image
      */
-    public ImageInfo preloadImage(String uri, FOUserAgent userAgent)
-                throws ImageException, IOException {
-        ImageSource imageSource = newImageSource(uri, userAgent);
-        return preloadImage(uri, imageSource, userAgent);
-    }
-
-    private ImageInfo preloadImage(String uri, Source src, FOUserAgent userAgent)
+    public ImageInfo preloadImage(String uri, Source src)
             throws ImageException, IOException {
         Iterator iter = registry.getPreloaderIterator();
         while (iter.hasNext()) {
             ImagePreloader preloader = (ImagePreloader)iter.next();
-            ImageInfo info = preloader.preloadImage(uri, src, userAgent);
+            ImageInfo info = preloader.preloadImage(uri, src, imageContext);
             if (info != null) {
                 return info;
             }
         }
-        ImageUtil.closeQuietly(src);
         throw new ImageException("No ImagePreloader found for " + uri);
     }
 
@@ -197,12 +175,14 @@
      *                  {@link #preloadImage(String, FOUserAgent)})
      * @param flavor the requested image flavor.
      * @param hints a Map of hints to any of the background components or null
+     * @param session the session context
      * @return the fully loaded image
      * @throws ImageException If no suitable loader/converter combination is available to fulfill
      *                  the request or if an error occurred while loading the image.
      * @throws IOException If an I/O error occurs
      */
-    public Image getImage(ImageInfo info, ImageFlavor flavor, Map hints)
+    public Image getImage(ImageInfo info, ImageFlavor flavor, Map hints,
+                ImageSessionContext session)
             throws ImageException, IOException {
         if (hints == null) {
             hints = Collections.EMPTY_MAP;
@@ -210,15 +190,17 @@
         String mime = info.getMimeType();
         
         Image img = null;
-        ImageConverterPipeline pipeline = registry.newImageConverterPipeline(mime, flavor);
+        ImageProviderPipeline pipeline = getPipelineFactory().newImageConverterPipeline(
+                mime, flavor);
         if (pipeline != null) {
-            img = pipeline.execute(info, hints);
+            img = pipeline.execute(info, hints, session);
         }
         if (img == null) {
             throw new ImageException(
                     "Cannot load image (no suitable loader/converter combination available) for "
                         + info);
         }
+        ImageUtil.closeQuietly(session.getSource(info.getOriginalURI()));
         return img;
     }
     
@@ -235,12 +217,14 @@
      *                  {@link #preloadImage(String, FOUserAgent)})
      * @param flavors the requested image flavors (in preferred order).
      * @param hints a Map of hints to any of the background components or null
+     * @param session the session context
      * @return the fully loaded image
      * @throws ImageException If no suitable loader/converter combination is available to fulfill
      *                  the request or if an error occurred while loading the image.
      * @throws IOException If an I/O error occurs
      */
-    public Image getImage(ImageInfo info, ImageFlavor[] flavors, Map hints)
+    public Image getImage(ImageInfo info, ImageFlavor[] flavors, Map hints,
+                        ImageSessionContext session)
                 throws ImageException, IOException {
         if (hints == null) {
             hints = Collections.EMPTY_MAP;
@@ -249,11 +233,11 @@
 
         Image img = null;
         int count = flavors.length;
-        ImageConverterPipeline[] candidates = new ImageConverterPipeline[count];
+        ImageProviderPipeline[] candidates = new ImageProviderPipeline[count];
         for (int i = 0; i < count; i++) {
-            candidates[i] = registry.newImageConverterPipeline(mime, flavors[i]);
+            candidates[i] = getPipelineFactory().newImageConverterPipeline(mime, flavors[i]);
         }
-        ImageConverterPipeline pipeline = null;
+        ImageProviderPipeline pipeline = null;
         int minPenalty = Integer.MAX_VALUE;
         for (int i = count - 1; i >= 0; i--) {
             if (candidates[i] == null) {
@@ -266,13 +250,14 @@
             }
         }    
         if (pipeline != null) {
-            img = pipeline.execute(info, hints);
+            img = pipeline.execute(info, hints, session);
         }
         if (img == null) {
             throw new ImageException(
                     "Cannot load image (no suitable loader/converter combination available) for "
                             + info);
         }
+        ImageUtil.closeQuietly(session.getSource(info.getOriginalURI()));
         return img;
     }
 
@@ -282,14 +267,15 @@
      * @param info the ImageInfo instance for the image (obtained by 
      *                  {@link #preloadImage(String, FOUserAgent)})
      * @param flavor the requested image flavor.
+     * @param session the session context
      * @return the fully loaded image
      * @throws ImageException If no suitable loader/converter combination is available to fulfill
      *                  the request or if an error occurred while loading the image.
      * @throws IOException If an I/O error occurs
      */
-    public Image getImage(ImageInfo info, ImageFlavor flavor)
+    public Image getImage(ImageInfo info, ImageFlavor flavor, ImageSessionContext session)
             throws ImageException, IOException {
-        return getImage(info, flavor, null);
+        return getImage(info, flavor, ImageUtil.getDefaultHints(session), session);
     }
 
     /**
@@ -298,14 +284,15 @@
      * @param info the ImageInfo instance for the image (obtained by 
      *                  {@link #preloadImage(String, FOUserAgent)})
      * @param flavors the requested image flavors (in preferred order).
+     * @param session the session context
      * @return the fully loaded image
      * @throws ImageException If no suitable loader/converter combination is available to fulfill
      *                  the request or if an error occurred while loading the image.
      * @throws IOException If an I/O error occurs
      */
-    public Image getImage(ImageInfo info, ImageFlavor[] flavors)
+    public Image getImage(ImageInfo info, ImageFlavor[] flavors, ImageSessionContext session)
             throws ImageException, IOException {
-        return getImage(info, flavors, null);
+        return getImage(info, flavors, ImageUtil.getDefaultHints(session), session);
     }
     
 }

Added: xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/ImageSessionContext.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/ImageSessionContext.java?rev=600870&view=auto
==============================================================================
--- xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/ImageSessionContext.java (added)
+++ xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/ImageSessionContext.java Tue Dec  4 02:27:51 2007
@@ -0,0 +1,83 @@
+/*
+ * 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.image2;
+
+import java.io.FileNotFoundException;
+
+import javax.xml.transform.Source;
+
+
+/**
+ * This interface is used to tell the cache which images are used by a session (in FOP that would
+ * be a rendering run). Images access within a session get a hard reference so they cannot be
+ * discarded. That could increase memory usage but helps with performance because the images
+ * don't get unloaded between layout and rendering which would mean that they have to be reloaded.
+ */
+public interface ImageSessionContext {
+
+    /**
+     * Returns the session-independent context object which provides configuration information.
+     * @return the associated ImageContext instance
+     */
+    ImageContext getParentContext();
+    
+    /**
+     * Returns the resolution (in dpi) of the target device used when painting images.
+     * @return the target resolution (in dpi)
+     */
+    float getTargetResolution();
+    
+    /**
+     * Attempts to create a Source object from the given URI. If possible this method returns
+     * ImageSource instance which provide the best possible method to access the image.
+     * @param uri URI to access
+     * @return A {@link javax.xml.transform.Source} object, or null if the URI
+     * cannot be resolved. 
+     */
+    Source newSource(String uri);
+    
+    /**
+     * Returns a Source object for a URI. This method is not guaranteed to return an instance.
+     * Implementations normally return already created Sources from a pool (normally populated
+     * through the {@link #returnSource(String, Source)} method).
+     * @param uri the URI of the image
+     * @return the Source object to load the image from, or null
+     */
+    Source getSource(String uri);
+    
+    /**
+     * Returns a Source object for a URI. This method is guaranteed to return a Source object. If
+     * the image cannot be found, a {@link FileNotFoundException} is thrown.
+     * @param uri the URI of the image
+     * @return the Source object to load the image from
+     * @throws FileNotFoundException if the image cannot be found
+     */
+    Source needSource(String uri) throws FileNotFoundException;
+    
+    /**
+     * Returns a Source object to a pool. This is provided in order to reuse a Source object
+     * between the preloading and the final loading of an image. Note that not all Source objects
+     * can be reused! Non-reusable Sources are discarded.
+     * @param uri the URI of the image
+     * @param src the Source object belonging to the URI
+     */
+    void returnSource(String uri, Source src);
+    
+}

Propchange: xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/ImageSessionContext.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/ImageSessionContext.java
------------------------------------------------------------------------------
    svn:keywords = Id

Modified: xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/ImageSize.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/ImageSize.java?rev=600870&r1=600869&r2=600870&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/ImageSize.java (original)
+++ xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/ImageSize.java Tue Dec  4 02:27:51 2007
@@ -196,6 +196,9 @@
      * Calculates the size in millipoints based on the size in pixels and the resolution.
      */
     public void calcSizeFromPixels() {
+        if (this.dpiHorizontal == 0 || this.dpiVertical == 0) {
+            throw new IllegalStateException("The resolution mus be set");
+        }
         this.widthMpt = (int)Math.round(UnitConv.in2mpt(this.widthPx / this.dpiHorizontal));
         this.heightMpt = (int)Math.round(UnitConv.in2mpt(this.heightPx / this.dpiVertical));
     }
@@ -204,6 +207,9 @@
      * Calculates the size in pixels based on the size in millipoints and the resolution.
      */
     public void calcPixelsFromSize() {
+        if (this.dpiHorizontal == 0 || this.dpiVertical == 0) {
+            throw new IllegalStateException("The resolution mus be set");
+        }
         this.widthPx = (int)Math.round(UnitConv.mpt2in(this.widthMpt * this.dpiHorizontal));
         this.heightPx = (int)Math.round(UnitConv.mpt2in(this.heightMpt * this.dpiVertical));
     }

Modified: xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/ImageSource.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/ImageSource.java?rev=600870&r1=600869&r2=600870&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/ImageSource.java (original)
+++ xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/ImageSource.java Tue Dec  4 02:27:51 2007
@@ -33,15 +33,18 @@
     
     private String systemId;
     private ImageInputStream iin;
+    private boolean fastSource;
 
     /**
      * Main constructor.
      * @param in the ImageInputStream to load from
      * @param systemId the system identifier (resolved URI) of the image
+     * @param fastSource true if it's a fast source (accessing local files)
      */
-    public ImageSource(ImageInputStream in, String systemId) {
+    public ImageSource(ImageInputStream in, String systemId, boolean fastSource) {
         this.iin = in;
         this.systemId = systemId;
+        this.fastSource = fastSource;
     }
 
     /**
@@ -49,7 +52,11 @@
      * @return the InputStream or null if the stream has been closed
      */
     public InputStream getInputStream() {
-        return new ImageInputStreamAdapter(this.iin);
+        if (this.iin == null) {
+            return null;
+        } else {
+            return new ImageInputStreamAdapter(this.iin);
+        }
     }
 
     /**
@@ -76,6 +83,15 @@
     /** {@inheritDoc} */
     public void setSystemId(String systemId) {
         this.systemId = systemId;
+    }
+    
+    /**
+     * Indicates whether this ImageSource is a fast source, i.e. accesses local files rather than
+     * network resources.
+     * @return true if it's a fast source
+     */
+    public boolean isFastSource() {
+        return this.fastSource;
     }
     
 }

Added: xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/cache/ImageCache.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/cache/ImageCache.java?rev=600870&view=auto
==============================================================================
--- xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/cache/ImageCache.java (added)
+++ xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/cache/ImageCache.java Tue Dec  4 02:27:51 2007
@@ -0,0 +1,228 @@
+/*
+ * 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.image2.cache;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.Set;
+
+import javax.xml.transform.Source;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.apache.fop.image2.Image;
+import org.apache.fop.image2.ImageException;
+import org.apache.fop.image2.ImageFlavor;
+import org.apache.fop.image2.ImageInfo;
+import org.apache.fop.image2.ImageManager;
+import org.apache.fop.image2.ImageSessionContext;
+import org.apache.fop.image2.util.SoftMapCache;
+
+/**
+ * This class provides a cache for images. The main key into the images is the original URI the
+ * image was accessed with.
+ * <p>
+ * Don't use one ImageCache instance in the context of multiple base URIs because relative URIs
+ * would not work correctly anymore.
+ */
+public class ImageCache {
+
+    /** logger */
+    protected static Log log = LogFactory.getLog(ImageCache.class);
+    
+    private Set invalidURIs = Collections.synchronizedSet(new java.util.HashSet());
+    
+    private SoftMapCache imageInfos = new SoftMapCache(true);
+    private SoftMapCache images = new SoftMapCache(true);
+    
+    private ImageCacheListener cacheListener;
+
+    /**
+     * Sets an ImageCacheListener instance so the events in the image cache can be observed.
+     * @param listener the listener instance
+     */
+    public void setCacheListener(ImageCacheListener listener) {
+        this.cacheListener = listener;
+    }
+    
+    /**
+     * Returns an ImageInfo instance for a given URI.
+     * @param uri the image's URI
+     * @param session the session context
+     * @param manager the ImageManager handling the images
+     * @return the ImageInfo instance
+     * @throws ImageException if an error occurs while parsing image data
+     * @throws IOException if an I/O error occurs while loading image data
+     */
+    public ImageInfo needImageInfo(String uri, ImageSessionContext session, ImageManager manager)
+            throws ImageException, IOException {
+        //Fetch unique version of the URI and use it for synchronization so we have some sort of
+        //"row-level" locking instead of "table-level" locking (to use a database analogy).
+        //The fine locking strategy is necessary since preloading an image is a potentially long
+        //operation.
+        if (isInvalidURI(uri)) {
+            throw new FileNotFoundException("Image not found: " + uri);
+        }
+        String lockURI = uri.intern();
+        synchronized (lockURI) {
+            ImageInfo info = getImageInfo(uri);
+            if (info == null) {
+                try {
+                    Source src = session.needSource(uri);
+                    if (src == null) {
+                        registerInvalidURI(uri);
+                        throw new FileNotFoundException("Image not found: " + uri);
+                    }
+                    info = manager.preloadImage(uri, src);
+                    session.returnSource(uri, src);
+                } catch (IOException ioe) {
+                    registerInvalidURI(uri);
+                    throw ioe;
+                } catch (ImageException e) {
+                    registerInvalidURI(uri);
+                    throw e;
+                }
+                putImageInfo(info);
+            }
+            return info;
+        }
+    }
+    
+    /**
+     * Indicates whether a URI has previously been identified as an invalid URI.
+     * @param uri the image's URI
+     * @return true if the URI is invalid
+     */
+    public boolean isInvalidURI(String uri) {
+        if (invalidURIs.contains(uri)) {
+            if (cacheListener != null) {
+                cacheListener.invalidHit(uri);
+            }
+            return true;
+        }
+        return false;
+    }
+    
+    /**
+     * Returns an ImageInfo instance from the cache or null if none is found.
+     * @param uri the image's URI
+     * @return the ImageInfo instance or null if the requested information is not in the cache
+     */
+    protected ImageInfo getImageInfo(String uri) {
+        ImageInfo info = (ImageInfo)imageInfos.get(uri);
+        if (cacheListener != null) {
+            if (info != null) {
+                cacheListener.cacheHitImageInfo(uri);
+            } else {
+                if (!isInvalidURI(uri)) {
+                    cacheListener.cacheMissImageInfo(uri);
+                }
+            }
+        }
+        return info;
+    }
+    
+    /**
+     * Registers an ImageInfo instance with the cache.
+     * @param info the ImageInfo instance
+     */
+    protected void putImageInfo(ImageInfo info) {
+        //An already existing ImageInfo is replaced.
+        imageInfos.put(info.getOriginalURI(), info);
+    }
+    
+    /**
+     * Registers a URI as invalid so getImageInfo can indicate that quickly with no I/O access.
+     * @param uri the URI of the invalid image
+     */
+    private void registerInvalidURI(String uri) {
+        synchronized (invalidURIs) {
+            // cap size of invalid list
+            if (invalidURIs.size() > 100) {
+                invalidURIs.clear();
+            }
+            invalidURIs.add(uri);
+        }
+    }
+    
+    /**
+     * Returns an image from the cache or null if it wasn't found.
+     * @param info the ImageInfo instance representing the image
+     * @param flavor the requested ImageFlavor for the image
+     * @return the requested image or null if the image is not in the cache
+     */
+    public Image getImage(ImageInfo info, ImageFlavor flavor) {
+        return getImage(info.getOriginalURI(), flavor);
+    }
+    
+    /**
+     * Returns an image from the cache or null if it wasn't found.
+     * @param uri the image's URI
+     * @param flavor the requested ImageFlavor for the image
+     * @return the requested image or null if the image is not in the cache
+     */
+    public Image getImage(String uri, ImageFlavor flavor) {
+        ImageKey key = new ImageKey(uri, flavor);
+        Image img = (Image)images.get(key);
+        if (cacheListener != null) {
+            if (img != null) {
+                cacheListener.cacheHitImage(key);
+            } else {
+                cacheListener.cacheMissImage(key);
+            }
+        }
+        return img;
+    }
+    
+    /**
+     * Registers an image with the cache.
+     * @param img the image
+     */
+    public void putImage(Image img) {
+        //An already existing Image is replaced.
+        if (!img.isCacheable()) {
+            throw new IllegalArgumentException(
+                    "Image is not cacheable! (Flavor: " + img.getFlavor() + ")");
+        }
+        ImageKey key = new ImageKey(img.getInfo().getOriginalURI(), img.getFlavor());
+        images.put(key, img);
+    }
+
+    /**
+     * Clears the image cache (all ImageInfo and Image objects).
+     */
+    public void clearCache() {
+        invalidURIs.clear();
+        imageInfos.clear();
+        images.clear();
+        doHouseKeeping();
+    }
+    
+    /**
+     * Triggers some house-keeping, i.e. removes stale entries.
+     */
+    public void doHouseKeeping() {
+        imageInfos.doHouseKeeping();
+        images.doHouseKeeping();
+    }
+    
+}

Propchange: xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/cache/ImageCache.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/cache/ImageCache.java
------------------------------------------------------------------------------
    svn:keywords = Id

Added: xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/cache/ImageCacheListener.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/cache/ImageCacheListener.java?rev=600870&view=auto
==============================================================================
--- xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/cache/ImageCacheListener.java (added)
+++ xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/cache/ImageCacheListener.java Tue Dec  4 02:27:51 2007
@@ -0,0 +1,60 @@
+/*
+ * 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.image2.cache;
+
+import java.util.EventListener;
+
+/**
+ * This interface can be implemented by classes which want to know what's going on inside the
+ * image cache.
+ */
+public interface ImageCacheListener extends EventListener {
+
+    /**
+     * An URi previously identified as invalid was requested again
+     * @param uri the invalid URI
+     */
+    void invalidHit(String uri);
+    
+    /**
+     * An ImageInfo was found in the cache
+     * @param uri the image's URI
+     */
+    void cacheHitImageInfo(String uri);
+    
+    /**
+     * An ImageInfo was not in the cache
+     * @param uri the image's URI
+     */
+    void cacheMissImageInfo(String uri);
+    
+    /**
+     * An Image was found in the cache
+     * @param key the image key
+     */
+    void cacheHitImage(ImageKey key);
+    
+    /**
+     * An Image was not in the cache
+     * @param key the image key
+     */
+    void cacheMissImage(ImageKey key);
+    
+}

Propchange: xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/cache/ImageCacheListener.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/cache/ImageCacheListener.java
------------------------------------------------------------------------------
    svn:keywords = Id

Added: xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/cache/ImageCacheStatistics.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/cache/ImageCacheStatistics.java?rev=600870&view=auto
==============================================================================
--- xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/cache/ImageCacheStatistics.java (added)
+++ xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/cache/ImageCacheStatistics.java Tue Dec  4 02:27:51 2007
@@ -0,0 +1,155 @@
+/*
+ * 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.image2.cache;
+
+import java.util.Collections;
+import java.util.Map;
+
+/**
+ * Convenience class that gathers statistical information about the image cache.
+ */
+public class ImageCacheStatistics implements ImageCacheListener {
+
+    private int invalidHits;
+    private int imageInfoCacheHits;
+    private int imageInfoCacheMisses;
+    private int imageCacheHits;
+    private int imageCacheMisses;
+    private Map imageCacheHitMap;
+    private Map imageCacheMissMap;
+    
+    /**
+     * Main constructor.
+     * @param detailed true if the cache hits/misses for each Image instance should be recorded.
+     */
+    public ImageCacheStatistics(boolean detailed) {
+        if (detailed) {
+            imageCacheHitMap = new java.util.HashMap();
+            imageCacheMissMap = new java.util.HashMap();
+        }
+    }
+    
+    /**
+     * Reset the gathered statistics information.
+     */
+    public void reset() {
+        this.imageInfoCacheHits = 0;
+        this.imageInfoCacheMisses = 0;
+        this.invalidHits = 0;
+    }
+    
+    /** {@inheritDoc} */
+    public void invalidHit(String uri) {
+        invalidHits++;
+    }
+
+    /** {@inheritDoc} */
+    public void cacheHitImageInfo(String uri) {
+        imageInfoCacheHits++;
+    }
+
+    /** {@inheritDoc} */
+    public void cacheMissImageInfo(String uri) {
+        imageInfoCacheMisses++;
+    }
+
+    private void increaseEntry(Map map, Object key) {
+        Integer v = (Integer)map.get(key);
+        if (v == null) {
+            v = new Integer(1);
+        } else {
+            v = new Integer(v.intValue() + 1);
+        }
+        map.put(key, v);
+    }
+
+    /** {@inheritDoc} */
+    public void cacheHitImage(ImageKey key) {
+        imageCacheHits++;
+        if (imageCacheHitMap != null) {
+            increaseEntry(imageCacheHitMap, key);
+        }
+    }
+    
+    /** {@inheritDoc} */
+    public void cacheMissImage(ImageKey key) {
+        imageCacheMisses++;
+        if (imageCacheMissMap != null) {
+            increaseEntry(imageCacheMissMap, key);
+        }
+    }
+
+    /**
+     * Returns the number of times an invalid URI is tried.
+     * @return the number of times an invalid URI is tried.
+     */
+    public int getInvalidHits() {
+        return invalidHits;
+    }
+
+    /**
+     * Returns the number of cache hits for ImageInfo instances.
+     * @return the number of cache hits for ImageInfo instances.
+     */
+    public int getImageInfoCacheHits() {
+        return imageInfoCacheHits;
+    }
+
+    /**
+     * Returns the number of cache misses for ImageInfo instances.
+     * @return the number of cache misses for ImageInfo instances.
+     */
+    public int getImageInfoCacheMisses() {
+        return imageInfoCacheMisses;
+    }
+
+    /**
+     * Returns the number of cache hits for Image instances.
+     * @return the number of cache hits for Image instances.
+     */
+    public int getImageCacheHits() {
+        return imageCacheHits;
+    }
+
+    /**
+     * Returns the number of cache misses for Image instances.
+     * @return the number of cache misses for Image instances.
+     */
+    public int getImageCacheMisses() {
+        return imageCacheMisses;
+    }
+
+    /**
+     * Returns a Map<ImageKey, Integer> with the number of cache hits.
+     * @return a Map<ImageKey, Integer> with the number of cache hits
+     */
+    public Map getImageCacheHitMap() {
+        return Collections.unmodifiableMap(imageCacheHitMap);
+    }
+
+    /**
+     * Returns a Map<ImageKey, Integer> with the number of cache misses.
+     * @return a Map<ImageKey, Integer> with the number of cache misses
+     */
+    public Map getImageCacheMissMap() {
+        return Collections.unmodifiableMap(imageCacheMissMap);
+    }
+    
+}
\ No newline at end of file

Propchange: xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/cache/ImageCacheStatistics.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/cache/ImageCacheStatistics.java
------------------------------------------------------------------------------
    svn:keywords = Id

Added: xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/cache/ImageKey.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/cache/ImageKey.java?rev=600870&view=auto
==============================================================================
--- xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/cache/ImageKey.java (added)
+++ xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/cache/ImageKey.java Tue Dec  4 02:27:51 2007
@@ -0,0 +1,83 @@
+/*
+ * 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.image2.cache;
+
+import org.apache.fop.image2.ImageFlavor;
+
+/**
+ * Key class for Image instances in the cache.
+ */
+public class ImageKey {
+    
+    private String uri;
+    private ImageFlavor flavor;
+    
+    /**
+     * Main constructor.
+     * @param uri the original URI
+     * @param flavor the image flavor
+     */
+    public ImageKey(String uri, ImageFlavor flavor) {
+        if (uri == null) {
+            throw new NullPointerException("URI must not be null");
+        }
+        if (flavor == null) {
+            throw new NullPointerException("flavor must not be null");
+        }
+        this.uri = uri;
+        this.flavor = flavor;
+    }
+
+    /** {@inheritDoc} */
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((flavor == null) ? 0 : flavor.hashCode());
+        result = prime * result + ((uri == null) ? 0 : uri.hashCode());
+        return result;
+    }
+
+    /** {@inheritDoc} */
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        final ImageKey other = (ImageKey)obj;
+        if (!uri.equals(other.uri)) {
+            return false;
+        }
+        if (!flavor.equals(other.flavor)) {
+            return false;
+        }
+        return true;
+    }
+
+    /** {@inheritDoc} */
+    public String toString() {
+        return uri + " (" + flavor + ")";
+    }
+    
+}
\ No newline at end of file

Propchange: xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/cache/ImageKey.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/cache/ImageKey.java
------------------------------------------------------------------------------
    svn:keywords = Id

Modified: xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/impl/AbstractImageLoader.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/impl/AbstractImageLoader.java?rev=600870&r1=600869&r2=600870&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/impl/AbstractImageLoader.java (original)
+++ xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/impl/AbstractImageLoader.java Tue Dec  4 02:27:51 2007
@@ -24,6 +24,7 @@
 import org.apache.fop.image2.Image;
 import org.apache.fop.image2.ImageException;
 import org.apache.fop.image2.ImageInfo;
+import org.apache.fop.image2.ImageSessionContext;
 import org.apache.fop.image2.spi.ImageLoader;
 
 /**
@@ -32,8 +33,9 @@
 public abstract class AbstractImageLoader implements ImageLoader {
 
     /** {@inheritDoc} */ 
-    public Image loadImage(ImageInfo info) throws ImageException, IOException {
-        return loadImage(info, null);
+    public Image loadImage(ImageInfo info, ImageSessionContext session)
+                throws ImageException, IOException {
+        return loadImage(info, null, session);
     }
 
     /** {@inheritDoc} */

Added: xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/impl/AbstractImageSessionContext.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/impl/AbstractImageSessionContext.java?rev=600870&view=auto
==============================================================================
--- xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/impl/AbstractImageSessionContext.java (added)
+++ xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/impl/AbstractImageSessionContext.java Tue Dec  4 02:27:51 2007
@@ -0,0 +1,226 @@
+/*
+ * 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.image2.impl;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import javax.imageio.ImageIO;
+import javax.imageio.stream.ImageInputStream;
+import javax.xml.transform.Source;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamSource;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.apache.fop.image2.ImageSessionContext;
+import org.apache.fop.image2.ImageSource;
+import org.apache.fop.image2.util.ImageUtil;
+import org.apache.fop.image2.util.SoftMapCache;
+
+/**
+ * Abstract base class for classes implementing ImageSessionContext. This class provides all the
+ * special treatment for Source creation, i.e. it provides optimized Source objects where possible.
+ */
+public abstract class AbstractImageSessionContext implements ImageSessionContext {
+
+    /** logger */
+    private static Log log = LogFactory.getLog(AbstractImageSessionContext.class);
+
+    /**
+     * Attempts to resolve the given URI.
+     * @param uri URI to access
+     * @return A {@link javax.xml.transform.Source} object, or null if the URI
+     * cannot be resolved. 
+     */
+    protected abstract Source resolveURI(String uri);
+
+    /** {@inheritDoc} */
+    public Source newSource(String uri) {
+        Source source = resolveURI(uri);
+        if (source == null) {
+            if (log.isDebugEnabled()) {
+                log.debug("URI could not be resolved: " + uri);
+            }
+            return null;
+        }
+        if (!(source instanceof StreamSource)) {
+            //Return any non-stream Sources and let the ImageLoaders deal with them
+            return source;
+        }
+        
+        ImageSource imageSource = null;
+        
+        String resolvedURI = source.getSystemId();
+        URL url;
+        try {
+            url = new URL(resolvedURI);
+        } catch (MalformedURLException e) {
+            url = null;
+        } 
+        File f = FileUtils.toFile(url);
+        if (f != null) {
+            boolean directFileAccess = true;
+            InputStream in = null;
+            if (source instanceof StreamSource) {
+                StreamSource streamSource = (StreamSource)source; 
+                in = streamSource.getInputStream();
+                in = ImageUtil.decorateMarkSupported(in);
+                try {
+                    if (ImageUtil.isGZIPCompressed(in)) {
+                        //GZIPped stream are not seekable, so buffer/cache like other URLs
+                        directFileAccess = false;
+                    }
+                } catch (IOException ioe) {
+                    log.error("Error while checking the InputStream for GZIP compression."
+                            + " Could not load image from system identifier '"
+                            + source.getSystemId() + "' (" + ioe.getMessage() + ")");
+                    return null;
+                }
+            }
+            
+            if (directFileAccess) {
+                //Close as the file is reopened in a more optimal way
+                IOUtils.closeQuietly(in);
+                try {
+                    //We let the OS' file system cache do the caching for us
+                    //--> lower Java memory consumption, probably no speed loss
+                    imageSource = new ImageSource(ImageIO.createImageInputStream(f),
+                            resolvedURI, true);
+                } catch (IOException ioe) {
+                    log.error("Unable to create ImageInputStream for local file"
+                            + " from system identifier '"
+                            + source.getSystemId() + "' (" + ioe.getMessage() + ")");
+                }
+            }
+        }
+        
+        if (imageSource == null) {
+            // Got a valid source, obtain an InputStream from it
+            InputStream in = null;
+            if (source instanceof StreamSource) {
+                StreamSource ssrc = (StreamSource)source;
+                if (ssrc.getReader() != null && ssrc.getInputStream() == null) {
+                    //We don't handle Reader instances here so return the Source unchanged
+                    return ssrc;
+                }
+                in = ssrc.getInputStream();
+            }
+            if (in == null && url != null) {
+                try {
+                    in = url.openStream();
+                } catch (Exception ex) {
+                    log.error("Unable to obtain stream from system identifier '" 
+                        + source.getSystemId() + "'");
+                }
+            }
+            if (in == null) {
+                log.error("The Source that was returned from URI resolution didn't contain"
+                        + " an InputStream for URI: " + uri);
+                return null;
+            }
+
+            try {
+                //Buffer and uncompress if necessary
+                in = ImageUtil.autoDecorateInputStream(in);
+                imageSource = new ImageSource(
+                        ImageIO.createImageInputStream(in), source.getSystemId(), false);
+            } catch (IOException ioe) {
+                log.error("Unable to create ImageInputStream for InputStream"
+                        + " from system identifier '"
+                        + source.getSystemId() + "' (" + ioe.getMessage() + ")");
+            }
+        }
+        return imageSource;
+    }
+    
+    private SoftMapCache sessionSources = new SoftMapCache(false); //no need for synchronization
+    
+    /** {@inheritDoc} */
+    public Source getSource(String uri) {
+        return (Source)sessionSources.remove(uri);
+    }
+    
+    /** {@inheritDoc} */
+    public Source needSource(String uri) throws FileNotFoundException {
+        Source src = getSource(uri);
+        if (src == null) {
+            log.debug("Creating new Source for " + uri);
+            src = newSource(uri);
+            if (src == null) {
+                throw new FileNotFoundException("Image not found: " + uri);
+            }
+        } else {
+            log.debug("Reusing Source for " + uri);
+        }
+        log.debug("  --> " + src);
+        log.debug("  --> " + Thread.currentThread().getName() + " " + Thread.currentThread());
+        return src;
+    }
+    
+    /** {@inheritDoc} */
+    public void returnSource(String uri, Source src) {
+        //Safety check to make sure the Preloaders behave
+        ImageInputStream in = ImageUtil.getImageInputStream(src);
+        try {
+            if (in != null && in.getStreamPosition() != 0) {
+                throw new IllegalStateException("ImageInputStream is not reset for: " + uri);
+            }
+        } catch (IOException ioe) {
+            //Ignore exception
+            ImageUtil.closeQuietly(src);
+        }
+        
+        if (isReusable(src)) {
+            //Only return the Source if it's reusable
+            log.debug("Returning Source for " + uri);
+            sessionSources.put(uri, src);
+        } else {
+            //Otherwise, try to close if possible and forget about it
+            ImageUtil.closeQuietly(src);
+        }
+    }
+    
+    /**
+     * Indicates whether a Source is reusable. A Source object is reusable if it's an
+     * {@link ImageSource} (containing an {@link ImageInputStream}) or a {@link DOMSource}.
+     * @param src the Source object
+     * @return true if the Source is reusable
+     */
+    protected boolean isReusable(Source src) {
+        if (src instanceof ImageSource) {
+            ImageSource is = (ImageSource)src;
+            if (is.getImageInputStream() != null) {
+                return true;
+            }
+        }
+        if (src instanceof DOMSource) {
+            return true;
+        }
+        return false;
+    }
+}

Propchange: xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/impl/AbstractImageSessionContext.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/impl/AbstractImageSessionContext.java
------------------------------------------------------------------------------
    svn:keywords = Id

Modified: xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/impl/ImageGraphics2D.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/impl/ImageGraphics2D.java?rev=600870&r1=600869&r2=600870&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/impl/ImageGraphics2D.java (original)
+++ xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/impl/ImageGraphics2D.java Tue Dec  4 02:27:51 2007
@@ -45,6 +45,11 @@
         return ImageFlavor.GRAPHICS2D;
     }
 
+    /** {@inheritDoc} */
+    public boolean isCacheable() {
+        return true;
+    }
+    
     /**
      * Returns the contained Graphics2DImagePainter instance.
      * @return the image painter

Modified: xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/impl/ImageLoaderEPS.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/impl/ImageLoaderEPS.java?rev=600870&r1=600869&r2=600870&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/impl/ImageLoaderEPS.java (original)
+++ xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/impl/ImageLoaderEPS.java Tue Dec  4 02:27:51 2007
@@ -23,6 +23,8 @@
 import java.io.InputStream;
 import java.util.Map;
 
+import javax.xml.transform.Source;
+
 import org.apache.xmlgraphics.util.io.SubInputStream;
 
 import org.apache.fop.apps.MimeConstants;
@@ -30,6 +32,7 @@
 import org.apache.fop.image2.ImageException;
 import org.apache.fop.image2.ImageFlavor;
 import org.apache.fop.image2.ImageInfo;
+import org.apache.fop.image2.ImageSessionContext;
 import org.apache.fop.image2.util.ImageUtil;
 
 /**
@@ -49,12 +52,15 @@
     }
 
     /** {@inheritDoc} */
-    public Image loadImage(ImageInfo info, Map hints) throws ImageException, IOException {
+    public Image loadImage(ImageInfo info, Map hints, ImageSessionContext session)
+                throws ImageException, IOException {
         if (!MimeConstants.MIME_EPS.equals(info.getMimeType())) {
             throw new IllegalArgumentException(
                     "ImageInfo must be from a image with MIME type: " + MimeConstants.MIME_EPS);
         }
-        InputStream in = ImageUtil.needInputStream(info.getSource());
+        Source src = session.needSource(info.getOriginalURI());
+        InputStream in = ImageUtil.needInputStream(src);
+        ImageUtil.removeStreams(src); //so others cannot close them, we take them over
 
         PreloaderEPS.EPSBinaryFileHeader binaryHeader;
         binaryHeader = (PreloaderEPS.EPSBinaryFileHeader)info.getCustomObjects().get(

Modified: xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/impl/ImageLoaderRaw.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/impl/ImageLoaderRaw.java?rev=600870&r1=600869&r2=600870&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/impl/ImageLoaderRaw.java (original)
+++ xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/impl/ImageLoaderRaw.java Tue Dec  4 02:27:51 2007
@@ -22,10 +22,14 @@
 import java.io.IOException;
 import java.util.Map;
 
+import javax.xml.transform.Source;
+
 import org.apache.fop.image2.Image;
 import org.apache.fop.image2.ImageException;
 import org.apache.fop.image2.ImageFlavor;
 import org.apache.fop.image2.ImageInfo;
+import org.apache.fop.image2.ImageSessionContext;
+import org.apache.fop.image2.util.ImageUtil;
 
 /**
  * ImageLoader for formats consumed "raw" (undecoded). Provides a raw/undecoded stream.
@@ -50,12 +54,15 @@
     }
 
     /** {@inheritDoc} */
-    public Image loadImage(ImageInfo info, Map hints) throws ImageException, IOException {
+    public Image loadImage(ImageInfo info, Map hints, ImageSessionContext session)
+                throws ImageException, IOException {
         if (!this.mime.equals(info.getMimeType())) {
             throw new IllegalArgumentException(
                     "ImageInfo must be from a image with MIME type: " + this.mime);
         }
-        ImageRawStream rawImage = new ImageRawStream(info, getTargetFlavor());
+        Source src = session.needSource(info.getOriginalURI());
+        ImageRawStream rawImage = new ImageRawStream(info, getTargetFlavor(),
+                ImageUtil.needInputStream(src));
         return rawImage;
     }
 

Modified: xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/impl/ImageLoaderRawJPEG.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/impl/ImageLoaderRawJPEG.java?rev=600870&r1=600869&r2=600870&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/impl/ImageLoaderRawJPEG.java (original)
+++ xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/impl/ImageLoaderRawJPEG.java Tue Dec  4 02:27:51 2007
@@ -25,6 +25,7 @@
 import java.util.Map;
 
 import javax.imageio.stream.ImageInputStream;
+import javax.xml.transform.Source;
 
 import org.apache.commons.io.output.ByteArrayOutputStream;
 import org.apache.commons.logging.Log;
@@ -35,6 +36,7 @@
 import org.apache.fop.image2.ImageException;
 import org.apache.fop.image2.ImageFlavor;
 import org.apache.fop.image2.ImageInfo;
+import org.apache.fop.image2.ImageSessionContext;
 import org.apache.fop.image2.util.ImageUtil;
 import org.apache.fop.util.CMYKColorSpace;
 
@@ -59,7 +61,8 @@
     }
 
     /** {@inheritDoc} */
-    public Image loadImage(ImageInfo info, Map hints) throws ImageException, IOException {
+    public Image loadImage(ImageInfo info, Map hints, ImageSessionContext session)
+                throws ImageException, IOException {
         if (!MimeConstants.MIME_JPEG.equals(info.getMimeType())) {
             throw new IllegalArgumentException("ImageInfo must be from a image with MIME type: "
                     + MimeConstants.MIME_JPEG);
@@ -70,14 +73,17 @@
         int sofType = 0;
         ByteArrayOutputStream iccStream = null;
         
-        ImageInputStream in = ImageUtil.needImageInputStream(info.getSource());
+        Source src = session.needSource(info.getOriginalURI());
+        ImageInputStream in = ImageUtil.needImageInputStream(src);
         in.mark();
         try {
             outer:
             while (true) {
                 int reclen;
                 int segID = readMarkerSegment(in);
-                log.debug("Seg Marker: " + Integer.toHexString(segID));
+                if (log.isDebugEnabled()) {
+                    log.debug("Seg Marker: " + Integer.toHexString(segID));
+                }
                 switch (segID) {
                 case EOI:
                     log.debug("EOI found. Stopping.");
@@ -191,7 +197,7 @@
         }
 
         ImageRawJPEG rawImage = new ImageRawJPEG(info,
-                ImageUtil.needInputStream(info.getSource()),
+                ImageUtil.needInputStream(src),
                 sofType, colorSpace, iccProfile, invertImage);
         return rawImage;
     }

Modified: xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/impl/ImageRawJPEG.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/impl/ImageRawJPEG.java?rev=600870&r1=600869&r2=600870&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/impl/ImageRawJPEG.java (original)
+++ xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/image2/impl/ImageRawJPEG.java Tue Dec  4 02:27:51 2007
@@ -47,7 +47,7 @@
      */
     public ImageRawJPEG(ImageInfo info, java.io.InputStream in,
                 int sofType, ColorSpace colorSpace, ICC_Profile iccProfile, boolean invertImage) {
-        super(info, ImageFlavor.RAW_EPS, in);
+        super(info, ImageFlavor.RAW_JPEG, in);
         this.sofType = sofType;
         this.colorSpace = colorSpace;
         this.iccProfile = iccProfile;



---------------------------------------------------------------------
To unsubscribe, e-mail: fop-commits-unsubscribe@xmlgraphics.apache.org
For additional commands, e-mail: fop-commits-help@xmlgraphics.apache.org