Use diamonds.
diff --git a/src/main/java/org/apache/commons/beanutils2/MappedPropertyDescriptor.java b/src/main/java/org/apache/commons/beanutils2/MappedPropertyDescriptor.java
index a798409..7248794 100644
--- a/src/main/java/org/apache/commons/beanutils2/MappedPropertyDescriptor.java
+++ b/src/main/java/org/apache/commons/beanutils2/MappedPropertyDescriptor.java
@@ -1,529 +1,529 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.beanutils2;
-
-
-import java.beans.IntrospectionException;
-import java.beans.PropertyDescriptor;
-import java.lang.ref.Reference;
-import java.lang.ref.SoftReference;
-import java.lang.ref.WeakReference;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-
-
-/**
- * A MappedPropertyDescriptor describes one mapped property.
- * Mapped properties are multivalued properties like indexed properties
- * but that are accessed with a String key instead of an index.
- * Such property values are typically stored in a Map collection.
- * For this class to work properly, a mapped value must have
- * getter and setter methods of the form
- * <p><code>get<strong>Property</strong>(String key)</code> and
- * <p><code>set<strong>Property</strong>(String key, Object value)</code>,
- * <p>where <code><strong>Property</strong></code> must be replaced
- * by the name of the property.
- * @see java.beans.PropertyDescriptor
- *
- */
-public class MappedPropertyDescriptor extends PropertyDescriptor {
-    // ----------------------------------------------------- Instance Variables
-
-    /**
-     * The underlying data type of the property we are describing.
-     */
-    private Reference<Class<?>> mappedPropertyTypeRef;
-
-    /**
-     * The reader method for this property (if any).
-     */
-    private MappedMethodReference mappedReadMethodRef;
-
-    /**
-     * The writer method for this property (if any).
-     */
-    private MappedMethodReference mappedWriteMethodRef;
-
-    /**
-     * The parameter types array for the reader method signature.
-     */
-    private static final Class<?>[] STRING_CLASS_PARAMETER = new Class[]{String.class};
-
-    // ----------------------------------------------------------- Constructors
-
-    /**
-     * Constructs a MappedPropertyDescriptor for a property that follows
-     * the standard Java convention by having getFoo and setFoo
-     * accessor methods, with the addition of a String parameter (the key).
-     * Thus if the argument name is "fred", it will
-     * assume that the writer method is "setFred" and the reader method
-     * is "getFred".  Note that the property name should start with a lower
-     * case character, which will be capitalized in the method names.
-     *
-     * @param propertyName The programmatic name of the property.
-     * @param beanClass The Class object for the target bean.  For
-     *        example sun.beans.OurButton.class.
-     *
-     * @throws IntrospectionException if an exception occurs during
-     *              introspection.
-     */
-    public MappedPropertyDescriptor(final String propertyName, final Class<?> beanClass)
-            throws IntrospectionException {
-
-        super(propertyName, null, null);
-
-        if (propertyName == null || propertyName.length() == 0) {
-            throw new IntrospectionException("bad property name: " +
-                    propertyName + " on class: " + beanClass.getClass().getName());
-        }
-
-        setName(propertyName);
-        final String base = capitalizePropertyName(propertyName);
-
-        // Look for mapped read method and matching write method
-        Method mappedReadMethod = null;
-        Method mappedWriteMethod = null;
-        try {
-            try {
-                mappedReadMethod = getMethod(beanClass, "get" + base,
-                        STRING_CLASS_PARAMETER);
-            } catch (final IntrospectionException e) {
-                mappedReadMethod = getMethod(beanClass, "is" + base,
-                        STRING_CLASS_PARAMETER);
-            }
-            final Class<?>[] params = { String.class, mappedReadMethod.getReturnType() };
-            mappedWriteMethod = getMethod(beanClass, "set" + base, params);
-        } catch (final IntrospectionException e) {
-            /* Swallow IntrospectionException
-             * TODO: Why?
-             */
-        }
-
-        // If there's no read method, then look for just a write method
-        if (mappedReadMethod == null) {
-            mappedWriteMethod = getMethod(beanClass, "set" + base, 2);
-        }
-
-        if (mappedReadMethod == null && mappedWriteMethod == null) {
-            throw new IntrospectionException("Property '" + propertyName +
-                    "' not found on " +
-                    beanClass.getName());
-        }
-        mappedReadMethodRef  = new MappedMethodReference(mappedReadMethod);
-        mappedWriteMethodRef = new MappedMethodReference(mappedWriteMethod);
-
-        findMappedPropertyType();
-    }
-
-
-    /**
-     * This constructor takes the name of a mapped property, and method
-     * names for reading and writing the property.
-     *
-     * @param propertyName The programmatic name of the property.
-     * @param beanClass The Class object for the target bean.  For
-     *        example sun.beans.OurButton.class.
-     * @param mappedGetterName The name of the method used for
-     *          reading one of the property values.  May be null if the
-     *          property is write-only.
-     * @param mappedSetterName The name of the method used for writing
-     *          one of the property values.  May be null if the property is
-     *          read-only.
-     *
-     * @throws IntrospectionException if an exception occurs during
-     *              introspection.
-     */
-    public MappedPropertyDescriptor(final String propertyName, final Class<?> beanClass,
-                                    final String mappedGetterName, final String mappedSetterName)
-            throws IntrospectionException {
-
-        super(propertyName, null, null);
-
-        if (propertyName == null || propertyName.length() == 0) {
-            throw new IntrospectionException("bad property name: " +
-                    propertyName);
-        }
-        setName(propertyName);
-
-        // search the mapped get and set methods
-        Method mappedReadMethod = null;
-        Method mappedWriteMethod = null;
-        mappedReadMethod =
-            getMethod(beanClass, mappedGetterName, STRING_CLASS_PARAMETER);
-
-        if (mappedReadMethod != null) {
-            final Class<?>[] params = { String.class, mappedReadMethod.getReturnType() };
-            mappedWriteMethod =
-                getMethod(beanClass, mappedSetterName, params);
-        } else {
-            mappedWriteMethod =
-                getMethod(beanClass, mappedSetterName, 2);
-        }
-        mappedReadMethodRef  = new MappedMethodReference(mappedReadMethod);
-        mappedWriteMethodRef = new MappedMethodReference(mappedWriteMethod);
-
-        findMappedPropertyType();
-    }
-
-    /**
-     * This constructor takes the name of a mapped property, and Method
-     * objects for reading and writing the property.
-     *
-     * @param propertyName The programmatic name of the property.
-     * @param mappedGetter The method used for reading one of
-     *          the property values.  May be be null if the property
-     *          is write-only.
-     * @param mappedSetter The method used for writing one the
-     *          property values.  May be null if the property is read-only.
-     *
-     * @throws IntrospectionException if an exception occurs during
-     *              introspection.
-     */
-    public MappedPropertyDescriptor(final String propertyName,
-                                    final Method mappedGetter, final Method mappedSetter)
-            throws IntrospectionException {
-
-        super(propertyName, mappedGetter, mappedSetter);
-
-        if (propertyName == null || propertyName.length() == 0) {
-            throw new IntrospectionException("bad property name: " +
-                    propertyName);
-        }
-
-        setName(propertyName);
-        mappedReadMethodRef  = new MappedMethodReference(mappedGetter);
-        mappedWriteMethodRef = new MappedMethodReference(mappedSetter);
-        findMappedPropertyType();
-    }
-
-    // -------------------------------------------------------- Public Methods
-
-    /**
-     * Gets the Class object for the property values.
-     *
-     * @return The Java type info for the property values.  Note that
-     * the "Class" object may describe a built-in Java type such as "int".
-     * The result may be "null" if this is a mapped property that
-     * does not support non-keyed access.
-     * <p>
-     * This is the type that will be returned by the mappedReadMethod.
-     */
-    public Class<?> getMappedPropertyType() {
-        return mappedPropertyTypeRef.get();
-    }
-
-    /**
-     * Gets the method that should be used to read one of the property value.
-     *
-     * @return The method that should be used to read the property value.
-     * May return null if the property can't be read.
-     */
-    public Method getMappedReadMethod() {
-        return mappedReadMethodRef.get();
-    }
-
-    /**
-     * Sets the method that should be used to read one of the property value.
-     *
-     * @param mappedGetter The mapped getter method.
-     * @throws IntrospectionException If an error occurs finding the
-     * mapped property
-     */
-    public void setMappedReadMethod(final Method mappedGetter)
-            throws IntrospectionException {
-        mappedReadMethodRef = new MappedMethodReference(mappedGetter);
-        findMappedPropertyType();
-    }
-
-    /**
-     * Gets the method that should be used to write one of the property value.
-     *
-     * @return The method that should be used to write one of the property value.
-     * May return null if the property can't be written.
-     */
-    public Method getMappedWriteMethod() {
-        return mappedWriteMethodRef.get();
-    }
-
-    /**
-     * Sets the method that should be used to write the property value.
-     *
-     * @param mappedSetter The mapped setter method.
-     * @throws IntrospectionException If an error occurs finding the
-     * mapped property
-     */
-    public void setMappedWriteMethod(final Method mappedSetter)
-            throws IntrospectionException {
-        mappedWriteMethodRef = new MappedMethodReference(mappedSetter);
-        findMappedPropertyType();
-    }
-
-    // ------------------------------------------------------- Private Methods
-
-    /**
-     * Introspect our bean class to identify the corresponding getter
-     * and setter methods.
-     */
-    private void findMappedPropertyType() throws IntrospectionException {
-        try {
-            final Method mappedReadMethod  = getMappedReadMethod();
-            final Method mappedWriteMethod = getMappedWriteMethod();
-            Class<?> mappedPropertyType = null;
-            if (mappedReadMethod != null) {
-                if (mappedReadMethod.getParameterTypes().length != 1) {
-                    throw new IntrospectionException
-                            ("bad mapped read method arg count");
-                }
-                mappedPropertyType = mappedReadMethod.getReturnType();
-                if (mappedPropertyType == Void.TYPE) {
-                    throw new IntrospectionException
-                            ("mapped read method " +
-                            mappedReadMethod.getName() + " returns void");
-                }
-            }
-
-            if (mappedWriteMethod != null) {
-                final Class<?>[] params = mappedWriteMethod.getParameterTypes();
-                if (params.length != 2) {
-                    throw new IntrospectionException
-                            ("bad mapped write method arg count");
-                }
-                if (mappedPropertyType != null &&
-                        mappedPropertyType != params[1]) {
-                    throw new IntrospectionException
-                            ("type mismatch between mapped read and write methods");
-                }
-                mappedPropertyType = params[1];
-            }
-            mappedPropertyTypeRef = new SoftReference<Class<?>>(mappedPropertyType);
-        } catch (final IntrospectionException ex) {
-            throw ex;
-        }
-    }
-
-
-    /**
-     * Return a capitalized version of the specified property name.
-     *
-     * @param s The property name
-     */
-    private static String capitalizePropertyName(final String s) {
-        if (s.length() == 0) {
-            return s;
-        }
-
-        final char[] chars = s.toCharArray();
-        chars[0] = Character.toUpperCase(chars[0]);
-        return new String(chars);
-    }
-
-    /**
-     * Find a method on a class with a specified number of parameters.
-     */
-    private static Method internalGetMethod(final Class<?> initial, final String methodName,
-                                            final int parameterCount) {
-        // For overridden methods we need to find the most derived version.
-        // So we start with the given class and walk up the superclass chain.
-        for (Class<?> clazz = initial; clazz != null; clazz = clazz.getSuperclass()) {
-            final Method[] methods = clazz.getDeclaredMethods();
-            for (final Method method : methods) {
-                if (method == null) {
-                    continue;
-                }
-                // skip static methods.
-                final int mods = method.getModifiers();
-                if (!Modifier.isPublic(mods) ||
-                    Modifier.isStatic(mods)) {
-                    continue;
-                }
-                if (method.getName().equals(methodName) &&
-                        method.getParameterTypes().length == parameterCount) {
-                    return method;
-                }
-            }
-        }
-
-        // Now check any inherited interfaces.  This is necessary both when
-        // the argument class is itself an interface, and when the argument
-        // class is an abstract class.
-        final Class<?>[] interfaces = initial.getInterfaces();
-        for (final Class<?> interface1 : interfaces) {
-            final Method method = internalGetMethod(interface1, methodName, parameterCount);
-            if (method != null) {
-                return method;
-            }
-        }
-
-        return null;
-    }
-
-    /**
-     * Find a method on a class with a specified number of parameters.
-     */
-    private static Method getMethod(final Class<?> clazz, final String methodName, final int parameterCount)
-            throws IntrospectionException {
-        if (methodName == null) {
-            return null;
-        }
-
-        final Method method = internalGetMethod(clazz, methodName, parameterCount);
-        if (method != null) {
-            return method;
-        }
-
-        // No Method found
-        throw new IntrospectionException("No method \"" + methodName +
-                "\" with " + parameterCount + " parameter(s)");
-    }
-
-    /**
-     * Find a method on a class with a specified parameter list.
-     */
-    private static Method getMethod(final Class<?> clazz, final String methodName, final Class<?>[] parameterTypes)
-                                           throws IntrospectionException {
-        if (methodName == null) {
-            return null;
-        }
-
-        final Method method = MethodUtils.getMatchingAccessibleMethod(clazz, methodName, parameterTypes);
-        if (method != null) {
-            return method;
-        }
-
-        final int parameterCount = parameterTypes == null ? 0 : parameterTypes.length;
-
-        // No Method found
-        throw new IntrospectionException("No method \"" + methodName +
-                "\" with " + parameterCount + " parameter(s) of matching types.");
-    }
-
-    /**
-     * Holds a {@link Method} in a {@link SoftReference} so that it
-     * it doesn't prevent any ClassLoader being garbage collected, but
-     * tries to re-create the method if the method reference has been
-     * released.
-     *
-     * See https://issues.apache.org/jira/browse/BEANUTILS-291
-     */
-    private static class MappedMethodReference {
-        private String className;
-        private String methodName;
-        private Reference<Method> methodRef;
-        private Reference<Class<?>> classRef;
-        private Reference<Class<?>> writeParamTypeRef0;
-        private Reference<Class<?>> writeParamTypeRef1;
-        private String[] writeParamClassNames;
-        MappedMethodReference(final Method m) {
-            if (m != null) {
-                className = m.getDeclaringClass().getName();
-                methodName = m.getName();
-                methodRef = new SoftReference<>(m);
-                classRef = new WeakReference<Class<?>>(m.getDeclaringClass());
-                final Class<?>[] types = m.getParameterTypes();
-                if (types.length == 2) {
-                    writeParamTypeRef0 = new WeakReference<Class<?>>(types[0]);
-                    writeParamTypeRef1 = new WeakReference<Class<?>>(types[1]);
-                    writeParamClassNames = new String[2];
-                    writeParamClassNames[0] = types[0].getName();
-                    writeParamClassNames[1] = types[1].getName();
-                }
-            }
-        }
-        private Method get() {
-            if (methodRef == null) {
-                return null;
-            }
-            Method m = methodRef.get();
-            if (m == null) {
-                Class<?> clazz = classRef.get();
-                if (clazz == null) {
-                    clazz = reLoadClass();
-                    if (clazz != null) {
-                        classRef = new WeakReference<Class<?>>(clazz);
-                    }
-                }
-                if (clazz == null) {
-                    throw new RuntimeException("Method " + methodName + " for " +
-                            className + " could not be reconstructed - class reference has gone");
-                }
-                Class<?>[] paramTypes = null;
-                if (writeParamClassNames != null) {
-                    paramTypes = new Class[2];
-                    paramTypes[0] = writeParamTypeRef0.get();
-                    if (paramTypes[0] == null) {
-                        paramTypes[0] = reLoadClass(writeParamClassNames[0]);
-                        if (paramTypes[0] != null) {
-                            writeParamTypeRef0 = new WeakReference<Class<?>>(paramTypes[0]);
-                        }
-                    }
-                    paramTypes[1] = writeParamTypeRef1.get();
-                    if (paramTypes[1] == null) {
-                        paramTypes[1] = reLoadClass(writeParamClassNames[1]);
-                        if (paramTypes[1] != null) {
-                            writeParamTypeRef1 = new WeakReference<Class<?>>(paramTypes[1]);
-                        }
-                    }
-                } else {
-                    paramTypes = STRING_CLASS_PARAMETER;
-                }
-                try {
-                    m = clazz.getMethod(methodName, paramTypes);
-                    // Un-comment following line for testing
-                    // System.out.println("Recreated Method " + methodName + " for " + className);
-                } catch (final NoSuchMethodException e) {
-                    throw new RuntimeException("Method " + methodName + " for " +
-                            className + " could not be reconstructed - method not found");
-                }
-                methodRef = new SoftReference<>(m);
-            }
-            return m;
-        }
-
-        /**
-         * Try to re-load the class
-         */
-        private Class<?> reLoadClass() {
-            return reLoadClass(className);
-        }
-
-        /**
-         * Try to re-load the class
-         */
-        private Class<?> reLoadClass(final String name) {
-
-            ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
-
-            // Try the context class loader
-            if (classLoader != null) {
-                try {
-                    return classLoader.loadClass(name);
-                } catch (final ClassNotFoundException e) {
-                    // ignore
-                }
-            }
-
-            // Try this class's class loader
-            classLoader = MappedPropertyDescriptor.class.getClassLoader();
-            try {
-                return classLoader.loadClass(name);
-            } catch (final ClassNotFoundException e) {
-                return null;
-            }
-        }
-    }
-}
+/*

+ * Licensed to the Apache Software Foundation (ASF) under one or more

+ * contributor license agreements.  See the NOTICE file distributed with

+ * this work for additional information regarding copyright ownership.

+ * The ASF licenses this file to You under the Apache License, Version 2.0

+ * (the "License"); you may not use this file except in compliance with

+ * the License.  You may obtain a copy of the License at

+ *

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+

+package org.apache.commons.beanutils2;

+

+

+import java.beans.IntrospectionException;

+import java.beans.PropertyDescriptor;

+import java.lang.ref.Reference;

+import java.lang.ref.SoftReference;

+import java.lang.ref.WeakReference;

+import java.lang.reflect.Method;

+import java.lang.reflect.Modifier;

+

+

+/**

+ * A MappedPropertyDescriptor describes one mapped property.

+ * Mapped properties are multivalued properties like indexed properties

+ * but that are accessed with a String key instead of an index.

+ * Such property values are typically stored in a Map collection.

+ * For this class to work properly, a mapped value must have

+ * getter and setter methods of the form

+ * <p><code>get<strong>Property</strong>(String key)</code> and

+ * <p><code>set<strong>Property</strong>(String key, Object value)</code>,

+ * <p>where <code><strong>Property</strong></code> must be replaced

+ * by the name of the property.

+ * @see java.beans.PropertyDescriptor

+ *

+ */

