You are viewing a plain text version of this content. The canonical link for it is here.
Posted to scm@geronimo.apache.org by gn...@apache.org on 2009/06/18 12:06:07 UTC
svn commit: r785996 - in
/geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint:
container/ di/ utils/
Author: gnodet
Date: Thu Jun 18 10:06:00 2009
New Revision: 785996
URL: http://svn.apache.org/viewvc?rev=785996&view=rev
Log:
Refactor the map / collection / array conversion inside the AggregateConverter now that the interface allows it
Removed:
geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/utils/ConversionUtils.java
Modified:
geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/AggregateConverter.java
geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/BlueprintRepository.java
geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/RefListRecipe.java
geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/ReferenceRecipe.java
geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/di/CollectionRecipe.java
geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/di/MapRecipe.java
geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/utils/TypeUtils.java
Modified: geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/AggregateConverter.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/AggregateConverter.java?rev=785996&r1=785995&r2=785996&view=diff
==============================================================================
--- geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/AggregateConverter.java (original)
+++ geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/AggregateConverter.java Thu Jun 18 10:06:00 2009
@@ -20,15 +20,22 @@
import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
+import java.lang.reflect.GenericArrayType;
+import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Properties;
+import java.util.Collection;
+import java.util.Map;
import java.util.regex.Pattern;
import org.apache.geronimo.blueprint.ExtendedBlueprintContainer;
+import org.apache.geronimo.blueprint.di.MapRecipe;
+import org.apache.geronimo.blueprint.di.CollectionRecipe;
import static org.apache.geronimo.blueprint.utils.ReflectionUtils.getRealCause;
import org.apache.geronimo.blueprint.utils.TypeUtils;
+import static org.apache.geronimo.blueprint.utils.TypeUtils.toClass;
import org.osgi.service.blueprint.container.Converter;
/**
@@ -81,17 +88,33 @@
}
public Object convert(Object fromValue, Object toType) throws Exception {
+ // Discard null values
if (fromValue == null) {
return null;
}
Type type = (Type) toType;
- if (TypeUtils.isInstance(type, fromValue)) {
+ // First convert service proxies
+ if (fromValue instanceof Convertible) {
+ return ((Convertible) fromValue).convert(type);
+ }
+ // If the object is an instance of the type, just return it
+ // We need to pass through for arrays / maps / collections because of genenrics
+ if (TypeUtils.isInstance(type, fromValue)
+ && !toClass(type).isArray()
+ && !Map.class.isAssignableFrom(toClass(type))
+ && !Collection.class.isAssignableFrom(toClass(type))) {
return fromValue;
}
- Object value = doConvert(fromValue, type);
+ Object value = convertWithConverters(fromValue, type);
if (value == null) {
if (fromValue instanceof String && toType instanceof Class) {
- return convertString((String) fromValue, (Class) type);
+ return convertFromString((String) fromValue, (Class) type, blueprintContainer);
+ } else if (toClass(type).isArray()) {
+ return convertArray(fromValue, type);
+ } else if (Map.class.isAssignableFrom(toClass(type))) {
+ return convertMap(fromValue, type);
+ } else if (Collection.class.isAssignableFrom(toClass(type))) {
+ return convertCollection(fromValue, type);
} else {
throw new Exception("Unable to convert value " + fromValue + " to type " + type);
}
@@ -100,7 +123,7 @@
}
}
- private Object doConvert(Object source, Type type) throws Exception {
+ private Object convertWithConverters(Object source, Type type) throws Exception {
Object value = null;
for (Converter converter : converters) {
if (converter.canConvert(source, type)) {
@@ -113,20 +136,14 @@
return value;
}
- private Object convertString(String value, Class toType) throws Exception {
- if (Class.class == toType) {
+ public static Object convertFromString(String value, Class toType, Object loader) throws Exception {
+ if (Class.class == toType || Type.class == toType) {
try {
- return blueprintContainer.loadClass(value);
+ return TypeUtils.parseJavaType(value, loader);
} catch (ClassNotFoundException e) {
throw new Exception("Unable to convert", e);
}
- } else {
- return defaultConversion(value, toType);
- }
- }
-
- public static Object defaultConversion(String value, Class toType) throws Exception {
- if (Locale.class == toType) {
+ } else if (Locale.class == toType) {
String[] tokens = value.split("_");
if (tokens.length == 1) {
return new Locale(tokens[0]);
@@ -167,7 +184,7 @@
int code = Integer.parseInt(value.substring(2), 16);
return (char)code;
} else if (value.length() == 1) {
- return Character.valueOf(value.charAt(0));
+ return value.charAt(0);
} else {
throw new Exception("Invalid value for character type: " + value);
}
@@ -197,4 +214,79 @@
}
}
+ private Object convertCollection(Object obj, Type type) throws Exception {
+ Type valueType = Object.class;
+ Type[] typeParameters = TypeUtils.getTypeParameters(Collection.class, type);
+ if (typeParameters != null && typeParameters.length == 1) {
+ valueType = typeParameters[0];
+ }
+ Collection newCol = (Collection) CollectionRecipe.getCollection(toClass(type)).newInstance();
+ if (obj.getClass().isArray()) {
+ for (int i = 0; i < Array.getLength(obj); i++) {
+ try {
+ newCol.add(convert(Array.get(obj, i), valueType));
+ } catch (Exception t) {
+ throw new Exception("Unable to convert from " + obj + " to " + type + "(error converting array element)", t);
+ }
+ }
+ } else {
+ for (Object item : (Collection) obj) {
+ try {
+ newCol.add(convert(item, valueType));
+ } catch (Exception t) {
+ throw new Exception("Unable to convert from " + obj + " to " + type + "(error converting collection entry)", t);
+ }
+ }
+ }
+ return newCol;
+ }
+
+ private Object convertMap(Object obj, Type type) throws Exception {
+ Type keyType = Object.class;
+ Type valueType = Object.class;
+ Type[] typeParameters = TypeUtils.getTypeParameters(Map.class, type);
+ if (typeParameters != null && typeParameters.length == 2) {
+ keyType = typeParameters[0];
+ valueType = typeParameters[1];
+ }
+ Map newMap = (Map) MapRecipe.getMap(toClass(type)).newInstance();
+ for (Map.Entry e : ((Map<Object,Object>) obj).entrySet()) {
+ try {
+ newMap.put(convert(e.getKey(), keyType), convert(e.getValue(), valueType));
+ } catch (Exception t) {
+ throw new Exception("Unable to convert from " + obj + " to " + type + "(error converting map entry)", t);
+ }
+ }
+ return newMap;
+ }
+
+ private Object convertArray(Object obj, Type type) throws Exception {
+ if (obj instanceof Collection) {
+ obj = ((Collection) obj).toArray();
+ }
+ if (!obj.getClass().isArray()) {
+ throw new Exception("Unable to convert from " + obj + " to " + type);
+ }
+ Type componentType = type instanceof GenericArrayType
+ ? ((GenericArrayType) type).getGenericComponentType()
+ : toClass(type).getComponentType();
+ Object array = Array.newInstance(TypeUtils.toClass(componentType), Array.getLength(obj));
+ for (int i = 0; i < Array.getLength(obj); i++) {
+ try {
+ Array.set(array, i, convert(Array.get(obj, i), componentType));
+ } catch (Exception t) {
+ throw new Exception("Unable to convert from " + obj + " to " + type + "(error converting array element)", t);
+ }
+ }
+ return array;
+ }
+
+ /**
+ * Objects implementing this interface will bypass the default conversion rules
+ * and be called directly to transform into the expected type.
+ */
+ public static interface Convertible {
+
+ Object convert(Type type) throws Exception;
+ }
}
\ No newline at end of file
Modified: geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/BlueprintRepository.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/BlueprintRepository.java?rev=785996&r1=785995&r2=785996&view=diff
==============================================================================
--- geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/BlueprintRepository.java (original)
+++ geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/BlueprintRepository.java Thu Jun 18 10:06:00 2009
@@ -23,7 +23,6 @@
import java.util.Map;
import java.util.Set;
import java.util.LinkedHashMap;
-import java.util.HashMap;
import java.util.Collections;
import java.util.Collection;
import java.util.Arrays;
@@ -42,7 +41,6 @@
import org.apache.geronimo.blueprint.di.RefRecipe;
import org.apache.geronimo.blueprint.di.IdRefRecipe;
import org.apache.geronimo.blueprint.di.CircularDependencyException;
-import org.apache.geronimo.blueprint.utils.ConversionUtils;
import org.apache.geronimo.blueprint.ExtendedBlueprintContainer;
/**
@@ -144,7 +142,7 @@
Object obj = createInstance(name);
try {
// Make sure to go through the conversion step in case we have a Convertible object
- obj = ConversionUtils.convert(obj, Object.class, blueprintContainer.getConverter());
+ obj = convert(obj, Object.class);
} catch (Exception e) {
throw new ComponentDefinitionException("Unable to convert instance " + name, e);
}
@@ -315,7 +313,7 @@
}
public Object convert(Object value, Type type) throws Exception {
- return ConversionUtils.convert(value, type, blueprintContainer.getConverter());
+ return blueprintContainer.getConverter().convert(value, type);
}
public Class loadClass(String typeName) throws ClassNotFoundException {
Modified: geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/RefListRecipe.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/RefListRecipe.java?rev=785996&r1=785995&r2=785996&view=diff
==============================================================================
--- geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/RefListRecipe.java (original)
+++ geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/RefListRecipe.java Thu Jun 18 10:06:00 2009
@@ -34,7 +34,6 @@
import org.apache.geronimo.blueprint.ExtendedBlueprintContainer;
import org.apache.geronimo.blueprint.ExtendedRefListMetadata;
import org.apache.geronimo.blueprint.di.Recipe;
-import org.apache.geronimo.blueprint.utils.ConversionUtils;
import org.apache.geronimo.blueprint.utils.DynamicCollection;
import org.apache.geronimo.blueprint.utils.TypeUtils;
import org.osgi.framework.Constants;
@@ -229,7 +228,7 @@
}
- public class ProvidedObject implements ConversionUtils.Convertible {
+ public class ProvidedObject implements AggregateConverter.Convertible {
public Object convert(Type type) {
LOGGER.debug("Converting ManagedCollection to {}", type);
Modified: geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/ReferenceRecipe.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/ReferenceRecipe.java?rev=785996&r1=785995&r2=785996&view=diff
==============================================================================
--- geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/ReferenceRecipe.java (original)
+++ geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/ReferenceRecipe.java Thu Jun 18 10:06:00 2009
@@ -25,7 +25,6 @@
import org.apache.geronimo.blueprint.ExtendedBlueprintContainer;
import org.apache.geronimo.blueprint.di.Recipe;
-import org.apache.geronimo.blueprint.utils.ConversionUtils;
import org.apache.geronimo.blueprint.utils.TypeUtils;
import org.osgi.framework.ServiceReference;
import org.osgi.service.blueprint.container.BlueprintEvent;
@@ -206,7 +205,7 @@
}
- public class ServiceProxyWrapper implements ConversionUtils.Convertible {
+ public class ServiceProxyWrapper implements AggregateConverter.Convertible {
public Object convert(Type type) throws Exception {
if (type == ServiceReference.class) {
Modified: geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/di/CollectionRecipe.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/di/CollectionRecipe.java?rev=785996&r1=785995&r2=785996&view=diff
==============================================================================
--- geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/di/CollectionRecipe.java (original)
+++ geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/di/CollectionRecipe.java Thu Jun 18 10:06:00 2009
@@ -19,8 +19,13 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
+import java.util.SortedSet;
+import java.util.TreeSet;
+import java.util.Set;
+import java.util.LinkedHashSet;
+import java.util.Queue;
+import java.util.LinkedList;
-import org.apache.geronimo.blueprint.utils.ConversionUtils;
import org.apache.geronimo.blueprint.utils.TypeUtils;
import org.osgi.service.blueprint.container.ComponentDefinitionException;
@@ -50,7 +55,7 @@
}
protected Object internalCreate() throws ComponentDefinitionException {
- Class type = ConversionUtils.getCollection(typeClass);
+ Class type = getCollection(typeClass);
if (!TypeUtils.hasDefaultConstructor(type)) {
throw new ComponentDefinitionException("Type does not have a default constructor " + type.getName());
@@ -88,4 +93,19 @@
list.add(value);
}
+ public static Class getCollection(Class type) {
+ if (TypeUtils.hasDefaultConstructor(type)) {
+ return type;
+ } else if (SortedSet.class.isAssignableFrom(type)) {
+ return TreeSet.class;
+ } else if (Set.class.isAssignableFrom(type)) {
+ return LinkedHashSet.class;
+ } else if (List.class.isAssignableFrom(type)) {
+ return ArrayList.class;
+ } else if (Queue.class.isAssignableFrom(type)) {
+ return LinkedList.class;
+ } else {
+ return ArrayList.class;
+ }
+ }
}
Modified: geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/di/MapRecipe.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/di/MapRecipe.java?rev=785996&r1=785995&r2=785996&view=diff
==============================================================================
--- geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/di/MapRecipe.java (original)
+++ geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/di/MapRecipe.java Thu Jun 18 10:06:00 2009
@@ -22,8 +22,12 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.SortedMap;
+import java.util.TreeMap;
+import java.util.LinkedHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.ConcurrentHashMap;
-import org.apache.geronimo.blueprint.utils.ConversionUtils;
import org.apache.geronimo.blueprint.utils.TypeUtils;
import org.osgi.service.blueprint.container.ComponentDefinitionException;
@@ -54,7 +58,7 @@
}
protected Object internalCreate() throws ComponentDefinitionException {
- Class mapType = ConversionUtils.getMap(typeClass);
+ Class mapType = getMap(typeClass);
if (!TypeUtils.hasDefaultConstructor(mapType)) {
throw new ComponentDefinitionException("Type does not have a default constructor " + mapType.getName());
@@ -99,6 +103,18 @@
}
}
+ public static Class getMap(Class type) {
+ if (TypeUtils.hasDefaultConstructor(type)) {
+ return type;
+ } else if (SortedMap.class.isAssignableFrom(type)) {
+ return TreeMap.class;
+ } else if (ConcurrentMap.class.isAssignableFrom(type)) {
+ return ConcurrentHashMap.class;
+ } else {
+ return LinkedHashMap.class;
+ }
+ }
+
public static class DummyDictionaryAsMap extends AbstractMap {
private final Dictionary dictionary;
Modified: geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/utils/TypeUtils.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/utils/TypeUtils.java?rev=785996&r1=785995&r2=785996&view=diff
==============================================================================
--- geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/utils/TypeUtils.java (original)
+++ geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/utils/TypeUtils.java Thu Jun 18 10:06:00 2009
@@ -90,6 +90,7 @@
}
public static boolean isAssignable(Type expectedType, Type actualType) {
+ // TODO: check parameterized Collection / Maps / Arrays ?
Class expectedClass = toClass(expectedType);
Class actualClass = toClass(actualType);
return expectedClass.isAssignableFrom(actualClass);
@@ -171,6 +172,7 @@
}
public static Type parseJavaType(String type, Object loader) throws ClassNotFoundException {
+ // TODO: support wilcards for generics
type = type.trim();
// Check if this is an array
if (type.endsWith("[]")) {