You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@xmlgraphics.apache.org by je...@apache.org on 2010/03/18 09:26:31 UTC

svn commit: r924666 - in /xmlgraphics/commons/trunk: src/documentation/content/xdocs/ src/java/org/apache/xmlgraphics/image/loader/ src/java/org/apache/xmlgraphics/image/loader/impl/ src/java/org/apache/xmlgraphics/image/loader/impl/imageio/ src/java/o...

Author: jeremias
Date: Thu Mar 18 08:26:30 2010
New Revision: 924666

URL: http://svn.apache.org/viewvc?rev=924666&view=rev
Log:
Enhancements to the image loading framework:
- Add support for configurable additional penalties for preloader, loader and converter plug-ins in the ImageImplRegistry (in addition to the hard-coded penalties). (See docs for details)
- Add image manager and image session context to hints map so implementations can use these objects.
- Deprecated usage penalty on ImageLoaderFactory due to a redundancy with the usage penalty on ImageLoader.
- Additional logging on raw CCITT loader factory

Added:
    xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/util/Penalty.java   (with props)
    xmlgraphics/commons/trunk/test/java/org/apache/xmlgraphics/image/loader/PenaltyTestCase.java   (with props)
    xmlgraphics/commons/trunk/test/java/org/apache/xmlgraphics/image/loader/PipelineFactoryTestCase.java   (with props)
    xmlgraphics/commons/trunk/test/java/org/apache/xmlgraphics/image/loader/mocks/
    xmlgraphics/commons/trunk/test/java/org/apache/xmlgraphics/image/loader/mocks/MockImageLoaderFactoryTIFF.java   (with props)
Modified:
    xmlgraphics/commons/trunk/src/documentation/content/xdocs/image-loader.xml
    xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/ImageManager.java
    xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/ImageProcessingHints.java
    xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/AbstractImageLoader.java
    xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/AbstractImageLoaderFactory.java
    xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/CompositeImageLoader.java
    xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/ImageLoaderFactoryEPS.java
    xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/ImageLoaderFactoryInternalTIFF.java
    xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/ImageLoaderFactoryRaw.java
    xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/ImageLoaderFactoryRawCCITTFax.java
    xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/ImageLoaderInternalTIFF.java
    xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/imageio/ImageLoaderFactoryImageIO.java
    xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/pipeline/ImageConversionEdge.java
    xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/pipeline/ImageProviderPipeline.java
    xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/pipeline/PipelineFactory.java
    xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/spi/ImageConverter.java
    xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/spi/ImageImplRegistry.java
    xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/spi/ImageLoader.java
    xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/spi/ImageLoaderFactory.java
    xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/util/ImageUtil.java
    xmlgraphics/commons/trunk/test/java/org/apache/xmlgraphics/image/loader/MockImageContext.java

Modified: xmlgraphics/commons/trunk/src/documentation/content/xdocs/image-loader.xml
URL: http://svn.apache.org/viewvc/xmlgraphics/commons/trunk/src/documentation/content/xdocs/image-loader.xml?rev=924666&r1=924665&r2=924666&view=diff
==============================================================================
--- xmlgraphics/commons/trunk/src/documentation/content/xdocs/image-loader.xml (original)
+++ xmlgraphics/commons/trunk/src/documentation/content/xdocs/image-loader.xml Thu Mar 18 08:26:30 2010
@@ -317,5 +317,44 @@ import org.apache.xmlgraphics.image.load
         </p>
       </section>
     </section>
+    <section id="customization">
+      <title>Customization</title>
+      <section id="source-reuse">
+        <title>Disabling Source Re-use</title>
+        <p>
+          By default, the Source object being used during the pre-loading stage is re-used when
+          the image is fully loaded later (assuming an ImageSessionContext is used that descends
+          from AbstractImageSessionContext). That means that a stream is only opened once and
+          the image loading framework tries to re-wind the stream when it has to re-read portions
+          of the stream when loading the complete image.
+        </p>
+        <p>
+          In some situations, this behavior may be undesired. Therefore, it can be disabled
+          through a system property 
+          (<code>org.apache.xmlgraphics.image.loader.impl.AbstractImageSessionContext.no-source-reuse</code>).
+          Set it to "true" and that feature will be disabled.
+        </p>
+      </section>
+      <section id="plugin-penalties">
+        <title>Adjusting plug-in penalties</title>
+        <p>
+          Every image loader plug-in has a hard-coded usage penalty that influences which solution
+          is chosen if there are multiple possibilities to load an image. Sometimes, though, these
+          penalties need to be tweaked. The <code>ImageImplRegistry</code> (reachable through
+          <code>ImageManager.getRegistry()</code>) supports storing additional penalty values.
+          An example:
+        </p>
+        <source><![CDATA[ImageImplRegistry registry = imageManager.getRegistry();
+registry.setAdditionalPenalty(
+    "org.apache.xmlgraphics.image.loader.impl.ImageLoaderRawCCITTFax",
+    Penalty.toPenalty(10000));]]></source>
+        <p>
+          This increases the penalty for the raw CCITT loader significantly so it will only be
+          used if no other solutions exist. You can also set <code>Penalty.INFINITE_PENALTY</code>
+          to disable the plug-in altogether. Negative penalties are possible to promote a plug-in
+          but a negative penalty sum will be treated as zero penalty in most cases.
+        </p>
+      </section>
+    </section>
   </body>
 </document>

Modified: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/ImageManager.java
URL: http://svn.apache.org/viewvc/xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/ImageManager.java?rev=924666&r1=924665&r2=924666&view=diff
==============================================================================
--- xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/ImageManager.java (original)
+++ xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/ImageManager.java Thu Mar 18 08:26:30 2010
@@ -20,7 +20,6 @@
 package org.apache.xmlgraphics.image.loader;
 
 import java.io.IOException;
-import java.util.Collections;
 import java.util.Iterator;
 import java.util.Map;
 
@@ -35,6 +34,7 @@ import org.apache.xmlgraphics.image.load
 import org.apache.xmlgraphics.image.loader.spi.ImageImplRegistry;
 import org.apache.xmlgraphics.image.loader.spi.ImagePreloader;
 import org.apache.xmlgraphics.image.loader.util.ImageUtil;
+import org.apache.xmlgraphics.image.loader.util.Penalty;
 
 /**
  * ImageManager is the central starting point for image access.
@@ -45,7 +45,7 @@ public class ImageManager {
     protected static Log log = LogFactory.getLog(ImageManager.class);
 
     /** Holds all registered interface implementations for the image package */
-    private ImageImplRegistry registry = ImageImplRegistry.getDefaultInstance();
+    private ImageImplRegistry registry;
 
     /** Provides session-independent information */
     private ImageContext imageContext;
@@ -60,6 +60,16 @@ public class ImageManager {
      * @param context the session-independent context information
      */
     public ImageManager(ImageContext context) {
+        this(ImageImplRegistry.getDefaultInstance(), context);
+    }
+
+    /**
+     * Constructor for testing purposes.
+     * @param registry the implementation registry with all plug-ins
+     * @param context the session-independent context information
+     */
+    public ImageManager(ImageImplRegistry registry, ImageContext context) {
+        this.registry = registry;
         this.imageContext = context;
     }
 
@@ -171,6 +181,22 @@ public class ImageManager {
                 + uri);
     }
 
