aboutsummaryrefslogtreecommitdiffstats
path: root/src/java/org/apache/fop/render/AbstractImageHandlerRegistry.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/java/org/apache/fop/render/AbstractImageHandlerRegistry.java')
-rw-r--r--src/java/org/apache/fop/render/AbstractImageHandlerRegistry.java209
1 files changed, 209 insertions, 0 deletions
diff --git a/src/java/org/apache/fop/render/AbstractImageHandlerRegistry.java b/src/java/org/apache/fop/render/AbstractImageHandlerRegistry.java
new file mode 100644
index 000000000..4196a1b19
--- /dev/null
+++ b/src/java/org/apache/fop/render/AbstractImageHandlerRegistry.java
@@ -0,0 +1,209 @@
+/*
+ * 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.render;
+
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Map;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.apache.xmlgraphics.image.loader.Image;
+import org.apache.xmlgraphics.image.loader.ImageFlavor;
+import org.apache.xmlgraphics.util.Service;
+
+/**
+ * This class holds references to various image handlers used by the renderers. It also
+ * supports automatic discovery of additional handlers available through
+ * the class path.
+ */
+public abstract class AbstractImageHandlerRegistry {
+
+ /** the logger */
+ private static Log log = LogFactory.getLog(AbstractImageHandlerRegistry.class);
+
+ private static final Comparator HANDLER_COMPARATOR = new Comparator() {
+ public int compare(Object o1, Object o2) {
+ ImageHandlerBase h1 = (ImageHandlerBase)o1;
+ ImageHandlerBase h2 = (ImageHandlerBase)o2;
+ return h1.getPriority() - h2.getPriority();
+ }
+ };
+
+ /** Map containing image handlers for various MIME types */
+ private final Map/*<Class, ImageHandler>*/ handlers
+ = new java.util.HashMap/*<Class, ImageHandler>*/();
+
+ /** List containing the same handlers as above but ordered by priority */
+ private final List/*<ImageHandler>*/ handlerList
+ = new java.util.LinkedList/*<ImageHandler>*/();
+
+ /** Sorted Set of registered handlers */
+ private ImageFlavor[] supportedFlavors = new ImageFlavor[0];
+
+ private int handlerRegistrations;
+ private int lastSync;
+
+ /**
+ * Default constructor.
+ */
+ public AbstractImageHandlerRegistry() {
+ discoverHandlers();
+ }
+
+ /**
+ * Add an ImageHandler. The handler itself is inspected to find out what it supports.
+ * @param classname the fully qualified class name
+ */
+ public void addHandler(String classname) {
+ try {
+ ImageHandlerBase handlerInstance
+ = (ImageHandlerBase)Class.forName(classname).newInstance();
+ addHandler(handlerInstance);
+ } catch (ClassNotFoundException e) {
+ throw new IllegalArgumentException("Could not find "
+ + classname);
+ } catch (InstantiationException e) {
+ throw new IllegalArgumentException("Could not instantiate "
+ + classname);
+ } catch (IllegalAccessException e) {
+ throw new IllegalArgumentException("Could not access "
+ + classname);
+ } catch (ClassCastException e) {
+ throw new IllegalArgumentException(classname
+ + " is not an "
+ + getHandlerClass().getName());
+ }
+ }
+
+ /**
+ * Add an image handler. The handler itself is inspected to find out what it supports.
+ * @param handler the ImageHandler instance
+ */
+ public synchronized void addHandler(ImageHandlerBase handler) {
+ this.handlers.put(handler.getSupportedImageClass(), handler);
+
+ //Sorted insert
+ ListIterator iter = this.handlerList.listIterator();
+ while (iter.hasNext()) {
+ ImageHandlerBase h = (ImageHandlerBase)iter.next();
+ if (getHandlerComparator().compare(handler, h) < 0) {
+ iter.previous();
+ break;
+ }
+ }
+ iter.add(handler);
+ this.handlerRegistrations++;
+ }
+
+ /**
+ * Returns an ImageHandler which handles an specific image type given the MIME type
+ * of the image.
+ * @param img the Image to be handled
+ * @return the ImageHandler responsible for handling the image or null if none is available
+ */
+ public ImageHandlerBase getHandler(Image img) {
+ return getHandler(img.getClass());
+ }
+
+ /**
+ * Returns an ImageHandler which handles an specific image type given the MIME type
+ * of the image.
+ * @param imageClass the Image subclass for which to get a handler
+ * @return the ImageHandler responsible for handling the image or null if none is available
+ */
+ public synchronized ImageHandlerBase getHandler(Class imageClass) {
+ ImageHandlerBase handler = null;
+ Class cl = imageClass;
+ while (cl != null) {
+ handler = (ImageHandlerBase)handlers.get(cl);
+ if (handler != null) {
+ break;
+ }
+ cl = cl.getSuperclass();
+ }
+ return handler;
+ }
+
+ /**
+ * Returns the ordered array of supported image flavors.
+ * @return the array of image flavors
+ */
+ public synchronized ImageFlavor[] getSupportedFlavors() {
+ if (this.lastSync != this.handlerRegistrations) {
+ //Extract all ImageFlavors into a single array
+ List flavors = new java.util.ArrayList();
+ Iterator iter = this.handlerList.iterator();
+ while (iter.hasNext()) {
+ ImageFlavor[] f = ((ImageHandlerBase)iter.next()).getSupportedImageFlavors();
+ for (int i = 0; i < f.length; i++) {
+ flavors.add(f[i]);
+ }
+ }
+ this.supportedFlavors = (ImageFlavor[])flavors.toArray(new ImageFlavor[flavors.size()]);
+ this.lastSync = this.handlerRegistrations;
+ }
+ return this.supportedFlavors;
+ }
+
+ /**
+ * Discovers ImageHandler implementations through the classpath and dynamically
+ * registers them.
+ */
+ private void discoverHandlers() {
+ // add mappings from available services
+ Class imageHandlerClass = getHandlerClass();
+ Iterator providers = Service.providers(imageHandlerClass);
+ if (providers != null) {
+ while (providers.hasNext()) {
+ ImageHandlerBase handler = (ImageHandlerBase)providers.next();
+ try {
+ if (log.isDebugEnabled()) {
+ log.debug("Dynamically adding ImageHandler: "
+ + handler.getClass().getName());
+ }
+ addHandler(handler);
+ } catch (IllegalArgumentException e) {
+ log.error("Error while adding ImageHandler", e);
+ }
+
+ }
+ }
+ }
+
+ /**
+ * Returns the ImageHandler comparator
+ *
+ * @return the ImageHandler comparator
+ */
+ public Comparator getHandlerComparator() {
+ return HANDLER_COMPARATOR;
+ }
+
+ /**
+ * Returns the ImageHandler implementing class
+ *
+ * @return the ImageHandler implementing class
+ */
+ public abstract Class getHandlerClass();
+}