+public class MappedPropertyDescriptor extends PropertyDescriptor {

+    // ----------------------------------------------------- Instance Variables

+

+    /**

+     * The underlying data type of the property we are describing.

+     */

+    private Reference<Class<?>> mappedPropertyTypeRef;

+

+    /**

+     * The reader method for this property (if any).

+     */

+    private MappedMethodReference mappedReadMethodRef;

+

+    /**

+     * The writer method for this property (if any).

+     */

+    private MappedMethodReference mappedWriteMethodRef;

+

+    /**

+     * The parameter types array for the reader method signature.

+     */

+    private static final Class<?>[] STRING_CLASS_PARAMETER = new Class[]{String.class};

+

+    // ----------------------------------------------------------- Constructors

+

+    /**

+     * Constructs a MappedPropertyDescriptor for a property that follows

+     * the standard Java convention by having getFoo and setFoo

+     * accessor methods, with the addition of a String parameter (the key).

+     * Thus if the argument name is "fred", it will

+     * assume that the writer method is "setFred" and the reader method

+     * is "getFred".  Note that the property name should start with a lower

+     * case character, which will be capitalized in the method names.

+     *

+     * @param propertyName The programmatic name of the property.

+     * @param beanClass The Class object for the target bean.  For

+     *        example sun.beans.OurButton.class.

+     *

+     * @throws IntrospectionException if an exception occurs during

+     *              introspection.

+     */

+    public MappedPropertyDescriptor(final String propertyName, final Class<?> beanClass)

+            throws IntrospectionException {

+

+        super(propertyName, null, null);

+

+        if (propertyName == null || propertyName.length() == 0) {

+            throw new IntrospectionException("bad property name: " +

+                    propertyName + " on class: " + beanClass.getClass().getName());

+        }

+

+        setName(propertyName);

+        final String base = capitalizePropertyName(propertyName);

+

+        // Look for mapped read method and matching write method

+        Method mappedReadMethod = null;

+        Method mappedWriteMethod = null;

+        try {

+            try {

+                mappedReadMethod = getMethod(beanClass, "get" + base,

+                        STRING_CLASS_PARAMETER);

+            } catch (final IntrospectionException e) {

+                mappedReadMethod = getMethod(beanClass, "is" + base,

+                        STRING_CLASS_PARAMETER);

+            }

+            final Class<?>[] params = { String.class, mappedReadMethod.getReturnType() };

+            mappedWriteMethod = getMethod(beanClass, "set" + base, params);

+        } catch (final IntrospectionException e) {

+            /* Swallow IntrospectionException

+             * TODO: Why?

+             */

+        }

+

+        // If there's no read method, then look for just a write method

+        if (mappedReadMethod == null) {

+            mappedWriteMethod = getMethod(beanClass, "set" + base, 2);

+        }

+

+        if (mappedReadMethod == null && mappedWriteMethod == null) {

+            throw new IntrospectionException("Property '" + propertyName +

+                    "' not found on " +

+                    beanClass.getName());

+        }

+        mappedReadMethodRef  = new MappedMethodReference(mappedReadMethod);

+        mappedWriteMethodRef = new MappedMethodReference(mappedWriteMethod);

+

+        findMappedPropertyType();

+    }

+

+

+    /**

+     * This constructor takes the name of a mapped property, and method

+     * names for reading and writing the property.

+     *

+     * @param propertyName The programmatic name of the property.

+     * @param beanClass The Class object for the target bean.  For

+     *        example sun.beans.OurButton.class.

+     * @param mappedGetterName The name of the method used for

+     *          reading one of the property values.  May be null if the

+     *          property is write-only.

+     * @param mappedSetterName The name of the method used for writing

+     *          one of the property values.  May be null if the property is

+     *          read-only.

+     *

+     * @throws IntrospectionException if an exception occurs during

+     *              introspection.

+     */

+    public MappedPropertyDescriptor(final String propertyName, final Class<?> beanClass,

+                                    final String mappedGetterName, final String mappedSetterName)

+            throws IntrospectionException {

+

+        super(propertyName, null, null);

+

+        if (propertyName == null || propertyName.length() == 0) {

+            throw new IntrospectionException("bad property name: " +

+                    propertyName);

+        }

+        setName(propertyName);

+

+        // search the mapped get and set methods

+        Method mappedReadMethod = null;

+        Method mappedWriteMethod = null;

+        mappedReadMethod =

+            getMethod(beanClass, mappedGetterName, STRING_CLASS_PARAMETER);

+

+        if (mappedReadMethod != null) {

+            final Class<?>[] params = { String.class, mappedReadMethod.getReturnType() };

+            mappedWriteMethod =

+                getMethod(beanClass, mappedSetterName, params);

+        } else {

+            mappedWriteMethod =

+                getMethod(beanClass, mappedSetterName, 2);

+        }

+        mappedReadMethodRef  = new MappedMethodReference(mappedReadMethod);

+        mappedWriteMethodRef = new MappedMethodReference(mappedWriteMethod);

+

+        findMappedPropertyType();

+    }

+

+    /**

+     * This constructor takes the name of a mapped property, and Method

+     * objects for reading and writing the property.

+     *

+     * @param propertyName The programmatic name of the property.

+     * @param mappedGetter The method used for reading one of

+     *          the property values.  May be be null if the property

+     *          is write-only.

+     * @param mappedSetter The method used for writing one the

+     *          property values.  May be null if the property is read-only.

+     *

+     * @throws IntrospectionException if an exception occurs during

+     *              introspection.

+     */

+    public MappedPropertyDescriptor(final String propertyName,

+                                    final Method mappedGetter, final Method mappedSetter)

+            throws IntrospectionException {

+

+        super(propertyName, mappedGetter, mappedSetter);

+

+        if (propertyName == null || propertyName.length() == 0) {

+            throw new IntrospectionException("bad property name: " +

+                    propertyName);

+        }

+

+        setName(propertyName);

+        mappedReadMethodRef  = new MappedMethodReference(mappedGetter);

+        mappedWriteMethodRef = new MappedMethodReference(mappedSetter);

+        findMappedPropertyType();

+    }

+

+    // -------------------------------------------------------- Public Methods

+

+    /**

+     * Gets the Class object for the property values.

+     *

+     * @return The Java type info for the property values.  Note that

+     * the "Class" object may describe a built-in Java type such as "int".

+     * The result may be "null" if this is a mapped property that

+     * does not support non-keyed access.

+     * <p>

+     * This is the type that will be returned by the mappedReadMethod.

+     */

+    public Class<?> getMappedPropertyType() {

+        return mappedPropertyTypeRef.get();

+    }

+

+    /**

+     * Gets the method that should be used to read one of the property value.

+     *

+     * @return The method that should be used to read the property value.

+     * May return null if the property can't be read.

+     */

+    public Method getMappedReadMethod() {

+        return mappedReadMethodRef.get();

+    }

+

+    /**

+     * Sets the method that should be used to read one of the property value.

+     *

+     * @param mappedGetter The mapped getter method.

+     * @throws IntrospectionException If an error occurs finding the

+     * mapped property

+     */

+    public void setMappedReadMethod(final Method mappedGetter)

+            throws IntrospectionException {

+        mappedReadMethodRef = new MappedMethodReference(mappedGetter);

+        findMappedPropertyType();

+    }

+

+    /**

+     * Gets the method that should be used to write one of the property value.

+     *

+     * @return The method that should be used to write one of the property value.

+     * May return null if the property can't be written.

+     */

+    public Method getMappedWriteMethod() {

+        return mappedWriteMethodRef.get();

+    }

+

+    /**

+     * Sets the method that should be used to write the property value.

+     *

+     * @param mappedSetter The mapped setter method.

+     * @throws IntrospectionException If an error occurs finding the

+     * mapped property

+     */

+    public void setMappedWriteMethod(final Method mappedSetter)

+            throws IntrospectionException {

+        mappedWriteMethodRef = new MappedMethodReference(mappedSetter);

+        findMappedPropertyType();

+    }

+

+    // ------------------------------------------------------- Private Methods

+

+    /**

+     * Introspect our bean class to identify the corresponding getter

+     * and setter methods.

+     */

+    private void findMappedPropertyType() throws IntrospectionException {

+        try {

+            final Method mappedReadMethod  = getMappedReadMethod();

+            final Method mappedWriteMethod = getMappedWriteMethod();

+            Class<?> mappedPropertyType = null;

+            if (mappedReadMethod != null) {

+                if (mappedReadMethod.getParameterTypes().length != 1) {

+                    throw new IntrospectionException

+                            ("bad mapped read method arg count");

+                }

+                mappedPropertyType = mappedReadMethod.getReturnType();

+                if (mappedPropertyType == Void.TYPE) {

+                    throw new IntrospectionException

+                            ("mapped read method " +

+                            mappedReadMethod.getName() + " returns void");

+                }

+            }

+

+            if (mappedWriteMethod != null) {

+                final Class<?>[] params = mappedWriteMethod.getParameterTypes();

+                if (params.length != 2) {

+                    throw new IntrospectionException

+                            ("bad mapped write method arg count");

+                }

+                if (mappedPropertyType != null &&

+                        mappedPropertyType != params[1]) {

+                    throw new IntrospectionException

+                            ("type mismatch between mapped read and write methods");

+                }

+                mappedPropertyType = params[1];

+            }

+            mappedPropertyTypeRef = new SoftReference<>(mappedPropertyType);

+        } catch (final IntrospectionException ex) {

+            throw ex;

+        }

+    }

+

+

+    /**

+     * Return a capitalized version of the specified property name.

+     *

+     * @param s The property name

+     */

+    private static String capitalizePropertyName(final String s) {

+        if (s.length() == 0) {

+            return s;

+        }

+

+        final char[] chars = s.toCharArray();

+        chars[0] = Character.toUpperCase(chars[0]);

+        return new String(chars);

+    }

+

+    /**

+     * Find a method on a class with a specified number of parameters.

+     */

+    private static Method internalGetMethod(final Class<?> initial, final String methodName,

+                                            final int parameterCount) {

+        // For overridden methods we need to find the most derived version.

+        // So we start with the given class and walk up the superclass chain.

+        for (Class<?> clazz = initial; clazz != null; clazz = clazz.getSuperclass()) {

+            final Method[] methods = clazz.getDeclaredMethods();

+            for (final Method method : methods) {

+                if (method == null) {

+                    continue;

+                }

+                // skip static methods.

+                final int mods = method.getModifiers();

+                if (!Modifier.isPublic(mods) ||

+                    Modifier.isStatic(mods)) {

+                    continue;

+                }

+                if (method.getName().equals(methodName) &&

+                        method.getParameterTypes().length == parameterCount) {

+                    return method;

+                }

+            }

+        }

+

+        // Now check any inherited interfaces.  This is necessary both when

+        // the argument class is itself an interface, and when the argument

+        // class is an abstract class.

+        final Class<?>[] interfaces = initial.getInterfaces();

+        for (final Class<?> interface1 : interfaces) {

+            final Method method = internalGetMethod(interface1, methodName, parameterCount);

+            if (method != null) {

+                return method;

+            }

+        }

+

+        return null;

+    }

+

+    /**

+     * Find a method on a class with a specified number of parameters.

+     */

+    private static Method getMethod(final Class<?> clazz, final String methodName, final int parameterCount)

+            throws IntrospectionException {

+        if (methodName == null) {

+            return null;

+        }

+

+        final Method method = internalGetMethod(clazz, methodName, parameterCount);

+        if (method != null) {

+            return method;

+        }

+

+        // No Method found

+        throw new IntrospectionException("No method \"" + methodName +

+                "\" with " + parameterCount + " parameter(s)");

+    }

+

+    /**

+     * Find a method on a class with a specified parameter list.

+     */

+    private static Method getMethod(final Class<?> clazz, final String methodName, final Class<?>[] parameterTypes)

+                                           throws IntrospectionException {

+        if (methodName == null) {

+            return null;

+        }

+

+        final Method method = MethodUtils.getMatchingAccessibleMethod(clazz, methodName, parameterTypes);

+        if (method != null) {

+            return method;

+        }

+

+        final int parameterCount = parameterTypes == null ? 0 : parameterTypes.length;

+

+        // No Method found

+        throw new IntrospectionException("No method \"" + methodName +

+                "\" with " + parameterCount + " parameter(s) of matching types.");

+    }

+

+    /**

+     * Holds a {@link Method} in a {@link SoftReference} so that it

+     * it doesn't prevent any ClassLoader being garbage collected, but

+     * tries to re-create the method if the method reference has been

+     * released.

+     *

+     * See https://issues.apache.org/jira/browse/BEANUTILS-291

+     */

+    private static class MappedMethodReference {

+        private String className;

+        private String methodName;

+        private Reference<Method> methodRef;

+        private Reference<Class<?>> classRef;

+        private Reference<Class<?>> writeParamTypeRef0;

+        private Reference<Class<?>> writeParamTypeRef1;

+        private String[] writeParamClassNames;

+        MappedMethodReference(final Method m) {

+            if (m != null) {

+                className = m.getDeclaringClass().getName();

+                methodName = m.getName();

+                methodRef = new SoftReference<>(m);

+                classRef = new WeakReference<>(m.getDeclaringClass());

+                final Class<?>[] types = m.getParameterTypes();

+                if (types.length == 2) {

+                    writeParamTypeRef0 = new WeakReference<>(types[0]);

+                    writeParamTypeRef1 = new WeakReference<>(types[1]);

+                    writeParamClassNames = new String[2];

+                    writeParamClassNames[0] = types[0].getName();

+                    writeParamClassNames[1] = types[1].getName();

+                }

+            }

+        }

+        private Method get() {

+            if (methodRef == null) {

+                return null;

+            }

+            Method m = methodRef.get();

+            if (m == null) {

+                Class<?> clazz = classRef.get();

+                if (clazz == null) {

+                    clazz = reLoadClass();

+                    if (clazz != null) {

+                        classRef = new WeakReference<>(clazz);

+                    }

+                }

+                if (clazz == null) {

+                    throw new RuntimeException("Method " + methodName + " for " +

+                            className + " could not be reconstructed - class reference has gone");

+                }

+                Class<?>[] paramTypes = null;

+                if (writeParamClassNames != null) {

+                    paramTypes = new Class[2];

+                    paramTypes[0] = writeParamTypeRef0.get();

+                    if (paramTypes[0] == null) {

+                        paramTypes[0] = reLoadClass(writeParamClassNames[0]);

+                        if (paramTypes[0] != null) {

+                            writeParamTypeRef0 = new WeakReference<>(paramTypes[0]);

+                        }

+                    }

+                    paramTypes[1] = writeParamTypeRef1.get();

+                    if (paramTypes[1] == null) {

+                        paramTypes[1] = reLoadClass(writeParamClassNames[1]);

+                        if (paramTypes[1] != null) {

+                            writeParamTypeRef1 = new WeakReference<>(paramTypes[1]);

+                        }

+                    }

+                } else {

+                    paramTypes = STRING_CLASS_PARAMETER;

+                }

+                try {

+                    m = clazz.getMethod(methodName, paramTypes);

+                    // Un-comment following line for testing

+                    // System.out.println("Recreated Method " + methodName + " for " + className);

+                } catch (final NoSuchMethodException e) {

+                    throw new RuntimeException("Method " + methodName + " for " +

+                            className + " could not be reconstructed - method not found");

+                }

+                methodRef = new SoftReference<>(m);

+            }

+            return m;

+        }

+

+        /**

+         * Try to re-load the class

+         */

+        private Class<?> reLoadClass() {

+            return reLoadClass(className);

+        }

+

+        /**

+         * Try to re-load the class

+         */

+        private Class<?> reLoadClass(final String name) {

+

+            ClassLoader classLoader = Thread.currentThread().getContextClassLoader();

+

+            // Try the context class loader

+            if (classLoader != null) {

+                try {

+                    return classLoader.loadClass(name);

+                } catch (final ClassNotFoundException e) {

+                    // ignore

+                }

+            }

+

+            // Try this class's class loader

+            classLoader = MappedPropertyDescriptor.class.getClassLoader();

+            try {

+                return classLoader.loadClass(name);

+            } catch (final ClassNotFoundException e) {

+                return null;

+            }

+        }

+    }

+}