+    private Map prepareHints(Map hints, ImageSessionContext sessionContext) {
+        Map newHints = new java.util.HashMap();
+        if (hints != null) {
+            newHints.putAll(hints); //Copy in case an unmodifiable map is passed in
+        }
+        if (!newHints.containsKey(ImageProcessingHints.IMAGE_SESSION_CONTEXT)
+                && sessionContext != null) {
+            newHints.put(ImageProcessingHints.IMAGE_SESSION_CONTEXT, sessionContext);
+
+        }
+        if (!newHints.containsKey(ImageProcessingHints.IMAGE_MANAGER)) {
+            newHints.put(ImageProcessingHints.IMAGE_MANAGER, this);
+        }
+        return newHints;
+    }
+
     /**
      * Loads an image. The caller can indicate what kind of image flavor is requested. When this
      * method is called the code looks for a suitable ImageLoader and, if necessary, builds
@@ -192,9 +218,7 @@ public class ImageManager {
     public Image getImage(ImageInfo info, ImageFlavor flavor, Map hints,
                 ImageSessionContext session)
             throws ImageException, IOException {
-        if (hints == null) {
-            hints = Collections.EMPTY_MAP;
-        }
+        hints = prepareHints(hints, session);
 
         Image img = null;
         ImageProviderPipeline pipeline = getPipelineFactory().newImageConverterPipeline(
@@ -233,9 +257,7 @@ public class ImageManager {
     public Image getImage(ImageInfo info, ImageFlavor[] flavors, Map hints,
                         ImageSessionContext session)
                 throws ImageException, IOException {
-        if (hints == null) {
-            hints = Collections.EMPTY_MAP;
-        }
+        hints = prepareHints(hints, session);
 
         Image img = null;
         ImageProviderPipeline[] candidates = getPipelineFactory().determineCandidatePipelines(
@@ -309,9 +331,7 @@ public class ImageManager {
      */
     public Image convertImage(Image image, ImageFlavor[] flavors, Map hints)
                 throws ImageException, IOException {
-        if (hints == null) {
-            hints = Collections.EMPTY_MAP;
-        }
+        hints = prepareHints(hints, null);
         ImageInfo info = image.getInfo();
 
         Image img = null;
@@ -362,14 +382,27 @@ public class ImageManager {
         ImageProviderPipeline pipeline = null;
         int minPenalty = Integer.MAX_VALUE;
         int count = candidates.length;
+        if (log.isTraceEnabled()) {
+            log.trace("Candidate Pipelines:");
+            for (int i = 0; i < count; i++) {
+                if (candidates[i] == null) {
+                    continue;
+                }
+                log.trace("  " + i + ": "
+                        + candidates[i].getConversionPenalty(getRegistry()) + " for " + candidates[i]);
+            }
+        }
         for (int i = count - 1; i >= 0; i--) {
             if (candidates[i] == null) {
                 continue;
             }
-            int penalty = candidates[i].getConversionPenalty();
-            if (penalty <= minPenalty) {
+            Penalty penalty = candidates[i].getConversionPenalty(getRegistry());
+            if (penalty.isInfinitePenalty()) {
+                continue; //Exclude candidate on infinite penalty
+            }
+            if (penalty.getValue() <= minPenalty) {
                 pipeline = candidates[i];
-                minPenalty = penalty;
+                minPenalty = penalty.getValue();
             }
         }
         if (log.isDebugEnabled()) {

Modified: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/ImageProcessingHints.java
URL: http://svn.apache.org/viewvc/xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/ImageProcessingHints.java?rev=924666&r1=924665&r2=924666&view=diff
==============================================================================
--- xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/ImageProcessingHints.java (original)
+++ xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/ImageProcessingHints.java Thu Mar 18 08:26:30 2010
@@ -22,6 +22,7 @@ package org.apache.xmlgraphics.image.loa
 /**
  * This interface defines some standard hints to be used for image processing in this package.
  * They are provided for convenience. You can define your own hints as you like.
+ * Generally, consumers should not rely on the presence of any hint!
  */
 public interface ImageProcessingHints {
 
@@ -30,6 +31,22 @@ public interface ImageProcessingHints {
     /** Used to send a hint about the target resolution (of the final output format). */
     Object TARGET_RESOLUTION = "TARGET_RESOLUTION"; //Value: Number (unit dpi)
 
+    /**
+     * Used to pass in the {@link ImageSessionContext}. A consumer can use this to load embedded
+     * images over the same mechanism as the main image (ex. JPEG images referenced in an
+     * SVG image).
+     * @since 1.4
+     */
+    Object IMAGE_SESSION_CONTEXT = "IMAGE_SESSION_CONTEXT"; //Value: ImageSessionContext instance
+
+    /**
+     * Used to pass in the {@link ImageManager}. A consumer can use this to load embedded
+     * images over the same mechanism as the main image (ex. JPEG images referenced in an
+     * SVG image).
+     * @since 1.4
+     */
+    Object IMAGE_MANAGER = "IMAGE_MANAGER"; //Value: ImageManager instance
+
     /** Used to tell the image loader to ignore any color profile in the image. */
     Object IGNORE_COLOR_PROFILE = "IGNORE_COLOR_PROFILE"; //Value: Boolean
 

Modified: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/AbstractImageLoader.java
URL: http://svn.apache.org/viewvc/xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/AbstractImageLoader.java?rev=924666&r1=924665&r2=924666&view=diff
==============================================================================
--- xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/AbstractImageLoader.java (original)
+++ xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/AbstractImageLoader.java Thu Mar 18 08:26:30 2010
@@ -42,7 +42,7 @@ public abstract class AbstractImageLoade
 
     /** {@inheritDoc} */
     public int getUsagePenalty() {
-        return 0;
+        return NO_LOADING_PENALTY;
     }
 
     /**

Modified: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/AbstractImageLoaderFactory.java
URL: http://svn.apache.org/viewvc/xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/AbstractImageLoaderFactory.java?rev=924666&r1=924665&r2=924666&view=diff
==============================================================================
--- xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/AbstractImageLoaderFactory.java (original)
+++ xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/AbstractImageLoaderFactory.java Thu Mar 18 08:26:30 2010
@@ -19,7 +19,9 @@
 
 package org.apache.xmlgraphics.image.loader.impl;
 
+import org.apache.xmlgraphics.image.loader.ImageFlavor;
 import org.apache.xmlgraphics.image.loader.ImageInfo;
+import org.apache.xmlgraphics.image.loader.spi.ImageLoader;
 import org.apache.xmlgraphics.image.loader.spi.ImageLoaderFactory;
 
 /**
@@ -34,4 +36,14 @@ public abstract class AbstractImageLoade
         return true;
     }
 
+    /**
+     * {@inheritDoc}
+     * @deprecated Redundancy with {@link ImageLoader#getUsagePenalty()}
+     */
+    public int getUsagePenalty(String mime, ImageFlavor flavor) {
+        //Kept for compatibility
+        ImageLoader loader = newImageLoader(flavor);
+        return loader.getUsagePenalty();
+    }
+
 }

Modified: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/CompositeImageLoader.java
URL: http://svn.apache.org/viewvc/xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/CompositeImageLoader.java?rev=924666&r1=924665&r2=924666&view=diff
==============================================================================
--- xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/CompositeImageLoader.java (original)
+++ xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/CompositeImageLoader.java Thu Mar 18 08:26:30 2010
@@ -66,6 +66,15 @@ public class CompositeImageLoader extend
     }
 
     /** {@inheritDoc} */
+    public int getUsagePenalty() {
+        int maxPenalty = NO_LOADING_PENALTY;
+        for (int i = 1, c = loaders.length; i < c; i++) {
+            maxPenalty = Math.max(maxPenalty, loaders[i].getUsagePenalty());
+        }
+        return maxPenalty;
+    }
+
+    /** {@inheritDoc} */
     public Image loadImage(ImageInfo info, Map hints, ImageSessionContext session)
             throws ImageException, IOException {
         ImageException firstException = null;

Modified: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/ImageLoaderFactoryEPS.java
URL: http://svn.apache.org/viewvc/xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/ImageLoaderFactoryEPS.java?rev=924666&r1=924665&r2=924666&view=diff
==============================================================================
--- xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/ImageLoaderFactoryEPS.java (original)
+++ xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/ImageLoaderFactoryEPS.java Thu Mar 18 08:26:30 2010
@@ -54,11 +54,6 @@ public class ImageLoaderFactoryEPS exten
     }
 
     /** {@inheritDoc} */
-    public int getUsagePenalty(String mime, ImageFlavor flavor) {
-        return 0;
-    }
-
-    /** {@inheritDoc} */
     public boolean isAvailable() {
         return true;
     }

Modified: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/ImageLoaderFactoryInternalTIFF.java
URL: http://svn.apache.org/viewvc/xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/ImageLoaderFactoryInternalTIFF.java?rev=924666&r1=924665&r2=924666&view=diff
==============================================================================
--- xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/ImageLoaderFactoryInternalTIFF.java (original)
+++ xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/ImageLoaderFactoryInternalTIFF.java Thu Mar 18 08:26:30 2010
@@ -54,11 +54,6 @@ public class ImageLoaderFactoryInternalT
     }
 
     /** {@inheritDoc} */
-    public int getUsagePenalty(String mime, ImageFlavor flavor) {
-        return 10000; //Provide this only as a fallback
-    }
-
-    /** {@inheritDoc} */
     public boolean isAvailable() {
         return true;
     }

Modified: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/ImageLoaderFactoryRaw.java
URL: http://svn.apache.org/viewvc/xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/ImageLoaderFactoryRaw.java?rev=924666&r1=924665&r2=924666&view=diff
==============================================================================
--- xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/ImageLoaderFactoryRaw.java (original)
+++ xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/ImageLoaderFactoryRaw.java Thu Mar 18 08:26:30 2010
@@ -87,11 +87,6 @@ public class ImageLoaderFactoryRaw exten
     }
 
     /** {@inheritDoc} */
-    public int getUsagePenalty(String mime, ImageFlavor flavor) {
-        return 0;
-    }
-
-    /** {@inheritDoc} */
     public boolean isAvailable() {
         return true;
     }

Modified: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/ImageLoaderFactoryRawCCITTFax.java
URL: http://svn.apache.org/viewvc/xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/ImageLoaderFactoryRawCCITTFax.java?rev=924666&r1=924665&r2=924666&view=diff
==============================================================================
--- xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/ImageLoaderFactoryRawCCITTFax.java (original)
+++ xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/ImageLoaderFactoryRawCCITTFax.java Thu Mar 18 08:26:30 2010
@@ -19,6 +19,9 @@
 
 package org.apache.xmlgraphics.image.loader.impl;
 
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
 import org.apache.xmlgraphics.image.codec.tiff.TIFFImage;
 import org.apache.xmlgraphics.image.loader.ImageFlavor;
 import org.apache.xmlgraphics.image.loader.ImageInfo;
@@ -30,6 +33,9 @@ import org.apache.xmlgraphics.util.MimeC
  */
 public class ImageLoaderFactoryRawCCITTFax extends AbstractImageLoaderFactory {
 
+    /** logger */
+    private transient Log log = LogFactory.getLog(ImageLoaderFactoryRawCCITTFax.class);
+
     private static final String[] MIMES = new String[] {
         MimeConstants.MIME_TIFF};
 
@@ -80,11 +86,6 @@ public class ImageLoaderFactoryRawCCITTF
     }
 
     /** {@inheritDoc} */
-    public int getUsagePenalty(String mime, ImageFlavor flavor) {
-        return 0;
-    }
-
-    /** {@inheritDoc} */
     public boolean isAvailable() {
         return true;
     }
@@ -94,6 +95,7 @@ public class ImageLoaderFactoryRawCCITTF
         Boolean tiled = (Boolean)imageInfo.getCustomObjects().get("TIFF_TILED");
         if (Boolean.TRUE.equals(tiled)) {
             //We don't support tiled images
+            log.trace("Raw CCITT loading not supported for tiled TIFF image");
             return false;
         }
         Integer compression = (Integer)imageInfo.getCustomObjects().get("TIFF_COMPRESSION");
@@ -105,7 +107,11 @@ public class ImageLoaderFactoryRawCCITTF
         case TIFFImage.COMP_FAX_G3_2D:
         case TIFFImage.COMP_FAX_G4_2D:
             Integer stripCount = (Integer)imageInfo.getCustomObjects().get("TIFF_STRIP_COUNT");
-            return (stripCount != null && stripCount.intValue() == 1);
+            boolean supported = (stripCount != null && stripCount.intValue() == 1);
+            if (!supported) {
+                log.trace("Raw CCITT loading not supported for multi-strip TIFF image");
+            }
+            return supported;
         default:
             return false;
         }

Modified: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/ImageLoaderInternalTIFF.java
URL: http://svn.apache.org/viewvc/xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/ImageLoaderInternalTIFF.java?rev=924666&r1=924665&r2=924666&view=diff
==============================================================================
--- xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/ImageLoaderInternalTIFF.java (original)
+++ xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/ImageLoaderInternalTIFF.java Thu Mar 18 08:26:30 2010
@@ -35,8 +35,6 @@ import org.apache.xmlgraphics.image.load
 import org.apache.xmlgraphics.image.loader.ImageFlavor;
 import org.apache.xmlgraphics.image.loader.ImageInfo;
 import org.apache.xmlgraphics.image.loader.ImageSessionContext;
-import org.apache.xmlgraphics.image.loader.impl.AbstractImageLoader;
-import org.apache.xmlgraphics.image.loader.impl.ImageRendered;
 import org.apache.xmlgraphics.image.loader.util.ImageUtil;
 
 /**
@@ -74,4 +72,9 @@ public class ImageLoaderInternalTIFF ext
         return new ImageRendered(info, img, null);
     }
 
+    /** {@inheritDoc} */
+    public int getUsagePenalty() {
+        return 1000; //Provide this only as a fallback
+    }
+
 }

