All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
aQute.configurable.Configurable Maven / Gradle / Ivy
package aQute.configurable;
import static java.nio.charset.StandardCharsets.UTF_8;
import java.io.File;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Proxy;
import java.lang.reflect.Type;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.Set;
import java.util.SortedMap;
import java.util.SortedSet;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.regex.Pattern;
public class Configurable {
public static Pattern SPLITTER_P = Pattern.compile("(? T createConfigurable(Class c, Map, ?> properties) {
Object o = Proxy.newProxyInstance(c.getClassLoader(), new Class>[] {
c
}, new ConfigurableHandler(properties, c.getClassLoader()));
return c.cast(o);
}
public static T createConfigurable(Class c, Dictionary, ?> properties) {
Map alt = new HashMap<>();
for (Enumeration> e = properties.keys(); e.hasMoreElements();) {
Object key = e.nextElement();
alt.put(key, properties.get(key));
}
return createConfigurable(c, alt);
}
static class ConfigurableHandler implements InvocationHandler {
final Map, ?> properties;
final ClassLoader loader;
ConfigurableHandler(Map, ?> properties, ClassLoader loader) {
this.properties = properties;
this.loader = loader;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Config ad = method.getAnnotation(Config.class);
String id = Configurable.mangleMethodName(method.getName());
if (ad != null && !ad.id()
.equals(Config.NULL))
id = ad.id();
Object o = properties.get(id);
if (o == null && args != null && args.length == 1)
o = args[0];
if (o == null) {
if (ad != null) {
if (ad.required())
throw new IllegalStateException("Attribute is required but not set " + method.getName());
o = ad.deflt();
if (o.equals(Config.NULL))
o = null;
}
}
if (o == null) {
Class> rt = method.getReturnType();
if (rt == boolean.class || rt == Boolean.class)
return false;
if (method.getReturnType()
.isPrimitive() || Number.class.isAssignableFrom(method.getReturnType())) {
o = "0";
} else
return null;
}
if (args != null && args.length == 1) {
String s = (String) convert(String.class, o);
// Allow a base to be specified for File and URL
if (method.getReturnType() == File.class && args[0].getClass() == File.class) {
return new File((File) args[0], s);
} else if (method.getReturnType() == URL.class && args[0].getClass() == File.class) {
return new URL(((File) args[0]).toURI()
.toURL(), s);
} else if (method.getReturnType() == URL.class && args[0].getClass() == URL.class) {
return new URL((URL) args[0], s);
}
}
return convert(method.getGenericReturnType(), o);
}
@SuppressWarnings({
"unchecked", "rawtypes"
})
public Object convert(Type type, Object o) throws Exception {
// TODO type variables
// TODO wildcards
if (type instanceof ParameterizedType) {
ParameterizedType pType = (ParameterizedType) type;
return convert(pType, o);
}
if (type instanceof GenericArrayType) {
GenericArrayType gType = (GenericArrayType) type;
return convertArray(gType.getGenericComponentType(), o);
}
Class> resultType = (Class>) type;
if (resultType.isArray()) {
return convertArray(resultType.getComponentType(), o);
}
Class> actualType = o.getClass();
if (actualType.isAssignableFrom(resultType))
return o;
if (resultType == boolean.class || resultType == Boolean.class) {
if (actualType == boolean.class || actualType == Boolean.class)
return o;
if (Number.class.isAssignableFrom(actualType)) {
double b = ((Number) o).doubleValue();
if (b == 0)
return false;
return true;
}
return true;
} else if (resultType == byte.class || resultType == Byte.class) {
if (Number.class.isAssignableFrom(actualType))
return ((Number) o).byteValue();
resultType = Byte.class;
} else if (resultType == char.class) {
resultType = Character.class;
} else if (resultType == short.class) {
if (Number.class.isAssignableFrom(actualType))
return ((Number) o).shortValue();
resultType = Short.class;
} else if (resultType == int.class) {
if (Number.class.isAssignableFrom(actualType))
return ((Number) o).intValue();
resultType = Integer.class;
} else if (resultType == long.class) {
if (Number.class.isAssignableFrom(actualType))
return ((Number) o).longValue();
resultType = Long.class;
} else if (resultType == float.class) {
if (Number.class.isAssignableFrom(actualType))
return ((Number) o).floatValue();
resultType = Float.class;
} else if (resultType == double.class) {
if (Number.class.isAssignableFrom(actualType))
return ((Number) o).doubleValue();
resultType = Double.class;
}
if (resultType.isPrimitive())
throw new IllegalArgumentException("Unknown primitive: " + resultType);
if (Number.class.isAssignableFrom(resultType) && actualType == Boolean.class) {
Boolean b = (Boolean) o;
o = b ? "1" : "0";
} else if (actualType == String.class) {
String input = (String) o;
if (Enum.class.isAssignableFrom(resultType)) {
return Enum.valueOf((Class) resultType, input);
}
if (resultType == Class.class && loader != null) {
return loader.loadClass(input);
}
if (resultType == Pattern.class) {
return Pattern.compile(input);
}
}
try {
Constructor> c = resultType.getConstructor(String.class);
return c.newInstance(o.toString());
} catch (Throwable t) {
// handled on next line
}
throw new IllegalArgumentException(
"No conversion to " + resultType + " from " + actualType + " value " + o);
}
private Object convert(ParameterizedType pType, Object o)
throws InstantiationException, IllegalAccessException, Exception {
Class> resultType = (Class>) pType.getRawType();
if (Collection.class.isAssignableFrom(resultType)) {
Collection> input = toCollection(o);
if (resultType.isInterface()) {
if (resultType == Collection.class || resultType == List.class)
resultType = ArrayList.class;
else if (resultType == Set.class || resultType == SortedSet.class)
resultType = TreeSet.class;
else if (resultType == Queue.class /*
* || resultType ==
* Deque.class
*/)
resultType = LinkedList.class;
else if (resultType == Queue.class /*
* || resultType ==
* Deque.class
*/)
resultType = LinkedList.class;
else
throw new IllegalArgumentException(
"Unknown interface for a collection, no concrete class found: " + resultType);
}
@SuppressWarnings("unchecked")
Collection result = (Collection) resultType.getConstructor()
.newInstance();
Type componentType = pType.getActualTypeArguments()[0];
for (Object i : input) {
result.add(convert(componentType, i));
}
return result;
} else if (pType.getRawType() == Class.class) {
return loader.loadClass(o.toString());
}
if (Map.class.isAssignableFrom(resultType)) {
Map, ?> input = toMap(o);
if (resultType.isInterface()) {
if (resultType == SortedMap.class)
resultType = TreeMap.class;
else if (resultType == Map.class)
resultType = LinkedHashMap.class;
else
throw new IllegalArgumentException(
"Unknown interface for a collection, no concrete class found: " + resultType);
}
@SuppressWarnings("unchecked")
Map result = (Map) resultType.getConstructor()
.newInstance();
Type keyType = pType.getActualTypeArguments()[0];
Type valueType = pType.getActualTypeArguments()[1];
for (Map.Entry, ?> entry : input.entrySet()) {
result.put(convert(keyType, entry.getKey()), convert(valueType, entry.getValue()));
}
return result;
}
throw new IllegalArgumentException(
"cannot convert to " + pType + " because it uses generics and is not a Collection or a map");
}
Object convertArray(Type componentType, Object o) throws Exception {
if (o instanceof String) {
String s = (String) o;
if (componentType == Byte.class || componentType == byte.class)
return s.getBytes(UTF_8);
if (componentType == Character.class || componentType == char.class)
return s.toCharArray();
}
Collection> input = toCollection(o);
Class> componentClass = getRawClass(componentType);
Object array = Array.newInstance(componentClass, input.size());
int i = 0;
for (Object next : input) {
Array.set(array, i++, convert(componentType, next));
}
return array;
}
private Class> getRawClass(Type type) {
if (type instanceof Class)
return (Class>) type;
if (type instanceof ParameterizedType)
return (Class>) ((ParameterizedType) type).getRawType();
throw new IllegalArgumentException(
"For the raw type, type must be ParamaterizedType or Class but is " + type);
}
private Collection> toCollection(Object o) {
if (o instanceof Collection)
return (Collection>) o;
if (o.getClass()
.isArray()) {
if (o.getClass()
.getComponentType()
.isPrimitive()) {
int length = Array.getLength(o);
List result = new ArrayList<>(length);
for (int i = 0; i < length; i++) {
result.add(Array.get(o, i));
}
return result;
}
return Arrays.asList((Object[]) o);
}
if (o instanceof String) {
String s = (String) o;
if (SPLITTER_P.matcher(s)
.find())
return Arrays.asList(s.split("\\|"));
else
return unescape(s);
}
return Arrays.asList(o);
}
private Map, ?> toMap(Object o) {
if (o instanceof Map)
return (Map, ?>) o;
throw new IllegalArgumentException("Cannot convert " + o + " to a map as requested");
}
}
public static String mangleMethodName(String id) {
StringBuilder sb = new StringBuilder(id);
for (int i = 0; i < sb.length(); i++) {
char c = sb.charAt(i);
boolean twice = i < sb.length() - 1 && sb.charAt(i + 1) == c;
if (c == '$' || c == '_') {
if (twice)
sb.deleteCharAt(i + 1);
else if (c == '$')
sb.deleteCharAt(i--); // Remove dollars
else
sb.setCharAt(i, '.'); // Make _ into .
}
}
return sb.toString();
}
public static List unescape(String s) {
// do it the OSGi way
List tokens = new ArrayList<>();
String[] parts = s.split("(?