org.valkyriercp.image.DefaultImageSource Maven / Gradle / Ivy
package org.valkyriercp.image;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.style.StylerUtils;
import org.springframework.core.style.ToStringCreator;
import org.springframework.stereotype.*;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import org.springframework.util.CachingMapDecorator;
import java.awt.*;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
/**
* A collection of image resources, each indexed by a common key alias.
*
* For example, action.edit.copy = /images/edit/copy.gif
*
* This class by default performs caching of all loaded image resources using
* soft references (TODO it just lazy loads them, but it doesn't use
* SoftReference).
*
*
Image resources can be set in the constructor or through the property imageResources
.
* The may should be a String-Resource or String-String where a string value will be converted to
* a resource using the configured ResourceLoader
. Because the value part of the pairs can be a
* string you can use the following code in your context to configure the map:
* <bean id="imageResourcesFactory" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="locations">
<list>
<value>classpath:org/springframework/richclient/image/images.properties</value>
<value>...your other locations here...</value>
</list>
</property>
</bean>
<bean id="imageSource" class="test.DefaultImageSource">
<property name="brokenImageIndicator"
value="/org/springframework/richclient/images/alert/error_obj.gif" />
<property name="imageResources" ref="imageResourcesFactory"/>
</bean>
*
* Spring 2.5 users can also use the deprecated ResourceMapFactoryBean
.
*
*
* An image {@link Handler} is available that handles the 'image' protocol.
* Check the javadocs of the handler to know how to use/register it.
*
*
* @author Keith Donald
*/
@Component
public class DefaultImageSource implements ImageSource {
protected static final Log logger = LogFactory.getLog(DefaultImageSource.class);
private Map imageResources;
private ImageCache imageCache;
private AwtImageResource brokenImageIndicatorResource;
private Image brokenImageIndicator;
@Autowired
private ResourceLoader resourceLoader;
/**
* Creates a image resource bundle containing the specified map of keys to
* resource paths.
*
* A custom URL protocol {@link Handler handler}will be installed for the
* "image:" protocol. This allows for images in this image source to be
* located using the Java URL classes:
* URL imageUrl = new URL("image:the.image.key")
*
* @param imageResources a map of key-to-image-resources.
*/
public DefaultImageSource(Map imageResources) {
this(true, imageResources);
}
/**
* Creates a image resource bundle containing the specified map of keys to
* resource paths.
*
* @param installUrlHandler should a URL handler be installed.
* @param imageResources a map of key-to-image-resources.
*/
public DefaultImageSource(boolean installUrlHandler, Map imageResources) {
Assert.notNull(imageResources);
this.imageResources = new HashMap(imageResources);
debugPrintResources();
this.imageCache = new ImageCache();
if (installUrlHandler) {
Handler.installImageUrlHandler(this);
}
}
public DefaultImageSource() {
this.imageCache = new ImageCache();
Handler.installImageUrlHandler(this);
}
public void setImageResources(Map imageResources) {
this.imageResources = new HashMap(imageResources);
debugPrintResources();
}
private void debugPrintResources() {
if (logger.isDebugEnabled()) {
logger.debug("Initialing image source with resources: " + StylerUtils.style(this.imageResources));
}
}
public Image getImage(String key) {
Assert.notNull(key);
AwtImageResource resource = getImageResource(key);
try {
return (Image) imageCache.get(resource);
}
catch (RuntimeException e) {
if (brokenImageIndicator != null) {
return returnBrokenImageIndicator(resource);
}
throw e;
}
}
public AwtImageResource getImageResource(String key) {
Assert.notNull(key);
Resource resource = null;
final Object tmp = imageResources.get(key);
if(tmp instanceof Resource)
resource = (Resource)tmp;
if(tmp instanceof String) {
resource = resourceLoader.getResource((String)tmp);
Assert.notNull(resourceLoader, "Resource loader must be set to resolve resources");
}
if (resource == null) {
throw new NoSuchImageResourceException(key);
}
try {
resource.getInputStream();
return new AwtImageResource(resource);
}
catch (IOException e) {
if (brokenImageIndicatorResource == null) {
throw new NoSuchImageResourceException(resource, e);
}
logger.warn("Unable to load image resource at '" + resource + "'; returning the broken image indicator.");
return brokenImageIndicatorResource;
}
}
public boolean containsKey(Object key) {
return imageResources.containsKey(key);
}
private Image returnBrokenImageIndicator(Resource resource) {
logger.warn("Unable to load image resource at '" + resource + "'; returning the broken image indicator.");
return brokenImageIndicator;
}
public Image getImageAtLocation(Resource location) {
try {
return new AwtImageResource(location).getImage();
}
catch (IOException e) {
if (brokenImageIndicator == null) {
throw new NoSuchImageResourceException(location, e);
}
return returnBrokenImageIndicator(location);
}
}
public int size() {
return imageResources.size();
}
public void setBrokenImageIndicator(Resource resource) {
try {
brokenImageIndicatorResource = new AwtImageResource(resource);
brokenImageIndicator = brokenImageIndicatorResource.getImage();
}
catch (IOException e) {
brokenImageIndicatorResource = null;
throw new NoSuchImageResourceException(resource, e);
}
}
public String toString() {
return new ToStringCreator(this).append("imageResources", imageResources).toString();
}
private static class ImageCache extends CachingMapDecorator {
public ImageCache() {
super(true);
}
public Object create(Object resource) {
try {
return ((AwtImageResource) resource).getImage();
}
catch (IOException e) {
throw new NoSuchImageResourceException("No image found at resource '" + resource + '"', e);
}
}
}
}