Modified: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/imageio/ImageLoaderFactoryImageIO.java
URL: http://svn.apache.org/viewvc/xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/imageio/ImageLoaderFactoryImageIO.java?rev=924666&r1=924665&r2=924666&view=diff
==============================================================================
--- xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/imageio/ImageLoaderFactoryImageIO.java (original)
+++ xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/imageio/ImageLoaderFactoryImageIO.java Thu Mar 18 08:26:30 2010
@@ -50,11 +50,6 @@ public class ImageLoaderFactoryImageIO e
     }
 
     /** {@inheritDoc} */
-    public int getUsagePenalty(String mime, ImageFlavor flavor) {
-        return 0;
-    }
-
-    /** {@inheritDoc} */
     public boolean isAvailable() {
         return (getSupportedMIMETypes().length > 0);
     }

Modified: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/pipeline/ImageConversionEdge.java
URL: http://svn.apache.org/viewvc/xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/pipeline/ImageConversionEdge.java?rev=924666&r1=924665&r2=924666&view=diff
==============================================================================
--- xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/pipeline/ImageConversionEdge.java (original)
+++ xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/pipeline/ImageConversionEdge.java Thu Mar 18 08:26:30 2010
@@ -20,6 +20,7 @@
 package org.apache.xmlgraphics.image.loader.pipeline;
 
 import org.apache.xmlgraphics.image.loader.spi.ImageConverter;
+import org.apache.xmlgraphics.image.loader.util.Penalty;
 import org.apache.xmlgraphics.util.dijkstra.Edge;
 import org.apache.xmlgraphics.util.dijkstra.Vertex;
 
@@ -27,21 +28,23 @@ import org.apache.xmlgraphics.util.dijks
  * Represents an image conversion. The class basically wraps an ImageConverter so it can be
  * used with Dijkstra's shortest route algorithm to build image conversion pipelines.
  */
