Fix a bug when the configuration admin send configurations containing Strings (Objects was expected). In this case, the objects are re-created from the Strings (arrays are parsed by according to the iPOJO syntax). This change impacts both service properties and instance properties.
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@615540 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/configuration/ConfigurableProperty.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/configuration/ConfigurableProperty.java
index 1ce6c98..26db364 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/configuration/ConfigurableProperty.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/configuration/ConfigurableProperty.java
@@ -104,14 +104,14 @@
}
}
-
+
/**
* The set type method fix the property type according to the given type name.
* @param type : the type name
* @throws ConfigurationException if an error occurs when loading the type class for non-primitive types.
*/
private void setType(String type) throws ConfigurationException {
- // Syntactic sugar to avoid writing java.lang.String
+ // Syntactic sugar to avoid writing java.lang.String
if ("string".equals(type) || "String".equals(type)) {
m_type = java.lang.String.class;
return;
@@ -203,7 +203,7 @@
throw new ConfigurationException("Argument problem to call the constructor of the type " + internalType);
}
}
-
+
// Non array, complex type.
try {
m_type = m_handler.getInstanceManager().getContext().getBundle().loadClass(type);
@@ -459,7 +459,191 @@
* @param value : the new value.
*/
public void setValue(Object value) {
- m_value = value;
+ // Is the object is directly assignable to the property, affect it.
+ if (isAssignable(m_type, value)) {
+ m_value = value;
+ } else {
+ // If the object is a String, we must recreate the object from the String form
+ if (value instanceof String) {
+ try {
+ m_value = create(m_type, (String) value);
+ } catch (ConfigurationException e) {
+ throw new ClassCastException("Incompatible type for the property " + m_name + " : " + e.getMessage());
+ }
+ } else {
+ // Error, the given property cannot be injected.
+ throw new ClassCastException("Incompatible type for the property " + m_name + " " + m_type.getName() + " expected, " + value.getClass() + " received");
+ }
+ }
+ }
+
+ /**
+ * Test if the given value is assignable to the given type.
+ * @param type : class of the type
+ * @param value : object to check
+ * @return true if the object is assignable in the property of type 'type'.
+ */
+ public static boolean isAssignable(Class type, Object value) {
+ if (type.isInstance(value)) {
+ return true;
+ } else if (type.isPrimitive()) {
+ // Manage all boxing types.
+ if (value instanceof Boolean && type.equals(Boolean.TYPE)) {
+ return true;
+ }
+ if (value instanceof Byte && type.equals(Byte.TYPE)) {
+ return true;
+ }
+ if (value instanceof Short && type.equals(Short.TYPE)) {
+ return true;
+ }
+ if (value instanceof Integer && type.equals(Integer.TYPE)) {
+ return true;
+ }
+ if (value instanceof Long && type.equals(Long.TYPE)) {
+ return true;
+ }
+ if (value instanceof Float && type.equals(Float.TYPE)) {
+ return true;
+ }
+ if (value instanceof Double && type.equals(Double.TYPE)) {
+ return true;
+ }
+ if (value instanceof Character && type.equals(Character.TYPE)) {
+ return true;
+ }
+ return false;
+ } else {
+ // Else return false.
+ return false;
+ }
+ }
+
+ /**
+ * Create an object of the given type with the given String value.
+ * @param type : type of the returned object
+ * @param strValue : String value.
+ * @return the object of type 'type' created from the String 'value'
+ * @throws ConfigurationException occurs when the object cannot be created.
+ */
+ public static Object create(Class type, String strValue) throws ConfigurationException {
+ if (type.equals(Boolean.TYPE)) { return new Boolean(strValue); }
+ if (type.equals(Byte.TYPE)) { return new Byte(strValue); }
+ if (type.equals(Short.TYPE)) { return new Short(strValue); }
+ if (type.equals(Integer.TYPE)) { return new Integer(strValue); }
+ if (type.equals(Long.TYPE)) { return new Long(strValue); }
+ if (type.equals(Float.TYPE)) { return new Float(strValue); }
+ if (type.equals(Double.TYPE)) { return new Double(strValue); }
+ if (type.equals(Character.TYPE)) { return new Character(strValue.charAt(0)); }
+
+ // Array :
+ if (type.isArray()) { return createArrayObject(type.getComponentType(), ParseUtils.parseArrays(strValue)); }
+ // Else it is a neither a primitive type neither a String -> create
+ // the object by calling a constructor with a string in argument.
+ try {
+ Constructor cst = type.getConstructor(new Class[] { String.class });
+ return cst.newInstance(new Object[] { strValue });
+ } catch (SecurityException e) {
+ throw new ConfigurationException("Security exception in create on " + type + " : " + e.getMessage());
+ } catch (NoSuchMethodException e) {
+ throw new ConfigurationException("Constructor not found exception in create on " + type + " : " + e.getMessage());
+ } catch (IllegalArgumentException e) {
+ throw new ConfigurationException("Argument problem to call the constructor of the type " + type);
+ } catch (InstantiationException e) {
+ throw new ConfigurationException("Instantiation problem " + type);
+ } catch (IllegalAccessException e) {
+ throw new ConfigurationException("Illegal Access " + type);
+ } catch (InvocationTargetException e) {
+ throw new ConfigurationException("Invocation problem " + type + " : " + e.getTargetException().getMessage());
+ }
+
+ }
+
+ /**
+ * Create an array object containing the type 'interntype' from the String array 'values'.
+ * @param interntype : internal type of the array.
+ * @param values : String array
+ * @return the array containing objects created from the 'values' array
+ * @throws ConfigurationException occurs when the array cannot be created correctly
+ */
+ public static Object createArrayObject(Class interntype, String[] values) throws ConfigurationException {
+ if (interntype.equals(Boolean.TYPE)) {
+ boolean[] bool = new boolean[values.length];
+ for (int i = 0; i < values.length; i++) {
+ bool[i] = new Boolean(values[i]).booleanValue();
+ }
+ return bool;
+ }
+ if (interntype.equals(Byte.TYPE)) {
+ byte[] byt = new byte[values.length];
+ for (int i = 0; i < values.length; i++) {
+ byt[i] = new Byte(values[i]).byteValue();
+ }
+ return byt;
+ }
+ if (interntype.equals(Short.TYPE)) {
+ short[] shor = new short[values.length];
+ for (int i = 0; i < values.length; i++) {
+ shor[i] = new Short(values[i]).shortValue();
+ }
+ return shor;
+ }
+ if (interntype.equals(Integer.TYPE)) {
+ int[] in = new int[values.length];
+ for (int i = 0; i < values.length; i++) {
+ in[i] = new Integer(values[i]).intValue();
+ }
+ return in;
+ }
+ if (interntype.equals(Long.TYPE)) {
+ long[] ll = new long[values.length];
+ for (int i = 0; i < values.length; i++) {
+ ll[i] = new Long(values[i]).longValue();
+ }
+ return ll;
+ }
+ if (interntype.equals(Float.TYPE)) {
+ float[] fl = new float[values.length];
+ for (int i = 0; i < values.length; i++) {
+ fl[i] = new Float(values[i]).floatValue();
+ }
+ return fl;
+ }
+ if (interntype.equals(Double.TYPE)) {
+ double[] dl = new double[values.length];
+ for (int i = 0; i < values.length; i++) {
+ dl[i] = new Double(values[i]).doubleValue();
+ }
+ return dl;
+ }
+ if (interntype.equals(Character.TYPE)) {
+ char[] dl = new char[values.length];
+ for (int i = 0; i < values.length; i++) {
+ dl[i] = values[i].toCharArray()[0];
+ }
+ return dl;
+ }
+
+ // Else it is a neither a primitive type -> create the
+ // object by calling a constructor with a string in argument.
+ try {
+ Constructor cst = interntype.getConstructor(new Class[] { String.class });
+ Object[] ob = (Object[]) Array.newInstance(interntype, values.length);
+ for (int i = 0; i < values.length; i++) {
+ ob[i] = cst.newInstance(new Object[] { values[i].trim() });
+ }
+ return ob;
+ } catch (NoSuchMethodException e) {
+ throw new ConfigurationException("Constructor not found exception in setValue on " + interntype.getName());
+ } catch (IllegalArgumentException e) {
+ throw new ConfigurationException("Argument problem to call the constructor of the type " + interntype.getName());
+ } catch (InstantiationException e) {
+ throw new ConfigurationException("Instantiation problem " + interntype.getName());
+ } catch (IllegalAccessException e) {
+ throw new ConfigurationException("Illegal Access Exception in " + interntype.getName());
+ } catch (InvocationTargetException e) {
+ throw new ConfigurationException("Invocation problem " + interntype.getName() + " : " + e.getTargetException().getMessage());
+ }
}
/**
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/providedservice/Property.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/providedservice/Property.java
index 20488bb..f6b3b6f 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/providedservice/Property.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/providedservice/Property.java
@@ -132,7 +132,18 @@
* @param o : the new value of the property (object)
*/
protected void set(Object o) {
- m_value = o;
+ // Is the object is directly assignable to the property, affect it.
+ if (!(o instanceof String) || m_type.equals("java.lang.String")) {
+ m_value = o;
+ } else {
+ // If the object is a String, we must recreate the object from the String form
+ if (o instanceof String) {
+ setValue((String) o);
+ } else {
+ // Error, the given property cannot be injected.
+ throw new ClassCastException("Incompatible type for the property " + m_name + " " + m_type + " expected");
+ }
+ }
}
/**