blob: 536fc19b07d5d2000d68590ed34d8dfa63b78107 [file] [log] [blame]
/*
* 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.pdf;
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 PDF renderer. It also
* supports automatic discovery of additional handlers available through
* the class path.
*/
public class PDFImageHandlerRegistry {
/** the logger */
private static Log log = LogFactory.getLog(PDFImageHandlerRegistry.class);
private static final Comparator HANDLER_COMPARATOR = new Comparator() {
public int compare(Object o1, Object o2) {
PDFImageHandler h1 = (PDFImageHandler)o1;
PDFImageHandler h2 = (PDFImageHandler)o2;
return h1.getPriority() - h2.getPriority();
}
};
/** Map containing PDF image handlers for various MIME types */
private Map handlers = new java.util.HashMap();
/** List containing the same handlers as above but ordered by priority */
private List handlerList = new java.util.LinkedList();
/** Sorted Set of registered handlers */
private ImageFlavor[] supportedFlavors = new ImageFlavor[0];
private int handlerRegistrations;
private int lastSync;
/**
* Default constructor.
*/
public PDFImageHandlerRegistry() {
discoverHandlers();
}
/**
* Add an PDFImageHandler. The handler itself is inspected to find out what it supports.
* @param classname the fully qualified class name
*/
public void addHandler(String classname) {
try {
PDFImageHandler handlerInstance
= (PDFImageHandler)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 "
+ PDFImageHandler.class.getName());
}
}
/**
* Add an image handler. The handler itself is inspected to find out what it supports.
* @param handler the PDFImageHandler instance
*/
public synchronized void addHandler(PDFImageHandler handler) {
Class imageClass = handler.getSupportedImageClass();
this.handlers.put(imageClass, handler);
//Sorted insert
ListIterator iter = this.handlerList.listIterator();
while (iter.hasNext()) {
PDFImageHandler h = (PDFImageHandler)iter.next();
if (HANDLER_COMPARATOR.compare(handler, h) < 0) {
iter.previous();
break;
}
}
iter.add(handler);
this.handlerRegistrations++;
}
/**
* Returns an PDFImageHandler which handles an specific image type given the MIME type
* of the image.
* @param img the Image to be handled
* @return the PDFImageHandler responsible for handling the image or null if none is available
*/
public PDFImageHandler getHandler(Image img) {
return getHandler(img.getClass());
}
/**
* Returns an PDFImageHandler 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 PDFImageHandler responsible for handling the image or null if none is available
*/
protected synchronized PDFImageHandler getHandler(Class imageClass) {
PDFImageHandler handler = null;
Class cl = imageClass;
while (cl != null) {
handler = (PDFImageHandler)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 = ((PDFImageHandler)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 PDFImageHandler implementations through the classpath and dynamically
* registers them.
*/
private void discoverHandlers() {
// add mappings from available services
Iterator providers = Service.providers(PDFImageHandler.class);
if (providers != null) {
while (providers.hasNext()) {
PDFImageHandler handler = (PDFImageHandler)providers.next();
try {
if (log.isDebugEnabled()) {
log.debug("Dynamically adding PDFImageHandler: "
+ handler.getClass().getName());
}
addHandler(handler);
} catch (IllegalArgumentException e) {
log.error("Error while adding PDFImageHandler", e);
}
}
}
}
}