/*
* Copyright (C) 2011 Nicolas Peransin. All rights reserved.
* Use is subject to license terms.
*/
package org.mypsycho.swing.app.reflect;
import java.awt.Image;
import java.lang.ref.Reference;
import java.lang.ref.SoftReference;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import org.mypsycho.beans.InjectionContext;
import org.mypsycho.beans.converter.AbstractTypeConverter;
/**
* Class for ...
* <p>Details</p>
*
* @author Peransin Nicolas
*
*/
public class ResourceConverter extends AbstractTypeConverter {
/**
*
*/
public ResourceConverter() {
super(Icon.class, Image.class, URL.class);
}
/*
* (non-Javadoc)
*
* @see com.psycho.beans.converter.TypeConverter#convert(java.lang.Class, java.lang.String,
* java.lang.Object)
*/
@Override
public Object convert(Class<?> expected, String value, Object context)
throws IllegalArgumentException {
if ((value == null) || value.isEmpty()) {
return null;
}
URI uri = null;
try {
uri = new URI(value);
} catch (URISyntaxException e) {
throw new IllegalArgumentException("Invalid uri " + value, e);
}
if (URI.class.isAssignableFrom(expected)) {
return uri;
}
URL location = null;
if (uri.getScheme() != null) {
try {
location = uri.toURL();
} catch (MalformedURLException e) {
reThrow("Invalid url " + value, e);
}
} else {
Class<?> current = context.getClass();
if (context instanceof InjectionContext) {
current = ((InjectionContext) context).getRoot().getClass();
}
location = searchResource(uri, current, current.getClassLoader());
}
if (location == null) {
return null;
}
if (URL.class.isAssignableFrom(expected)) {
return location;
}
if (Icon.class.isAssignableFrom(expected)) {
return ref(new ImageIcon(location));
}
if (Image.class.isAssignableFrom(expected)) {
return ref(new ImageIcon(location).getImage());
}
throw new IllegalArgumentException("Unexpected class " + expected.getName());
}
URL searchResource(URI uri, Class<?> current, ClassLoader cl) {
if (current == null) {
return null;
}
if (cl == null) {
cl = ClassLoader.getSystemClassLoader();
}
// else resource
if (uri.getPath().startsWith("/")) {
return cl.getResource(uri.getPath().substring(1));
}
URI ref = resolvePath(current);
String path = ref.resolve(uri).getPath(); // Handle parent '..'
URL res = !path.startsWith("/../") ? cl.getResource(path.substring(1)) : null;
return (res != null) ? res : searchResource(uri, current.getSuperclass(), cl);
}
private URI resolvePath(Class<?> c) {
while (c.isArray()) {
c = c.getComponentType();
}
String path = "/" + c.getName().replace('.', '/');
try {
return new URI(path);
} catch (URISyntaxException e) { // Impossible ?
return reThrow("Unknown class name syntax: " + path, e);
}
}
private static <T> Reference<T> ref(T o) {
return new SoftReference<T>(o);
}
}