-public class ImageConversionEdge implements Edge {
+class ImageConversionEdge implements Edge {
 
     private ImageRepresentation source;
     private ImageRepresentation target;
     private ImageConverter converter;
+    private int penalty;
 
     /**
      * Main constructor.
      * @param converter the image converter
+     * @param penalty the penalty for this edge
      */
-    public ImageConversionEdge(
-            ImageConverter converter) {
+    public ImageConversionEdge(ImageConverter converter, Penalty penalty) {
         this.converter = converter;
         this.source = new ImageRepresentation(converter.getSourceFlavor());
         this.target = new ImageRepresentation(converter.getTargetFlavor());
+        this.penalty = Math.max(0, penalty.getValue());
     }
 
     /**
@@ -54,7 +57,7 @@ public class ImageConversionEdge impleme
 
     /** {@inheritDoc} */
     public int getPenalty() {
-        return getImageConverter().getConversionPenalty();
+        return this.penalty;
     }
 
     /** {@inheritDoc} */

Modified: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/pipeline/ImageProviderPipeline.java
URL: http://svn.apache.org/viewvc/xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/pipeline/ImageProviderPipeline.java?rev=924666&r1=924665&r2=924666&view=diff
==============================================================================
--- xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/pipeline/ImageProviderPipeline.java (original)
+++ xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/pipeline/ImageProviderPipeline.java Thu Mar 18 08:26:30 2010
@@ -39,7 +39,9 @@ import org.apache.xmlgraphics.image.load
 import org.apache.xmlgraphics.image.loader.cache.ImageCache;
 import org.apache.xmlgraphics.image.loader.impl.ImageRawStream;
 import org.apache.xmlgraphics.image.loader.spi.ImageConverter;
+import org.apache.xmlgraphics.image.loader.spi.ImageImplRegistry;
 import org.apache.xmlgraphics.image.loader.spi.ImageLoader;
+import org.apache.xmlgraphics.image.loader.util.Penalty;
 
 /**
  * Represents a pipeline of ImageConverters with an ImageLoader at the beginning of the
@@ -272,14 +274,32 @@ public class ImageProviderPipeline {
      * @return the overall penalty (a non-negative integer)
      */
     public int getConversionPenalty() {
-        int penalty = 0;
+        return getConversionPenalty(null).getValue();
+    }
+
+    /**
+     * Returns the overall conversion penalty for the pipeline. This can be used to choose among
+     * different possible pipelines.
+     * @param registry the image implementation registry
+     * @return the overall penalty (a non-negative integer)
+     */
+    public Penalty getConversionPenalty(ImageImplRegistry registry) {
+        Penalty penalty = Penalty.ZERO_PENALTY;
         if (loader != null) {
-            penalty += loader.getUsagePenalty();
+            penalty = penalty.add(loader.getUsagePenalty());
+            if (registry != null) {
+                penalty = penalty.add(
+                        registry.getAdditionalPenalty(loader.getClass().getName()));
+            }
         }
         Iterator iter = converters.iterator();
         while (iter.hasNext()) {
             ImageConverter converter = (ImageConverter)iter.next();
-            penalty += converter.getConversionPenalty();
+            penalty = penalty.add(converter.getConversionPenalty());
+            if (registry != null) {
+                penalty = penalty.add(
+                        registry.getAdditionalPenalty(converter.getClass().getName()));
+            }
         }
         return penalty;
     }

Modified: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/pipeline/PipelineFactory.java
URL: http://svn.apache.org/viewvc/xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/pipeline/PipelineFactory.java?rev=924666&r1=924665&r2=924666&view=diff
==============================================================================
--- xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/pipeline/PipelineFactory.java (original)
+++ xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/pipeline/PipelineFactory.java Thu Mar 18 08:26:30 2010
@@ -19,8 +19,8 @@
 
 package org.apache.xmlgraphics.image.loader.pipeline;
 
+import java.util.Arrays;
 import java.util.Collection;
-import java.util.Collections;
 import java.util.Comparator;
 import java.util.Iterator;
 import java.util.LinkedList;
@@ -38,6 +38,7 @@ import org.apache.xmlgraphics.image.load
 import org.apache.xmlgraphics.image.loader.spi.ImageImplRegistry;
 import org.apache.xmlgraphics.image.loader.spi.ImageLoader;
 import org.apache.xmlgraphics.image.loader.spi.ImageLoaderFactory;
+import org.apache.xmlgraphics.image.loader.util.Penalty;
 import org.apache.xmlgraphics.util.dijkstra.DefaultEdgeDirectory;
 import org.apache.xmlgraphics.util.dijkstra.DijkstraAlgorithm;
 import org.apache.xmlgraphics.util.dijkstra.Vertex;
@@ -75,7 +76,10 @@ public class PipelineFactory {
             Iterator iter = converters.iterator();
             while (iter.hasNext()) {
                 ImageConverter converter = (ImageConverter)iter.next();
-                dir.addEdge(new ImageConversionEdge(converter));
+                Penalty penalty = Penalty.toPenalty(converter.getConversionPenalty());
+                penalty = penalty.add(
+                        registry.getAdditionalPenalty(converter.getClass().getName()));
+                dir.addEdge(new ImageConversionEdge(converter, penalty));
             }
 
             converterEdgeDirectoryVersion = registry.getImageConverterModifications();
@@ -109,9 +113,34 @@ public class PipelineFactory {
      */
     public ImageProviderPipeline newImageConverterPipeline(
                 ImageInfo imageInfo, ImageFlavor targetFlavor) {
+        ImageProviderPipeline[] candidates = determineCandidatePipelines(imageInfo, targetFlavor);
+
+        //Choose best pipeline
+        if (candidates.length > 0) {
+            Arrays.sort(candidates, new PipelineComparator());
+            ImageProviderPipeline pipeline = (ImageProviderPipeline)candidates[0];
+            if (pipeline != null && log.isDebugEnabled()) {
+                log.debug("Pipeline: " + pipeline
+                        + " with penalty " + pipeline.getConversionPenalty());
+            }
+            return pipeline;
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Determines all possible pipelines for the given image that can produce the requested
+     * target flavor.
+     * @param imageInfo the image information
+     * @param targetFlavor the target flavor
+     * @return the candidate pipelines
+     */
+    public ImageProviderPipeline[] determineCandidatePipelines(
+                ImageInfo imageInfo, ImageFlavor targetFlavor) {
         String originalMime = imageInfo.getMimeType();
         ImageImplRegistry registry = manager.getRegistry();
-        ImageProviderPipeline pipeline = null;
+        List candidates = new java.util.ArrayList();
 
         //Get snapshot to avoid concurrent modification problems (thread-safety)
         DefaultEdgeDirectory dir = getEdgeDirectory();
@@ -131,12 +160,13 @@ public class PipelineFactory {
                 }
                 loader = new CompositeImageLoader(loaders);
             }
-            pipeline = new ImageProviderPipeline(manager.getCache(), loader);
+            ImageProviderPipeline pipeline = new ImageProviderPipeline(manager.getCache(), loader);
+            candidates.add(pipeline);
         } else {
             //Need to use ImageConverters
             if (log.isTraceEnabled()) {
-                log.trace("No ImageLoaderFactory found that can load this format directly."
-                        + " Trying ImageConverters instead...");
+                log.trace("No ImageLoaderFactory found that can load this format ("
+                        + targetFlavor + ") directly. Trying ImageConverters instead...");
             }
 
             ImageRepresentation destination = new ImageRepresentation(targetFlavor);
@@ -144,14 +174,13 @@ public class PipelineFactory {
             // --> List of resulting flavors, possibly multiple loaders
             loaderFactories = registry.getImageLoaderFactories(originalMime);
             if (loaderFactories != null) {
-                List candidates = new java.util.ArrayList();
 
                 //Find best pipeline -> best loader
                 for (int i = 0, ci = loaderFactories.length; i < ci; i++) {
                     ImageLoaderFactory loaderFactory = loaderFactories[i];
                     ImageFlavor[] flavors = loaderFactory.getSupportedFlavors(originalMime);
                     for (int j = 0, cj = flavors.length; j < cj; j++) {
-                        pipeline = findPipeline(dir, flavors[j], destination);
+                        ImageProviderPipeline pipeline = findPipeline(dir, flavors[j], destination);
                         if (pipeline != null) {
                             ImageLoader loader = loaderFactory.newImageLoader(flavors[j]);
                             pipeline.setImageLoader(loader);
@@ -159,20 +188,13 @@ public class PipelineFactory {
                         }
                     }
                 }
-
-                Collections.sort(candidates, new PipelineComparator());
-                //Build final pipeline
-                if (candidates.size() > 0) {
-                    pipeline = (ImageProviderPipeline)candidates.get(0);
-                }
             }
         }
-        if (pipeline != null && log.isDebugEnabled()) {
-            log.debug("Pipeline: " + pipeline + " with penalty " + pipeline.getConversionPenalty());
-        }
-        return pipeline;
+        return (ImageProviderPipeline[])candidates.toArray(
+                new ImageProviderPipeline[candidates.size()]);
     }
 
+    /** Compares two pipelines based on their conversion penalty. */
     private static class PipelineComparator implements Comparator {
 
         public int compare(Object o1, Object o2) {
@@ -228,12 +250,21 @@ public class PipelineFactory {
      */
     public ImageProviderPipeline[] determineCandidatePipelines(ImageInfo imageInfo,
             ImageFlavor[] flavors) {
+        List candidates = new java.util.ArrayList();
         int count = flavors.length;
-        ImageProviderPipeline[] candidates = new ImageProviderPipeline[count];
         for (int i = 0; i < count; i++) {
-            candidates[i] = newImageConverterPipeline(imageInfo, flavors[i]);
+            //Find the best pipeline for each flavor
+            ImageProviderPipeline pipeline = newImageConverterPipeline(imageInfo, flavors[i]);
+            if (pipeline == null) {
+                continue; //No suitable pipeline found for flavor
+            }
+            Penalty p = pipeline.getConversionPenalty(this.manager.getRegistry());
+            if (!p.isInfinitePenalty()) {
+                candidates.add(pipeline);
+            }
         }
-        return candidates;
+        return (ImageProviderPipeline[])candidates.toArray(
+                new ImageProviderPipeline[candidates.size()]);
     }
 
     /**
@@ -245,12 +276,17 @@ public class PipelineFactory {
      */
     public ImageProviderPipeline[] determineCandidatePipelines(Image sourceImage,
             ImageFlavor[] flavors) {
+        List candidates = new java.util.ArrayList();
         int count = flavors.length;
-        ImageProviderPipeline[] candidates = new ImageProviderPipeline[count];
         for (int i = 0; i < count; i++) {
-            candidates[i] = newImageConverterPipeline(sourceImage, flavors[i]);
+            //Find the best pipeline for each flavor
+            ImageProviderPipeline pipeline = newImageConverterPipeline(sourceImage, flavors[i]);
+            if (pipeline != null) {
+                candidates.add(pipeline);
+            }
         }
-        return candidates;
+        return (ImageProviderPipeline[])candidates.toArray(
+                new ImageProviderPipeline[candidates.size()]);
     }
 
 

Modified: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/spi/ImageConverter.java
URL: http://svn.apache.org/viewvc/xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/spi/ImageConverter.java?rev=924666&r1=924665&r2=924666&view=diff
==============================================================================
--- xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/spi/ImageConverter.java (original)
+++ xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/spi/ImageConverter.java Thu Mar 18 08:26:30 2010
@@ -25,6 +25,7 @@ import java.util.Map;
 import org.apache.xmlgraphics.image.loader.Image;
 import org.apache.xmlgraphics.image.loader.ImageException;
 import org.apache.xmlgraphics.image.loader.ImageFlavor;
+import org.apache.xmlgraphics.image.loader.ImageInfo;
 
 /**
  * Defines an image converter that can convert one image representation into another.
@@ -40,6 +41,8 @@ public interface ImageConverter {
 
     /**
      * Converts an image into a different representation.
+     * <p> The new image returned shall preserve the original {@link ImageInfo} instance.
+     * Consumers can get the effective MIME type (if any) from the associated {@link ImageFlavor}.
      * @param src the source image
      * @param hints the conversion hints
      * @return the converted image

Modified: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/spi/ImageImplRegistry.java
URL: http://svn.apache.org/viewvc/xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/spi/ImageImplRegistry.java?rev=924666&r1=924665&r2=924666&view=diff
==============================================================================
--- xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/spi/ImageImplRegistry.java (original)
+++ xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/spi/ImageImplRegistry.java Thu Mar 18 08:26:30 2010
@@ -32,6 +32,7 @@ import org.apache.commons.logging.LogFac
 
 import org.apache.xmlgraphics.image.loader.ImageFlavor;
 import org.apache.xmlgraphics.image.loader.ImageInfo;
+import org.apache.xmlgraphics.image.loader.util.Penalty;
 import org.apache.xmlgraphics.util.Service;
 
 /**
@@ -43,6 +44,9 @@ public class ImageImplRegistry {
     /** logger */
     protected static Log log = LogFactory.getLog(ImageImplRegistry.class);
 
+    /** Infinite penalty value which shall force any implementation to become ineligible. */
+    public static final int INFINITE_PENALTY = Integer.MAX_VALUE;
+
     /** Holds the list of preloaders */
     private List preloaders = new java.util.ArrayList();
     //Content: List<ImagePreloader>
@@ -59,15 +63,29 @@ public class ImageImplRegistry {
 
     private int converterModifications;
 
+    /** A Map (key: implementation classes) with additional penalties to fine-tune the registry. */
+    private Map additionalPenalties = new java.util.HashMap(); //<String, Penalty>
+    //Note: String as key chosen to avoid possible class-unloading leaks
+
     /** Singleton instance */
     private static ImageImplRegistry defaultInstance;
 
     /**
+     * Main constructor. This constructor allows to disable plug-in discovery for testing purposes.
+     * @param discover true if implementation classes shall automatically be discovered.
+     */
+    public ImageImplRegistry(boolean discover) {
+        if (discover) {
+            discoverClasspathImplementations();
+        }
+    }
+
+    /**
      * Main constructor.
      * @see #getDefaultInstance()
      */
     public ImageImplRegistry() {
-        discoverClasspathImplementations();
+        this(true);
     }
 
     /**
@@ -123,7 +141,8 @@ public class ImageImplRegistry {
         return holder;
     }
 
-    private class PreloaderHolder {
+    /** Holder class for registered {@link ImagePreloader} instances. */
+    private static class PreloaderHolder {
         private ImagePreloader preloader;
         private int identifier;
 
@@ -138,10 +157,14 @@ public class ImageImplRegistry {
 
                 public int compare(Object o1, Object o2) {
                     PreloaderHolder h1 = (PreloaderHolder)o1;
+                    long p1 = h1.preloader.getPriority();
+                    p1 += getAdditionalPenalty(h1.preloader.getClass().getName()).getValue();
+
                     PreloaderHolder h2 = (PreloaderHolder)o2;
-                    int p1 = h1.preloader.getPriority();
                     int p2 = h2.preloader.getPriority();
-                    int diff = p1 - p2;
+                    p2 += getAdditionalPenalty(h2.preloader.getClass().getName()).getValue();
+
+                    int diff = Penalty.truncate(p1 - p2);
                     if (diff != 0) {
                         return diff;
                     } else {
@@ -278,7 +301,8 @@ public class ImageImplRegistry {
                     if (!factory.isSupported(imageInfo)) {
                         continue;
                     }
-                    int penalty = factory.getUsagePenalty(mime, flavor);
+                    ImageLoader loader = factory.newImageLoader(flavor);
+                    int penalty = loader.getUsagePenalty();
                     if (penalty < bestPenalty) {
                         bestPenalty = penalty;
                         bestFactory = factory;
@@ -299,7 +323,7 @@ public class ImageImplRegistry {
      */
     public ImageLoaderFactory[] getImageLoaderFactories(ImageInfo imageInfo, ImageFlavor flavor) {
         String mime = imageInfo.getMimeType();
-        Collection matches = new java.util.TreeSet(new ImageLoaderFactoryComparator(mime, flavor));
+        Collection matches = new java.util.TreeSet(new ImageLoaderFactoryComparator(flavor));
         Map flavorMap = (Map)loaders.get(mime);
         if (flavorMap != null) {
             Iterator flavorIter = flavorMap.keySet().iterator();
@@ -326,21 +350,28 @@ public class ImageImplRegistry {
         }
     }
 
-    private static class ImageLoaderFactoryComparator implements Comparator {
+    /** Comparator for {@link ImageLoaderFactory} classes. */
+    private class ImageLoaderFactoryComparator implements Comparator {
 
-        private String mime;
         private ImageFlavor targetFlavor;
 
-        public ImageLoaderFactoryComparator(String mime, ImageFlavor targetFlavor) {
-            this.mime = mime;
+        public ImageLoaderFactoryComparator(ImageFlavor targetFlavor) {
             this.targetFlavor = targetFlavor;
         }
 
         public int compare(Object o1, Object o2) {
             ImageLoaderFactory f1 = (ImageLoaderFactory)o1;
+            ImageLoader l1 = f1.newImageLoader(targetFlavor);
+            long p1 = l1.getUsagePenalty();
+            p1 += getAdditionalPenalty(l1.getClass().getName()).getValue();
+
             ImageLoaderFactory f2 = (ImageLoaderFactory)o2;
+            ImageLoader l2 = f2.newImageLoader(targetFlavor);
+            long p2 = l2.getUsagePenalty();
+            p2 = getAdditionalPenalty(l2.getClass().getName()).getValue();
+
             //Lowest penalty first
-            return f1.getUsagePenalty(mime, targetFlavor) - f2.getUsagePenalty(mime, targetFlavor);
+            return Penalty.truncate(p1 - p2);
         }
 
     }
@@ -370,4 +401,31 @@ public class ImageImplRegistry {
         return null;
     }
 
+    /**
+     * Sets an additional penalty for a particular implementation class for any of the interface
+     * administered by this registry class. No checking is performed to verify if the className
+     * parameter is valid.
+     * @param className the fully qualified class name of the implementation class
+     * @param penalty the additional penalty or null to clear any existing value
+     */
+    public void setAdditionalPenalty(String className, Penalty penalty) {
+        if (penalty != null) {
+            this.additionalPenalties.put(className, penalty);
+        } else {
+            this.additionalPenalties.remove(className);
+        }
+        this.lastPreloaderSort = -1; //Force resort, just in case this was a preloader
+    }
+
+    /**
+     * Returns the additional penalty value set for a particular implementation class.
+     * If no such value is set, 0 is returned.
+     * @param className the fully qualified class name of the implementation class
+     * @return the additional penalty value
+     */
+    public Penalty getAdditionalPenalty(String className) {
+        Penalty p = (Penalty)this.additionalPenalties.get(className);
+        return (p != null ? p : Penalty.ZERO_PENALTY);
+    }
+
 }

Modified: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/spi/ImageLoader.java
URL: http://svn.apache.org/viewvc/xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/spi/ImageLoader.java?rev=924666&r1=924665&r2=924666&view=diff
==============================================================================
--- xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/spi/ImageLoader.java (original)
+++ xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/spi/ImageLoader.java Thu Mar 18 08:26:30 2010
@@ -34,6 +34,11 @@ import org.apache.xmlgraphics.image.load
  */
 public interface ImageLoader {
 
+    /** Used if the loading penalty is negligible (image doesn't need to be decoded). */
+    int NO_LOADING_PENALTY = 0;
+    /** Default/Medium conversion penalty (if there's some effort to load the image format) */
+    int MEDIUM_LOADING_PENALTY = 10;
+
     /**
      * Loads and returns an image.
      * @param info the image info object indicating the image

Modified: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/spi/ImageLoaderFactory.java
URL: http://svn.apache.org/viewvc/xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/spi/ImageLoaderFactory.java?rev=924666&r1=924665&r2=924666&view=diff
==============================================================================
--- xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/spi/ImageLoaderFactory.java (original)
+++ xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/spi/ImageLoaderFactory.java Thu Mar 18 08:26:30 2010
@@ -70,6 +70,7 @@ public interface ImageLoaderFactory {
      * @param mime the MIME type
      * @param flavor the target image flavor
      * @return the usage penalty (must be a non-negative integer)
+     * @deprecated Redundancy with {@link ImageLoader#getUsagePenalty()}
      */
     int getUsagePenalty(String mime, ImageFlavor flavor);
 

Modified: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/util/ImageUtil.java
URL: http://svn.apache.org/viewvc/xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/util/ImageUtil.java?rev=924666&r1=924665&r2=924666&view=diff
==============================================================================
--- xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/util/ImageUtil.java (original)
+++ xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/util/ImageUtil.java Thu Mar 18 08:26:30 2010
@@ -317,6 +317,7 @@ public class ImageUtil {
                 new Float(session.getParentContext().getSourceResolution()));
         hints.put(ImageProcessingHints.TARGET_RESOLUTION,
                 new Float(session.getTargetResolution()));
+        hints.put(ImageProcessingHints.IMAGE_SESSION_CONTEXT, session);
         return hints;
     }
 

Added: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/util/Penalty.java
URL: http://svn.apache.org/viewvc/xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/util/Penalty.java?rev=924666&view=auto
==============================================================================
--- xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/util/Penalty.java (added)
+++ xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/util/Penalty.java Thu Mar 18 08:26:30 2010
@@ -0,0 +1,106 @@
+/*
+ * 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.xmlgraphics.image.loader.util;
+
+/**
+ * Immutable class representing a penalty value. It's valid value range is that of an
+ * {@link Integer}, but giving {@link Integer#MAX_VALUE} a special meaning: it means infinite
+ * penalty, i.e. a candidate with this penalty will be excluded from any choice.
+ */
+public class Penalty {
+
+    public static final Penalty ZERO_PENALTY = new Penalty(0);
+    public static final Penalty INFINITE_PENALTY = new Penalty(Integer.MAX_VALUE);
+
+    private final int value;
+
+    /**
+     * Turns a penalty value into a penaly object.
+     * @param value the penalty value
+     * @return the penalty object
+     */
+    public static Penalty toPenalty(int value) {
+        switch (value) {
+        case 0:
+            return ZERO_PENALTY;
+        case Integer.MAX_VALUE:
+            return INFINITE_PENALTY;
+        default:
+            return new Penalty(value);
+        }
+    }
+
+    private Penalty(int value) {
+        this.value = value;
+    }
+
+    /**
+     * Adds a penalty to this one and returns the combined penalty.
+     * @param value the penalty value to add
+     * @return the resulting penalty
+     */
+    public Penalty add(Penalty value) {
+        return add(value.getValue());
+    }
+
+    /**
+     * Adds a penalty to this one and returns the combined penalty.
+     * @param value the penalty value to add
+     * @return the resulting penalty
+     */
+    public Penalty add(int value) {
+        long p = (long)getValue() + value;
+        return toPenalty(truncate(p));
+    }
+
+    /**
+     * Returns the penalty value.
+     * @return the penalty value
+     */
+    public int getValue() {
+        return this.value;
+    }
+
+    /**
+     * Indicates whether this is an infinite penalty, meaning that a solution with this penalty
+     * is effectively ineligible.
+     * @return true if this is an infinite penalty
+     */
+    public boolean isInfinitePenalty() {
+        return (value == Integer.MAX_VALUE);
+    }
+
+    /** {@inheritDoc} */
+    public String toString() {
+        return "Penalty: " + (isInfinitePenalty() ? "INF" : Integer.toString(getValue()));
+    }
+
+    /**
+     * Truncates the long penalty value to an integer without sign side-effects.
+     * @param penalty the penalty value as a long
+     * @return the penalty value as an int
+     */
+    public static int truncate(long penalty) {
+        penalty = Math.min(Integer.MAX_VALUE, penalty);
+        penalty = Math.max(Integer.MIN_VALUE, penalty);
+        return (int)penalty;
+    }
+
+}

Propchange: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/util/Penalty.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/util/Penalty.java
------------------------------------------------------------------------------
    svn:keywords = Id

Modified: xmlgraphics/commons/trunk/test/java/org/apache/xmlgraphics/image/loader/MockImageContext.java
URL: http://svn.apache.org/viewvc/xmlgraphics/commons/trunk/test/java/org/apache/xmlgraphics/image/loader/MockImageContext.java?rev=924666&r1=924665&r2=924666&view=diff
==============================================================================
--- xmlgraphics/commons/trunk/test/java/org/apache/xmlgraphics/image/loader/MockImageContext.java (original)
+++ xmlgraphics/commons/trunk/test/java/org/apache/xmlgraphics/image/loader/MockImageContext.java Thu Mar 18 08:26:30 2010
@@ -19,6 +19,16 @@
 
 package org.apache.xmlgraphics.image.loader;
 
+import org.apache.xmlgraphics.image.loader.impl.ImageConverterBitmap2G2D;
+import org.apache.xmlgraphics.image.loader.impl.ImageConverterBuffered2Rendered;
+import org.apache.xmlgraphics.image.loader.impl.ImageConverterG2D2Bitmap;
+import org.apache.xmlgraphics.image.loader.impl.ImageLoaderFactoryInternalTIFF;
+import org.apache.xmlgraphics.image.loader.impl.ImageLoaderFactoryRawCCITTFax;
+import org.apache.xmlgraphics.image.loader.impl.PreloaderEPS;
+import org.apache.xmlgraphics.image.loader.impl.PreloaderJPEG;
+import org.apache.xmlgraphics.image.loader.impl.PreloaderTIFF;
+import org.apache.xmlgraphics.image.loader.spi.ImageImplRegistry;
+
 /**
  * Mock implementation for testing.
  */
@@ -26,24 +36,64 @@ public class MockImageContext implements
 
     private static MockImageContext instance;
 
-    private ImageManager imageManager = new ImageManager(this);
+    private ImageManager imageManager;
 
+    /**
+     * Returns a singleton instance of the mock image context.
+     * @return the singleton
+     */
     public static MockImageContext getInstance() {
         if (instance == null) {
-            instance = new MockImageContext();
+            instance = new MockImageContext(true);
         }
         return instance;
     }
 
+    /**
+     * Returns an image context for testing that only contains platform- and classpath-independent
+     * implementations so consistent test results can be obtained irrespective of the test
+     * environment.
+     * @return a new image context
+     */
+    public static MockImageContext newSafeInstance() {
+        MockImageContext ic = new MockImageContext(false);
+        ImageImplRegistry registry = ic.getImageManager().getRegistry();
+        registry.registerPreloader(new PreloaderTIFF());
+        registry.registerPreloader(new PreloaderJPEG());
+        registry.registerPreloader(new PreloaderEPS());
+        registry.registerLoaderFactory(new ImageLoaderFactoryInternalTIFF());
+        registry.registerLoaderFactory(new ImageLoaderFactoryRawCCITTFax());
+        registry.registerConverter(new ImageConverterBitmap2G2D());
+        registry.registerConverter(new ImageConverterG2D2Bitmap());
+        registry.registerConverter(new ImageConverterBuffered2Rendered());
+        return ic;
+    }
+
+    /**
+     * Creates a new mock image context.
+     * @param discover true to enable plug-in discovery
+     */
+    public MockImageContext(boolean discover) {
+        this.imageManager = new ImageManager(new ImageImplRegistry(discover), this);
+    }
+
     /** {@inheritDoc} */
     public float getSourceResolution() {
         return 72;
     }
 
+    /**
+     * Returns the image manager.
+     * @return the image manager
+     */
     public ImageManager getImageManager() {
         return this.imageManager;
     }
 
+    /**
+     * Creates a new image session context.
+     * @return the image session context
+     */
     public ImageSessionContext newSessionContext() {
         return new MockImageSessionContext(this);
     }

Added: xmlgraphics/commons/trunk/test/java/org/apache/xmlgraphics/image/loader/PenaltyTestCase.java
URL: http://svn.apache.org/viewvc/xmlgraphics/commons/trunk/test/java/org/apache/xmlgraphics/image/loader/PenaltyTestCase.java?rev=924666&view=auto
==============================================================================
--- xmlgraphics/commons/trunk/test/java/org/apache/xmlgraphics/image/loader/PenaltyTestCase.java (added)
+++ xmlgraphics/commons/trunk/test/java/org/apache/xmlgraphics/image/loader/PenaltyTestCase.java Thu Mar 18 08:26:30 2010
@@ -0,0 +1,78 @@
+/*
+ * 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.xmlgraphics.image.loader;
+
+import junit.framework.TestCase;
+
+import org.apache.xmlgraphics.image.loader.util.Penalty;
+
+/**
+ * Tests for the {@link Penalty}.
+ */
+public class PenaltyTestCase extends TestCase {
+
+    /**
+     * Tests for penalty handling.
+     * @throws Exception if an error occurs
+     */
+    public void testTruncatePenalty() throws Exception {
+        assertEquals(0, Penalty.truncate(0));
+        long penalty = Integer.MAX_VALUE;
+        assertEquals(Integer.MAX_VALUE, Penalty.truncate(penalty));
+
+        //Force integer wrap-around
+        penalty++;
+        assertEquals(Integer.MAX_VALUE, Penalty.truncate(penalty));
+        //For comparison, normal casting does this
+        assertEquals(Integer.MIN_VALUE, (int)penalty);
+
+        //Now on the other end of the spectrum...
+        penalty = Integer.MIN_VALUE;
+        assertEquals(Integer.MIN_VALUE, Penalty.truncate(penalty));
+
+        //Force integer wrap-around
+        penalty -= 500;
+        assertEquals(Integer.MIN_VALUE, Penalty.truncate(penalty));
+        //For comparison, normal casting does this
+        assertEquals(Integer.MAX_VALUE - 499, (int)penalty);
+    }
+
+    /**
+     * Tests for the {@link Penalty} class.
+     * @throws Exception if an error occurs
+     */
+    public void testPenalty() throws Exception {
+        Penalty p1 = Penalty.toPenalty(100);
+        assertEquals(100, p1.getValue());
+        Penalty p2 = p1.add(Penalty.toPenalty(50));
+        assertEquals(150, p2.getValue());
+
+        p1 = Penalty.toPenalty(0);
+        assertEquals(0, p1.getValue());
+
+        p1 = Penalty.INFINITE_PENALTY;
+        assertEquals(Integer.MAX_VALUE, p1.getValue());
+        assertTrue(p1.isInfinitePenalty());
+        p2 = p1.add(p2);
+        assertEquals(Integer.MAX_VALUE, p2.getValue());
+        assertTrue(p2.isInfinitePenalty());
+    }
+
+}

Propchange: xmlgraphics/commons/trunk/test/java/org/apache/xmlgraphics/image/loader/PenaltyTestCase.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: xmlgraphics/commons/trunk/test/java/org/apache/xmlgraphics/image/loader/PenaltyTestCase.java
------------------------------------------------------------------------------
    svn:keywords = Id

Added: xmlgraphics/commons/trunk/test/java/org/apache/xmlgraphics/image/loader/PipelineFactoryTestCase.java
URL: http://svn.apache.org/viewvc/xmlgraphics/commons/trunk/test/java/org/apache/xmlgraphics/image/loader/PipelineFactoryTestCase.java?rev=924666&view=auto
==============================================================================
--- xmlgraphics/commons/trunk/test/java/org/apache/xmlgraphics/image/loader/PipelineFactoryTestCase.java (added)
+++ xmlgraphics/commons/trunk/test/java/org/apache/xmlgraphics/image/loader/PipelineFactoryTestCase.java Thu Mar 18 08:26:30 2010
@@ -0,0 +1,199 @@
+/*
+ * 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.xmlgraphics.image.loader;
+
+import junit.framework.TestCase;
+
+import org.apache.xmlgraphics.image.codec.tiff.TIFFImage;
+import org.apache.xmlgraphics.image.loader.impl.ImageLoaderRawCCITTFax;
+import org.apache.xmlgraphics.image.loader.mocks.MockImageLoaderFactoryTIFF;
+import org.apache.xmlgraphics.image.loader.pipeline.ImageProviderPipeline;
+import org.apache.xmlgraphics.image.loader.pipeline.PipelineFactory;
+import org.apache.xmlgraphics.image.loader.spi.ImageImplRegistry;
+import org.apache.xmlgraphics.image.loader.util.Penalty;
+
+/**
+ * Tests the pipeline factory.
+ */
+public class PipelineFactoryTestCase extends TestCase {
+
+    /**
+     * Tests the pipeline factory by checking to load a TIFF image.
+     * @throws Exception if an error occurs
+     */
+    public void testPipelineFactoryPlain() throws Exception {
+        MockImageContext imageContext = MockImageContext.newSafeInstance();
+        ImageManager manager = imageContext.getImageManager();
+        PipelineFactory pFactory = new PipelineFactory(manager);
+
+        //Input is some TIFF file
+        ImageInfo imageInfo = new ImageInfo("test:tiff", "image/tiff");
+
+        //We want a G2D image
+        ImageFlavor targetFlavor = ImageFlavor.GRAPHICS2D;
+
+        ImageProviderPipeline pipeline = pFactory.newImageConverterPipeline(
+                imageInfo, targetFlavor);
+        assertNotNull(pipeline);
+        assertEquals(pipeline.getTargetFlavor(), targetFlavor);
+
+        //penalty for internal TIFF implementation (fallback role) is 1000 + 10 for the conversion
+        assertEquals(1010, pipeline.getConversionPenalty());
+        assertEquals(ImageFlavor.GRAPHICS2D, pipeline.getTargetFlavor());
+        if (pipeline.toString().indexOf("LoaderInternalTIFF") < 0) {
+            fail("Chose the wrong pipeline: " + pipeline.toString());
+        }
+        if (pipeline.toString().indexOf("ImageConverterBitmap2G2D") < 0) {
+            fail("Chose the wrong pipeline: " + pipeline.toString());
+        }
+
+        ImageProviderPipeline[] candidates = pFactory.determineCandidatePipelines(
+                imageInfo, new ImageFlavor[] {targetFlavor});
+        assertEquals(1, candidates.length);
+
+        //Now add another implementation that poses as TIFF loader
+        imageContext.getImageManager().getRegistry().registerLoaderFactory(
+                new MockImageLoaderFactoryTIFF());
+
+        candidates = pFactory.determineCandidatePipelines(
+                imageInfo, targetFlavor);
+        assertEquals(3, candidates.length);
+        //3 because the mock impl provides Buffered- and RenderedImage capabilities
+
+        pipeline = pFactory.newImageConverterPipeline(imageInfo, targetFlavor);
+        assertNotNull(pipeline);
+        assertEquals(pipeline.getTargetFlavor(), targetFlavor);
+
+        //Assuming mock impl without penalty + 10 for the conversion
+        assertEquals(10, pipeline.getConversionPenalty());
+        assertEquals(ImageFlavor.GRAPHICS2D, pipeline.getTargetFlavor());
+        if (pipeline.toString().indexOf(MockImageLoaderFactoryTIFF.class.getName()) < 0) {
+            fail("Chose the wrong pipeline: " + pipeline.toString());
+        }
+        if (pipeline.toString().indexOf("ImageConverterBitmap2G2D") < 0) {
+            fail("Chose the wrong pipeline: " + pipeline.toString());
+        }
+    }
+
+    /**
+     * Similar test as above but here we take raw CCITT loading into consideration, too.
+     * @throws Exception if an error occurs
+     */
+    public void testPipelineFactoryImageInfoDependency() throws Exception {
+        MockImageContext imageContext = MockImageContext.newSafeInstance();
+        ImageManager manager = imageContext.getImageManager();
+        PipelineFactory pFactory = new PipelineFactory(manager);
+
+        //Input is some TIFF file with CCITT Group 4 compression
+        ImageInfo imageInfo = new ImageInfo("test:tiff", "image/tiff");
+        imageInfo.getCustomObjects().put("TIFF_STRIP_COUNT", new Integer(1));
+        imageInfo.getCustomObjects().put("TIFF_COMPRESSION", new Integer(TIFFImage.COMP_FAX_G4_2D));
+
+        //We want either a G2D image or a raw CCITT image
+        ImageFlavor[] targetFlavors = new ImageFlavor[] {
+                ImageFlavor.GRAPHICS2D, ImageFlavor.RAW_CCITTFAX};
+
+        ImageProviderPipeline[] candidates = pFactory.determineCandidatePipelines(
+                imageInfo, targetFlavors);
+        assertNotNull(candidates);
+        assertEquals(2, candidates.length);
+
+        ImageProviderPipeline pipeline = manager.choosePipeline(candidates);
+
+        //0 penalty because the raw loader is the most efficient choice here
+        assertEquals(0, pipeline.getConversionPenalty());
+        assertEquals(ImageFlavor.RAW_CCITTFAX, pipeline.getTargetFlavor());
+        if (pipeline.toString().indexOf("LoaderRawCCITTFax") < 0) {
+            fail("Chose the wrong pipeline: " + pipeline.toString());
+        }
+
+        //Now, we set this to a multi-strip TIFF which should disable the raw loader
+        imageInfo.getCustomObjects().put("TIFF_STRIP_COUNT", new Integer(7));
+
+        candidates = pFactory.determineCandidatePipelines(
+                imageInfo, targetFlavors);
+        assertNotNull(candidates);
+        assertEquals(1, candidates.length);
+
+        pipeline = manager.choosePipeline(candidates);
+
+        //penalty for internal TIFF implementation (fallback role) is 1000 + 10 for the conversion
+        assertEquals(1010, pipeline.getConversionPenalty());
+        assertEquals(ImageFlavor.GRAPHICS2D, pipeline.getTargetFlavor());
+        if (pipeline.toString().indexOf("LoaderInternalTIFF") < 0) {
+            fail("Chose the wrong pipeline: " + pipeline.toString());
+        }
+        if (pipeline.toString().indexOf("ImageConverterBitmap2G2D") < 0) {
+            fail("Chose the wrong pipeline: " + pipeline.toString());
+        }
+    }
+
+    /**
+     * Similar test as above but now we're playing with additional penalties in the registry.
+     * @throws Exception if an error occurs
+     */
+    public void testPipelineFactoryAdditionalPenalty() throws Exception {
+        MockImageContext imageContext = MockImageContext.newSafeInstance();
+        ImageManager manager = imageContext.getImageManager();
+        PipelineFactory pFactory = new PipelineFactory(manager);
+
+        //Adding additional penalty for CCITT loading
+        ImageImplRegistry registry = imageContext.getImageManager().getRegistry();
+        registry.setAdditionalPenalty(ImageLoaderRawCCITTFax.class.getName(),
+                Penalty.toPenalty(10000));
+
+        //Input is some TIFF file with CCITT Group 4 compression
+        ImageInfo imageInfo = new ImageInfo("test:tiff", "image/tiff");
+        imageInfo.getCustomObjects().put("TIFF_STRIP_COUNT", new Integer(1));
+        imageInfo.getCustomObjects().put("TIFF_COMPRESSION", new Integer(TIFFImage.COMP_FAX_G4_2D));
+
+        //We want either a G2D image or a raw CCITT image
+        ImageFlavor[] targetFlavors = new ImageFlavor[] {
+                ImageFlavor.GRAPHICS2D, ImageFlavor.RAW_CCITTFAX};
+
+        ImageProviderPipeline[] candidates = pFactory.determineCandidatePipelines(
+                imageInfo, targetFlavors);
+        assertNotNull(candidates);
+        assertEquals(2, candidates.length);
+
+        ImageProviderPipeline pipeline = manager.choosePipeline(candidates);
+
+        //penalty for internal TIFF implementation (fallback role) is 1000 + 10 for the conversion
+        assertEquals(1010, pipeline.getConversionPenalty());
+        assertEquals(ImageFlavor.GRAPHICS2D, pipeline.getTargetFlavor());
+        if (pipeline.toString().indexOf("LoaderInternalTIFF") < 0) {
+            fail("Chose the wrong pipeline: " + pipeline.toString());
+        }
+        if (pipeline.toString().indexOf("ImageConverterBitmap2G2D") < 0) {
+            fail("Chose the wrong pipeline: " + pipeline.toString());
+        }
+
+        //Now set an infinite penalty making the solution ineligible
+        registry.setAdditionalPenalty(ImageLoaderRawCCITTFax.class.getName(),
+                Penalty.INFINITE_PENALTY);
+
+        candidates = pFactory.determineCandidatePipelines(imageInfo, targetFlavors);
+        assertNotNull(candidates);
+        assertEquals(1, candidates.length);
+        //While earlier 2 candidates were returned, here we only get 1 because of the infinite
+        //penalty.
+    }
+
+}

Propchange: xmlgraphics/commons/trunk/test/java/org/apache/xmlgraphics/image/loader/PipelineFactoryTestCase.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: xmlgraphics/commons/trunk/test/java/org/apache/xmlgraphics/image/loader/PipelineFactoryTestCase.java
------------------------------------------------------------------------------
    svn:keywords = Id

Added: xmlgraphics/commons/trunk/test/java/org/apache/xmlgraphics/image/loader/mocks/MockImageLoaderFactoryTIFF.java
URL: http://svn.apache.org/viewvc/xmlgraphics/commons/trunk/test/java/org/apache/xmlgraphics/image/loader/mocks/MockImageLoaderFactoryTIFF.java?rev=924666&view=auto
==============================================================================
--- xmlgraphics/commons/trunk/test/java/org/apache/xmlgraphics/image/loader/mocks/MockImageLoaderFactoryTIFF.java (added)
+++ xmlgraphics/commons/trunk/test/java/org/apache/xmlgraphics/image/loader/mocks/MockImageLoaderFactoryTIFF.java Thu Mar 18 08:26:30 2010
@@ -0,0 +1,108 @@
+/*
+ * 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.xmlgraphics.image.loader.mocks;
+
+import java.io.IOException;
+import java.util.Map;
+
+import junit.framework.Assert;
+
+import org.apache.xmlgraphics.image.loader.Image;
+import org.apache.xmlgraphics.image.loader.ImageException;
+import org.apache.xmlgraphics.image.loader.ImageFlavor;
+import org.apache.xmlgraphics.image.loader.ImageInfo;
+import org.apache.xmlgraphics.image.loader.ImageSessionContext;
+import org.apache.xmlgraphics.image.loader.impl.AbstractImageLoaderFactory;
+import org.apache.xmlgraphics.image.loader.spi.ImageLoader;
+import org.apache.xmlgraphics.util.MimeConstants;
+
+/**
+ * Mock implementation posing as a TIFF-compatible loader.
+ */
+public class MockImageLoaderFactoryTIFF extends AbstractImageLoaderFactory {
+
+    /** {@inheritDoc} */
+    public ImageFlavor[] getSupportedFlavors(String mime) {
+        return new ImageFlavor[] {ImageFlavor.BUFFERED_IMAGE, ImageFlavor.RENDERED_IMAGE};
+    }
+
+    /** {@inheritDoc} */
+    public String[] getSupportedMIMETypes() {
+        return new String[] {MimeConstants.MIME_TIFF};
+    }
+
+    private void checkSuppportedFlavor(String mime, ImageFlavor flavor) {
+        ImageFlavor[] flavors = getSupportedFlavors(mime);
+        boolean found = false;
+        for (int i = 0; i < flavors.length; i++) {
+            if (flavors[i].equals(flavor)) {
+                found = true;
+                break;
+            }
+        }
+        Assert.assertTrue(found);
+    }
+
+    /** {@inheritDoc} */
+    public boolean isAvailable() {
+        return true;
+    }
+
+    /** {@inheritDoc} */
+    public boolean isSupported(ImageInfo imageInfo) {
+        return MimeConstants.MIME_TIFF.equals(imageInfo.getMimeType());
+    }
+
+    /** {@inheritDoc} */
+    public ImageLoader newImageLoader(ImageFlavor targetFlavor) {
+        checkSuppportedFlavor(MimeConstants.MIME_TIFF, targetFlavor);
+        return new ImageLoaderImpl(targetFlavor);
+    }
+
+    /** Mock image loader implementation. */
+    private static class ImageLoaderImpl implements ImageLoader {
+
+        private ImageFlavor flavor;
+
+        public ImageLoaderImpl(ImageFlavor flavor) {
+            this.flavor = flavor;
+        }
+
+        public ImageFlavor getTargetFlavor() {
+            return flavor;
+        }
+
+        public int getUsagePenalty() {
+            return 0;
+        }
+
+        public Image loadImage(ImageInfo info, Map hints, ImageSessionContext session)
+                throws ImageException, IOException {
+            throw new UnsupportedOperationException("not implemented");
+        }
+
+        public Image loadImage(ImageInfo info, ImageSessionContext session) throws ImageException,
+                IOException {
+            throw new UnsupportedOperationException("not implemented");
+        }
+
+    }
+
+}

Propchange: xmlgraphics/commons/trunk/test/java/org/apache/xmlgraphics/image/loader/mocks/MockImageLoaderFactoryTIFF.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: xmlgraphics/commons/trunk/test/java/org/apache/xmlgraphics/image/loader/mocks/MockImageLoaderFactoryTIFF.java
------------------------------------------------------------------------------
    svn:keywords = Id



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