http://git-wip-us.apache.org/repos/asf/commons-dbutils/blob/084f286a/src/main/java/org/apache/commons/dbutils/BeanProcessor.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/dbutils/BeanProcessor.java 
b/src/main/java/org/apache/commons/dbutils/BeanProcessor.java
index e18dc01..b15920f 100644
--- a/src/main/java/org/apache/commons/dbutils/BeanProcessor.java
+++ b/src/main/java/org/apache/commons/dbutils/BeanProcessor.java
@@ -1,534 +1,534 @@
-/*
- * 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.dbutils;
-
-import java.beans.BeanInfo;
-import java.beans.IntrospectionException;
-import java.beans.Introspector;
-import java.beans.PropertyDescriptor;
-import java.lang.reflect.Field;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.sql.ResultSet;
-import java.sql.ResultSetMetaData;
-import java.sql.SQLException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.ServiceLoader;
-
-/**
- * <p>
- * <code>BeanProcessor</code> matches column names to bean property names
- * and converts <code>ResultSet</code> columns into objects for those bean
- * properties.  Subclasses should override the methods in the processing chain
- * to customize behavior.
- * </p>
- *
- * <p>
- * This class is thread-safe.
- * </p>
- *
- * @see BasicRowProcessor
- *
- * @since DbUtils 1.1
- */
-public class BeanProcessor {
-
-    /**
-     * Special array value used by <code>mapColumnsToProperties</code> that
-     * indicates there is no bean property that matches a column from a
-     * <code>ResultSet</code>.
-     */
-    protected static final int PROPERTY_NOT_FOUND = -1;
-
-    /**
-     * Set a bean's primitive properties to these defaults when SQL NULL
-     * is returned.  These are the same as the defaults that ResultSet get*
-     * methods return in the event of a NULL column.
-     */
-    private static final Map<Class<?>, Object> primitiveDefaults = new 
HashMap<Class<?>, Object>();
-
-    private static final List<ColumnHandler> columnHandlers = new 
ArrayList<ColumnHandler>();
-
-    private static final List<PropertyHandler> propertyHandlers = new 
ArrayList<PropertyHandler>();
-
-    /**
-     * ResultSet column to bean property name overrides.
-     */
-    private final Map<String, String> columnToPropertyOverrides;
-
-    static {
-        primitiveDefaults.put(Integer.TYPE, Integer.valueOf(0));
-        primitiveDefaults.put(Short.TYPE, Short.valueOf((short) 0));
-        primitiveDefaults.put(Byte.TYPE, Byte.valueOf((byte) 0));
-        primitiveDefaults.put(Float.TYPE, Float.valueOf(0f));
-        primitiveDefaults.put(Double.TYPE, Double.valueOf(0d));
-        primitiveDefaults.put(Long.TYPE, Long.valueOf(0L));
-        primitiveDefaults.put(Boolean.TYPE, Boolean.FALSE);
-        primitiveDefaults.put(Character.TYPE, Character.valueOf((char) 0));
-    
-        // Use a ServiceLoader to find implementations
-        for (ColumnHandler handler : ServiceLoader.load(ColumnHandler.class)) {
-            columnHandlers.add(handler);
-        }
-    
-        // Use a ServiceLoader to find implementations
-        for (PropertyHandler handler : 
ServiceLoader.load(PropertyHandler.class)) {
-            propertyHandlers.add(handler);
-        }
-    }
-
-    /**
-     * Constructor for BeanProcessor.
-     */
-    public BeanProcessor() {
-        this(new HashMap<String, String>());
-    }
-
-    /**
-     * Constructor for BeanProcessor configured with column to property name 
overrides.
-     *
-     * @param columnToPropertyOverrides ResultSet column to bean property name 
overrides
-     * @since 1.5
-     */
-    public BeanProcessor(Map<String, String> columnToPropertyOverrides) {
-        super();
-        if (columnToPropertyOverrides == null) {
-            throw new IllegalArgumentException("columnToPropertyOverrides map 
cannot be null");
-        }
-        this.columnToPropertyOverrides = columnToPropertyOverrides;
-    }
-
-    /**
-     * Convert a <code>ResultSet</code> row into a JavaBean.  This
-     * implementation uses reflection and <code>BeanInfo</code> classes to
-     * match column names to bean property names.  Properties are matched to
-     * columns based on several factors:
-     * &lt;br/&gt;
-     * &lt;ol&gt;
-     *     &lt;li&gt;
-     *     The class has a writable property with the same name as a column.
-     *     The name comparison is case insensitive.
-     *     &lt;/li&gt;
-     *
-     *     &lt;li&gt;
-     *     The column type can be converted to the property's set method
-     *     parameter type with a ResultSet.get* method.  If the conversion 
fails
-     *     (ie. the property was an int and the column was a Timestamp) an
-     *     SQLException is thrown.
-     *     &lt;/li&gt;
-     * &lt;/ol&gt;
-     *
-     * &lt;p&gt;
-     * Primitive bean properties are set to their defaults when SQL NULL is
-     * returned from the <code>ResultSet</code>.  Numeric fields are set to 0
-     * and booleans are set to false.  Object bean properties are set to
-     * <code>null</code> when SQL NULL is returned.  This is the same behavior
-     * as the <code>ResultSet</code> get* methods.
-     * &lt;/p&gt;
-     * @param <T> The type of bean to create
-     * @param rs ResultSet that supplies the bean data
-     * @param type Class from which to create the bean instance
-     * @throws SQLException if a database access error occurs
-     * @return the newly created bean
-     */
-    public <T> T toBean(ResultSet rs, Class<? extends T> type) throws 
SQLException {
-        T bean = this.newInstance(type);
-        return this.populateBean(rs, bean);
-    }
-
-    /**
-     * Convert a <code>ResultSet</code> into a <code>List</code> of JavaBeans.
-     * This implementation uses reflection and <code>BeanInfo</code> classes to
-     * match column names to bean property names. Properties are matched to
-     * columns based on several factors:
-     * &lt;br/&gt;
-     * &lt;ol&gt;
-     *     &lt;li&gt;
-     *     The class has a writable property with the same name as a column.
-     *     The name comparison is case insensitive.
-     *     &lt;/li&gt;
-     *
-     *     &lt;li&gt;
-     *     The column type can be converted to the property's set method
-     *     parameter type with a ResultSet.get* method.  If the conversion 
fails
-     *     (ie. the property was an int and the column was a Timestamp) an
-     *     SQLException is thrown.
-     *     &lt;/li&gt;
-     * &lt;/ol&gt;
-     *
-     * <p>
-     * Primitive bean properties are set to their defaults when SQL NULL is
-     * returned from the <code>ResultSet</code>.  Numeric fields are set to 0
-     * and booleans are set to false.  Object bean properties are set to
-     * <code>null</code> when SQL NULL is returned.  This is the same behavior
-     * as the <code>ResultSet</code> get* methods.
-     * &lt;/p&gt;
-     * @param <T> The type of bean to create
-     * @param rs ResultSet that supplies the bean data
-     * @param type Class from which to create the bean instance
-     * @throws SQLException if a database access error occurs
-     * @return the newly created List of beans
-     */
-    public <T> List<T> toBeanList(ResultSet rs, Class<? extends T> type) 
throws SQLException {
-        List<T> results = new ArrayList<T>();
-
-        if (!rs.next()) {
-            return results;
-        }
-
-        PropertyDescriptor[] props = this.propertyDescriptors(type);
-        ResultSetMetaData rsmd = rs.getMetaData();
-        int[] columnToProperty = this.mapColumnsToProperties(rsmd, props);
-
-        do {
-            results.add(this.createBean(rs, type, props, columnToProperty));
-        } while (rs.next());
-
-        return results;
-    }
-
-    /**
-     * Creates a new object and initializes its fields from the ResultSet.
-     * @param <T> The type of bean to create
-     * @param rs The result set.
-     * @param type The bean type (the return type of the object).
-     * @param props The property descriptors.
-     * @param columnToProperty The column indices in the result set.
-     * @return An initialized object.
-     * @throws SQLException if a database error occurs.
-     */
-    private <T> T createBean(ResultSet rs, Class<T> type,
-                             PropertyDescriptor[] props, int[] 
columnToProperty)
-    throws SQLException {
-
-        T bean = this.newInstance(type);
-        return populateBean(rs, bean, props, columnToProperty);
-    }
-
-    /**
-     * Initializes the fields of the provided bean from the ResultSet.
-     * @param <T> The type of bean
-     * @param rs The result set.
-     * @param bean The bean to be populated.
-     * @return An initialized object.
-     * @throws SQLException if a database error occurs.
-     */
-    public <T> T populateBean(ResultSet rs, T bean) throws SQLException {
-        PropertyDescriptor[] props = this.propertyDescriptors(bean.getClass());
-        ResultSetMetaData rsmd = rs.getMetaData();
-        int[] columnToProperty = this.mapColumnsToProperties(rsmd, props);
-
-        return populateBean(rs, bean, props, columnToProperty);
-    }
-
-    /**
-     * This method populates a bean from the ResultSet based upon the 
underlying meta-data.
-     *
-     * @param <T> The type of bean
-     * @param rs The result set.
-     * @param bean The bean to be populated.
-     * @param props The property descriptors.
-     * @param columnToProperty The column indices in the result set.
-     * @return An initialized object.
-     * @throws SQLException if a database error occurs.
-     */
-    private <T> T populateBean(ResultSet rs, T bean,
-            PropertyDescriptor[] props, int[] columnToProperty)
-            throws SQLException {
-
-        for (int i = 1; i < columnToProperty.length; i++) {
-
-            if (columnToProperty[i] == PROPERTY_NOT_FOUND) {
-                continue;
-            }
-
-            PropertyDescriptor prop = props[columnToProperty[i]];
-            Class<?> propType = prop.getPropertyType();
-
-            Object value = null;
-            if(propType != null) {
-                value = this.processColumn(rs, i, propType);
-
-                if (value == null && propType.isPrimitive()) {
-                    value = primitiveDefaults.get(propType);
-                }
-            }
-
-            this.callSetter(bean, prop, value);
-        }
-
-        return bean;
-    }
-
-    /**
-     * Calls the setter method on the target object for the given property.
-     * If no setter method exists for the property, this method does nothing.
-     * @param target The object to set the property on.
-     * @param prop The property to set.
-     * @param value The value to pass into the setter.
-     * @throws SQLException if an error occurs setting the property.
-     */
-    private void callSetter(Object target, PropertyDescriptor prop, Object 
value)
-            throws SQLException {
-
-        Method setter = getWriteMethod(target, prop, value);
-
-        if (setter == null || setter.getParameterTypes().length != 1) {
-            return;
-        }
-
-        try {
-            Class<?> firstParam = setter.getParameterTypes()[0];
-            for (PropertyHandler handler : propertyHandlers) {
-                if (handler.match(firstParam, value)) {
-                    value = handler.apply(firstParam, value);
-                    break;
-                }
-            }
-
-            // Don't call setter if the value object isn't the right type
-            if (this.isCompatibleType(value, firstParam)) {
-                setter.invoke(target, new Object[]{value});
-            } else {
-              throw new SQLException(
-                  "Cannot set " + prop.getName() + ": incompatible types, 
cannot convert "
-                  + value.getClass().getName() + " to " + 
firstParam.getName());
-                  // value cannot be null here because isCompatibleType allows 
null
-            }
-
-        } catch (IllegalArgumentException e) {
-            throw new SQLException(
-                "Cannot set " + prop.getName() + ": " + e.getMessage());
-
-        } catch (IllegalAccessException e) {
-            throw new SQLException(
-                "Cannot set " + prop.getName() + ": " + e.getMessage());
-
-        } catch (InvocationTargetException e) {
-            throw new SQLException(
-                "Cannot set " + prop.getName() + ": " + e.getMessage());
-        }
-    }
-
-    /**
-     * ResultSet.getObject() returns an Integer object for an INT column.  The
-     * setter method for the property might take an Integer or a primitive int.
-     * This method returns true if the value can be successfully passed into
-     * the setter method.  Remember, Method.invoke() handles the unwrapping
-     * of Integer into an int.
-     *
-     * @param value The value to be passed into the setter method.
-     * @param type The setter's parameter type (non-null)
-     * @return boolean True if the value is compatible (null => true)
-     */
-    private boolean isCompatibleType(Object value, Class<?> type) {
-        // Do object check first, then primitives
-        if (value == null || type.isInstance(value) || matchesPrimitive(type, 
value.getClass())) {
-            return true;
-
-        }
-        return false;
-
-    }
-
-    /**
-     * Check whether a value is of the same primitive type as 
<code>targetType</code>.
-     *
-     * @param targetType The primitive type to target.
-     * @param valueType The value to match to the primitive type.
-     * @return Whether <code>valueType</code> can be coerced (e.g. autoboxed) 
into <code>targetType</code>.
-     */
-    private boolean matchesPrimitive(Class<?> targetType, Class<?> valueType) {
-        if (!targetType.isPrimitive()) {
-            return false;
-        }
-
-        try {
-            // see if there is a "TYPE" field.  This is present for primitive 
wrappers.
-            Field typeField = valueType.getField("TYPE");
-            Object primitiveValueType = typeField.get(valueType);
-
-            if (targetType == primitiveValueType) {
-                return true;
-            }
-        } catch (NoSuchFieldException e) {
-            // lacking the TYPE field is a good sign that we're not working 
with a primitive wrapper.
-            // we can't match for compatibility
-        } catch (IllegalAccessException e) {
-            // an inaccessible TYPE field is a good sign that we're not 
working with a primitive wrapper.
-            // nothing to do.  we can't match for compatibility
-        }
-        return false;
-    }
-
-    /**
-     * Get the write method to use when setting {@code value} to the {@code 
target}.
-     *
-     * @param target Object where the write method will be called.
-     * @param prop   BeanUtils information.
-     * @param value  The value that will be passed to the write method.
-     * @return The {@link java.lang.reflect.Method} to call on {@code target} 
to write {@code value} or {@code null} if
-     *         there is no suitable write method.
-     */
-    protected Method getWriteMethod(Object target, PropertyDescriptor prop, 
Object value) {
-        Method method = prop.getWriteMethod();
-        return method;
-    }
-
-    /**
-     * Factory method that returns a new instance of the given Class.  This
-     * is called at the start of the bean creation process and may be
-     * overridden to provide custom behavior like returning a cached bean
-     * instance.
-     * @param <T> The type of object to create
-     * @param c The Class to create an object from.
-     * @return A newly created object of the Class.
-     * @throws SQLException if creation failed.
-     */
-    protected <T> T newInstance(Class<T> c) throws SQLException {
-        try {
-            return c.newInstance();
-
-        } catch (InstantiationException e) {
-            throw new SQLException(
-                "Cannot create " + c.getName() + ": " + e.getMessage());
-
-        } catch (IllegalAccessException e) {
-            throw new SQLException(
-                "Cannot create " + c.getName() + ": " + e.getMessage());
-        }
-    }
-
-    /**
-     * Returns a PropertyDescriptor[] for the given Class.
-     *
-     * @param c The Class to retrieve PropertyDescriptors for.
-     * @return A PropertyDescriptor[] describing the Class.
-     * @throws SQLException if introspection failed.
-     */
-    private PropertyDescriptor[] propertyDescriptors(Class<?> c)
-        throws SQLException {
-        // Introspector caches BeanInfo classes for better performance
-        BeanInfo beanInfo = null;
-        try {
-            beanInfo = Introspector.getBeanInfo(c);
-
-        } catch (IntrospectionException e) {
-            throw new SQLException(
-                "Bean introspection failed: " + e.getMessage());
-        }
-
-        return beanInfo.getPropertyDescriptors();
-    }
-
-    /**
-     * The positions in the returned array represent column numbers.  The
-     * values stored at each position represent the index in the
-     * <code>PropertyDescriptor[]</code> for the bean property that matches
-     * the column name.  If no bean property was found for a column, the
-     * position is set to <code>PROPERTY_NOT_FOUND</code>.
-     *
-     * @param rsmd The <code>ResultSetMetaData</code> containing column
-     * information.
-     *
-     * @param props The bean property descriptors.
-     *
-     * @throws SQLException if a database access error occurs
-     *
-     * @return An int[] with column index to property index mappings.  The 0th
-     * element is meaningless because JDBC column indexing starts at 1.
-     */
-    protected int[] mapColumnsToProperties(ResultSetMetaData rsmd,
-            PropertyDescriptor[] props) throws SQLException {
-
-        int cols = rsmd.getColumnCount();
-        int[] columnToProperty = new int[cols + 1];
-        Arrays.fill(columnToProperty, PROPERTY_NOT_FOUND);
-
-        for (int col = 1; col <= cols; col++) {
-            String columnName = rsmd.getColumnLabel(col);
-            if (null == columnName || 0 == columnName.length()) {
-              columnName = rsmd.getColumnName(col);
-            }
-            String propertyName = columnToPropertyOverrides.get(columnName);
-            if (propertyName == null) {
-                propertyName = columnName;
-            }
-            for (int i = 0; i < props.length; i++) {
-
-                if (propertyName.equalsIgnoreCase(props[i].getName())) {
-                    columnToProperty[col] = i;
-                    break;
-                }
-            }
-        }
-
-        return columnToProperty;
-    }
-
-    /**
-     * Convert a <code>ResultSet</code> column into an object.  Simple
-     * implementations could just call <code>rs.getObject(index)</code> while
-     * more complex implementations could perform type manipulation to match
-     * the column's type to the bean property type.
-     *
-     * <p>
-     * This implementation calls the appropriate <code>ResultSet</code> getter
-     * method for the given property type to perform the type conversion.  If
-     * the property type doesn't match one of the supported
-     * <code>ResultSet</code> types, <code>getObject</code> is called.
-     * </p>
-     *
-     * @param rs The <code>ResultSet</code> currently being processed.  It is
-     * positioned on a valid row before being passed into this method.
-     *
-     * @param index The current column index being processed.
-     *
-     * @param propType The bean property type that this column needs to be
-     * converted into.
-     *
-     * @throws SQLException if a database access error occurs
-     *
-     * @return The object from the <code>ResultSet</code> at the given column
-     * index after optional type processing or <code>null</code> if the column
-     * value was SQL NULL.
-     */
-    protected Object processColumn(ResultSet rs, int index, Class<?> propType)
-        throws SQLException {
-
-        Object retval = rs.getObject(index);
-
-        if ( !propType.isPrimitive() && retval == null ) {
-            return null;
-        }
-
-        for (ColumnHandler handler : columnHandlers) {
-            if (handler.match(propType)) {
-                retval = handler.apply(rs, index);
-                break;
-            }
-        }
-
-        return retval;
-
-    }
-
-}
+/*
+ * 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.dbutils;
+
+import java.beans.BeanInfo;
+import java.beans.IntrospectionException;
+import java.beans.Introspector;
+import java.beans.PropertyDescriptor;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.ServiceLoader;
+
+/**
+ * <p>
+ * <code>BeanProcessor</code> matches column names to bean property names
+ * and converts <code>ResultSet</code> columns into objects for those bean
+ * properties.  Subclasses should override the methods in the processing chain
+ * to customize behavior.
+ * </p>
+ *
+ * <p>
+ * This class is thread-safe.
+ * </p>
+ *
+ * @see BasicRowProcessor
+ *
+ * @since DbUtils 1.1
+ */
+public class BeanProcessor {
+
+    /**
+     * Special array value used by <code>mapColumnsToProperties</code> that
+     * indicates there is no bean property that matches a column from a
+     * <code>ResultSet</code>.
+     */
+    protected static final int PROPERTY_NOT_FOUND = -1;
+
+    /**
+     * Set a bean's primitive properties to these defaults when SQL NULL
+     * is returned.  These are the same as the defaults that ResultSet get*
+     * methods return in the event of a NULL column.
+     */
+    private static final Map<Class<?>, Object> primitiveDefaults = new 
HashMap<Class<?>, Object>();
+
+    private static final List<ColumnHandler> columnHandlers = new 
ArrayList<ColumnHandler>();
+
+    private static final List<PropertyHandler> propertyHandlers = new 
ArrayList<PropertyHandler>();
+
+    /**
+     * ResultSet column to bean property name overrides.
+     */
+    private final Map<String, String> columnToPropertyOverrides;
+
+    static {
+        primitiveDefaults.put(Integer.TYPE, Integer.valueOf(0));
+        primitiveDefaults.put(Short.TYPE, Short.valueOf((short) 0));
+        primitiveDefaults.put(Byte.TYPE, Byte.valueOf((byte) 0));
+        primitiveDefaults.put(Float.TYPE, Float.valueOf(0f));
+        primitiveDefaults.put(Double.TYPE, Double.valueOf(0d));
+        primitiveDefaults.put(Long.TYPE, Long.valueOf(0L));
+        primitiveDefaults.put(Boolean.TYPE, Boolean.FALSE);
+        primitiveDefaults.put(Character.TYPE, Character.valueOf((char) 0));
+
+        // Use a ServiceLoader to find implementations
+        for (ColumnHandler handler : ServiceLoader.load(ColumnHandler.class)) {
+            columnHandlers.add(handler);
+        }
+
+        // Use a ServiceLoader to find implementations
+        for (PropertyHandler handler : 
ServiceLoader.load(PropertyHandler.class)) {
+            propertyHandlers.add(handler);
+        }
+    }
+
+    /**
+     * Constructor for BeanProcessor.
+     */
+    public BeanProcessor() {
+        this(new HashMap<String, String>());
+    }
+
+    /**
+     * Constructor for BeanProcessor configured with column to property name 
overrides.
+     *
+     * @param columnToPropertyOverrides ResultSet column to bean property name 
overrides
+     * @since 1.5
+     */
+    public BeanProcessor(Map<String, String> columnToPropertyOverrides) {
+        super();
+        if (columnToPropertyOverrides == null) {
+            throw new IllegalArgumentException("columnToPropertyOverrides map 
cannot be null");
+        }
+        this.columnToPropertyOverrides = columnToPropertyOverrides;
+    }
+
+    /**
+     * Convert a <code>ResultSet</code> row into a JavaBean.  This
+     * implementation uses reflection and <code>BeanInfo</code> classes to
+     * match column names to bean property names.  Properties are matched to
+     * columns based on several factors:
+     * &lt;br/&gt;
+     * &lt;ol&gt;
+     *     &lt;li&gt;
+     *     The class has a writable property with the same name as a column.
+     *     The name comparison is case insensitive.
+     *     &lt;/li&gt;
+     *
+     *     &lt;li&gt;
+     *     The column type can be converted to the property's set method
+     *     parameter type with a ResultSet.get* method.  If the conversion 
fails
+     *     (ie. the property was an int and the column was a Timestamp) an
+     *     SQLException is thrown.
+     *     &lt;/li&gt;
+     * &lt;/ol&gt;
+     *
+     * &lt;p&gt;
+     * Primitive bean properties are set to their defaults when SQL NULL is
+     * returned from the <code>ResultSet</code>.  Numeric fields are set to 0
+     * and booleans are set to false.  Object bean properties are set to
+     * <code>null</code> when SQL NULL is returned.  This is the same behavior
+     * as the <code>ResultSet</code> get* methods.
+     * &lt;/p&gt;
+     * @param <T> The type of bean to create
+     * @param rs ResultSet that supplies the bean data
+     * @param type Class from which to create the bean instance
+     * @throws SQLException if a database access error occurs
+     * @return the newly created bean
+     */
+    public <T> T toBean(ResultSet rs, Class<? extends T> type) throws 
SQLException {
+        T bean = this.newInstance(type);
+        return this.populateBean(rs, bean);
+    }
+
+    /**
+     * Convert a <code>ResultSet</code> into a <code>List</code> of JavaBeans.
+     * This implementation uses reflection and <code>BeanInfo</code> classes to
+     * match column names to bean property names. Properties are matched to
+     * columns based on several factors:
+     * &lt;br/&gt;
+     * &lt;ol&gt;
+     *     &lt;li&gt;
+     *     The class has a writable property with the same name as a column.
+     *     The name comparison is case insensitive.
+     *     &lt;/li&gt;
+     *
+     *     &lt;li&gt;
+     *     The column type can be converted to the property's set method
+     *     parameter type with a ResultSet.get* method.  If the conversion 
fails
+     *     (ie. the property was an int and the column was a Timestamp) an
+     *     SQLException is thrown.
+     *     &lt;/li&gt;
+     * &lt;/ol&gt;
+     *
+     * <p>
+     * Primitive bean properties are set to their defaults when SQL NULL is
+     * returned from the <code>ResultSet</code>.  Numeric fields are set to 0
+     * and booleans are set to false.  Object bean properties are set to
+     * <code>null</code> when SQL NULL is returned.  This is the same behavior
+     * as the <code>ResultSet</code> get* methods.
+     * &lt;/p&gt;
+     * @param <T> The type of bean to create
+     * @param rs ResultSet that supplies the bean data
+     * @param type Class from which to create the bean instance
+     * @throws SQLException if a database access error occurs
+     * @return the newly created List of beans
+     */
+    public <T> List<T> toBeanList(ResultSet rs, Class<? extends T> type) 
throws SQLException {
+        List<T> results = new ArrayList<T>();
+
+        if (!rs.next()) {
+            return results;
+        }
+
+        PropertyDescriptor[] props = this.propertyDescriptors(type);
+        ResultSetMetaData rsmd = rs.getMetaData();
+        int[] columnToProperty = this.mapColumnsToProperties(rsmd, props);
+
+        do {
+            results.add(this.createBean(rs, type, props, columnToProperty));
+        } while (rs.next());
+
+        return results;
+    }
+
+    /**
+     * Creates a new object and initializes its fields from the ResultSet.
+     * @param <T> The type of bean to create
+     * @param rs The result set.
+     * @param type The bean type (the return type of the object).
+     * @param props The property descriptors.
+     * @param columnToProperty The column indices in the result set.
+     * @return An initialized object.
+     * @throws SQLException if a database error occurs.
+     */
+    private <T> T createBean(ResultSet rs, Class<T> type,
+                             PropertyDescriptor[] props, int[] 
columnToProperty)
+    throws SQLException {
+
+        T bean = this.newInstance(type);
+        return populateBean(rs, bean, props, columnToProperty);
+    }
+
+    /**
+     * Initializes the fields of the provided bean from the ResultSet.
+     * @param <T> The type of bean
+     * @param rs The result set.
+     * @param bean The bean to be populated.
+     * @return An initialized object.
+     * @throws SQLException if a database error occurs.
+     */
+    public <T> T populateBean(ResultSet rs, T bean) throws SQLException {
+        PropertyDescriptor[] props = this.propertyDescriptors(bean.getClass());
+        ResultSetMetaData rsmd = rs.getMetaData();
+        int[] columnToProperty = this.mapColumnsToProperties(rsmd, props);
+
+        return populateBean(rs, bean, props, columnToProperty);
+    }
+
+    /**
+     * This method populates a bean from the ResultSet based upon the 
underlying meta-data.
+     *
+     * @param <T> The type of bean
+     * @param rs The result set.
+     * @param bean The bean to be populated.
+     * @param props The property descriptors.
+     * @param columnToProperty The column indices in the result set.
+     * @return An initialized object.
+     * @throws SQLException if a database error occurs.
+     */
+    private <T> T populateBean(ResultSet rs, T bean,
+            PropertyDescriptor[] props, int[] columnToProperty)
+            throws SQLException {
+
+        for (int i = 1; i < columnToProperty.length; i++) {
+
+            if (columnToProperty[i] == PROPERTY_NOT_FOUND) {
+                continue;
+            }
+
+            PropertyDescriptor prop = props[columnToProperty[i]];
+            Class<?> propType = prop.getPropertyType();
+
+            Object value = null;
+            if(propType != null) {
+                value = this.processColumn(rs, i, propType);
+
+                if (value == null && propType.isPrimitive()) {
+                    value = primitiveDefaults.get(propType);
+                }
+            }
+
+            this.callSetter(bean, prop, value);
+        }
+
+        return bean;
+    }
+
+    /**
+     * Calls the setter method on the target object for the given property.
+     * If no setter method exists for the property, this method does nothing.
+     * @param target The object to set the property on.
+     * @param prop The property to set.
+     * @param value The value to pass into the setter.
+     * @throws SQLException if an error occurs setting the property.
+     */
+    private void callSetter(Object target, PropertyDescriptor prop, Object 
value)
+            throws SQLException {
+
+        Method setter = getWriteMethod(target, prop, value);
+
+        if (setter == null || setter.getParameterTypes().length != 1) {
+            return;
+        }
+
+        try {
+            Class<?> firstParam = setter.getParameterTypes()[0];
+            for (PropertyHandler handler : propertyHandlers) {
+                if (handler.match(firstParam, value)) {
+                    value = handler.apply(firstParam, value);
+                    break;
+                }
+            }
+
+            // Don't call setter if the value object isn't the right type
+            if (this.isCompatibleType(value, firstParam)) {
+                setter.invoke(target, new Object[]{value});
+            } else {
+              throw new SQLException(
+                  "Cannot set " + prop.getName() + ": incompatible types, 
cannot convert "
+                  + value.getClass().getName() + " to " + 
firstParam.getName());
+                  // value cannot be null here because isCompatibleType allows 
null
+            }
+
+        } catch (IllegalArgumentException e) {
+            throw new SQLException(
+                "Cannot set " + prop.getName() + ": " + e.getMessage());
+
+        } catch (IllegalAccessException e) {
+            throw new SQLException(
+                "Cannot set " + prop.getName() + ": " + e.getMessage());
+
+        } catch (InvocationTargetException e) {
+            throw new SQLException(
+                "Cannot set " + prop.getName() + ": " + e.getMessage());
+        }
+    }
+
+    /**
+     * ResultSet.getObject() returns an Integer object for an INT column.  The
+     * setter method for the property might take an Integer or a primitive int.
+     * This method returns true if the value can be successfully passed into
+     * the setter method.  Remember, Method.invoke() handles the unwrapping
+     * of Integer into an int.
+     *
+     * @param value The value to be passed into the setter method.
+     * @param type The setter's parameter type (non-null)
+     * @return boolean True if the value is compatible (null => true)
+     */
+    private boolean isCompatibleType(Object value, Class<?> type) {
+        // Do object check first, then primitives
+        if (value == null || type.isInstance(value) || matchesPrimitive(type, 
value.getClass())) {
+            return true;
+
+        }
+        return false;
+
+    }
+
+    /**
+     * Check whether a value is of the same primitive type as 
<code>targetType</code>.
+     *
+     * @param targetType The primitive type to target.
+     * @param valueType The value to match to the primitive type.
+     * @return Whether <code>valueType</code> can be coerced (e.g. autoboxed) 
into <code>targetType</code>.
+     */
+    private boolean matchesPrimitive(Class<?> targetType, Class<?> valueType) {
+        if (!targetType.isPrimitive()) {
+            return false;
+        }
+
+        try {
+            // see if there is a "TYPE" field.  This is present for primitive 
wrappers.
+            Field typeField = valueType.getField("TYPE");
+            Object primitiveValueType = typeField.get(valueType);
+
+            if (targetType == primitiveValueType) {
+                return true;
+            }
+        } catch (NoSuchFieldException e) {
+            // lacking the TYPE field is a good sign that we're not working 
with a primitive wrapper.
+            // we can't match for compatibility
+        } catch (IllegalAccessException e) {
+            // an inaccessible TYPE field is a good sign that we're not 
working with a primitive wrapper.
+            // nothing to do.  we can't match for compatibility
+        }
+        return false;
+    }
+
+    /**
+     * Get the write method to use when setting {@code value} to the {@code 
target}.
+     *
+     * @param target Object where the write method will be called.
+     * @param prop   BeanUtils information.
+     * @param value  The value that will be passed to the write method.
+     * @return The {@link java.lang.reflect.Method} to call on {@code target} 
to write {@code value} or {@code null} if
+     *         there is no suitable write method.
+     */
+    protected Method getWriteMethod(Object target, PropertyDescriptor prop, 
Object value) {
+        Method method = prop.getWriteMethod();
+        return method;
+    }
+
+    /**
+     * Factory method that returns a new instance of the given Class.  This
+     * is called at the start of the bean creation process and may be
+     * overridden to provide custom behavior like returning a cached bean
+     * instance.
+     * @param <T> The type of object to create
+     * @param c The Class to create an object from.
+     * @return A newly created object of the Class.
+     * @throws SQLException if creation failed.
+     */
+    protected <T> T newInstance(Class<T> c) throws SQLException {
+        try {
+            return c.newInstance();
+
+        } catch (InstantiationException e) {
+            throw new SQLException(
+                "Cannot create " + c.getName() + ": " + e.getMessage());
+
+        } catch (IllegalAccessException e) {
+            throw new SQLException(
+                "Cannot create " + c.getName() + ": " + e.getMessage());
+        }
+    }
+
+    /**
+     * Returns a PropertyDescriptor[] for the given Class.
+     *
+     * @param c The Class to retrieve PropertyDescriptors for.
+     * @return A PropertyDescriptor[] describing the Class.
+     * @throws SQLException if introspection failed.
+     */
+    private PropertyDescriptor[] propertyDescriptors(Class<?> c)
+        throws SQLException {
+        // Introspector caches BeanInfo classes for better performance
+        BeanInfo beanInfo = null;
+        try {
+            beanInfo = Introspector.getBeanInfo(c);
+
+        } catch (IntrospectionException e) {
+            throw new SQLException(
+                "Bean introspection failed: " + e.getMessage());
+        }
+
+        return beanInfo.getPropertyDescriptors();
+    }
+
+    /**
+     * The positions in the returned array represent column numbers.  The
+     * values stored at each position represent the index in the
+     * <code>PropertyDescriptor[]</code> for the bean property that matches
+     * the column name.  If no bean property was found for a column, the
+     * position is set to <code>PROPERTY_NOT_FOUND</code>.
+     *
+     * @param rsmd The <code>ResultSetMetaData</code> containing column
+     * information.
+     *
+     * @param props The bean property descriptors.
+     *
+     * @throws SQLException if a database access error occurs
+     *
+     * @return An int[] with column index to property index mappings.  The 0th
+     * element is meaningless because JDBC column indexing starts at 1.
+     */
+    protected int[] mapColumnsToProperties(ResultSetMetaData rsmd,
+            PropertyDescriptor[] props) throws SQLException {
+
+        int cols = rsmd.getColumnCount();
+        int[] columnToProperty = new int[cols + 1];
+        Arrays.fill(columnToProperty, PROPERTY_NOT_FOUND);
+
+        for (int col = 1; col <= cols; col++) {
+            String columnName = rsmd.getColumnLabel(col);
+            if (null == columnName || 0 == columnName.length()) {
+              columnName = rsmd.getColumnName(col);
+            }
+            String propertyName = columnToPropertyOverrides.get(columnName);
+            if (propertyName == null) {
+                propertyName = columnName;
+            }
+            for (int i = 0; i < props.length; i++) {
+
+                if (propertyName.equalsIgnoreCase(props[i].getName())) {
+                    columnToProperty[col] = i;
+                    break;
+                }
+            }
+        }
+
+        return columnToProperty;
+    }
+
+    /**
+     * Convert a <code>ResultSet</code> column into an object.  Simple
+     * implementations could just call <code>rs.getObject(index)</code> while
+     * more complex implementations could perform type manipulation to match
+     * the column's type to the bean property type.
+     *
+     * <p>
+     * This implementation calls the appropriate <code>ResultSet</code> getter
+     * method for the given property type to perform the type conversion.  If
+     * the property type doesn't match one of the supported
+     * <code>ResultSet</code> types, <code>getObject</code> is called.
+     * </p>
+     *
+     * @param rs The <code>ResultSet</code> currently being processed.  It is
+     * positioned on a valid row before being passed into this method.
+     *
+     * @param index The current column index being processed.
+     *
+     * @param propType The bean property type that this column needs to be
+     * converted into.
+     *
+     * @throws SQLException if a database access error occurs
+     *
+     * @return The object from the <code>ResultSet</code> at the given column
+     * index after optional type processing or <code>null</code> if the column
+     * value was SQL NULL.
+     */
+    protected Object processColumn(ResultSet rs, int index, Class<?> propType)
+        throws SQLException {
+
+        Object retval = rs.getObject(index);
+
+        if ( !propType.isPrimitive() && retval == null ) {
+            return null;
+        }
+
+        for (ColumnHandler handler : columnHandlers) {
+            if (handler.match(propType)) {
+                retval = handler.apply(rs, index);
+                break;
+            }
+        }
+
+        return retval;
+
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/commons-dbutils/blob/084f286a/src/test/java/org/apache/commons/dbutils/AsyncQueryRunnerTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/commons/dbutils/AsyncQueryRunnerTest.java 
b/src/test/java/org/apache/commons/dbutils/AsyncQueryRunnerTest.java
index 24f3900..3a00aa9 100644
--- a/src/test/java/org/apache/commons/dbutils/AsyncQueryRunnerTest.java
+++ b/src/test/java/org/apache/commons/dbutils/AsyncQueryRunnerTest.java
@@ -1,496 +1,496 @@
-/*
- * 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.dbutils;
-
-import static org.junit.Assert.fail;
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.doThrow;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import java.sql.Connection;
-import java.sql.ParameterMetaData;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
-import java.util.concurrent.TimeUnit;
-
-import javax.sql.DataSource;
-
-import org.apache.commons.dbutils.handlers.ArrayHandler;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-@SuppressWarnings("boxing") // test code
-public class AsyncQueryRunnerTest {
-    AsyncQueryRunner runner;
-    ArrayHandler handler;
-
-    @Mock DataSource dataSource;
-    @Mock Connection conn;
-    @Mock PreparedStatement stmt;
-    @Mock ParameterMetaData meta;
-    @Mock ResultSet results;
-
-    @Before
-    public void setUp() throws Exception {
-        MockitoAnnotations.initMocks(this);
-
-        when(dataSource.getConnection()).thenReturn(conn);
-        when(conn.prepareStatement(any(String.class))).thenReturn(stmt);
-        when(stmt.getParameterMetaData()).thenReturn(meta);
-        when(stmt.getResultSet()).thenReturn(results);
-        when(stmt.executeQuery()).thenReturn(results);
-        when(results.next()).thenReturn(false);
-
-         handler = new ArrayHandler();
-         runner = new AsyncQueryRunner(Executors.newFixedThreadPool(1), new 
QueryRunner(dataSource));
-    }
-
-    //
-    // Batch test cases
-    //
-    private void callGoodBatch(Connection conn, Object[][] params) throws 
Exception {
-        when(meta.getParameterCount()).thenReturn(2);
-        Future<int[]> future = runner.batch(conn, "select * from blah where ? 
= ?", params);
-
-        future.get();
-
-        verify(stmt, times(2)).addBatch();
-        verify(stmt, times(1)).executeBatch();
-        verify(stmt, times(1)).close();    // make sure we closed the statement
-        verify(conn, times(0)).close();    // make sure we closed the 
connection
-    }
-
-    private void callGoodBatch(Object[][] params) throws Exception {
-        when(meta.getParameterCount()).thenReturn(2);
-        Future<int[]> future = runner.batch("select * from blah where ? = ?", 
params);
-
-        future.get();
-        
-        verify(stmt, times(2)).addBatch();
-        verify(stmt, times(1)).executeBatch();
-        verify(stmt, times(1)).close();    // make sure we closed the statement
-        verify(conn, times(1)).close();    // make sure we closed the 
connection
-    }
-
-    @Test
-    public void testGoodBatch() throws Exception {
-        String[][] params = new String[][] { { "unit", "unit" }, { "test", 
"test" } };
-
-        callGoodBatch(params);
-    }
-
-    @SuppressWarnings("deprecation") // deliberate test of deprecated code
-    @Test
-    public void testGoodBatchPmdTrue() throws Exception {
-        runner = new AsyncQueryRunner(dataSource, true, 
Executors.newFixedThreadPool(1));
-        String[][] params = new String[][] { { "unit", "unit" }, { "test", 
"test" } };
-
-        callGoodBatch(params);
-    }
-
-    @Test
-    public void testGoodBatchDefaultConstructor() throws Exception {
-        runner = new AsyncQueryRunner(Executors.newFixedThreadPool(1));
-        String[][] params = new String[][] { { "unit", "unit" }, { "test", 
"test" } };
-
-        callGoodBatch(conn, params);
-    }
-
-    @Test
-    public void testNullParamsBatch() throws Exception {
-        String[][] params = new String[][] { { null, "unit" }, { "test", null 
} };
-
-        callGoodBatch(params);
-    }
-
-
-
-    // helper method for calling batch when an exception is expected
-    private void callBatchWithException(String sql, Object[][] params) throws 
Exception {
-        Future<int[]> future = null;
-        boolean caught = false;
-
-        try {
-            future = runner.batch(sql, params);
-            
-            future.get();
-            
-            verify(stmt, times(2)).addBatch();
-            verify(stmt, times(1)).executeBatch();
-            verify(stmt, times(1)).close();    // make sure the statement is 
closed
-            verify(conn, times(1)).close();    // make sure the connection is 
closed
-        } catch(Exception e) {
-            caught = true;
-        }
-
-        if(!caught) {
-            fail("Exception never thrown, but expected");
-        }
-    }
-
-    @Test
-    public void testTooFewParamsBatch() throws Exception {
-        String[][] params = new String[][] { { "unit" }, { "test" } };
-
-        callBatchWithException("select * from blah where ? = ?", params);
-    }
-
-    @Test
-    public void testTooManyParamsBatch() throws Exception {
-        String[][] params = new String[][] { { "unit", "unit", "unit" }, { 
"test", "test", "test" } };
-
-        callBatchWithException("select * from blah where ? = ?", params);
-    }
-
-    @Test(expected=ExecutionException.class)
-    public void testNullConnectionBatch() throws Exception {
-        String[][] params = new String[][] { { "unit", "unit" }, { "test", 
"test" } };
-
-        when(meta.getParameterCount()).thenReturn(2);
-        when(dataSource.getConnection()).thenReturn(null);
-
-        runner.batch("select * from blah where ? = ?", params).get();
-    }
-
-    @Test(expected=ExecutionException.class)
-    public void testNullSqlBatch() throws Exception {
-        String[][] params = new String[][] { { "unit", "unit" }, { "test", 
"test" } };
-
-        when(meta.getParameterCount()).thenReturn(2);
-
-        runner.batch(null, params).get();
-    }
-
-    @Test(expected=ExecutionException.class)
-    public void testNullParamsArgBatch() throws Exception {
-        when(meta.getParameterCount()).thenReturn(2);
-
-        runner.batch("select * from blah where ? = ?", null).get();
-    }
-
-    @Test
-    public void testAddBatchException() throws Exception {
-        String[][] params = new String[][] { { "unit", "unit" }, { "test", 
"test" } };
-
-        doThrow(new SQLException()).when(stmt).addBatch();
-
-        callBatchWithException("select * from blah where ? = ?", params);
-    }
-
-    @Test
-    public void testExecuteBatchException() throws Exception {
-        String[][] params = new String[][] { { "unit", "unit" }, { "test", 
"test" } };
-
-        doThrow(new SQLException()).when(stmt).executeBatch();
-
-        callBatchWithException("select * from blah where ? = ?", params);
-    }
-
-
-    //
-    // Query test cases
-    //
-    private void callGoodQuery(Connection conn) throws Exception {
-        when(meta.getParameterCount()).thenReturn(2);
-        runner.query(conn, "select * from blah where ? = ?", handler, "unit", 
"test").get();
-
-        verify(stmt, times(1)).executeQuery();
-        verify(results, times(1)).close();
-        verify(stmt, times(1)).close();    // make sure we closed the statement
-        verify(conn, times(0)).close();    // make sure we closed the 
connection
-
-        // call the other variation of query
-        when(meta.getParameterCount()).thenReturn(0);
-        runner.query(conn, "select * from blah", handler).get();
-
-        verify(stmt, times(2)).executeQuery();
-        verify(results, times(2)).close();
-        verify(stmt, times(2)).close();    // make sure we closed the statement
-        verify(conn, times(0)).close();    // make sure we closed the 
connection
-    }
-
-    private void callGoodQuery() throws Exception {
-        when(meta.getParameterCount()).thenReturn(2);
-        runner.query("select * from blah where ? = ?", handler, "unit", 
"test").get();
-
-        verify(stmt, times(1)).executeQuery();
-        verify(results, times(1)).close();
-        verify(stmt, times(1)).close();    // make sure we closed the statement
-        verify(conn, times(1)).close();    // make sure we closed the 
connection
-
-        // call the other variation of query
-        when(meta.getParameterCount()).thenReturn(0);
-        runner.query("select * from blah", handler).get();
-
-        verify(stmt, times(2)).executeQuery();
-        verify(results, times(2)).close();
-        verify(stmt, times(2)).close();    // make sure we closed the statement
-        verify(conn, times(2)).close();    // make sure we closed the 
connection
-    }
-
-    @Test
-    public void testGoodQuery() throws Exception {
-        callGoodQuery();
-    }
-
-    @SuppressWarnings("deprecation") // deliberate test of deprecated code
-    @Test
-    public void testGoodQueryPmdTrue() throws Exception {
-        runner = new AsyncQueryRunner(true, Executors.newFixedThreadPool(1));
-        callGoodQuery(conn);
-    }
-
-    @Test
-    public void testGoodQueryDefaultConstructor() throws Exception {
-        runner = new AsyncQueryRunner(Executors.newFixedThreadPool(1));
-        callGoodQuery(conn);
-    }
-
-
-    // helper method for calling batch when an exception is expected
-    private void callQueryWithException(Object... params) throws Exception {
-        boolean caught = false;
-
-        try {
-            when(meta.getParameterCount()).thenReturn(2);
-            runner.query("select * from blah where ? = ?", handler, 
params).get();
-
-            verify(stmt, times(1)).executeQuery();
-            verify(results, times(1)).close();
-            verify(stmt, times(1)).close();    // make sure we closed the 
statement
-            verify(conn, times(1)).close();    // make sure we closed the 
connection
-        } catch(Exception e) {
-            caught = true;
-        }
-
-        if(!caught) {
-            fail("Exception never thrown, but expected");
-        }
-    }
-
-    @Test
-    public void testNoParamsQuery() throws Exception {
-        callQueryWithException();
-    }
-
-    @Test
-    public void testTooFewParamsQuery() throws Exception {
-        callQueryWithException("unit");
-    }
-
-    @Test
-    public void testTooManyParamsQuery() throws Exception {
-        callQueryWithException("unit", "test", "fail");
-    }
-
-    @Test(expected=ExecutionException.class)
-    public void testNullConnectionQuery() throws Exception {
-        when(meta.getParameterCount()).thenReturn(2);
-        when(dataSource.getConnection()).thenReturn(null);
-
-        runner.query("select * from blah where ? = ?", handler, "unit", 
"test").get();
-    }
-
-    @Test(expected=ExecutionException.class)
-    public void testNullSqlQuery() throws Exception {
-        when(meta.getParameterCount()).thenReturn(2);
-
-        runner.query(null, handler).get();
-    }
-
-    @Test(expected=ExecutionException.class)
-    public void testNullHandlerQuery() throws Exception {
-        when(meta.getParameterCount()).thenReturn(2);
-
-        runner.query("select * from blah where ? = ?", null).get();
-    }
-
-    @Test
-    public void testExecuteQueryException() throws Exception {
-        doThrow(new SQLException()).when(stmt).executeQuery();
-
-        callQueryWithException(handler, "unit", "test");
-    }
-
-
-    //
-    // Update test cases
-    //
-    private void callGoodUpdate(Connection conn) throws Exception {
-        when(meta.getParameterCount()).thenReturn(2);
-        runner.update(conn, "update blah set ? = ?", "unit", "test").get();
-
-        verify(stmt, times(1)).executeUpdate();
-        verify(stmt, times(1)).close();    // make sure we closed the statement
-        verify(conn, times(0)).close();    // make sure we closed the 
connection
-
-        // call the other variation
-        when(meta.getParameterCount()).thenReturn(0);
-        runner.update(conn, "update blah set unit = test").get();
-
-        verify(stmt, times(2)).executeUpdate();
-        verify(stmt, times(2)).close();    // make sure we closed the statement
-        verify(conn, times(0)).close();    // make sure we closed the 
connection
-
-        // call the other variation
-        when(meta.getParameterCount()).thenReturn(1);
-        runner.update(conn, "update blah set unit = ?", "test").get();
-
-        verify(stmt, times(3)).executeUpdate();
-        verify(stmt, times(3)).close();    // make sure we closed the statement
-        verify(conn, times(0)).close();    // make sure we closed the 
connection
-    }
-
-    private void callGoodUpdate() throws Exception {
-        when(meta.getParameterCount()).thenReturn(2);
-        runner.update("update blah set ? = ?", "unit", "test").get();
-
-        verify(stmt, times(1)).executeUpdate();
-        verify(stmt, times(1)).close();    // make sure we closed the statement
-        verify(conn, times(1)).close();    // make sure we closed the 
connection
-
-        // call the other variation
-        when(meta.getParameterCount()).thenReturn(0);
-        runner.update("update blah set unit = test").get();
-
-        verify(stmt, times(2)).executeUpdate();
-        verify(stmt, times(2)).close();    // make sure we closed the statement
-        verify(conn, times(2)).close();    // make sure we closed the 
connection
-
-        // call the other variation
-        when(meta.getParameterCount()).thenReturn(1);
-        runner.update("update blah set unit = ?", "test").get();
-
-        verify(stmt, times(3)).executeUpdate();
-        verify(stmt, times(3)).close();    // make sure we closed the statement
-        verify(conn, times(3)).close();    // make sure we closed the 
connection
-    }
-
-    @Test
-    public void testGoodUpdate() throws Exception {
-        callGoodUpdate();
-    }
-
-    @SuppressWarnings("deprecation") // deliberate test of deprecated code
-    @Test
-    public void testGoodUpdatePmdTrue() throws Exception {
-        runner = new AsyncQueryRunner(true, Executors.newFixedThreadPool(1));
-        callGoodUpdate(conn);
-    }
-
-    @Test
-    public void testGoodUpdateDefaultConstructor() throws Exception {
-        runner = new AsyncQueryRunner(Executors.newFixedThreadPool(1));
-        callGoodUpdate(conn);
-    }
-
-    // helper method for calling batch when an exception is expected
-    private void callUpdateWithException(Object... params) throws Exception {
-        boolean caught = false;
-
-        try {
-            when(meta.getParameterCount()).thenReturn(2);
-            runner.update("select * from blah where ? = ?", params).get();
-
-            verify(stmt, times(1)).executeUpdate();
-            verify(stmt, times(1)).close();    // make sure we closed the 
statement
-            verify(conn, times(1)).close();    // make sure we closed the 
connection
-        } catch(Exception e) {
-            caught = true;
-        }
-
-        if(!caught) {
-            fail("Exception never thrown, but expected");
-        }
-    }
-
-    @Test
-    public void testNoParamsUpdate() throws Exception {
-        callUpdateWithException();
-    }
-
-    @Test
-    public void testTooFewParamsUpdate() throws Exception {
-        callUpdateWithException("unit");
-    }
-
-    @Test
-    public void testTooManyParamsUpdate() throws Exception {
-        callUpdateWithException("unit", "test", "fail");
-    }
-    
-    @Test
-    public void testInsertUsesGivenQueryRunner() throws Exception {
-        QueryRunner mockQueryRunner = mock(QueryRunner.class
-                , org.mockito.Mockito.withSettings().verboseLogging() // debug 
for Continuum
-                );
-        runner = new AsyncQueryRunner(Executors.newSingleThreadExecutor(), 
mockQueryRunner);
-
-        runner.insert("1", handler);
-        runner.insert("2", handler, "param1");
-        runner.insert(conn, "3", handler);
-        runner.insert(conn, "4", handler, "param1");
-
-        // give the Executor time to submit all insert statements. Otherwise 
the following verify statements will fail from time to time.
-        TimeUnit.MILLISECONDS.sleep(50);
-
-        verify(mockQueryRunner).insert("1", handler);
-        verify(mockQueryRunner).insert("2", handler, "param1");
-        verify(mockQueryRunner).insert(conn, "3", handler);
-        verify(mockQueryRunner).insert(conn, "4", handler, "param1");
-    }
-
-    @Test(expected=ExecutionException.class)
-    public void testNullConnectionUpdate() throws Exception {
-        when(meta.getParameterCount()).thenReturn(2);
-        when(dataSource.getConnection()).thenReturn(null);
-
-        runner.update("select * from blah where ? = ?", "unit", "test").get();
-    }
-
-    @Test(expected=ExecutionException.class)
-    public void testNullSqlUpdate() throws Exception {
-        when(meta.getParameterCount()).thenReturn(2);
-
-        runner.update(null).get();
-    }
-
-    @Test
-    public void testExecuteUpdateException() throws Exception {
-        doThrow(new SQLException()).when(stmt).executeUpdate();
-
-        callUpdateWithException("unit", "test");
-    }
-
-    //
-    // Random tests
-    //
-    @Test(expected=ExecutionException.class)
-    public void testBadPrepareConnection() throws Exception {
-        runner = new AsyncQueryRunner(Executors.newFixedThreadPool(1));
-        runner.update("update blah set unit = test").get();
-    }
-}
+/*
+ * 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.dbutils;
+
+import static org.junit.Assert.fail;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.sql.Connection;
+import java.sql.ParameterMetaData;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+
+import javax.sql.DataSource;
+
+import org.apache.commons.dbutils.handlers.ArrayHandler;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@SuppressWarnings("boxing") // test code
+public class AsyncQueryRunnerTest {
+    AsyncQueryRunner runner;
+    ArrayHandler handler;
+
+    @Mock DataSource dataSource;
+    @Mock Connection conn;
+    @Mock PreparedStatement stmt;
+    @Mock ParameterMetaData meta;
+    @Mock ResultSet results;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+
+        when(dataSource.getConnection()).thenReturn(conn);
+        when(conn.prepareStatement(any(String.class))).thenReturn(stmt);
+        when(stmt.getParameterMetaData()).thenReturn(meta);
+        when(stmt.getResultSet()).thenReturn(results);
+        when(stmt.executeQuery()).thenReturn(results);
+        when(results.next()).thenReturn(false);
+
+         handler = new ArrayHandler();
+         runner = new AsyncQueryRunner(Executors.newFixedThreadPool(1), new 
QueryRunner(dataSource));
+    }
+
+    //
+    // Batch test cases
+    //
+    private void callGoodBatch(Connection conn, Object[][] params) throws 
Exception {
+        when(meta.getParameterCount()).thenReturn(2);
+        Future<int[]> future = runner.batch(conn, "select * from blah where ? 
= ?", params);
+
+        future.get();
+
+        verify(stmt, times(2)).addBatch();
+        verify(stmt, times(1)).executeBatch();
+        verify(stmt, times(1)).close();    // make sure we closed the statement
+        verify(conn, times(0)).close();    // make sure we closed the 
connection
+    }
+
+    private void callGoodBatch(Object[][] params) throws Exception {
+        when(meta.getParameterCount()).thenReturn(2);
+        Future<int[]> future = runner.batch("select * from blah where ? = ?", 
params);
+
+        future.get();
+
+        verify(stmt, times(2)).addBatch();
+        verify(stmt, times(1)).executeBatch();
+        verify(stmt, times(1)).close();    // make sure we closed the statement
+        verify(conn, times(1)).close();    // make sure we closed the 
connection
+    }
+
+    @Test
+    public void testGoodBatch() throws Exception {
+        String[][] params = new String[][] { { "unit", "unit" }, { "test", 
"test" } };
+
+        callGoodBatch(params);
+    }
+
+    @SuppressWarnings("deprecation") // deliberate test of deprecated code
+    @Test
+    public void testGoodBatchPmdTrue() throws Exception {
+        runner = new AsyncQueryRunner(dataSource, true, 
Executors.newFixedThreadPool(1));
+        String[][] params = new String[][] { { "unit", "unit" }, { "test", 
"test" } };
+
+        callGoodBatch(params);
+    }
+
+    @Test
+    public void testGoodBatchDefaultConstructor() throws Exception {
+        runner = new AsyncQueryRunner(Executors.newFixedThreadPool(1));
+        String[][] params = new String[][] { { "unit", "unit" }, { "test", 
"test" } };
+
+        callGoodBatch(conn, params);
+    }
+
+    @Test
+    public void testNullParamsBatch() throws Exception {
+        String[][] params = new String[][] { { null, "unit" }, { "test", null 
} };
+
+        callGoodBatch(params);
+    }
+
+
+
+    // helper method for calling batch when an exception is expected
+    private void callBatchWithException(String sql, Object[][] params) throws 
Exception {
+        Future<int[]> future = null;
+        boolean caught = false;
+
+        try {
+            future = runner.batch(sql, params);
+
+            future.get();
+
+            verify(stmt, times(2)).addBatch();
+            verify(stmt, times(1)).executeBatch();
+            verify(stmt, times(1)).close();    // make sure the statement is 
closed
+            verify(conn, times(1)).close();    // make sure the connection is 
closed
+        } catch(Exception e) {
+            caught = true;
+        }
+
+        if(!caught) {
+            fail("Exception never thrown, but expected");
+        }
+    }
+
+    @Test
+    public void testTooFewParamsBatch() throws Exception {
+        String[][] params = new String[][] { { "unit" }, { "test" } };
+
+        callBatchWithException("select * from blah where ? = ?", params);
+    }
+
+    @Test
+    public void testTooManyParamsBatch() throws Exception {
+        String[][] params = new String[][] { { "unit", "unit", "unit" }, { 
"test", "test", "test" } };
+
+        callBatchWithException("select * from blah where ? = ?", params);
+    }
+
+    @Test(expected=ExecutionException.class)
+    public void testNullConnectionBatch() throws Exception {
+        String[][] params = new String[][] { { "unit", "unit" }, { "test", 
"test" } };
+
+        when(meta.getParameterCount()).thenReturn(2);
+        when(dataSource.getConnection()).thenReturn(null);
+
+        runner.batch("select * from blah where ? = ?", params).get();
+    }
+
+    @Test(expected=ExecutionException.class)
+    public void testNullSqlBatch() throws Exception {
+        String[][] params = new String[][] { { "unit", "unit" }, { "test", 
"test" } };
+
+        when(meta.getParameterCount()).thenReturn(2);
+
+        runner.batch(null, params).get();
+    }
+
+    @Test(expected=ExecutionException.class)
+    public void testNullParamsArgBatch() throws Exception {
+        when(meta.getParameterCount()).thenReturn(2);
+
+        runner.batch("select * from blah where ? = ?", null).get();
+    }
+
+    @Test
+    public void testAddBatchException() throws Exception {
+        String[][] params = new String[][] { { "unit", "unit" }, { "test", 
"test" } };
+
+        doThrow(new SQLException()).when(stmt).addBatch();
+
+        callBatchWithException("select * from blah where ? = ?", params);
+    }
+
+    @Test
+    public void testExecuteBatchException() throws Exception {
+        String[][] params = new String[][] { { "unit", "unit" }, { "test", 
"test" } };
+
+        doThrow(new SQLException()).when(stmt).executeBatch();
+
+        callBatchWithException("select * from blah where ? = ?", params);
+    }
+
+
+    //
+    // Query test cases
+    //
+    private void callGoodQuery(Connection conn) throws Exception {
+        when(meta.getParameterCount()).thenReturn(2);
+        runner.query(conn, "select * from blah where ? = ?", handler, "unit", 
"test").get();
+
+        verify(stmt, times(1)).executeQuery();
+        verify(results, times(1)).close();
+        verify(stmt, times(1)).close();    // make sure we closed the statement
+        verify(conn, times(0)).close();    // make sure we closed the 
connection
+
+        // call the other variation of query
+        when(meta.getParameterCount()).thenReturn(0);
+        runner.query(conn, "select * from blah", handler).get();
+
+        verify(stmt, times(2)).executeQuery();
+        verify(results, times(2)).close();
+        verify(stmt, times(2)).close();    // make sure we closed the statement
+        verify(conn, times(0)).close();    // make sure we closed the 
connection
+    }
+
+    private void callGoodQuery() throws Exception {
+        when(meta.getParameterCount()).thenReturn(2);
+        runner.query("select * from blah where ? = ?", handler, "unit", 
"test").get();
+
+        verify(stmt, times(1)).executeQuery();
+        verify(results, times(1)).close();
+        verify(stmt, times(1)).close();    // make sure we closed the statement
+        verify(conn, times(1)).close();    // make sure we closed the 
connection
+
+        // call the other variation of query
+        when(meta.getParameterCount()).thenReturn(0);
+        runner.query("select * from blah", handler).get();
+
+        verify(stmt, times(2)).executeQuery();
+        verify(results, times(2)).close();
+        verify(stmt, times(2)).close();    // make sure we closed the statement
+        verify(conn, times(2)).close();    // make sure we closed the 
connection
+    }
+
+    @Test
+    public void testGoodQuery() throws Exception {
+        callGoodQuery();
+    }
+
+    @SuppressWarnings("deprecation") // deliberate test of deprecated code
+    @Test
+    public void testGoodQueryPmdTrue() throws Exception {
+        runner = new AsyncQueryRunner(true, Executors.newFixedThreadPool(1));
+        callGoodQuery(conn);
+    }
+
+    @Test
+    public void testGoodQueryDefaultConstructor() throws Exception {
+        runner = new AsyncQueryRunner(Executors.newFixedThreadPool(1));
+        callGoodQuery(conn);
+    }
+
+
+    // helper method for calling batch when an exception is expected
+    private void callQueryWithException(Object... params) throws Exception {
+        boolean caught = false;
+
+        try {
+            when(meta.getParameterCount()).thenReturn(2);
+            runner.query("select * from blah where ? = ?", handler, 
params).get();
+
+            verify(stmt, times(1)).executeQuery();
+            verify(results, times(1)).close();
+            verify(stmt, times(1)).close();    // make sure we closed the 
statement
+            verify(conn, times(1)).close();    // make sure we closed the 
connection
+        } catch(Exception e) {
+            caught = true;
+        }
+
+        if(!caught) {
+            fail("Exception never thrown, but expected");
+        }
+    }
+
+    @Test
+    public void testNoParamsQuery() throws Exception {
+        callQueryWithException();
+    }
+
+    @Test
+    public void testTooFewParamsQuery() throws Exception {
+        callQueryWithException("unit");
+    }
+
+    @Test
+    public void testTooManyParamsQuery() throws Exception {
+        callQueryWithException("unit", "test", "fail");
+    }
+
+    @Test(expected=ExecutionException.class)
+    public void testNullConnectionQuery() throws Exception {
+        when(meta.getParameterCount()).thenReturn(2);
+        when(dataSource.getConnection()).thenReturn(null);
+
+        runner.query("select * from blah where ? = ?", handler, "unit", 
"test").get();
+    }
+
+    @Test(expected=ExecutionException.class)
+    public void testNullSqlQuery() throws Exception {
+        when(meta.getParameterCount()).thenReturn(2);
+
+        runner.query(null, handler).get();
+    }
+
+    @Test(expected=ExecutionException.class)
+    public void testNullHandlerQuery() throws Exception {
+        when(meta.getParameterCount()).thenReturn(2);
+
+        runner.query("select * from blah where ? = ?", null).get();
+    }
+
+    @Test
+    public void testExecuteQueryException() throws Exception {
+        doThrow(new SQLException()).when(stmt).executeQuery();
+
+        callQueryWithException(handler, "unit", "test");
+    }
+
+
+    //
+    // Update test cases
+    //
+    private void callGoodUpdate(Connection conn) throws Exception {
+        when(meta.getParameterCount()).thenReturn(2);
+        runner.update(conn, "update blah set ? = ?", "unit", "test").get();
+
+        verify(stmt, times(1)).executeUpdate();
+        verify(stmt, times(1)).close();    // make sure we closed the statement
+        verify(conn, times(0)).close();    // make sure we closed the 
connection
+
+        // call the other variation
+        when(meta.getParameterCount()).thenReturn(0);
+        runner.update(conn, "update blah set unit = test").get();
+
+        verify(stmt, times(2)).executeUpdate();
+        verify(stmt, times(2)).close();    // make sure we closed the statement
+        verify(conn, times(0)).close();    // make sure we closed the 
connection
+
+        // call the other variation
+        when(meta.getParameterCount()).thenReturn(1);
+        runner.update(conn, "update blah set unit = ?", "test").get();
+
+        verify(stmt, times(3)).executeUpdate();
+        verify(stmt, times(3)).close();    // make sure we closed the statement
+        verify(conn, times(0)).close();    // make sure we closed the 
connection
+    }
+
+    private void callGoodUpdate() throws Exception {
+        when(meta.getParameterCount()).thenReturn(2);
+        runner.update("update blah set ? = ?", "unit", "test").get();
+
+        verify(stmt, times(1)).executeUpdate();
+        verify(stmt, times(1)).close();    // make sure we closed the statement
+        verify(conn, times(1)).close();    // make sure we closed the 
connection
+
+        // call the other variation
+        when(meta.getParameterCount()).thenReturn(0);
+        runner.update("update blah set unit = test").get();
+
+        verify(stmt, times(2)).executeUpdate();
+        verify(stmt, times(2)).close();    // make sure we closed the statement
+        verify(conn, times(2)).close();    // make sure we closed the 
connection
+
+        // call the other variation
+        when(meta.getParameterCount()).thenReturn(1);
+        runner.update("update blah set unit = ?", "test").get();
+
+        verify(stmt, times(3)).executeUpdate();
+        verify(stmt, times(3)).close();    // make sure we closed the statement
+        verify(conn, times(3)).close();    // make sure we closed the 
connection
+    }
+
+    @Test
+    public void testGoodUpdate() throws Exception {
+        callGoodUpdate();
+    }
+
+    @SuppressWarnings("deprecation") // deliberate test of deprecated code
+    @Test
+    public void testGoodUpdatePmdTrue() throws Exception {
+        runner = new AsyncQueryRunner(true, Executors.newFixedThreadPool(1));
+        callGoodUpdate(conn);
+    }
+
+    @Test
+    public void testGoodUpdateDefaultConstructor() throws Exception {
+        runner = new AsyncQueryRunner(Executors.newFixedThreadPool(1));
+        callGoodUpdate(conn);
+    }
+
+    // helper method for calling batch when an exception is expected
+    private void callUpdateWithException(Object... params) throws Exception {
+        boolean caught = false;
+
+        try {
+            when(meta.getParameterCount()).thenReturn(2);
+            runner.update("select * from blah where ? = ?", params).get();
+
+            verify(stmt, times(1)).executeUpdate();
+            verify(stmt, times(1)).close();    // make sure we closed the 
statement
+            verify(conn, times(1)).close();    // make sure we closed the 
connection
+        } catch(Exception e) {
+            caught = true;
+        }
+
+        if(!caught) {
+            fail("Exception never thrown, but expected");
+        }
+    }
+
+    @Test
+    public void testNoParamsUpdate() throws Exception {
+        callUpdateWithException();
+    }
+
+    @Test
+    public void testTooFewParamsUpdate() throws Exception {
+        callUpdateWithException("unit");
+    }
+
+    @Test
+    public void testTooManyParamsUpdate() throws Exception {
+        callUpdateWithException("unit", "test", "fail");
+    }
+
+    @Test
+    public void testInsertUsesGivenQueryRunner() throws Exception {
+        QueryRunner mockQueryRunner = mock(QueryRunner.class
+                , org.mockito.Mockito.withSettings().verboseLogging() // debug 
for Continuum
+                );
+        runner = new AsyncQueryRunner(Executors.newSingleThreadExecutor(), 
mockQueryRunner);
+
+        runner.insert("1", handler);
+        runner.insert("2", handler, "param1");
+        runner.insert(conn, "3", handler);
+        runner.insert(conn, "4", handler, "param1");
+
+        // give the Executor time to submit all insert statements. Otherwise 
the following verify statements will fail from time to time.
+        TimeUnit.MILLISECONDS.sleep(50);
+
+        verify(mockQueryRunner).insert("1", handler);
+        verify(mockQueryRunner).insert("2", handler, "param1");
+        verify(mockQueryRunner).insert(conn, "3", handler);
+        verify(mockQueryRunner).insert(conn, "4", handler, "param1");
+    }
+
+    @Test(expected=ExecutionException.class)
+    public void testNullConnectionUpdate() throws Exception {
+        when(meta.getParameterCount()).thenReturn(2);
+        when(dataSource.getConnection()).thenReturn(null);
+
+        runner.update("select * from blah where ? = ?", "unit", "test").get();
+    }
+
+    @Test(expected=ExecutionException.class)
+    public void testNullSqlUpdate() throws Exception {
+        when(meta.getParameterCount()).thenReturn(2);
+
+        runner.update(null).get();
+    }
+
+    @Test
+    public void testExecuteUpdateException() throws Exception {
+        doThrow(new SQLException()).when(stmt).executeUpdate();
+
+        callUpdateWithException("unit", "test");
+    }
+
+    //
+    // Random tests
+    //
+    @Test(expected=ExecutionException.class)
+    public void testBadPrepareConnection() throws Exception {
+        runner = new AsyncQueryRunner(Executors.newFixedThreadPool(1));
+        runner.update("update blah set unit = test").get();
+    }
+}

http://git-wip-us.apache.org/repos/asf/commons-dbutils/blob/084f286a/src/test/java/org/apache/commons/dbutils/BaseTestCase.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/commons/dbutils/BaseTestCase.java 
b/src/test/java/org/apache/commons/dbutils/BaseTestCase.java
index 913397f..dc5e479 100644
--- a/src/test/java/org/apache/commons/dbutils/BaseTestCase.java
+++ b/src/test/java/org/apache/commons/dbutils/BaseTestCase.java
@@ -1,138 +1,138 @@
-/*
- * 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.dbutils;
-
-import java.math.BigInteger;
-import java.sql.ResultSet;
-import java.sql.ResultSetMetaData;
-import java.sql.Timestamp;
-import java.util.Date;
-
-import junit.framework.TestCase;
-
-/**
- * BaseTestCase is the base class for all test cases as well as the "all tests"
- * runner.
- */
-public class BaseTestCase extends TestCase {
-
-    private static final String[] columnNames =
-        new String[] {
-            "one",
-            "two",
-            "three",
-            "notInBean",
-            "intTest",
-            "integerTest",
-            "nullObjectTest",
-            "nullPrimitiveTest",
-            "notDate",
-            "columnProcessorDoubleTest" };
-
-    /**
-     * The number of columns in the MockResultSet.
-     */
-    protected static final int COLS = columnNames.length;
-
-    protected static final ResultSetMetaData metaData =
-        MockResultSetMetaData.create(columnNames);
-
-    /**
-     * A Timestamp for test purposes having 9 decimals
-     */
-    static final Timestamp ts789456123;
-
-    static {
-        ts789456123 = new Timestamp(new Date().getTime());
-        ts789456123.setNanos(789456123);
-    }
-    
-    private static final Object[] row1 =
-        new Object[] {
-            "1",
-            "2",
-            "THREE",
-            "  notInBean  ",
-            Integer.valueOf(1),
-            Integer.valueOf(2),
-            null,
-            null,
-            new Date(),
-            BigInteger.valueOf(13)};
-
-    private static final Object[] row2 =
-        new Object[] {
-            "4",
-            "5",
-            "SIX",
-            "  notInBean  ",
-            Integer.valueOf(3),
-            Integer.valueOf(4),
-            null,
-            null,
-            ts789456123,
-            BigInteger.valueOf(13)};
-
-    private static final Object[][] rows = new Object[][] { row1, row2 };
-
-    /**
-     * The number of rows in the MockResultSet.
-     */
-    protected static final int ROWS = rows.length;
-
-    /**
-     * The ResultSet all test methods will use.
-     */
-    protected ResultSet rs = null;
-
-    /**
-     * A ResultSet with 0 rows.
-     */
-    protected ResultSet emptyResultSet = null;
-
-    /**
-     * This is called before each test method so ResultSet will be fresh each
-     * time.
-     * @see junit.framework.TestCase#setUp()
-     */
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-
-        rs = this.createMockResultSet();
-        emptyResultSet = MockResultSet.create(metaData, null);
-    }
-
-    /**
-     * Creates a freshly initialized ResultSet.
-     */
-    protected ResultSet createMockResultSet() {
-        return MockResultSet.create(metaData, rows);
-    }
-
-    // Test which allows Eclipse to be run on full project (avoids no tests 
found)
-    // check that the rows are valid for the column definition
-    public void testCheckDataSizes() {
-        assertEquals("Row 1 must contain correct number of columns", 
columnNames.length, row1.length);
-        assertEquals("Row 1 must contain correct number of columns", 
columnNames.length, row2.length);
-    }
-
-    public void testResultSets() throws Exception {
-        assertFalse("emptyResultSet should be empty", emptyResultSet.next());
-        // fails in SqlNullCheckedResultSetTest assertTrue("rs should not be 
empty", rs.next());
-    }
-}
+/*
+ * 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.dbutils;
+
+import java.math.BigInteger;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.Timestamp;
+import java.util.Date;
+
+import junit.framework.TestCase;
+
+/**
+ * BaseTestCase is the base class for all test cases as well as the "all tests"
+ * runner.
+ */
+public class BaseTestCase extends TestCase {
+
+    private static final String[] columnNames =
+        new String[] {
+            "one",
+            "two",
+            "three",
+            "notInBean",
+            "intTest",
+            "integerTest",
+            "nullObjectTest",
+            "nullPrimitiveTest",
+            "notDate",
+            "columnProcessorDoubleTest" };
+
+    /**
+     * The number of columns in the MockResultSet.
+     */
+    protected static final int COLS = columnNames.length;
+
+    protected static final ResultSetMetaData metaData =
+        MockResultSetMetaData.create(columnNames);
+
+    /**
+     * A Timestamp for test purposes having 9 decimals
+     */
+    static final Timestamp ts789456123;
+
+    static {
+        ts789456123 = new Timestamp(new Date().getTime());
+        ts789456123.setNanos(789456123);
+    }
+
+    private static final Object[] row1 =
+        new Object[] {
+            "1",
+            "2",
+            "THREE",
+            "  notInBean  ",
+            Integer.valueOf(1),
+            Integer.valueOf(2),
+            null,
+            null,
+            new Date(),
+            BigInteger.valueOf(13)};
+
+    private static final Object[] row2 =
+        new Object[] {
+            "4",
+            "5",
+            "SIX",
+            "  notInBean  ",
+            Integer.valueOf(3),
+            Integer.valueOf(4),
+            null,
+            null,
+            ts789456123,
+            BigInteger.valueOf(13)};
+
+    private static final Object[][] rows = new Object[][] { row1, row2 };
+
+    /**
+     * The number of rows in the MockResultSet.
+     */
+    protected static final int ROWS = rows.length;
+
+    /**
+     * The ResultSet all test methods will use.
+     */
+    protected ResultSet rs = null;
+
+    /**
+     * A ResultSet with 0 rows.
+     */
+    protected ResultSet emptyResultSet = null;
+
+    /**
+     * This is called before each test method so ResultSet will be fresh each
+     * time.
+     * @see junit.framework.TestCase#setUp()
+     */
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        rs = this.createMockResultSet();
+        emptyResultSet = MockResultSet.create(metaData, null);
+    }
+
+    /**
+     * Creates a freshly initialized ResultSet.
+     */
+    protected ResultSet createMockResultSet() {
+        return MockResultSet.create(metaData, rows);
+    }
+
+    // Test which allows Eclipse to be run on full project (avoids no tests 
found)
+    // check that the rows are valid for the column definition
+    public void testCheckDataSizes() {
+        assertEquals("Row 1 must contain correct number of columns", 
columnNames.length, row1.length);
+        assertEquals("Row 1 must contain correct number of columns", 
columnNames.length, row2.length);
+    }
+
+    public void testResultSets() throws Exception {
+        assertFalse("emptyResultSet should be empty", emptyResultSet.next());
+        // fails in SqlNullCheckedResultSetTest assertTrue("rs should not be 
empty", rs.next());
+    }
+}

Reply via email to