|
From: aappddeevv (JIRA) <no...@sp...> - 2010-03-24 21:32:35
|
[ https://jira.springsource.org/browse/RCP-630?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=52378#action_52378 ]
aappddeevv commented on RCP-630:
--------------------------------
Here's some code with an update on the comments as well. I did not check to ensure that ResourceLoaderAware is in spring 2.5.
/*
* Copyright 2002-2004 the original author or authors.
*
* Licensed 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.
*/
package org.springframework.richclient.image;
import java.awt.Image;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
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.util.Assert;
import org.springframework.util.CachingMapDecorator;
/**
* A collection of image resources, each indexed by a common key alias.
* <p>
* For example, <code>action.edit.copy = /images/edit/copy.gif</code>
* <p>
* 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).
*
* <p>Image resources can be set in the constructor or through the property <code>imageResources</code>.
* The may should be a String-Resource or String-String where a string value will be converted to
* a resource using the configured <code>ResourceLoader</code>. Because the value part of the pairs can be a
* string you can use the following code in your context to configure the map:<pre>
* <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>
* </pre>
* Spring 2.5 users can also use the deprecated <code>ResourceMapFactoryBean</code>.
*
* <p>
* An image {@link Handler} is available that handles the 'image' protocol.
* Check the javadocs of the handler to know how to use/register it.
* </p>
*
* @author Keith Donald
*/
public class DefaultImageSource implements ImageSource, ResourceLoaderAware {
protected static final Log logger = LogFactory.getLog(DefaultImageSource.class);
private Map imageResources;
private ImageCache imageCache;
private AwtImageResource brokenImageIndicatorResource;
private Image brokenImageIndicator;
ResourceLoader resourceLoader;
/**
* Creates a image resource bundle containing the specified map of keys to
* resource paths.
* <p>
* 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: <br>
* <code>URL imageUrl = new URL("image:the.image.key")</code>
*
* @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);
}
}
}
public void setResourceLoader(ResourceLoader arg0) {
this.resourceLoader = arg0;
}
}
> Allow DefaultImageSource to resolve resources
> ---------------------------------------------
>
> Key: RCP-630
> URL: https://jira.springsource.org/browse/RCP-630
> Project: Spring Rich Client Project
> Issue Type: Improvement
> Components: Core
> Affects Versions: 1.1.0
> Environment: all
> Reporter: aappddeevv
> Assignee: Lieven Doclo
>
> Allow DefaultImageSource to convert string specifications to resources for loading images. Other spring components interpret string arguments as resources depending on the "context" of the string itself e.g. ClassPathXmlApplicationContext interprets string resources as classpath resources by default.
> Change DefaultImageSource to allow values in the imageResources map to be either resources or strings. Strings are converted to resources automatically by allowing DefaultImageSource to inherit from ResourceLoaderAware. We should probably also take map initialization out of the constructor or at least provide an alternative.
> There are other fancier ideas for creating image resolver objects that plug in a strategy for image resolution but this is probably sufficient for now. This also allows the issue around the ResourceMapFactoryBean class being removed in spring 3.0. Users could still use PropertiesLoaderSupport if they wanted to load properties files as well as ResourceMapFactoryBean if they are still on spring 2.5
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: https://jira.springsource.org/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
|