commons-beanutilsでハマったこと


```commons-beanutils``` のバージョンを```1.8.3```から```1.9.2```にあげたところ、
```ConvertUtils.register(new CharacterConverter("0"), Character.class);```
がfromのpropertyが```null```のときに動かなかった。
原因は次のコードの変化によるものだった。

```BeanUtilsBean.java(commons-beanutils-1.8.3)
  ・
  ・
  ・
    public void copyProperty(Object bean, String name, Object value)
        throws IllegalAccessException, InvocationTargetException {
  ・
  ・
  ・
        // Convert the specified value to the required type and store it
        if (index >= 0) {                    // Destination must be indexed
            value = convert(value, type.getComponentType());
            try {
                getPropertyUtils().setIndexedProperty(target, propName,
                                                 index, value);
            } catch (NoSuchMethodException e) {
                throw new InvocationTargetException
                    (e, "Cannot set " + propName);
            }
        } else if (key != null) {            // Destination must be mapped
            // Maps do not know what the preferred data type is,
            // so perform no conversions at all
            // FIXME - should we create or support a TypedMap?
            try {
                getPropertyUtils().setMappedProperty(target, propName,
                                                key, value);
            } catch (NoSuchMethodException e) {
                throw new InvocationTargetException
                    (e, "Cannot set " + propName);
            }
        } else {                             // Destination must be simple
            value = convert(value, type);
            try {
                getPropertyUtils().setSimpleProperty(target, propName, value);
            } catch (NoSuchMethodException e) {
                throw new InvocationTargetException
                    (e, "Cannot set " + propName);
            }
        }

    }
  ・
  ・
  ・
    protected Object convert(Object value, Class type) {
        Converter converter = getConvertUtils().lookup(type);
        if (converter != null) {
            log.trace("        USING CONVERTER " + converter);
            return converter.convert(type, value);
        } else {
            return value;
        }
    }
  ・
  ・
  ・
```

```BeanUtilsBean.java(commons-beanUtils-1.9.2)
    public void copyProperty(Object bean, String name, Object value)
        throws IllegalAccessException, InvocationTargetException {
  ・
  ・
  ・
        // Convert the specified value to the required type and store it
        if (index >= 0) {                    // Destination must be indexed
            value = convertForCopy(value, type.getComponentType());
            try {
                getPropertyUtils().setIndexedProperty(target, propName,
                                                 index, value);
            } catch (NoSuchMethodException e) {
                throw new InvocationTargetException
                    (e, "Cannot set " + propName);
            }
        } else if (key != null) {            // Destination must be mapped
            // Maps do not know what the preferred data type is,
            // so perform no conversions at all
            // FIXME - should we create or support a TypedMap?
            try {
                getPropertyUtils().setMappedProperty(target, propName,
                                                key, value);
            } catch (NoSuchMethodException e) {
                throw new InvocationTargetException
                    (e, "Cannot set " + propName);
            }
        } else {                             // Destination must be simple
            value = convertForCopy(value, type);
            try {
                getPropertyUtils().setSimpleProperty(target, propName, value);
            } catch (NoSuchMethodException e) {
                throw new InvocationTargetException
                    (e, "Cannot set " + propName);
            }
        }

    }
  ・
  ・
  ・
    protected Object convert(Object value, Class<?> type) {
        Converter converter = getConvertUtils().lookup(type);
        if (converter != null) {
            log.trace("        USING CONVERTER " + converter);
            return converter.convert(type, value);
        } else {
            return value;
        }
    }
    
    private Object convertForCopy(Object value, Class<?> type) {
        return (value != null) ? convert(value, type) : value;
    }
  ・
  ・
  ・
    
```

今までfromのpropertyが```null```のときは、Converterの```defaultValue```が使われていたのに、
```1.9.2```では使わないようになっていた。

この変化は改悪だと思うんだけどなー