diff --git a/src/main/java/org/apache/commons/beanutils2/WrapDynaClass.java b/src/main/java/org/apache/commons/beanutils2/WrapDynaClass.java
index 00f1008..2d298b4 100644
--- a/src/main/java/org/apache/commons/beanutils2/WrapDynaClass.java
+++ b/src/main/java/org/apache/commons/beanutils2/WrapDynaClass.java
@@ -58,7 +58,7 @@
      */

     private WrapDynaClass(final Class<?> beanClass, final PropertyUtilsBean propUtils) {

 

-        this.beanClassRef = new SoftReference<Class<?>>(beanClass);

+        this.beanClassRef = new SoftReference<>(beanClass);

         this.beanClassName = beanClass.getName();

         propertyUtilsBean = propUtils;

         introspect();

diff --git a/src/test/java/org/apache/commons/beanutils2/BeanificationTestCase.java b/src/test/java/org/apache/commons/beanutils2/BeanificationTestCase.java
index 18ae331..a2381b3 100644
--- a/src/test/java/org/apache/commons/beanutils2/BeanificationTestCase.java
+++ b/src/test/java/org/apache/commons/beanutils2/BeanificationTestCase.java
@@ -1,544 +1,544 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.beanutils2;
-
-import java.lang.ref.ReferenceQueue;
-import java.lang.ref.WeakReference;
-import java.util.Map;
-import java.util.WeakHashMap;
-
-import org.apache.commons.logging.LogFactory;
-
-import junit.framework.Test;
-import junit.framework.TestCase;
-import junit.framework.TestSuite;
-
-/**
- * <p>
- * Test Case for changes made during Beanutils Beanification
- * </p>
- *
- */
-
-public class BeanificationTestCase extends TestCase {
-
-    // ---------------------------------------------------- Constants
-
-    /** Maximum number of iterations before our test fails */
-    public static final int MAX_GC_ITERATIONS = 50;
-
-    // ---------------------------------------------------- Instance Variables
-
-
-    // ---------------------------------------------------------- Constructors
-
-
-    /**
-     * Construct a new instance of this test case.
-     *
-     * @param name Name of the test case
-     */
-    public BeanificationTestCase(final String name) {
-        super(name);
-    }
-
-
-    // -------------------------------------------------- Overall Test Methods
-
-
-    /**
-     * Set up instance variables required by this test case.
-     */
-    @Override
-    public void setUp() {
-
-        ConvertUtils.deregister();
-
-    }
-
-
-    /**
-     * Return the tests included in this test suite.
-     */
-    public static Test suite() {
-        return new TestSuite(BeanificationTestCase.class);
-    }
-
-
-    /**
-     * Tear down instance variables required by this test case.
-     */
-    @Override
-    public void tearDown() {
-        // No action required
-    }
-
-
-    // ------------------------------------------------ Individual Test Methods
-
-    /** Test of the methodology we'll use for some of the later tests */
-    public void testMemoryTestMethodology() throws Exception {
-        // test methodology
-        // many thanks to Juozas Baliuka for suggesting this method
-        ClassLoader loader = new ClassLoader(this.getClass().getClassLoader()) {};
-        final WeakReference<ClassLoader> reference = new  WeakReference<>(loader);
-        @SuppressWarnings("unused")
-        Class<?> myClass = loader.loadClass("org.apache.commons.beanutils2.BetaBean");
-
-        assertNotNull("Weak reference released early", reference.get());
-
-        // dereference class loader and class:
-        loader = null;
-        myClass = null;
-
-        int iterations = 0;
-        int bytz = 2;
-        while(true) {
-            System.gc();
-            if(iterations++ > MAX_GC_ITERATIONS){
-                fail("Max iterations reached before resource released.");
-            }
-            if( reference.get() == null ) {
-                break;
-
-            }
-            // create garbage:
-            @SuppressWarnings("unused")
-            final
-            byte[] b =  new byte[bytz];
-            bytz = bytz * 2;
-        }
-    }
-
-    /** Tests whether classloaders and beans are released from memory by the map used by beanutils */
-    public void testMemoryLeak2() throws Exception {
-        // tests when the map used by beanutils has the right behaviour
-
-        if (BeanUtilsTestCase.isPre14JVM()) {
-            System.out.println("WARNING: CANNOT TEST MEMORY LEAK ON PRE1.4 JVM");
-            return;
-        }
-
-        // many thanks to Juozas Baliuka for suggesting this methodology
-        TestClassLoader loader = new TestClassLoader();
-        final ReferenceQueue<Object> queue = new ReferenceQueue<>();
-        final WeakReference<ClassLoader> loaderReference = new WeakReference<ClassLoader>(loader, queue);
-        Integer test = new Integer(1);
-
-        final WeakReference<Integer> testReference = new WeakReference<>(test, queue);
-        //Map map = new ReferenceMap(ReferenceMap.WEAK, ReferenceMap.HARD, true);
-        final Map<Object, Object> map = new WeakHashMap<>();
-        map.put(loader, test);
-
-        assertEquals("In map", test, map.get(loader));
-        assertNotNull("Weak reference released early (1)", loaderReference.get());
-        assertNotNull("Weak reference released early (2)", testReference.get());
-
-        // dereference strong references
-        loader = null;
-        test = null;
-
-        int iterations = 0;
-        int bytz = 2;
-        while(true) {
-            System.gc();
-            if(iterations++ > MAX_GC_ITERATIONS){
-                fail("Max iterations reached before resource released.");
-            }
-            map.isEmpty();
-
-            if(
-                loaderReference.get() == null &&
-                testReference.get() == null) {
-                break;
-
-            }
-            // create garbage:
-            @SuppressWarnings("unused")
-            final
-            byte[] b =  new byte[bytz];
-            bytz = bytz * 2;
-        }
-    }
-
-    /** Tests whether classloaders and beans are released from memory */
-    public void testMemoryLeak() throws Exception {
-        if (BeanUtilsTestCase.isPre14JVM()) {
-            System.out.println("WARNING: CANNOT TEST MEMORY LEAK ON PRE1.4 JVM");
-            return;
-        }
-
-        // many thanks to Juozas Baliuka for suggesting this methodology
-        TestClassLoader loader = new TestClassLoader();
-        final WeakReference<ClassLoader> loaderReference = new  WeakReference<ClassLoader>(loader);
-        BeanUtilsBean.getInstance();
-
-        class GetBeanUtilsBeanThread extends Thread {
-
-            BeanUtilsBean beanUtils;
-            ConvertUtilsBean convertUtils;
-            PropertyUtilsBean propertyUtils;
-
-            GetBeanUtilsBeanThread() {}
-
-            @Override
-            public void run() {
-                beanUtils = BeanUtilsBean.getInstance();
-                convertUtils = ConvertUtilsBean.getInstance();
-                propertyUtils = PropertyUtilsBean.getInstance();
-                // XXX Log keeps a reference around!
-                LogFactory.releaseAll();
-            }
-
-            @Override
-            public String toString() {
-                return "GetBeanUtilsBeanThread";
-            }
-        }
-
-
-        GetBeanUtilsBeanThread thread = new GetBeanUtilsBeanThread();
-        @SuppressWarnings("unused")
-        final
-        WeakReference<Thread> threadWeakReference = new WeakReference<Thread>(thread);
-        thread.setContextClassLoader(loader);
-
-        thread.start();
-        thread.join();
-
-        final WeakReference<BeanUtilsBean> beanUtilsReference = new WeakReference<>(thread.beanUtils);
-        final WeakReference<PropertyUtilsBean> propertyUtilsReference =  new WeakReference<>(thread.propertyUtils);
-        final WeakReference<ConvertUtilsBean> convertUtilsReference = new WeakReference<>(thread.convertUtils);
-
-        assertNotNull("Weak reference released early (1)", loaderReference.get());
-        assertNotNull("Weak reference released early (2)", beanUtilsReference.get());
-        assertNotNull("Weak reference released early (3)", propertyUtilsReference.get());
-        assertNotNull("Weak reference released early (4)", convertUtilsReference.get());
-
-        // dereference strong references
-        loader = null;
-        thread.setContextClassLoader(null);
-        thread = null;
-
-        int iterations = 0;
-        int bytz = 2;
-        while(true) {
-            BeanUtilsBean.getInstance();
-            System.gc();
-            if(iterations++ > MAX_GC_ITERATIONS){
-                fail("Max iterations reached before resource released.");
-            }
-
-            if(
-                loaderReference.get() == null &&
-                beanUtilsReference.get() == null &&
-                propertyUtilsReference.get() == null &&
-                convertUtilsReference.get() == null) {
-                break;
-
-            }
-            // create garbage:
-            @SuppressWarnings("unused")
-            final
-            byte[] b =  new byte[bytz];
-            bytz = bytz * 2;
-        }
-    }
-
-    /**
-     * Tests whether difference instances are loaded by different
-     * context classloaders.
-     */
-    public void testGetByContextClassLoader() throws Exception {
-
-        class GetBeanUtilsBeanThread extends Thread {
-
-            private final Signal signal;
-
-            GetBeanUtilsBeanThread(final Signal signal) {
-                this.signal = signal;
-            }
-
-            @Override
-            public void run() {
-                signal.setSignal(2);
-                signal.setBean(BeanUtilsBean.getInstance());
-                signal.setConvertUtils(ConvertUtilsBean.getInstance());
-                signal.setPropertyUtils(PropertyUtilsBean.getInstance());
-            }
-
-            @Override
-            public String toString() {
-                return "GetBeanUtilsBeanThread";
-            }
-        }
-
-        final Signal signal = new Signal();
-        signal.setSignal(1);
-
-        final GetBeanUtilsBeanThread thread = new GetBeanUtilsBeanThread(signal);
-        thread.setContextClassLoader(new TestClassLoader());
-
-        thread.start();
-        thread.join();
-
-        assertEquals("Signal not set by test thread", 2, signal.getSignal());
-        assertTrue(
-                    "Different BeanUtilsBean instances per context classloader",
-                    BeanUtilsBean.getInstance() != signal.getBean());
-        assertTrue(
-                    "Different ConvertUtilsBean instances per context classloader",
-                    ConvertUtilsBean.getInstance() != signal.getConvertUtils());
-        assertTrue(
-                    "Different PropertyUtilsBean instances per context classloader",
-                    PropertyUtilsBean.getInstance() != signal.getPropertyUtils());
-    }
-
-
-    /**
-     * Tests whether difference instances are loaded by different
-     * context classloaders.
-     */
-    public void testContextClassLoaderLocal() throws Exception {
-
-        class CCLLTesterThread extends Thread {
-
-            private final Signal signal;
-            private final ContextClassLoaderLocal<Integer> ccll;
-
-            CCLLTesterThread(final Signal signal, final ContextClassLoaderLocal<Integer> ccll) {
-                this.signal = signal;
-                this.ccll = ccll;
-            }
-
-            @Override
-            public void run() {
-                ccll.set(new Integer(1789));
-                signal.setSignal(2);
-                signal.setMarkerObject(ccll.get());
-            }
-
-            @Override
-            public String toString() {
-                return "CCLLTesterThread";
-            }
-        }
-
-        final ContextClassLoaderLocal<Integer> ccll = new ContextClassLoaderLocal<>();
-        ccll.set(new Integer(1776));
-        assertEquals("Start thread sets value", new Integer(1776), ccll.get());
-
-        final Signal signal = new Signal();
-        signal.setSignal(1);
-
-        final CCLLTesterThread thread = new CCLLTesterThread(signal, ccll);
-        thread.setContextClassLoader(new TestClassLoader());
-
-        thread.start();
-        thread.join();
-
-        assertEquals("Signal not set by test thread", 2, signal.getSignal());
-        assertEquals("Second thread preserves value", new Integer(1776), ccll.get());
-        assertEquals("Second thread gets value it set", new Integer(1789), signal.getMarkerObject());
-    }
-
-    /** Tests whether calls are independent for different classloaders */
-    public void testContextClassloaderIndependence() throws Exception {
-
-        class TestIndependenceThread extends Thread {
-            private final Signal signal;
-            private final PrimitiveBean bean;
-
-            TestIndependenceThread(final Signal signal, final PrimitiveBean bean) {
-                this.signal = signal;
-                this.bean = bean;
-            }
-
-            @Override
-            public void run() {
-                try {
-                    signal.setSignal(3);
-                    ConvertUtils.register(new Converter() {
-                                            @Override
-                                            public <T> T convert(final Class<T> type, final Object value) {
-                                                return ConvertUtils.primitiveToWrapper(type).cast(new Integer(9));
-                                            }
-                                                }, Integer.TYPE);
-                    BeanUtils.setProperty(bean, "int", new Integer(1));
-                } catch (final Exception e) {
-                    e.printStackTrace();
-                    signal.setException(e);
-                }
-            }
-
-            @Override
-            public String toString() {
-                return "TestIndependenceThread";
-            }
-        }
-
-        final PrimitiveBean bean = new PrimitiveBean();
-        BeanUtils.setProperty(bean, "int", new Integer(1));
-        assertEquals("Wrong property value (1)", 1, bean.getInt());
-
-        ConvertUtils.register(new Converter() {
-                                @Override
-                                public <T> T convert(final Class<T> type, final Object value) {
-                                    return ConvertUtils.primitiveToWrapper(type).cast(new Integer(5));
-                                }
-                                    }, Integer.TYPE);
-        BeanUtils.setProperty(bean, "int", new Integer(1));
-        assertEquals("Wrong property value(2)", 5, bean.getInt());
-
-        final Signal signal = new Signal();
-        signal.setSignal(1);
-        final TestIndependenceThread thread = new TestIndependenceThread(signal, bean);
-        thread.setContextClassLoader(new TestClassLoader());
-
-        thread.start();
-        thread.join();
-
-        assertNull("Exception thrown by test thread:" + signal.getException(), signal.getException());
-        assertEquals("Signal not set by test thread", 3, signal.getSignal());
-        assertEquals("Wrong property value(3)", 9, bean.getInt());
-
-    }
-
-    /** Tests whether different threads can set beanutils instances correctly */
-    public void testBeanUtilsBeanSetInstance() throws Exception {
-
-        class SetInstanceTesterThread extends Thread {
-
-            private final Signal signal;
-            private final BeanUtilsBean bean;
-
-            SetInstanceTesterThread(final Signal signal, final BeanUtilsBean bean) {
-                this.signal = signal;
-                this.bean = bean;
-            }
-
-            @Override
-            public void run() {
-                BeanUtilsBean.setInstance(bean);
-                signal.setSignal(21);
-                signal.setBean(BeanUtilsBean.getInstance());
-            }
-
-            @Override
-            public String toString() {
-                return "SetInstanceTesterThread";
-            }
-        }
-
-        final Signal signal = new Signal();
-        signal.setSignal(1);
-
-        final BeanUtilsBean beanOne = new BeanUtilsBean();
-        final BeanUtilsBean beanTwo = new BeanUtilsBean();
-
-        final SetInstanceTesterThread thread = new SetInstanceTesterThread(signal, beanTwo);
-        thread.setContextClassLoader(new TestClassLoader());
-
-        BeanUtilsBean.setInstance(beanOne);
-        assertEquals("Start thread gets right instance", beanOne, BeanUtilsBean.getInstance());
-
-        thread.start();
-        thread.join();
-
-        assertEquals("Signal not set by test thread", 21, signal.getSignal());
-        assertEquals("Second thread preserves value", beanOne, BeanUtilsBean.getInstance());
-        assertEquals("Second thread gets value it set", beanTwo, signal.getBean());
-    }
-
-    /** Tests whether the unset method works*/
-    public void testContextClassLoaderUnset() throws Exception {
-        final BeanUtilsBean beanOne = new BeanUtilsBean();
-        final ContextClassLoaderLocal<BeanUtilsBean> ccll = new ContextClassLoaderLocal<>();
-        ccll.set(beanOne);
-        assertEquals("Start thread gets right instance", beanOne, ccll.get());
-        ccll.unset();
-        assertTrue("Unset works", !beanOne.equals(ccll.get()));
-    }
-
-    // ---- Auxillary classes
-
-    class TestClassLoader extends ClassLoader {
-        @Override
-        public String toString() {
-            return "TestClassLoader";
-        }
-    }
-
-    class Signal {
-        private Exception e;
-        private int signal = 0;
-        private BeanUtilsBean bean;
-        private PropertyUtilsBean propertyUtils;
-        private ConvertUtilsBean convertUtils;
-        private Object marker;
-
-        public Exception getException() {
-            return e;
-        }
-
-        public void setException(final Exception e) {
-            this.e = e;
-        }
-
-        public int getSignal() {
-            return signal;
-        }
-
-        public void setSignal(final int signal) {
-            this.signal = signal;
-        }
-
-        public Object getMarkerObject() {
-            return marker;
-        }
-
-        public void setMarkerObject(final Object marker) {
-            this.marker = marker;
-        }
-
-        public BeanUtilsBean getBean() {
-            return bean;
-        }
-
-        public void setBean(final BeanUtilsBean bean) {
-            this.bean = bean;
-        }
-
-        public PropertyUtilsBean getPropertyUtils() {
-            return propertyUtils;
-        }
-
-        public void setPropertyUtils(final PropertyUtilsBean propertyUtils) {
-            this.propertyUtils = propertyUtils;
-        }
-
-        public ConvertUtilsBean getConvertUtils() {
-            return convertUtils;
-        }
-
-        public void setConvertUtils(final ConvertUtilsBean convertUtils) {
-            this.convertUtils = convertUtils;
-        }
-    }
-}
-
+/*

+ * Licensed to the Apache Software Foundation (ASF) under one or more

+ * contributor license agreements.  See the NOTICE file distributed with

+ * this work for additional information regarding copyright ownership.

+ * The ASF licenses this file to You under the Apache License, Version 2.0

+ * (the "License"); you may not use this file except in compliance with

+ * the License.  You may obtain a copy of the License at

+ *

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+

+package org.apache.commons.beanutils2;

+

+import java.lang.ref.ReferenceQueue;

+import java.lang.ref.WeakReference;

+import java.util.Map;

+import java.util.WeakHashMap;

+

+import org.apache.commons.logging.LogFactory;

+

+import junit.framework.Test;

+import junit.framework.TestCase;

+import junit.framework.TestSuite;

+

+/**

+ * <p>

+ * Test Case for changes made during Beanutils Beanification

+ * </p>

+ *

+ */

+

+public class BeanificationTestCase extends TestCase {

+

+    // ---------------------------------------------------- Constants

+

+    /** Maximum number of iterations before our test fails */

+    public static final int MAX_GC_ITERATIONS = 50;

+

+    // ---------------------------------------------------- Instance Variables

+

+

+    // ---------------------------------------------------------- Constructors

+

+

+    /**

+     * Construct a new instance of this test case.

+     *

+     * @param name Name of the test case

+     */

+    public BeanificationTestCase(final String name) {

+        super(name);

+    }

+

+

+    // -------------------------------------------------- Overall Test Methods

+

+

+    /**

+     * Set up instance variables required by this test case.

+     */

+    @Override

+    public void setUp() {

+

+        ConvertUtils.deregister();

+

+    }

+

+

+    /**

+     * Return the tests included in this test suite.

+     */

+    public static Test suite() {

+        return new TestSuite(BeanificationTestCase.class);

+    }

+

+

+    /**

+     * Tear down instance variables required by this test case.

+     */

+    @Override

+    public void tearDown() {

+        // No action required

+    }

+

+

+    // ------------------------------------------------ Individual Test Methods

+

+    /** Test of the methodology we'll use for some of the later tests */

+    public void testMemoryTestMethodology() throws Exception {

+        // test methodology

+        // many thanks to Juozas Baliuka for suggesting this method

+        ClassLoader loader = new ClassLoader(this.getClass().getClassLoader()) {};

+        final WeakReference<ClassLoader> reference = new  WeakReference<>(loader);

+        @SuppressWarnings("unused")

+        Class<?> myClass = loader.loadClass("org.apache.commons.beanutils2.BetaBean");

+

+        assertNotNull("Weak reference released early", reference.get());

+

+        // dereference class loader and class:

+        loader = null;

+        myClass = null;

+

+        int iterations = 0;

+        int bytz = 2;

+        while(true) {

+            System.gc();

+            if(iterations++ > MAX_GC_ITERATIONS){

+                fail("Max iterations reached before resource released.");

+            }

+            if( reference.get() == null ) {

+                break;

+

+            }

+            // create garbage:

+            @SuppressWarnings("unused")

+            final

+            byte[] b =  new byte[bytz];

+            bytz = bytz * 2;

+        }

+    }

+

+    /** Tests whether classloaders and beans are released from memory by the map used by beanutils */

+    public void testMemoryLeak2() throws Exception {

+        // tests when the map used by beanutils has the right behaviour

+

+        if (BeanUtilsTestCase.isPre14JVM()) {

+            System.out.println("WARNING: CANNOT TEST MEMORY LEAK ON PRE1.4 JVM");

+            return;

+        }

+

+        // many thanks to Juozas Baliuka for suggesting this methodology

+        TestClassLoader loader = new TestClassLoader();

+        final ReferenceQueue<Object> queue = new ReferenceQueue<>();

+        final WeakReference<ClassLoader> loaderReference = new WeakReference<>(loader, queue);

+        Integer test = new Integer(1);

+

+        final WeakReference<Integer> testReference = new WeakReference<>(test, queue);

+        //Map map = new ReferenceMap(ReferenceMap.WEAK, ReferenceMap.HARD, true);

+        final Map<Object, Object> map = new WeakHashMap<>();

+        map.put(loader, test);

+

+        assertEquals("In map", test, map.get(loader));

+        assertNotNull("Weak reference released early (1)", loaderReference.get());

+        assertNotNull("Weak reference released early (2)", testReference.get());

+

+        // dereference strong references

+        loader = null;

+        test = null;

+

+        int iterations = 0;

+        int bytz = 2;

+        while(true) {

+            System.gc();

+            if(iterations++ > MAX_GC_ITERATIONS){

+                fail("Max iterations reached before resource released.");

+            }

+            map.isEmpty();

+

+            if(

+                loaderReference.get() == null &&

+                testReference.get() == null) {

+                break;

+

+            }

+            // create garbage:

+            @SuppressWarnings("unused")

+            final

+            byte[] b =  new byte[bytz];

+            bytz = bytz * 2;

+        }

+    }

+

+    /** Tests whether classloaders and beans are released from memory */

+    public void testMemoryLeak() throws Exception {

+        if (BeanUtilsTestCase.isPre14JVM()) {

+            System.out.println("WARNING: CANNOT TEST MEMORY LEAK ON PRE1.4 JVM");

+            return;

+        }

+

+        // many thanks to Juozas Baliuka for suggesting this methodology

+        TestClassLoader loader = new TestClassLoader();

+        final WeakReference<ClassLoader> loaderReference = new  WeakReference<>(loader);

+        BeanUtilsBean.getInstance();

+

+        class GetBeanUtilsBeanThread extends Thread {

+

+            BeanUtilsBean beanUtils;

+            ConvertUtilsBean convertUtils;

+            PropertyUtilsBean propertyUtils;

+

+            GetBeanUtilsBeanThread() {}

+

+            @Override

+            public void run() {

+                beanUtils = BeanUtilsBean.getInstance();

+                convertUtils = ConvertUtilsBean.getInstance();

+                propertyUtils = PropertyUtilsBean.getInstance();

+                // XXX Log keeps a reference around!

+                LogFactory.releaseAll();

+            }

+

+            @Override

+            public String toString() {

+                return "GetBeanUtilsBeanThread";

+            }

+        }

+

+

+        GetBeanUtilsBeanThread thread = new GetBeanUtilsBeanThread();

+        @SuppressWarnings("unused")

+        final

+        WeakReference<Thread> threadWeakReference = new WeakReference<>(thread);

+        thread.setContextClassLoader(loader);

+

+        thread.start();

+        thread.join();

+

+        final WeakReference<BeanUtilsBean> beanUtilsReference = new WeakReference<>(thread.beanUtils);

+        final WeakReference<PropertyUtilsBean> propertyUtilsReference =  new WeakReference<>(thread.propertyUtils);

+        final WeakReference<ConvertUtilsBean> convertUtilsReference = new WeakReference<>(thread.convertUtils);

+

+        assertNotNull("Weak reference released early (1)", loaderReference.get());

+        assertNotNull("Weak reference released early (2)", beanUtilsReference.get());

+        assertNotNull("Weak reference released early (3)", propertyUtilsReference.get());

+        assertNotNull("Weak reference released early (4)", convertUtilsReference.get());

+

+        // dereference strong references

+        loader = null;

+        thread.setContextClassLoader(null);

+        thread = null;

+

+        int iterations = 0;

+        int bytz = 2;

+        while(true) {

+            BeanUtilsBean.getInstance();

+            System.gc();

+            if(iterations++ > MAX_GC_ITERATIONS){

+                fail("Max iterations reached before resource released.");

+            }

+

+            if(

+                loaderReference.get() == null &&

+                beanUtilsReference.get() == null &&

+                propertyUtilsReference.get() == null &&

+                convertUtilsReference.get() == null) {

+                break;

+

+            }

+            // create garbage:

+            @SuppressWarnings("unused")

+            final

+            byte[] b =  new byte[bytz];

+            bytz = bytz * 2;

+        }

+    }

+

+    /**

+     * Tests whether difference instances are loaded by different

+     * context classloaders.

+     */

+    public void testGetByContextClassLoader() throws Exception {

+

+        class GetBeanUtilsBeanThread extends Thread {

+

+            private final Signal signal;

+

+            GetBeanUtilsBeanThread(final Signal signal) {

+                this.signal = signal;

+            }

+

+            @Override

+            public void run() {

+                signal.setSignal(2);

+                signal.setBean(BeanUtilsBean.getInstance());

+                signal.setConvertUtils(ConvertUtilsBean.getInstance());

+                signal.setPropertyUtils(PropertyUtilsBean.getInstance());

+            }

+

+            @Override

+            public String toString() {

+                return "GetBeanUtilsBeanThread";

+            }

+        }

+

+        final Signal signal = new Signal();

+        signal.setSignal(1);

+

+        final GetBeanUtilsBeanThread thread = new GetBeanUtilsBeanThread(signal);

+        thread.setContextClassLoader(new TestClassLoader());

+

+        thread.start();

+        thread.join();

+

+        assertEquals("Signal not set by test thread", 2, signal.getSignal());

+        assertTrue(

+                    "Different BeanUtilsBean instances per context classloader",

+                    BeanUtilsBean.getInstance() != signal.getBean());

+        assertTrue(

+                    "Different ConvertUtilsBean instances per context classloader",

+                    ConvertUtilsBean.getInstance() != signal.getConvertUtils());

+        assertTrue(

+                    "Different PropertyUtilsBean instances per context classloader",

+                    PropertyUtilsBean.getInstance() != signal.getPropertyUtils());

+    }

+

+

+    /**

+     * Tests whether difference instances are loaded by different

+     * context classloaders.

+     */

+    public void testContextClassLoaderLocal() throws Exception {

+

+        class CCLLTesterThread extends Thread {

+

+            private final Signal signal;

+            private final ContextClassLoaderLocal<Integer> ccll;

+

+            CCLLTesterThread(final Signal signal, final ContextClassLoaderLocal<Integer> ccll) {

+                this.signal = signal;

+                this.ccll = ccll;

+            }

+

+            @Override

+            public void run() {

+                ccll.set(new Integer(1789));

+                signal.setSignal(2);

+                signal.setMarkerObject(ccll.get());

+            }

+

+            @Override

+            public String toString() {

+                return "CCLLTesterThread";

+            }

+        }

+

+        final ContextClassLoaderLocal<Integer> ccll = new ContextClassLoaderLocal<>();

+        ccll.set(new Integer(1776));

+        assertEquals("Start thread sets value", new Integer(1776), ccll.get());

+

+        final Signal signal = new Signal();

+        signal.setSignal(1);

+

+        final CCLLTesterThread thread = new CCLLTesterThread(signal, ccll);

+        thread.setContextClassLoader(new TestClassLoader());

+

+        thread.start();

+        thread.join();

+

+        assertEquals("Signal not set by test thread", 2, signal.getSignal());

+        assertEquals("Second thread preserves value", new Integer(1776), ccll.get());

+        assertEquals("Second thread gets value it set", new Integer(1789), signal.getMarkerObject());

+    }

+

+    /** Tests whether calls are independent for different classloaders */

+    public void testContextClassloaderIndependence() throws Exception {

+

+        class TestIndependenceThread extends Thread {

+            private final Signal signal;

+            private final PrimitiveBean bean;

+

+            TestIndependenceThread(final Signal signal, final PrimitiveBean bean) {

+                this.signal = signal;

+                this.bean = bean;

+            }

+

+            @Override

+            public void run() {

+                try {

+                    signal.setSignal(3);

+                    ConvertUtils.register(new Converter() {

+                                            @Override

+                                            public <T> T convert(final Class<T> type, final Object value) {

+                                                return ConvertUtils.primitiveToWrapper(type).cast(new Integer(9));

+                                            }

+                                                }, Integer.TYPE);

+                    BeanUtils.setProperty(bean, "int", new Integer(1));

+                } catch (final Exception e) {

+                    e.printStackTrace();

+                    signal.setException(e);

+                }

+            }

+

+            @Override

+            public String toString() {

+                return "TestIndependenceThread";

+            }

+        }

+

+        final PrimitiveBean bean = new PrimitiveBean();

+        BeanUtils.setProperty(bean, "int", new Integer(1));

+        assertEquals("Wrong property value (1)", 1, bean.getInt());

+

+        ConvertUtils.register(new Converter() {

+                                @Override

+                                public <T> T convert(final Class<T> type, final Object value) {

+                                    return ConvertUtils.primitiveToWrapper(type).cast(new Integer(5));

+                                }

+                                    }, Integer.TYPE);

+        BeanUtils.setProperty(bean, "int", new Integer(1));

+        assertEquals("Wrong property value(2)", 5, bean.getInt());

+

+        final Signal signal = new Signal();

+        signal.setSignal(1);

+        final TestIndependenceThread thread = new TestIndependenceThread(signal, bean);

+        thread.setContextClassLoader(new TestClassLoader());

+

+        thread.start();

+        thread.join();

+

+        assertNull("Exception thrown by test thread:" + signal.getException(), signal.getException());

+        assertEquals("Signal not set by test thread", 3, signal.getSignal());

+        assertEquals("Wrong property value(3)", 9, bean.getInt());

+

+    }

+

+    /** Tests whether different threads can set beanutils instances correctly */

+    public void testBeanUtilsBeanSetInstance() throws Exception {

+

+        class SetInstanceTesterThread extends Thread {

+

+            private final Signal signal;

+            private final BeanUtilsBean bean;

+

+            SetInstanceTesterThread(final Signal signal, final BeanUtilsBean bean) {

+                this.signal = signal;

+                this.bean = bean;

+            }

+

+            @Override

+            public void run() {

+                BeanUtilsBean.setInstance(bean);

+                signal.setSignal(21);

+                signal.setBean(BeanUtilsBean.getInstance());

+            }

+

+            @Override

+            public String toString() {

+                return "SetInstanceTesterThread";

+            }

+        }

+

+        final Signal signal = new Signal();

+        signal.setSignal(1);

+

+        final BeanUtilsBean beanOne = new BeanUtilsBean();

+        final BeanUtilsBean beanTwo = new BeanUtilsBean();

+

+        final SetInstanceTesterThread thread = new SetInstanceTesterThread(signal, beanTwo);

+        thread.setContextClassLoader(new TestClassLoader());

+

+        BeanUtilsBean.setInstance(beanOne);

+        assertEquals("Start thread gets right instance", beanOne, BeanUtilsBean.getInstance());

+

+        thread.start();

+        thread.join();

+

+        assertEquals("Signal not set by test thread", 21, signal.getSignal());

+        assertEquals("Second thread preserves value", beanOne, BeanUtilsBean.getInstance());

+        assertEquals("Second thread gets value it set", beanTwo, signal.getBean());

+    }

+

+    /** Tests whether the unset method works*/

+    public void testContextClassLoaderUnset() throws Exception {

+        final BeanUtilsBean beanOne = new BeanUtilsBean();

+        final ContextClassLoaderLocal<BeanUtilsBean> ccll = new ContextClassLoaderLocal<>();

+        ccll.set(beanOne);

+        assertEquals("Start thread gets right instance", beanOne, ccll.get());

+        ccll.unset();

+        assertTrue("Unset works", !beanOne.equals(ccll.get()));

+    }

+

+    // ---- Auxillary classes

+

+    class TestClassLoader extends ClassLoader {

+        @Override

+        public String toString() {

+            return "TestClassLoader";

+        }

+    }

+

+    class Signal {

+        private Exception e;

+        private int signal = 0;

+        private BeanUtilsBean bean;

+        private PropertyUtilsBean propertyUtils;

+        private ConvertUtilsBean convertUtils;

+        private Object marker;

+

+        public Exception getException() {

+            return e;

+        }

+

+        public void setException(final Exception e) {

+            this.e = e;

+        }

+

+        public int getSignal() {

+            return signal;

+        }

+

+        public void setSignal(final int signal) {

+            this.signal = signal;

+        }

+

+        public Object getMarkerObject() {

+            return marker;

+        }

+

+        public void setMarkerObject(final Object marker) {

+            this.marker = marker;

+        }

+

+        public BeanUtilsBean getBean() {

+            return bean;

+        }

+

+        public void setBean(final BeanUtilsBean bean) {

+            this.bean = bean;

+        }

+

+        public PropertyUtilsBean getPropertyUtils() {

+            return propertyUtils;

+        }

+

+        public void setPropertyUtils(final PropertyUtilsBean propertyUtils) {

+            this.propertyUtils = propertyUtils;

+        }

+

+        public ConvertUtilsBean getConvertUtils() {

+            return convertUtils;

+        }

+

+        public void setConvertUtils(final ConvertUtilsBean convertUtils) {

+            this.convertUtils = convertUtils;

+        }

+    }

+}

+

diff --git a/src/test/java/org/apache/commons/beanutils2/converters/MemoryTestCase.java b/src/test/java/org/apache/commons/beanutils2/converters/MemoryTestCase.java
index dc6ffcc..15e8480 100644
--- a/src/test/java/org/apache/commons/beanutils2/converters/MemoryTestCase.java
+++ b/src/test/java/org/apache/commons/beanutils2/converters/MemoryTestCase.java
@@ -1,291 +1,291 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.beanutils2.converters;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-
-import java.lang.ref.WeakReference;
-
-import org.apache.commons.beanutils2.ConvertUtils;
-import org.apache.commons.beanutils2.Converter;
-import org.junit.Test;
-
-/**
- * This class provides a number of unit tests related to classloaders and
- * garbage collection, particularly in j2ee-like situations.
- *
- */
-public class MemoryTestCase {
-
-    @Test
-    public void testWeakReference() throws Exception {
-        final ClassLoader origContextClassLoader = Thread.currentThread().getContextClassLoader();
-        try {
-        ClassReloader componentLoader = new ClassReloader(origContextClassLoader);
-
-        Thread.currentThread().setContextClassLoader(componentLoader);
-        Thread.currentThread().setContextClassLoader(origContextClassLoader);
-
-        final WeakReference<ClassLoader> ref = new WeakReference<ClassLoader>(componentLoader);
-        componentLoader = null;
-
-        forceGarbageCollection(ref);
-        assertNull(ref.get());
-        } finally {
-            // Restore context classloader that was present before this
-            // test started. It is expected to be the same as the system
-            // classloader, but we handle all cases here..
-            Thread.currentThread().setContextClassLoader(origContextClassLoader);
-
-            // and restore all the standard converters
-            ConvertUtils.deregister();
-        }
-    }
-
-    /**
-     * Test whether registering a standard Converter instance while
-     * a custom context classloader is set causes a memory leak.
-     *
-     * <p>This test emulates a j2ee container where BeanUtils has been
-     * loaded from a "common" lib location that is shared across all
-     * components running within the container. The "component" registers
-     * a converter object, whose class was loaded from the "common" lib
-     * location. The registered converter:
-     * <ul>
-     * <li>should not be visible to other components; and</li>
-     * <li>should not prevent the component-specific classloader from being
-     *  garbage-collected when the container sets its reference to null.
-     * </ul>
-     *
-     */
-    @Test
-    public void testComponentRegistersStandardConverter() throws Exception {
-
-        final ClassLoader origContextClassLoader = Thread.currentThread().getContextClassLoader();
-        try {
-            // sanity check; who's paranoid?? :-)
-            assertEquals(origContextClassLoader, ConvertUtils.class.getClassLoader());
-
-            // create a custom classloader for a "component"
-            // just like a container would.
-            ClassLoader componentLoader1 = new ClassLoader() {};
-            final ClassLoader componentLoader2 = new ClassLoader() {};
-
-            final Converter origFloatConverter = ConvertUtils.lookup(Float.TYPE);
-            final Converter floatConverter1 = new FloatConverter();
-
-            // Emulate the container invoking a component #1, and the component
-            // registering a custom converter instance whose class is
-            // available via the "shared" classloader.
-            Thread.currentThread().setContextClassLoader(componentLoader1);
-            {
-                // here we pretend we're running inside component #1
-
-                // When we first do a ConvertUtils operation inside a custom
-                // classloader, we get a completely fresh copy of the
-                // ConvertUtilsBean, with all-new Converter objects in it..
-                assertFalse(ConvertUtils.lookup(Float.TYPE) == origFloatConverter);
-
-                // Now we register a custom converter (but of a standard class).
-                // This should only affect code that runs with exactly the
-                // same context classloader set.
-                ConvertUtils.register(floatConverter1, Float.TYPE);
-                assertTrue(ConvertUtils.lookup(Float.TYPE) == floatConverter1);
-            }
-            Thread.currentThread().setContextClassLoader(origContextClassLoader);
-
-            // The converter visible outside any custom component should not
-            // have been altered.
-            assertTrue(ConvertUtils.lookup(Float.TYPE) == origFloatConverter);
-
-            // Emulate the container invoking a component #2.
-            Thread.currentThread().setContextClassLoader(componentLoader2);
-            {
-                // here we pretend we're running inside component #2
-
-                // we should get a completely fresh ConvertUtilsBean, with
-                // all-new Converter objects again.
-                assertFalse(ConvertUtils.lookup(Float.TYPE) == origFloatConverter);
-                assertFalse(ConvertUtils.lookup(Float.TYPE) == floatConverter1);
-            }
-            Thread.currentThread().setContextClassLoader(origContextClassLoader);
-
-            // Emulate a container "undeploying" component #1. This should
-            // make component loader available for garbage collection (we hope)
-            final WeakReference<ClassLoader> weakRefToComponent1 = new WeakReference<>(componentLoader1);
-            componentLoader1 = null;
-
-            // force garbage collection and  verify that the componentLoader
-            // has been garbage-collected
-            forceGarbageCollection(weakRefToComponent1);
-            assertNull(
-                "Component classloader did not release properly; memory leak present",
-                weakRefToComponent1.get());
-        } finally {
-            // Restore context classloader that was present before this
-            // test started, so that in case of a test failure we don't stuff
-            // up later tests...
-            Thread.currentThread().setContextClassLoader(origContextClassLoader);
-
-            // and restore all the standard converters
-            ConvertUtils.deregister();
-        }
-    }
-
-    /**
-     * Test whether registering a custom Converter subclass while
-     * a custom context classloader is set causes a memory leak.
-     *
-     * <p>This test emulates a j2ee container where BeanUtils has been
-     * loaded from a "common" lib location that is shared across all
-     * components running within the container. The "component" registers
-     * a converter object, whose class was loaded via the component-specific
-     * classloader. The registered converter:
-     * <ul>
-     * <li>should not be visible to other components; and</li>
-     * <li>should not prevent the component-specific classloader from being
-     *  garbage-collected when the container sets its reference to null.
-     * </ul>
-     *
-     */
-    @Test
-    public void testComponentRegistersCustomConverter() throws Exception {
-
-        final ClassLoader origContextClassLoader = Thread.currentThread().getContextClassLoader();
-        try {
-            // sanity check; who's paranoid?? :-)
-            assertEquals(origContextClassLoader, ConvertUtils.class.getClassLoader());
-
-            // create a custom classloader for a "component"
-            // just like a container would.
-            ClassReloader componentLoader = new ClassReloader(origContextClassLoader);
-
-            // Load a custom Converter via component loader. This emulates what
-            // would happen if a user wrote their own FloatConverter subclass
-            // and deployed it via the component-specific classpath.
-            Thread.currentThread().setContextClassLoader(componentLoader);
-            {
-              // Here we pretend we're running inside the component, and that
-              // a class FloatConverter has been loaded from the component's
-              // private classpath.
-              final Class<?> newFloatConverterClass = componentLoader.reload(FloatConverter.class);
-              Object newFloatConverter = newFloatConverterClass.newInstance();
-              assertTrue(newFloatConverter.getClass().getClassLoader() == componentLoader);
-
-              // verify that this new object does implement the Converter type
-              // despite being loaded via a classloader different from the one
-              // that loaded the Converter class.
-              assertTrue(
-                "Converter loader via child does not implement parent type",
-                Converter.class.isInstance(newFloatConverter));
-
-              // this converter registration will only apply to the
-              // componentLoader classloader...
-              ConvertUtils.register((Converter)newFloatConverter, Float.TYPE);
-
-              // After registering a custom converter, lookup should return
-              // it back to us. We'll try this lookup again with a different
-              // context-classloader set, and shouldn't see it
-              final Converter componentConverter = ConvertUtils.lookup(Float.TYPE);
-              assertTrue(componentConverter.getClass().getClassLoader() == componentLoader);
-
-              newFloatConverter = null;
-            }
-            Thread.currentThread().setContextClassLoader(origContextClassLoader);
-
-            // Because the context classloader has been reset, we shouldn't
-            // see the custom registered converter here...
-            final Converter sharedConverter = ConvertUtils.lookup(Float.TYPE);
-            assertFalse(sharedConverter.getClass().getClassLoader() == componentLoader);
-
-            // and here we should see it again
-            Thread.currentThread().setContextClassLoader(componentLoader);
-            {
-                final Converter componentConverter = ConvertUtils.lookup(Float.TYPE);
-                assertTrue(componentConverter.getClass().getClassLoader() == componentLoader);
-            }
-            Thread.currentThread().setContextClassLoader(origContextClassLoader);
-            // Emulate a container "undeploying" the component. This should
-            // make component loader available for garbage collection (we hope)
-            final WeakReference<ClassLoader> weakRefToComponent = new WeakReference<ClassLoader>(componentLoader);
-            componentLoader = null;
-
-            // force garbage collection and  verify that the componentLoader
-            // has been garbage-collected
-            forceGarbageCollection(weakRefToComponent);
-            assertNull(
-                "Component classloader did not release properly; memory leak present",
-                weakRefToComponent.get());
-        } finally {
-            // Restore context classloader that was present before this
-            // test started. It is expected to be the same as the system
-            // classloader, but we handle all cases here..
-            Thread.currentThread().setContextClassLoader(origContextClassLoader);
-
-            // and restore all the standard converters
-            ConvertUtils.deregister();
-        }
-    }
-
-    /**
-     * Attempt to force garbage collection of the specified target.
-     *
-     * <p>Unfortunately there is no way to force a JVM to perform
-     * garbage collection; all we can do is <i>hint</i> to it that
-     * garbage-collection would be a good idea, and to consume
-     * memory in order to trigger it.</p>
-     *
-     * <p>On return, target.get() will return null if the target has
-     * been garbage collected.</p>
-     *
-     * <p>If target.get() still returns non-null after this method has returned,
-     * then either there is some reference still being held to the target, or
-     * else we were not able to trigger garbage collection; there is no way
-     * to tell these scenarios apart.</p>
-     */
-    private void forceGarbageCollection(final WeakReference<?> target) {
-        int bytes = 2;
-
-        while(target.get() != null) {
-            System.gc();
-
-            // Create increasingly-large amounts of non-referenced memory
-            // in order to persuade the JVM to collect it. We are hoping
-            // here that the JVM is dumb enough to run a full gc pass over
-            // all data (including the target) rather than simply collecting
-            // this easily-reclaimable memory!
-            try {
-                @SuppressWarnings("unused")
-                final
-                byte[] b = new byte[bytes];
-                bytes = bytes * 2;
-            } catch(final OutOfMemoryError e) {
-                // well that sure should have forced a garbage collection
-                // run to occur!
-                break;
-            }
-        }
-
-        // and let's do one more just to clean up any garbage we might have
-        // created on the last pass..
-        System.gc();
-    }
-}
+/*

+ * Licensed to the Apache Software Foundation (ASF) under one or more

+ * contributor license agreements.  See the NOTICE file distributed with

+ * this work for additional information regarding copyright ownership.

+ * The ASF licenses this file to You under the Apache License, Version 2.0

+ * (the "License"); you may not use this file except in compliance with

+ * the License.  You may obtain a copy of the License at

+ *

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+

+package org.apache.commons.beanutils2.converters;

+

+import static org.junit.Assert.assertEquals;

+import static org.junit.Assert.assertFalse;

+import static org.junit.Assert.assertNull;

+import static org.junit.Assert.assertTrue;

+

+import java.lang.ref.WeakReference;

+

+import org.apache.commons.beanutils2.ConvertUtils;

+import org.apache.commons.beanutils2.Converter;

+import org.junit.Test;

+

+/**

+ * This class provides a number of unit tests related to classloaders and

+ * garbage collection, particularly in j2ee-like situations.

+ *

+ */

+public class MemoryTestCase {

+

+    @Test

+    public void testWeakReference() throws Exception {

+        final ClassLoader origContextClassLoader = Thread.currentThread().getContextClassLoader();

+        try {

+        ClassReloader componentLoader = new ClassReloader(origContextClassLoader);

+

+        Thread.currentThread().setContextClassLoader(componentLoader);

+        Thread.currentThread().setContextClassLoader(origContextClassLoader);

+

+        final WeakReference<ClassLoader> ref = new WeakReference<>(componentLoader);

+        componentLoader = null;

+

+        forceGarbageCollection(ref);

+        assertNull(ref.get());

+        } finally {

+            // Restore context classloader that was present before this

+            // test started. It is expected to be the same as the system

+            // classloader, but we handle all cases here..

+            Thread.currentThread().setContextClassLoader(origContextClassLoader);

+

+            // and restore all the standard converters

+            ConvertUtils.deregister();

+        }

+    }

+

+    /**

+     * Test whether registering a standard Converter instance while

+     * a custom context classloader is set causes a memory leak.

+     *

+     * <p>This test emulates a j2ee container where BeanUtils has been

+     * loaded from a "common" lib location that is shared across all

+     * components running within the container. The "component" registers

+     * a converter object, whose class was loaded from the "common" lib

+     * location. The registered converter:

+     * <ul>

+     * <li>should not be visible to other components; and</li>

+     * <li>should not prevent the component-specific classloader from being

+     *  garbage-collected when the container sets its reference to null.

+     * </ul>

+     *

+     */

+    @Test

+    public void testComponentRegistersStandardConverter() throws Exception {

+

+        final ClassLoader origContextClassLoader = Thread.currentThread().getContextClassLoader();

+        try {

+            // sanity check; who's paranoid?? :-)

+            assertEquals(origContextClassLoader, ConvertUtils.class.getClassLoader());

+

+            // create a custom classloader for a "component"

+            // just like a container would.

+            ClassLoader componentLoader1 = new ClassLoader() {};

+            final ClassLoader componentLoader2 = new ClassLoader() {};

+

+            final Converter origFloatConverter = ConvertUtils.lookup(Float.TYPE);

+            final Converter floatConverter1 = new FloatConverter();

+

+            // Emulate the container invoking a component #1, and the component

+            // registering a custom converter instance whose class is

+            // available via the "shared" classloader.

+            Thread.currentThread().setContextClassLoader(componentLoader1);

+            {

+                // here we pretend we're running inside component #1

+

+                // When we first do a ConvertUtils operation inside a custom

+                // classloader, we get a completely fresh copy of the

+                // ConvertUtilsBean, with all-new Converter objects in it..

+                assertFalse(ConvertUtils.lookup(Float.TYPE) == origFloatConverter);

+

+                // Now we register a custom converter (but of a standard class).

+                // This should only affect code that runs with exactly the

+                // same context classloader set.

+                ConvertUtils.register(floatConverter1, Float.TYPE);

+                assertTrue(ConvertUtils.lookup(Float.TYPE) == floatConverter1);

+            }

+            Thread.currentThread().setContextClassLoader(origContextClassLoader);

+

+            // The converter visible outside any custom component should not

+            // have been altered.

+            assertTrue(ConvertUtils.lookup(Float.TYPE) == origFloatConverter);

+

+            // Emulate the container invoking a component #2.

+            Thread.currentThread().setContextClassLoader(componentLoader2);

+            {

+                // here we pretend we're running inside component #2

+

+                // we should get a completely fresh ConvertUtilsBean, with

+                // all-new Converter objects again.

+                assertFalse(ConvertUtils.lookup(Float.TYPE) == origFloatConverter);

+                assertFalse(ConvertUtils.lookup(Float.TYPE) == floatConverter1);

+            }

+            Thread.currentThread().setContextClassLoader(origContextClassLoader);

+

+            // Emulate a container "undeploying" component #1. This should

+            // make component loader available for garbage collection (we hope)

+            final WeakReference<ClassLoader> weakRefToComponent1 = new WeakReference<>(componentLoader1);

+            componentLoader1 = null;

+

+            // force garbage collection and  verify that the componentLoader

+            // has been garbage-collected

+            forceGarbageCollection(weakRefToComponent1);

+            assertNull(

+                "Component classloader did not release properly; memory leak present",

+                weakRefToComponent1.get());

+        } finally {

+            // Restore context classloader that was present before this

+            // test started, so that in case of a test failure we don't stuff

+            // up later tests...

+            Thread.currentThread().setContextClassLoader(origContextClassLoader);

+

+            // and restore all the standard converters

+            ConvertUtils.deregister();

+        }

+    }

+

+    /**

+     * Test whether registering a custom Converter subclass while

+     * a custom context classloader is set causes a memory leak.

+     *

+     * <p>This test emulates a j2ee container where BeanUtils has been

+     * loaded from a "common" lib location that is shared across all

+     * components running within the container. The "component" registers

+     * a converter object, whose class was loaded via the component-specific

+     * classloader. The registered converter:

+     * <ul>

+     * <li>should not be visible to other components; and</li>

+     * <li>should not prevent the component-specific classloader from being

+     *  garbage-collected when the container sets its reference to null.

+     * </ul>

+     *

+     */

+    @Test

+    public void testComponentRegistersCustomConverter() throws Exception {

+

+        final ClassLoader origContextClassLoader = Thread.currentThread().getContextClassLoader();

+        try {

+            // sanity check; who's paranoid?? :-)

+            assertEquals(origContextClassLoader, ConvertUtils.class.getClassLoader());

+

+            // create a custom classloader for a "component"

+            // just like a container would.

+            ClassReloader componentLoader = new ClassReloader(origContextClassLoader);

+

+            // Load a custom Converter via component loader. This emulates what

+            // would happen if a user wrote their own FloatConverter subclass

+            // and deployed it via the component-specific classpath.

+            Thread.currentThread().setContextClassLoader(componentLoader);

+            {

+              // Here we pretend we're running inside the component, and that

+              // a class FloatConverter has been loaded from the component's

+              // private classpath.

+              final Class<?> newFloatConverterClass = componentLoader.reload(FloatConverter.class);

+              Object newFloatConverter = newFloatConverterClass.newInstance();

+              assertTrue(newFloatConverter.getClass().getClassLoader() == componentLoader);

+

+              // verify that this new object does implement the Converter type

+              // despite being loaded via a classloader different from the one

+              // that loaded the Converter class.

+              assertTrue(

+                "Converter loader via child does not implement parent type",

+                Converter.class.isInstance(newFloatConverter));

+

+              // this converter registration will only apply to the

+              // componentLoader classloader...

+              ConvertUtils.register((Converter)newFloatConverter, Float.TYPE);

+

+              // After registering a custom converter, lookup should return

+              // it back to us. We'll try this lookup again with a different

+              // context-classloader set, and shouldn't see it

+              final Converter componentConverter = ConvertUtils.lookup(Float.TYPE);

+              assertTrue(componentConverter.getClass().getClassLoader() == componentLoader);

+

+              newFloatConverter = null;

+            }

+            Thread.currentThread().setContextClassLoader(origContextClassLoader);

+

+            // Because the context classloader has been reset, we shouldn't

+            // see the custom registered converter here...

+            final Converter sharedConverter = ConvertUtils.lookup(Float.TYPE);

+            assertFalse(sharedConverter.getClass().getClassLoader() == componentLoader);

+

+            // and here we should see it again

+            Thread.currentThread().setContextClassLoader(componentLoader);

+            {

+                final Converter componentConverter = ConvertUtils.lookup(Float.TYPE);

+                assertTrue(componentConverter.getClass().getClassLoader() == componentLoader);

+            }

+            Thread.currentThread().setContextClassLoader(origContextClassLoader);

+            // Emulate a container "undeploying" the component. This should

+            // make component loader available for garbage collection (we hope)

+            final WeakReference<ClassLoader> weakRefToComponent = new WeakReference<>(componentLoader);

+            componentLoader = null;

+

+            // force garbage collection and  verify that the componentLoader

+            // has been garbage-collected

+            forceGarbageCollection(weakRefToComponent);

+            assertNull(

+                "Component classloader did not release properly; memory leak present",

+                weakRefToComponent.get());

+        } finally {

+            // Restore context classloader that was present before this

+            // test started. It is expected to be the same as the system

+            // classloader, but we handle all cases here..

+            Thread.currentThread().setContextClassLoader(origContextClassLoader);

+

+            // and restore all the standard converters

+            ConvertUtils.deregister();

+        }

+    }

+

+    /**

+     * Attempt to force garbage collection of the specified target.

+     *

+     * <p>Unfortunately there is no way to force a JVM to perform

+     * garbage collection; all we can do is <i>hint</i> to it that

+     * garbage-collection would be a good idea, and to consume

+     * memory in order to trigger it.</p>

+     *

+     * <p>On return, target.get() will return null if the target has

+     * been garbage collected.</p>

+     *

+     * <p>If target.get() still returns non-null after this method has returned,

+     * then either there is some reference still being held to the target, or

+     * else we were not able to trigger garbage collection; there is no way

+     * to tell these scenarios apart.</p>

+     */

+    private void forceGarbageCollection(final WeakReference<?> target) {

+        int bytes = 2;

+

+        while(target.get() != null) {

+            System.gc();

+

+            // Create increasingly-large amounts of non-referenced memory

+            // in order to persuade the JVM to collect it. We are hoping

+            // here that the JVM is dumb enough to run a full gc pass over

+            // all data (including the target) rather than simply collecting

+            // this easily-reclaimable memory!

+            try {

+                @SuppressWarnings("unused")

+                final

+                byte[] b = new byte[bytes];

+                bytes = bytes * 2;

+            } catch(final OutOfMemoryError e) {

+                // well that sure should have forced a garbage collection

+                // run to occur!

+                break;

+            }

+        }

+

+        // and let's do one more just to clean up any garbage we might have

+        // created on the last pass..

+        System.gc();

+    }

+}

diff --git a/src/test/java/org/apache/commons/beanutils2/locale/LocaleBeanificationTestCase.java b/src/test/java/org/apache/commons/beanutils2/locale/LocaleBeanificationTestCase.java
index adfc844..cdc9a26 100644
--- a/src/test/java/org/apache/commons/beanutils2/locale/LocaleBeanificationTestCase.java
+++ b/src/test/java/org/apache/commons/beanutils2/locale/LocaleBeanificationTestCase.java
@@ -1,580 +1,580 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.beanutils2.locale;
-
-import java.lang.ref.ReferenceQueue;
-import java.lang.ref.WeakReference;
-import java.util.Locale;
-import java.util.Map;
-import java.util.WeakHashMap;
-
-import org.apache.commons.beanutils2.BeanUtilsBean;
-import org.apache.commons.beanutils2.BeanUtilsTestCase;
-import org.apache.commons.beanutils2.ContextClassLoaderLocal;
-import org.apache.commons.beanutils2.ConversionException;
-import org.apache.commons.beanutils2.ConvertUtils;
-import org.apache.commons.beanutils2.PrimitiveBean;
-import org.apache.commons.beanutils2.locale.converters.LongLocaleConverter;
-import org.apache.commons.logging.LogFactory;
-
-import junit.framework.Test;
-import junit.framework.TestCase;
-import junit.framework.TestSuite;
-
-/**
- * <p>
- * Test Case for changes made during LocaleBeanutils Beanification.
- * This is basically a cut-and-correct version of the beanutils beanifications tests.
- * </p>
- *
- */
-
-public class LocaleBeanificationTestCase extends TestCase {
-
-    // ---------------------------------------------------- Constants
-
-    /** Maximum number of iterations before our test fails */
-    public static final int MAX_GC_ITERATIONS = 50;
-
-    // ---------------------------------------------------- Instance Variables
-
-
-    // ---------------------------------------------------------- Constructors
-
-
-    /**
-     * Construct a new instance of this test case.
-     *
-     * @param name Name of the test case
-     */
-    public LocaleBeanificationTestCase(final String name) {
-        super(name);
-    }
-
-
-    // -------------------------------------------------- Overall Test Methods
-
-
-    /**
-     * Set up instance variables required by this test case.
-     */
-    @Override
-    public void setUp() {
-
-        LocaleConvertUtils.deregister();
-
-    }
-
-
-    /**
-     * Return the tests included in this test suite.
-     */
-    public static Test suite() {
-        return new TestSuite(LocaleBeanificationTestCase.class);
-    }
-
-
-    /**
-     * Tear down instance variables required by this test case.
-     */
-    @Override
-    public void tearDown() {
-        // No action required
-    }
-
-
-    // ------------------------------------------------ Individual Test Methods
-
-    /** Test of the methodology we'll use for some of the later tests */
-    public void testMemoryTestMethodology() throws Exception {
-        // test methodology
-        // many thanks to Juozas Baliuka for suggesting this method
-        ClassLoader loader = new ClassLoader(this.getClass().getClassLoader()) {};
-        final WeakReference<ClassLoader> reference = new  WeakReference<>(loader);
-        Class<?> myClass = loader.loadClass("org.apache.commons.beanutils2.BetaBean");
-
-        assertNotNull("Weak reference released early", reference.get());
-
-        // dereference class loader and class:
-        loader = null;
-        myClass = null;
-
-        int iterations = 0;
-        int bytz = 2;
-        while(true) {
-            System.gc();
-            if(iterations++ > MAX_GC_ITERATIONS){
-                fail("Max iterations reached before resource released.");
-            }
-            if( reference.get() == null ) {
-                break;
-
-            }
-            // create garbage:
-            final byte[] b =  new byte[bytz];
-            bytz = bytz * 2;
-        }
-    }
-
-    /** Tests whether classloaders and beans are released from memory by the map used by beanutils */
-    public void testMemoryLeak2() throws Exception {
-        // tests when the map used by beanutils has the right behaviour
-
-        if (BeanUtilsTestCase.isPre14JVM()) {
-            System.out.println("WARNING: CANNOT TEST MEMORY LEAK ON PRE1.4 JVM");
-            return;
-        }
-
-        // many thanks to Juozas Baliuka for suggesting this methodology
-        TestClassLoader loader = new TestClassLoader();
-        final ReferenceQueue<Object> queue = new ReferenceQueue<>();
-        final WeakReference<ClassLoader> loaderReference = new WeakReference<ClassLoader>(loader, queue);
-        Integer test = new Integer(1);
-
-        final WeakReference<Integer> testReference = new WeakReference<>(test, queue);
-        //Map map = new ReferenceMap(ReferenceMap.WEAK, ReferenceMap.HARD, true);
-        final Map<TestClassLoader, Integer> map = new WeakHashMap<>();
-        map.put(loader, test);
-
-        assertEquals("In map", test, map.get(loader));
-        assertNotNull("Weak reference released early (1)", loaderReference.get());
-        assertNotNull("Weak reference released early (2)", testReference.get());
-
-        // dereference strong references
-        loader = null;
-        test = null;
-
-        int iterations = 0;
-        int bytz = 2;
-        while(true) {
-            System.gc();
-            if(iterations++ > MAX_GC_ITERATIONS){
-                fail("Max iterations reached before resource released.");
-            }
-            map.isEmpty();
-
-            if(
-                loaderReference.get() == null &&
-                testReference.get() == null) {
-                break;
-
-            }
-            // create garbage:
-            final byte[] b =  new byte[bytz];
-            bytz = bytz * 2;
-        }
-    }
-
-    /** Tests whether classloaders and beans are released from memory */
-    public void testMemoryLeak() throws Exception {
-        if (BeanUtilsTestCase.isPre14JVM()) {
-            System.out.println("WARNING: CANNOT TEST MEMORY LEAK ON PRE1.4 JVM");
-            return;
-        }
-
-        // many thanks to Juozas Baliuka for suggesting this methodology
-        TestClassLoader loader = new TestClassLoader();
-        final WeakReference<TestClassLoader> loaderReference = new  WeakReference<>(loader);
-        LocaleBeanUtilsBean.getLocaleBeanUtilsInstance();
-
-        class GetBeanUtilsBeanThread extends Thread {
-
-            LocaleBeanUtilsBean beanUtils;
-            LocaleConvertUtilsBean convertUtils;
-
-            GetBeanUtilsBeanThread() {}
-
-            @Override
-            public void run() {
-                beanUtils = LocaleBeanUtilsBean.getLocaleBeanUtilsInstance();
-                convertUtils = LocaleConvertUtilsBean.getInstance();
-                // XXX Log keeps a reference around!
-                LogFactory.releaseAll();
-            }
-
-            @Override
-            public String toString() {
-                return "GetBeanUtilsBeanThread";
-            }
-        }
-
-
-        GetBeanUtilsBeanThread thread = new GetBeanUtilsBeanThread();
-        final WeakReference<GetBeanUtilsBeanThread> threadWeakReference = new WeakReference<>(thread);
-        thread.setContextClassLoader(loader);
-
-        thread.start();
-        thread.join();
-
-        final WeakReference<LocaleBeanUtilsBean> beanUtilsReference = new WeakReference<>(thread.beanUtils);
-        final WeakReference<LocaleConvertUtilsBean> convertUtilsReference = new WeakReference<>(thread.convertUtils);
-
-        assertNotNull("Weak reference released early (1)", loaderReference.get());
-        assertNotNull("Weak reference released early (2)", beanUtilsReference.get());
-        assertNotNull("Weak reference released early (4)", convertUtilsReference.get());
-
-        // dereference strong references
-        loader = null;
-        thread.setContextClassLoader(null);
-        thread = null;
-
-        int iterations = 0;
-        int bytz = 2;
-        while(true) {
-            LocaleBeanUtilsBean.getLocaleBeanUtilsInstance();
-            System.gc();
-            if(iterations++ > MAX_GC_ITERATIONS){
-                fail("Max iterations reached before resource released.");
-            }
-
-            if(
-                loaderReference.get() == null &&
-                beanUtilsReference.get() == null &&
-                convertUtilsReference.get() == null) {
-                break;
-
-            }
-            // create garbage:
-            final byte[] b =  new byte[bytz];
-            bytz = bytz * 2;
-        }
-    }
-
-    /**
-     * Tests whether difference instances are loaded by different
-     * context classloaders.
-     */
-    public void testGetByContextClassLoader() throws Exception {
-
-        class GetBeanUtilsBeanThread extends Thread {
-
-            private final Signal signal;
-
-            GetBeanUtilsBeanThread(final Signal signal) {
-                this.signal = signal;
-            }
-
-            @Override
-            public void run() {
-                signal.setSignal(2);
-                signal.setBean(LocaleBeanUtilsBean.getLocaleBeanUtilsInstance());
-                signal.setConvertUtils(LocaleConvertUtilsBean.getInstance());
-            }
-
-            @Override
-            public String toString() {
-                return "GetBeanUtilsBeanThread";
-            }
-        }
-
-        final Signal signal = new Signal();
-        signal.setSignal(1);
-
-        final GetBeanUtilsBeanThread thread = new GetBeanUtilsBeanThread(signal);
-        thread.setContextClassLoader(new TestClassLoader());
-
-        thread.start();
-        thread.join();
-
-        assertEquals("Signal not set by test thread", 2, signal.getSignal());
-        assertTrue(
-                    "Different LocaleBeanUtilsBean instances per context classloader",
-                    BeanUtilsBean.getInstance() != signal.getBean());
-        assertTrue(
-                    "Different LocaleConvertUtilsBean instances per context classloader",
-                    LocaleConvertUtilsBean.getInstance() != signal.getConvertUtils());
-    }
-
-
-    /**
-     * Tests whether difference instances are loaded by different
-     * context classloaders.
-     */
-    public void testContextClassLoaderLocal() throws Exception {
-
-        class CCLLTesterThread extends Thread {
-
-            private final Signal signal;
-            private final ContextClassLoaderLocal<Integer> ccll;
-
-            CCLLTesterThread(final Signal signal, final ContextClassLoaderLocal<Integer> ccll) {
-                this.signal = signal;
-                this.ccll = ccll;
-            }
-
-            @Override
-            public void run() {
-                ccll.set(new Integer(1789));
-                signal.setSignal(2);
-                signal.setMarkerObject(ccll.get());
-            }
-
-            @Override
-            public String toString() {
-                return "CCLLTesterThread";
-            }
-        }
-
-        final ContextClassLoaderLocal<Integer> ccll = new ContextClassLoaderLocal<>();
-        ccll.set(1776);
-        assertEquals("Start thread sets value", new Integer(1776), ccll.get());
-
-        final Signal signal = new Signal();
-        signal.setSignal(1);
-
-        final CCLLTesterThread thread = new CCLLTesterThread(signal, ccll);
-        thread.setContextClassLoader(new TestClassLoader());
-
-        thread.start();
-        thread.join();
-
-        assertEquals("Signal not set by test thread", 2, signal.getSignal());
-        assertEquals("Second thread preserves value", new Integer(1776), ccll.get());
-        assertEquals("Second thread gets value it set", new Integer(1789), signal.getMarkerObject());
-    }
-
-    /** Tests whether calls are independent for different classloaders */
-    public void testContextClassloaderIndependence() throws Exception {
-
-        class TestIndependenceThread extends Thread {
-            private final Signal signal;
-            private final PrimitiveBean bean;
-
-            TestIndependenceThread(final Signal signal, final PrimitiveBean bean) {
-                this.signal = signal;
-                this.bean = bean;
-            }
-
-            @Override
-            public void run() {
-                try {
-                    signal.setSignal(3);
-                    LocaleConvertUtils.register(new LocaleConverter() {
-                                            @Override
-                                            public <T> T convert(final Class<T> type, final Object value) {
-                                                return ConvertUtils.primitiveToWrapper(type).cast(9);
-                                            }
-                                            @Override
-                                            public <T> T convert(final Class<T> type, final Object value, final String pattern) {
-                                                return ConvertUtils.primitiveToWrapper(type).cast(9);
-                                            }
-                                                }, Integer.TYPE, Locale.getDefault());
-                    LocaleBeanUtils.setProperty(bean, "int", "1");
-                } catch (final Exception e) {
-                    e.printStackTrace();
-                    signal.setException(e);
-                }
-            }
-
-            @Override
-            public String toString() {
-                return "TestIndependenceThread";
-            }
-        }
-
-        final PrimitiveBean bean = new PrimitiveBean();
-        LocaleBeanUtils.setProperty(bean, "int", new Integer(1));
-        assertEquals("Wrong property value (1)", 1, bean.getInt());
-
-        LocaleConvertUtils.register(new LocaleConverter() {
-                                @Override
-                                public <T> T convert(final Class<T> type, final Object value) {
-                                    return ConvertUtils.primitiveToWrapper(type).cast(5);
-                                }
-                                @Override
-                                public <T> T convert(final Class<T> type, final Object value, final String pattern) {
-                                    return ConvertUtils.primitiveToWrapper(type).cast(5);
-                                }
-                                    }, Integer.TYPE, Locale.getDefault());
-        LocaleBeanUtils.setProperty(bean, "int", "1");
-        assertEquals("Wrong property value(2)", 5, bean.getInt());
-
-        final Signal signal = new Signal();
-        signal.setSignal(1);
-        final TestIndependenceThread thread = new TestIndependenceThread(signal, bean);
-        thread.setContextClassLoader(new TestClassLoader());
-
-        thread.start();
-        thread.join();
-
-        assertNull("Exception thrown by test thread:" + signal.getException(), signal.getException());
-        assertEquals("Signal not set by test thread", 3, signal.getSignal());
-        assertEquals("Wrong property value(3)", 9, bean.getInt());
-
-    }
-
-    /** Tests whether different threads can set beanutils instances correctly */
-    public void testBeanUtilsBeanSetInstance() throws Exception {
-
-        class SetInstanceTesterThread extends Thread {
-
-            private final Signal signal;
-            private final LocaleBeanUtilsBean bean;
-
-            SetInstanceTesterThread(final Signal signal, final LocaleBeanUtilsBean bean) {
-                this.signal = signal;
-                this.bean = bean;
-            }
-
-            @Override
-            public void run() {
-                LocaleBeanUtilsBean.setInstance(bean);
-                signal.setSignal(21);
-                signal.setBean(LocaleBeanUtilsBean.getLocaleBeanUtilsInstance());
-            }
-
-            @Override
-            public String toString() {
-                return "SetInstanceTesterThread";
-            }
-        }
-
-        final Signal signal = new Signal();
-        signal.setSignal(1);
-
-        final LocaleBeanUtilsBean beanOne = new LocaleBeanUtilsBean();
-        final LocaleBeanUtilsBean beanTwo = new LocaleBeanUtilsBean();
-
-        final SetInstanceTesterThread thread = new SetInstanceTesterThread(signal, beanTwo);
-        thread.setContextClassLoader(new TestClassLoader());
-
-        LocaleBeanUtilsBean.setInstance(beanOne);
-        assertEquals("Start thread gets right instance", beanOne, LocaleBeanUtilsBean.getLocaleBeanUtilsInstance());
-
-        thread.start();
-        thread.join();
-
-        assertEquals("Signal not set by test thread", 21, signal.getSignal());
-        assertEquals("Second thread preserves value", beanOne, LocaleBeanUtilsBean.getLocaleBeanUtilsInstance());
-        assertEquals("Second thread gets value it set", beanTwo, signal.getBean());
-    }
-
-    /** Tests whether the unset method works*/
-    public void testContextClassLoaderUnset() throws Exception {
-        final LocaleBeanUtilsBean beanOne = new LocaleBeanUtilsBean();
-        final ContextClassLoaderLocal<LocaleBeanUtilsBean> ccll = new ContextClassLoaderLocal<>();
-        ccll.set(beanOne);
-        assertEquals("Start thread gets right instance", beanOne, ccll.get());
-        ccll.unset();
-        assertTrue("Unset works", !beanOne.equals(ccll.get()));
-    }
-
-    /**
-     * Test registering a locale-aware converter with the standard ConvertUtils.
-     */
-    public void testLocaleAwareConverterInConvertUtils() throws Exception {
-        try {
-            // first use the default non-locale-aware converter
-            try {
-                final Long data = (Long) ConvertUtils.convert("777", Long.class);
-                assertEquals("Standard format long converted ok", 777, data.longValue());
-            }
-            catch(final ConversionException ex) {
-                fail("Unable to convert non-locale-aware number 777");
-            }
-
-            // now try default converter with special delimiters
-            try {
-                // This conversion will cause an error. But the default
-                // Long converter is set up to return a default value of
-                // zero on error.
-                final Long data = (Long) ConvertUtils.convert("1.000.000", Long.class);
-                assertEquals("Standard format behaved as expected", 0, data.longValue());
-            }
-            catch(final ConversionException ex) {
-                fail("Unexpected exception from standard Long converter.");
-            }
-
-            // Now try using a locale-aware converter together with
-            // locale-specific input string. Note that in the german locale,
-            // large numbers can be split up into groups of three digits
-            // using a dot character (and comma is the decimal-point indicator).
-            try {
-
-                final Locale germanLocale = Locale.GERMAN;
-                final LongLocaleConverter longLocaleConverter = new LongLocaleConverter(germanLocale);
-                ConvertUtils.register(longLocaleConverter, Long.class);
-
-                final Long data = (Long) ConvertUtils.convert("1.000.000", Long.class);
-                assertEquals("German-format long converted ok", 1000000, data.longValue());
-            } catch(final ConversionException ex) {
-                fail("Unable to convert german-format number");
-            }
-        } finally {
-            ConvertUtils.deregister();
-        }
-    }
-
-    // ---- Auxillary classes
-
-    class TestClassLoader extends ClassLoader {
-        @Override
-        public String toString() {
-            return "TestClassLoader";
-        }
-    }
-
-    class Signal {
-        private Exception e;
-        private int signal = 0;
-        private LocaleBeanUtilsBean bean;
-        private LocaleConvertUtilsBean convertUtils;
-        private Object marker;
-
-        public Exception getException() {
-            return e;
-        }
-
-        public void setException(final Exception e) {
-            this.e = e;
-        }
-
-        public int getSignal() {
-            return signal;
-        }
-
-        public void setSignal(final int signal) {
-            this.signal = signal;
-        }
-
-        public Object getMarkerObject() {
-            return marker;
-        }
-
-        public void setMarkerObject(final Object marker) {
-            this.marker = marker;
-        }
-
-        public LocaleBeanUtilsBean getBean() {
-            return bean;
-        }
-
-        public void setBean(final LocaleBeanUtilsBean bean) {
-            this.bean = bean;
-        }
-
-        public LocaleConvertUtilsBean getConvertUtils() {
-            return convertUtils;
-        }
-
-        public void setConvertUtils(final LocaleConvertUtilsBean convertUtils) {
-            this.convertUtils = convertUtils;
-        }
-    }
-}
-
+/*

+ * Licensed to the Apache Software Foundation (ASF) under one or more

+ * contributor license agreements.  See the NOTICE file distributed with

+ * this work for additional information regarding copyright ownership.

+ * The ASF licenses this file to You under the Apache License, Version 2.0

+ * (the "License"); you may not use this file except in compliance with

+ * the License.  You may obtain a copy of the License at

+ *

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+

+package org.apache.commons.beanutils2.locale;

+

+import java.lang.ref.ReferenceQueue;

+import java.lang.ref.WeakReference;

+import java.util.Locale;

+import java.util.Map;

+import java.util.WeakHashMap;

+

+import org.apache.commons.beanutils2.BeanUtilsBean;

+import org.apache.commons.beanutils2.BeanUtilsTestCase;

+import org.apache.commons.beanutils2.ContextClassLoaderLocal;

+import org.apache.commons.beanutils2.ConversionException;

+import org.apache.commons.beanutils2.ConvertUtils;

+import org.apache.commons.beanutils2.PrimitiveBean;

+import org.apache.commons.beanutils2.locale.converters.LongLocaleConverter;

+import org.apache.commons.logging.LogFactory;

+

+import junit.framework.Test;

+import junit.framework.TestCase;

+import junit.framework.TestSuite;

+

+/**

+ * <p>

+ * Test Case for changes made during LocaleBeanutils Beanification.

+ * This is basically a cut-and-correct version of the beanutils beanifications tests.

+ * </p>

+ *

+ */

+

+public class LocaleBeanificationTestCase extends TestCase {

+

+    // ---------------------------------------------------- Constants

+

+    /** Maximum number of iterations before our test fails */

+    public static final int MAX_GC_ITERATIONS = 50;

+

+    // ---------------------------------------------------- Instance Variables

+

+

+    // ---------------------------------------------------------- Constructors

+

+

+    /**

+     * Construct a new instance of this test case.

+     *

+     * @param name Name of the test case

+     */

+    public LocaleBeanificationTestCase(final String name) {

+        super(name);

+    }

+

+

+    // -------------------------------------------------- Overall Test Methods

+

+

+    /**

+     * Set up instance variables required by this test case.

+     */

+    @Override

+    public void setUp() {

+

+        LocaleConvertUtils.deregister();

+

+    }

+

+

+    /**

+     * Return the tests included in this test suite.

+     */

+    public static Test suite() {

+        return new TestSuite(LocaleBeanificationTestCase.class);

+    }

+

+

+    /**

+     * Tear down instance variables required by this test case.

+     */

+    @Override

+    public void tearDown() {

+        // No action required

+    }

+

+

+    // ------------------------------------------------ Individual Test Methods

+

+    /** Test of the methodology we'll use for some of the later tests */

+    public void testMemoryTestMethodology() throws Exception {

+        // test methodology

+        // many thanks to Juozas Baliuka for suggesting this method

+        ClassLoader loader = new ClassLoader(this.getClass().getClassLoader()) {};

+        final WeakReference<ClassLoader> reference = new  WeakReference<>(loader);

+        Class<?> myClass = loader.loadClass("org.apache.commons.beanutils2.BetaBean");

+

+        assertNotNull("Weak reference released early", reference.get());

+

+        // dereference class loader and class:

+        loader = null;

+        myClass = null;

+

+        int iterations = 0;

+        int bytz = 2;

+        while(true) {

+            System.gc();

+            if(iterations++ > MAX_GC_ITERATIONS){

+                fail("Max iterations reached before resource released.");

+            }

+            if( reference.get() == null ) {

+                break;

+

+            }

+            // create garbage:

+            final byte[] b =  new byte[bytz];

+            bytz = bytz * 2;

+        }

+    }

+

+    /** Tests whether classloaders and beans are released from memory by the map used by beanutils */

+    public void testMemoryLeak2() throws Exception {

+        // tests when the map used by beanutils has the right behaviour

+

+        if (BeanUtilsTestCase.isPre14JVM()) {

+            System.out.println("WARNING: CANNOT TEST MEMORY LEAK ON PRE1.4 JVM");

+            return;

+        }

+

+        // many thanks to Juozas Baliuka for suggesting this methodology

+        TestClassLoader loader = new TestClassLoader();

+        final ReferenceQueue<Object> queue = new ReferenceQueue<>();

+        final WeakReference<ClassLoader> loaderReference = new WeakReference<>(loader, queue);

+        Integer test = new Integer(1);

+

+        final WeakReference<Integer> testReference = new WeakReference<>(test, queue);

+        //Map map = new ReferenceMap(ReferenceMap.WEAK, ReferenceMap.HARD, true);

+        final Map<TestClassLoader, Integer> map = new WeakHashMap<>();

+        map.put(loader, test);

+

+        assertEquals("In map", test, map.get(loader));

+        assertNotNull("Weak reference released early (1)", loaderReference.get());

+        assertNotNull("Weak reference released early (2)", testReference.get());

+

+        // dereference strong references

+        loader = null;

+        test = null;

+

+        int iterations = 0;

+        int bytz = 2;

+        while(true) {

+            System.gc();

+            if(iterations++ > MAX_GC_ITERATIONS){

+                fail("Max iterations reached before resource released.");

+            }

+            map.isEmpty();

+

+            if(

+                loaderReference.get() == null &&

+                testReference.get() == null) {

+                break;

+

+            }

+            // create garbage:

+            final byte[] b =  new byte[bytz];

+            bytz = bytz * 2;

+        }

+    }

+

+    /** Tests whether classloaders and beans are released from memory */

+    public void testMemoryLeak() throws Exception {

+        if (BeanUtilsTestCase.isPre14JVM()) {

+            System.out.println("WARNING: CANNOT TEST MEMORY LEAK ON PRE1.4 JVM");

+            return;

+        }

+

+        // many thanks to Juozas Baliuka for suggesting this methodology

+        TestClassLoader loader = new TestClassLoader();

+        final WeakReference<TestClassLoader> loaderReference = new  WeakReference<>(loader);

+        LocaleBeanUtilsBean.getLocaleBeanUtilsInstance();

+

+        class GetBeanUtilsBeanThread extends Thread {

+

+            LocaleBeanUtilsBean beanUtils;

+            LocaleConvertUtilsBean convertUtils;

+

+            GetBeanUtilsBeanThread() {}

+

+            @Override

+            public void run() {

+                beanUtils = LocaleBeanUtilsBean.getLocaleBeanUtilsInstance();

+                convertUtils = LocaleConvertUtilsBean.getInstance();

+                // XXX Log keeps a reference around!

+                LogFactory.releaseAll();

+            }

+

+            @Override

+            public String toString() {

+                return "GetBeanUtilsBeanThread";

+            }

+        }

+

+

+        GetBeanUtilsBeanThread thread = new GetBeanUtilsBeanThread();

+        final WeakReference<GetBeanUtilsBeanThread> threadWeakReference = new WeakReference<>(thread);

+        thread.setContextClassLoader(loader);

+

+        thread.start();

+        thread.join();

+

+        final WeakReference<LocaleBeanUtilsBean> beanUtilsReference = new WeakReference<>(thread.beanUtils);

+        final WeakReference<LocaleConvertUtilsBean> convertUtilsReference = new WeakReference<>(thread.convertUtils);

+

+        assertNotNull("Weak reference released early (1)", loaderReference.get());

+        assertNotNull("Weak reference released early (2)", beanUtilsReference.get());

+        assertNotNull("Weak reference released early (4)", convertUtilsReference.get());

+

+        // dereference strong references

+        loader = null;

+        thread.setContextClassLoader(null);

+        thread = null;

+

+        int iterations = 0;

+        int bytz = 2;

+        while(true) {

+            LocaleBeanUtilsBean.getLocaleBeanUtilsInstance();

+            System.gc();

+            if(iterations++ > MAX_GC_ITERATIONS){

+                fail("Max iterations reached before resource released.");

+            }

+

+            if(

+                loaderReference.get() == null &&

+                beanUtilsReference.get() == null &&

+                convertUtilsReference.get() == null) {

+                break;

+

+            }

+            // create garbage:

+            final byte[] b =  new byte[bytz];

+            bytz = bytz * 2;

+        }

+    }

+

+    /**

+     * Tests whether difference instances are loaded by different

+     * context classloaders.

+     */

+    public void testGetByContextClassLoader() throws Exception {

+

+        class GetBeanUtilsBeanThread extends Thread {

+

+            private final Signal signal;

+

+            GetBeanUtilsBeanThread(final Signal signal) {

+                this.signal = signal;

+            }

+

+            @Override

+            public void run() {

+                signal.setSignal(2);

+                signal.setBean(LocaleBeanUtilsBean.getLocaleBeanUtilsInstance());

+                signal.setConvertUtils(LocaleConvertUtilsBean.getInstance());

+            }

+

+            @Override

+            public String toString() {

+                return "GetBeanUtilsBeanThread";

+            }

+        }

+

+        final Signal signal = new Signal();

+        signal.setSignal(1);

+

+        final GetBeanUtilsBeanThread thread = new GetBeanUtilsBeanThread(signal);

+        thread.setContextClassLoader(new TestClassLoader());

+

+        thread.start();

+        thread.join();

+

+        assertEquals("Signal not set by test thread", 2, signal.getSignal());

+        assertTrue(

+                    "Different LocaleBeanUtilsBean instances per context classloader",

+                    BeanUtilsBean.getInstance() != signal.getBean());

+        assertTrue(

+                    "Different LocaleConvertUtilsBean instances per context classloader",

+                    LocaleConvertUtilsBean.getInstance() != signal.getConvertUtils());

+    }

+

+

+    /**

+     * Tests whether difference instances are loaded by different

+     * context classloaders.

+     */

+    public void testContextClassLoaderLocal() throws Exception {

+

+        class CCLLTesterThread extends Thread {

+

+            private final Signal signal;

+            private final ContextClassLoaderLocal<Integer> ccll;

+

+            CCLLTesterThread(final Signal signal, final ContextClassLoaderLocal<Integer> ccll) {

+                this.signal = signal;

+                this.ccll = ccll;

+            }

+

+            @Override

+            public void run() {

+                ccll.set(new Integer(1789));

+                signal.setSignal(2);

+                signal.setMarkerObject(ccll.get());

+            }

+

+            @Override

+            public String toString() {

+                return "CCLLTesterThread";

+            }

+        }

+

+        final ContextClassLoaderLocal<Integer> ccll = new ContextClassLoaderLocal<>();

+        ccll.set(1776);

+        assertEquals("Start thread sets value", new Integer(1776), ccll.get());

+

+        final Signal signal = new Signal();

+        signal.setSignal(1);

+

+        final CCLLTesterThread thread = new CCLLTesterThread(signal, ccll);

+        thread.setContextClassLoader(new TestClassLoader());

+

+        thread.start();

+        thread.join();

+

+        assertEquals("Signal not set by test thread", 2, signal.getSignal());

+        assertEquals("Second thread preserves value", new Integer(1776), ccll.get());

+        assertEquals("Second thread gets value it set", new Integer(1789), signal.getMarkerObject());

+    }

+

+    /** Tests whether calls are independent for different classloaders */

+    public void testContextClassloaderIndependence() throws Exception {

+

+        class TestIndependenceThread extends Thread {

+            private final Signal signal;

+            private final PrimitiveBean bean;

+

+            TestIndependenceThread(final Signal signal, final PrimitiveBean bean) {

+                this.signal = signal;

+                this.bean = bean;

+            }

+

+            @Override

+            public void run() {

+                try {

+                    signal.setSignal(3);

+                    LocaleConvertUtils.register(new LocaleConverter() {

+                                            @Override

+                                            public <T> T convert(final Class<T> type, final Object value) {

+                                                return ConvertUtils.primitiveToWrapper(type).cast(9);

+                                            }

+                                            @Override

+                                            public <T> T convert(final Class<T> type, final Object value, final String pattern) {

+                                                return ConvertUtils.primitiveToWrapper(type).cast(9);

+                                            }

+                                                }, Integer.TYPE, Locale.getDefault());

+                    LocaleBeanUtils.setProperty(bean, "int", "1");

+                } catch (final Exception e) {

+                    e.printStackTrace();

+                    signal.setException(e);

+                }

+            }

+

+            @Override

+            public String toString() {

+                return "TestIndependenceThread";

+            }

+        }

+

+        final PrimitiveBean bean = new PrimitiveBean();

+        LocaleBeanUtils.setProperty(bean, "int", new Integer(1));

+        assertEquals("Wrong property value (1)", 1, bean.getInt());

+

+        LocaleConvertUtils.register(new LocaleConverter() {

+                                @Override

+                                public <T> T convert(final Class<T> type, final Object value) {

+                                    return ConvertUtils.primitiveToWrapper(type).cast(5);

+                                }

+                                @Override

+                                public <T> T convert(final Class<T> type, final Object value, final String pattern) {

+                                    return ConvertUtils.primitiveToWrapper(type).cast(5);

+                                }

+                                    }, Integer.TYPE, Locale.getDefault());

+        LocaleBeanUtils.setProperty(bean, "int", "1");

+        assertEquals("Wrong property value(2)", 5, bean.getInt());

+

+        final Signal signal = new Signal();

+        signal.setSignal(1);

+        final TestIndependenceThread thread = new TestIndependenceThread(signal, bean);

+        thread.setContextClassLoader(new TestClassLoader());

+

+        thread.start();

+        thread.join();

+

+        assertNull("Exception thrown by test thread:" + signal.getException(), signal.getException());

+        assertEquals("Signal not set by test thread", 3, signal.getSignal());

+        assertEquals("Wrong property value(3)", 9, bean.getInt());

+

+    }

+

+    /** Tests whether different threads can set beanutils instances correctly */

+    public void testBeanUtilsBeanSetInstance() throws Exception {

+

+        class SetInstanceTesterThread extends Thread {

+

+            private final Signal signal;

+            private final LocaleBeanUtilsBean bean;

+

+            SetInstanceTesterThread(final Signal signal, final LocaleBeanUtilsBean bean) {

+                this.signal = signal;

+                this.bean = bean;

+            }

+

+            @Override

+            public void run() {

+                LocaleBeanUtilsBean.setInstance(bean);

+                signal.setSignal(21);

+                signal.setBean(LocaleBeanUtilsBean.getLocaleBeanUtilsInstance());

+            }

+

+            @Override

+            public String toString() {

+                return "SetInstanceTesterThread";

+            }

+        }

+

+        final Signal signal = new Signal();

+        signal.setSignal(1);

+

+        final LocaleBeanUtilsBean beanOne = new LocaleBeanUtilsBean();

+        final LocaleBeanUtilsBean beanTwo = new LocaleBeanUtilsBean();

+

+        final SetInstanceTesterThread thread = new SetInstanceTesterThread(signal, beanTwo);

+        thread.setContextClassLoader(new TestClassLoader());

+

+        LocaleBeanUtilsBean.setInstance(beanOne);

+        assertEquals("Start thread gets right instance", beanOne, LocaleBeanUtilsBean.getLocaleBeanUtilsInstance());

+

+        thread.start();

+        thread.join();

+

+        assertEquals("Signal not set by test thread", 21, signal.getSignal());

+        assertEquals("Second thread preserves value", beanOne, LocaleBeanUtilsBean.getLocaleBeanUtilsInstance());

+        assertEquals("Second thread gets value it set", beanTwo, signal.getBean());

+    }

+

+    /** Tests whether the unset method works*/

+    public void testContextClassLoaderUnset() throws Exception {

+        final LocaleBeanUtilsBean beanOne = new LocaleBeanUtilsBean();

+        final ContextClassLoaderLocal<LocaleBeanUtilsBean> ccll = new ContextClassLoaderLocal<>();

+        ccll.set(beanOne);

+        assertEquals("Start thread gets right instance", beanOne, ccll.get());

+        ccll.unset();

+        assertTrue("Unset works", !beanOne.equals(ccll.get()));

+    }

+

+    /**

+     * Test registering a locale-aware converter with the standard ConvertUtils.

+     */

+    public void testLocaleAwareConverterInConvertUtils() throws Exception {

+        try {

+            // first use the default non-locale-aware converter

+            try {

+                final Long data = (Long) ConvertUtils.convert("777", Long.class);

+                assertEquals("Standard format long converted ok", 777, data.longValue());

+            }

+            catch(final ConversionException ex) {

+                fail("Unable to convert non-locale-aware number 777");

+            }

+

+            // now try default converter with special delimiters

+            try {

+                // This conversion will cause an error. But the default

+                // Long converter is set up to return a default value of

+                // zero on error.

+                final Long data = (Long) ConvertUtils.convert("1.000.000", Long.class);

+                assertEquals("Standard format behaved as expected", 0, data.longValue());

+            }

+            catch(final ConversionException ex) {

+                fail("Unexpected exception from standard Long converter.");

+            }

+

+            // Now try using a locale-aware converter together with

+            // locale-specific input string. Note that in the german locale,

+            // large numbers can be split up into groups of three digits

+            // using a dot character (and comma is the decimal-point indicator).

+            try {

+

+                final Locale germanLocale = Locale.GERMAN;

+                final LongLocaleConverter longLocaleConverter = new LongLocaleConverter(germanLocale);

+                ConvertUtils.register(longLocaleConverter, Long.class);

+

+                final Long data = (Long) ConvertUtils.convert("1.000.000", Long.class);

+                assertEquals("German-format long converted ok", 1000000, data.longValue());

+            } catch(final ConversionException ex) {

+                fail("Unable to convert german-format number");

+            }

+        } finally {

+            ConvertUtils.deregister();

+        }

+    }

+

+    // ---- Auxillary classes

+

+    class TestClassLoader extends ClassLoader {

+        @Override

+        public String toString() {

+            return "TestClassLoader";

+        }

+    }

+

+    class Signal {

+        private Exception e;

+        private int signal = 0;

+        private LocaleBeanUtilsBean bean;

+        private LocaleConvertUtilsBean convertUtils;

+        private Object marker;

+

+        public Exception getException() {

+            return e;

+        }

+

+        public void setException(final Exception e) {

+            this.e = e;

+        }

+

+        public int getSignal() {

+            return signal;

+        }

+

+        public void setSignal(final int signal) {

+            this.signal = signal;

+        }

+

+        public Object getMarkerObject() {

+            return marker;

+        }

+

+        public void setMarkerObject(final Object marker) {

+            this.marker = marker;

+        }

+

+        public LocaleBeanUtilsBean getBean() {

+            return bean;

+        }

+

+        public void setBean(final LocaleBeanUtilsBean bean) {

+            this.bean = bean;

+        }

+

+        public LocaleConvertUtilsBean getConvertUtils() {

+            return convertUtils;

+        }

+

+        public void setConvertUtils(final LocaleConvertUtilsBean convertUtils) {

+            this.convertUtils = convertUtils;

+        }

+    }

+}

+